pax_global_header00006660000000000000000000000064141062572610014516gustar00rootroot0000000000000052 comment=c26a02cb649a7f8de342e57ffdef9b7a60fb128a Akira-0.0.16/000077500000000000000000000000001410625726100126315ustar00rootroot00000000000000Akira-0.0.16/.editorconfig000066400000000000000000000004311410625726100153040ustar00rootroot00000000000000root = true [*] end_of_line = lf indent_style = space trim_trailing_whitespace = true insert_final_newline = true charset = utf-8 [*.{txt,build,json,xml,xml.in,in}] indent_size = 2 [*.{vala,py}] indent_size = 4 block_comment_start = /** block_comment = * block_comment_end = */ Akira-0.0.16/.github/000077500000000000000000000000001410625726100141715ustar00rootroot00000000000000Akira-0.0.16/.github/CODE_OF_CONDUCT.md000066400000000000000000000062161410625726100167750ustar00rootroot00000000000000# Code of Conduct ## Our Pledge In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. ## Our Standards Examples of behavior that contributes to creating a positive environment include: * Using welcoming and inclusive language * Being respectful of differing viewpoints and experiences * Gracefully accepting constructive criticism * Focusing on what is best for the community * Showing empathy towards other community members Examples of unacceptable behavior by participants include: * The use of sexualized language or imagery and unwelcome sexual attention or advances * Trolling, insulting/derogatory comments, and personal or political attacks * Public or private harassment * Publishing others' private information, such as a physical or electronic address, without explicit permission * Other conduct which could reasonably be considered inappropriate in a professional setting ## Our Responsibilities Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. ## Scope This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. ## Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at **castellani.ale@gmail.com**. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. ## Attribution This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] [homepage]: http://contributor-covenant.org [version]: http://contributor-covenant.org/version/1/4/Akira-0.0.16/.github/FUNDING.yml000066400000000000000000000001461410625726100160070ustar00rootroot00000000000000# These are supported funding model platforms github: [alecaddd] patreon: akiraux liberapay: AkiraUX Akira-0.0.16/.github/ISSUE_TEMPLATE.md000066400000000000000000000027461410625726100167070ustar00rootroot00000000000000## Expected Behavior ## Current Behavior ## Possible Solution ## Steps to Reproduce (for bugs) 1. 2. 3. 4. ## Context ## Screenshots of the Problem ## Your Environment (for bugs) - Akira Version: - OS Info: Akira-0.0.16/.github/PULL_REQUEST_TEMPLATE.md000066400000000000000000000023041410625726100177710ustar00rootroot00000000000000 ## Summary / How this PR fixes the problem? ## Steps to Test ## Screenshots ## Known Issues / Things To Do ## This PR fixes/implements the following **bugs/features**: - Fixes # - Fixes # Akira-0.0.16/.github/workflows/000077500000000000000000000000001410625726100162265ustar00rootroot00000000000000Akira-0.0.16/.github/workflows/build.yml000066400000000000000000000041011410625726100200440ustar00rootroot00000000000000name: "CI" on: push: branches: - "master" pull_request: jobs: build: runs-on: ubuntu-latest container: image: elementary/docker:unstable steps: - uses: actions/checkout@v1 - name: Install Dependencies run: | apt update apt install -y libarchive-dev valac meson appstream-util xvfb at-spi2-core git build-essential autoconf autoconf-archive autopoint automake pkg-config libtool m4 autoconf-archive gtk-doc-tools libxml2-utils gobject-introspection libgirepository1.0-dev libglib2.0-dev libjson-glib-dev gettext libcairo2-dev libgtk-3-dev - name: goocanvas-3.0 from source run: | git clone https://gitlab.gnome.org/GNOME/goocanvas cd goocanvas git checkout goocanvas-3.0 git revert --no-commit 9103e2f mkdir build cd build ../autogen.sh ../configure --prefix /usr make make install - name: Build # env: # DESTDIR: out run: | meson build ninja -C build ninja -C build install xvfb-run -a -s "-screen 0 1024x768x24" \ dbus-run-session meson test -C build --no-rebuild -v --no-stdsplit --wrap catchsegv - name: cleanup xvfb run: | xvfb_pids=`ps aux | grep tmp/xvfb-run | grep -v grep | awk '{print $2}'` if [ "$xvfb_pids" != "" ]; then echo "Killing the following xvfb processes: $xvfb_pids" sudo kill $xvfb_pids else echo "No xvfb processes to kill" fi flatpak: name: "Flatpak" runs-on: ubuntu-latest container: image: bilelmoussaoui/flatpak-github-actions:elementary-juno options: --privileged steps: - uses: actions/checkout@v2 - uses: bilelmoussaoui/flatpak-github-actions/flatpak-builder@master with: bundle: "akira-dev.flatpak" manifest-path: "build-aux/flatpak/com.github.akiraux.akira.json" cache-key: flatpak-builder-${{ github.sha }} run-tests: "true" Akira-0.0.16/.github/workflows/lint.yml000066400000000000000000000004101410625726100177120ustar00rootroot00000000000000name: "CI: Lint" on: push: branches: - "master" pull_request: jobs: lint: runs-on: ubuntu-latest container: image: valalang/lint steps: - uses: actions/checkout@v1 - name: Lint run: io.elementary.vala-lint -d . Akira-0.0.16/.gitignore000066400000000000000000000001211410625726100146130ustar00rootroot00000000000000.snapcraft .vscode src/config.vala build/ builddir/ _build/ .flatpak-builder/ *~ Akira-0.0.16/AUTHORS000066400000000000000000000000741410625726100137020ustar00rootroot00000000000000Alessandro "Alecaddd" Castellani Akira-0.0.16/CONTRIBUTING.md000066400000000000000000000152251410625726100150670ustar00rootroot00000000000000# Contributing to Akira :tada: First off, thank you for considering contributing to Akira :tada: Akira is an open source project and we love to receive contributions from our community — you! There are many ways to contribute, from submitting bug reports and feature requests or writing code which can be incorporated into Akira itself. All members of our community are expected to follow our [Code of Conduct](.github/CODE_OF_CONDUCT.md). Please make sure you are welcoming and friendly in all of our spaces. The following is a set of guidelines for contributing to Akira, which is hosted in the [Akira UX Organization](https://github.com/akiraux) on GitHub. Following these guidelines helps to communicate that you respect the time of the developers managing and developing this open source project. In return, they should reciprocate that respect in addressing your issue, assessing changes, and helping you finalize your pull requests. These are mostly guidelines, not rules. Use your best judgment, and feel free to propose changes to this document in a pull request. ## Table of contents * [Getting started](#getting-started) * [Reporting bugs and issues](#reporting-bugs-and-issues) * [Feature requests](#feature-requests) * [Your first contributions](#your-first-contribution) * [Pull requests](#pull-requests) * [Code review process](#code-review-process) ## Getting started * Akira is written in [Vala language](https://wiki.gnome.org/Projects/Vala). * To start learning how to program in Vala, check out the [official tutorial](https://wiki.gnome.org/Projects/Vala/Tutorial) * To follow up on general questions about development in GTK, head over to [Gnome Wiki](https://wiki.gnome.org/Newcomers/) * Akira's main source repository is at [Github](https://github.com/akiraux/Akira). * Development happens in the `master` branch, thus all Pull Request should be opened against the `master` branch. * Installing You can install Akira by compiling it from the source 1. Install required dependencies: * `gtk+-3.0>=3.18` * `granite>=6.0.0` * `glib-2.0` * `gee-0.8` * `gobject-2.0` * `libxml-2.0` * `libarchive` * `goocanvas-3.0` * `gettext` * `cairo` * `meson` > For non-elementary distros, (such as Arch, Debian etc) you are required to install "vala" as additional dependency. > If goocanvas-3.0 is still not available on your distro you can build from source: ``` git clone https://gitlab.gnome.org/GNOME/goocanvas cd goocanvas git checkout goocanvas-3.0 mkdir build cd build ../autogen.sh ../configure --prefix /usr make make install ``` * Debian (Elementary/Ubuntu/Linux Mint) ```sh sudo apt-get install gtk+-3.0 elementary-sdk glib-2.0 gee-0.8 gobject-2.0 libxml2 libjson-glib-1.0 goocanvas-3.0-dev libarchive-dev libcairo2-dev meson valac ``` 2. Building: ``` meson build --prefix=/usr -Dprofile=default|development cd build ninja && sudo ninja install ``` ## Reporting bugs and issues ### Security vulnerability **If you find a security vulnerability, do NOT open an issue. Email _castellani.ale@gmail.com_ instead.** In order to determine whether you are dealing with a security issue, ask yourself these two questions: * Can I access something that's not mine, or something I shouldn't have access to? * Can I disable something for other people? If the answer to either of those two questions are "yes", then you're probably dealing with a security issue. Note that even if you answer "no" to both questions, you may still be dealing with a security issue, so if you're unsure, just email us at _castellani.ale@gmail.com_. ### Bugs/Issues If you think you have found a bug in Akira, first make sure that you are testing against the latest version of Akira (latest commit on `master` branch) - your issue may already have been fixed. If not, search our [issues list](https://github.com/akiraux/Akira/issues) on GitHub in case a similar issue has already been opened. If the issue has not been reported before, simply create [a new issue](https://github.com/akiraux/Akira/issues/new) via the [**Issues** section](https://github.com/akiraux/Akira/issues) It is very helpful if you can prepare a reproduction of the bug. In other words, provide all the steps as well as a GIF demonstrating the bug. It makes it easier to find the problem and to fix it. Please adhere to the issue template and make sure you have provided as much information as possible. This helps the maintainers in resolving these issues considerably. > **Please be careful** of publishing sensitive information you don't want other people to see, or images whose copyright does not allow redistribution; the bug tracker is a public resource and attachments are visible to everyone. ## Feature requests If you find yourself wishing for a feature that doesn't exist in Akira, you are probably not alone. There are bound to be others out there with similar needs. Many of the features that Akira has today have been added because our users saw the need. To request a feature, open an issue on our [issues list](https://github.com/akiraux/Akira/issues) on GitHub which describes the feature you would like to see, why you need it, and how it should work. > Akira is maintained by a small team of individuals, who aim to provide good support as much as possible. ## Your first contribution Unsure where to begin contributing to Akira? You can start by looking through the help-wanted issues: * [Help wanted issues](https://github.com/akiraux/Akira/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22) - issues which the team has marked for some help. > Working on your first Pull Request? You can learn how from this [link](https://www.firsttimersonly.com/). At this point, you're ready to make your changes! Feel free to ask for help; everyone is a beginner at first 😸 > If a maintainer asks you to "rebase" your PR, they're saying that a lot of code has changed, and that you need to update your branch so it's easier to merge. ## Pull requests For something that is bigger than a one or two line fix: 1. Create your own fork of the code 1. Create a branch 1. Commit your changes in the new branch 1. If you like the change and think the project could use it: * Be sure you have followed the code style for the project. * Open a pull request with a good description (including issue number) ## Code review process The core team looks at Pull Requests on a regular basis and they are dealt with on case by case basis and roadmap in mind. Akira-0.0.16/COPYING000066400000000000000000001045051410625726100136710ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. 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 them 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 prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. 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. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey 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; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If 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 convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU 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 that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. 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. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 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. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. 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 state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. {one line to give the program's name and a brief idea of what it does.} Copyright (C) {year} {name of author} 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 . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: {project} Copyright (C) {year} {fullname} This program 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, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU 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. But first, please read . Akira-0.0.16/README.md000066400000000000000000000112161410625726100141110ustar00rootroot00000000000000


Akira

The Linux Design Tool

Build Status AkiraUX on Liberapay AkiraUX on Patreon

InstallCompileQuestionsContributingSupportMascotLicense

![screenshot](data/screenshots/screenshot-1.png) Akira is a native Linux Design application built in Vala and GTK. Akira focuses on offering a modern and fast approach to UI and UX Design, mainly targeting web designers and graphic designers. The main goal is to offer a valid and professional solution for designers who want to use Linux as their main OS. ⚠️⚠️ **AKIRA IS CURRENTLY IN EARLY DEVELOPMENT, NOT READY TO BE USED FOR PRODUCTION!** ⚠️⚠️ Feel free to download the Alpha and help us testing it. ## 📦 Install | elementaryOS AppCenter | FlatHub | |------------------------ |--------------- | |[![Get it on AppCenter](https://appcenter.elementary.io/badge.svg)](https://appcenter.elementary.io/com.github.akiraux.akira/)|Get it from Flathub! ### Flathub Beta ``` flatpak remote-add flathub-beta https://flathub.org/beta-repo/flathub-beta.flatpakrepo flatpak install akira ``` ## 🛠 Compile You can install Akira by compiling it from the source ### Install Dependencies - `gtk+-3.0>=3.18` - `granite>=6.0.0` - `glib-2.0` - `gee-0.8` - `gobject-2.0` - `libxml-2.0` - `libjson-glib-1.0` - `goocanvas-3.0` - `libarchive` - `gettext` - `cairo` - `meson` > _**Note:** For non-elementary distros, (such as Arch, Debian etc) you are required to install "vala", "elementary-theme" and "elementary-icon-theme" as additional dependencies._ ### Compile & Run Once the above mentioned dependencies are resolved, Akira can be compiled & installed ```sh meson build --prefix=/usr -Dprofile=default cd build ninja && sudo ninja install ``` > _**Note:** Replace the `-Dprofile=default` with `-Dprofile=development` to compile and install Akira in **development** mode where you can make changes._ ## 🤔 Questions If you want to ask any questions about the project, join us on our public Matrix channel at [#akiraux:matrix.org](https://matrix.to/#/#akiraux:matrix.org) or on IRC at #akiraux on LiberaChat. We also have a dedicated Discord channel available to any [Patreon](https://www.patreon.com/akiraux) supporters where we offer more direct support, and we're open to discussing new features and implementations. If you are trying out Akira and you encounter an error or any problem feel free to just open an issue here on GitHub. ## 👨‍💻 Contributing Feel free to send a pull request to this repository with your code contributions, but first read our [contributing guidelines](CONTRIBUTING.md) :page_with_curl: ## 📌 Code of Conduct This project adheres to the adapted version of Contributor Covenant [code of conduct](.github/CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code. ## 🎉 Support If you like Akira and you want to support its development, consider donating via [Liberapay](https://liberapay.com/AkiraUX/) or pledge on [Patreon](https://www.patreon.com/akiraux). ## ✨ Mascot ![](https://raw.githubusercontent.com/akiraux/assets/master/mascot/akira-mascot-akari.png) **Akari the Cyber Phoenix** is a perfectionist. She is tidy, collected and has a sharp eye for detail. Her name Akari (灯理、) means *"the enlightenment of a sophisticated order"*. Her costume resembles the project's icon. Get the Mascot and all the other assets from [here](https://github.com/akiraux/assets). Mascot character designed by **Tyson Tan**. Tyson Tan offers mascot design service for free and open source software, free of charge, under free license. Contact: [http://tysontan.com](http://tysontan.com) / [tysontan@mail.com](mailto:tysontan@mail.com) ## 📜 License #### [GNU GPLv3 / Creative Commons BY-SA](./COPYING) Copyright © 2019-2020 Akira Project. Akira-0.0.16/SUPPORTERS.md000066400000000000000000000031461410625726100147050ustar00rootroot00000000000000# List of Akira Supporters :tada: All the awesome people that donated to the project :tada: * LordVarkson * Coryn * Kiyoshi Aman * Pierre Paul Lefebvre * Jan Masak * Alexandru Nedel * Samuel Gyger * Patrick Nafarrete * Tyler Compton * Vagner Rodrigues * Frederick M. Rogers * Matko * veritanuda * Jof Rey * Paul Demers * Bob Patraque * Wilhelm Fitzpatrick * Sage Ross * Joshua Draxten * Nick Richards * Simon Hafner * Alexander Poselentsev * Aris Papathéodorou * Wesley Moore * Noel * Isak Westerlund * Sam Muirhead * Christopher Crouse * manokara * Sumner Evans * Steven Teskey * nicolas * Alexander Nesterenko * Xaviju * Joshua Heidrich * snorpey * Per Thomas Lundal * Gernot Premper * Markus Huggler * Luis Barron * Wtcher * maylme * Marek Pikuła * Rebecca Bulboaca * Benjamin Altpeter * Raí Biason Toffoletto * Daniel Foré * Guillaume Chau * Stephan Müller * Imanuel * Andrew Sauber * Alexey Bolonia * Andreas Libak Jørgensen * Arthur Nieuwland * Pyves & Ran * Aode (Lion) * Nacheta Menjibar * sStevemMartin * Jebedaia * Sebi * Shaleen Jain * Ezra Sharp * TheCrealm * rickard * Roberto * Bryan Paget * Shelby Cruver * Markus Rubey * Miura Seiji * Vladislav Petrov * Bruno Paz * Gonçalo * Ben Oliver * Tenné * Antonio Maciej Matamoros Ochman * Stephan Plöhn * Gabriel J Perez * Jonas Rudlang * Pietro Vertechi * dehahost * Marián Brém * Bacchus * Selwyn * User * Martin Kregar * oliver * James Dyson * Wout * Thomas Höß * Brian Hinton * Ryan Halliday * janowhatever * Darshak Parikh * Pawel Kozlowski * Dave Lane * Sebastian * Maïtané * Bogdan Vatulya * Saku Tiihonen * Somebody * I Sutter * Bailey * Marie Ingabire Akira-0.0.16/akira-logo-transparent.png000066400000000000000000000277241410625726100177370ustar00rootroot00000000000000PNG  IHDR,d< bKGD pHYs  tIME 3 IDATx[yW`w,q%@INHJlɱcIm,*~H%RJ%)/N*N*Ie+&-I$LQ" $,ܧOg/{fo)W53=ݧO||;BJ)$H"A$DV$DIXDIXDI$`EI$l tqDWZǮ KT s,l㩨v#$'ىK\@8{ yX|c9Ύn$D&QJdfxFT!d'bVVڍ$nsi@``fJqn27&GvZ3 vŨv#$#)A.k27SSB)7ɓ^01t0teXըv#$i~p,4@`!]cyn4V7/0PCͺ^Uٹ#$͕rN5:!52^Kc0sś,T4a湨#$M6?<i Dd'%clIue>H"kc4s\Sx] >4b=qYw(F{$DR~r6H5X"I,VҲ O k#.|Wy%{b9@zA7Lsŝs ~:H"kk̼&hZ{J jy0ݮ 2?AudXDVUj'Н sXa9>FX1j#'0{$D^Zg@$S=nᇮaz0 Y.٨#$uȫQ}5XFX<'e OA-|$Oy}rt]O+[A g` <|$Dd@!=֧}O'`dTDVWV@a#wG;cXW'Dj%}Ψͼx71~ =߅G5I$`RFOBn5r7 L FjfҲ=H"jW ` " i*`j VEF=uSg!$OܹY‰s0V9魵(p|' 5%+0vc;[XX(˘ܼJ$ :;RhZKJI6BQuzBo<+VRBzH$;Z):;dsKۖ! ftuv`F$T./P65aA,ߝZF_Z:C3f3Ҩ_7q|:lJJ ^VVK,3pt\Ƕм]o^sO=}ܽf*Ky.pz)}:{/<4ӋߓgBDXY^Bwmu669Nev> Hd@z+^yhBH$3u=J2]+]gzvr.OZLxLfy%qv~+}Ove$z -KV:{8>u.xS~ĤGp`QwS/126/<{@#dxdk7G ȗ`n>{Кktbw޿Ln%y?p<ȧIknanPTp/@\>g8N E|A`I)7\D^''%f o/ާX*ۙ ޾󻃵OS 5*dY%^ZE{ - zY >53Ǚƭ LS"Mkĵo\?k!# ;=)DJj9OYўJ^>L)%cS h7ʠZ ~1Mi<}LZ:;w!6+y~zdfn߿LZsGs[]$!pA[|4<׌MN3;m1;6Zerjz{o3`*0r̢nkW" ?j{%v$~ :v1*d9vpBy-p;ϫ*Vqi9CR \|W+[[O:,-gmjD6vMٻk%a'ʲS2'|z@Rl6"y>\L.Gj6Lswl2m[!ה+;a-\3nuѱqZ+ gZ|:5 kZSHh&f FM@KK֟j-$hҙtԁ\{9\[^]5N{4B/˷Y.QEt#)OƪС|c_RutuƔcbj0\z@&]e'ļA*Ii7~G44OAnqiU^@ito "'O/[hT͹8o!|5CDkH=U'}M|ؘtho*p-T)=24]H1_ROxg\T-=Ss!<桕x4"ܼpjfobGUAà L<V~2U`ǭ4g`MǺ>n,/3yJ4=JĮz}hu46`w@!e0ז/0;vJ}{vJBӫ;z0Ho^ TGIq̕!D+ަ1UFW QY;%hIf^E6}$C~ N ;j`u V@f7D| Ӗ%q!h DxPT^᜗ݸMH=EÒR2:>J.ț1I+79I eyI)ɭ}e3?w7}[MBg' &)AtRLp5ͩ|'r| #d6-=JޅH?4 m,v{Vl mhFb]ʊ?Spwhs~qvlpO@ ӳ8:醹%߃'#r\* _97QBߖ^v0vlwքFI26tKO7Kgp@8-cG=]t~V4Ii-Uga]ָxC^;ӖKidbI$h|z_t=(>vS )ʼs ֠ ٮҔ$^~C*ϵnUV`,o^C%]`Ro;w7<)Vcٳk33ל3(P%q- RƶLvkFAv`ni+9 nM@0 \vw0c۪H%?VUShY7]Dذz]y5-rCڕ~<ϴ2I7͕]Az8Yan.`+YTH`+Z[b]H=Z', ʓ"W2@hXt^`LbiX)ӳL̹(U3gݵΐ8eh0׹HY/t NSKp0AOS)x5fQuEmI(%d;EA&jLJ K*.^9ۍVLV/N=r}#׉VxV~=[.YX5gI6twh0UZeq9-J~)X,)48{Muau8=ךP)WY\04 ˔Li6ЇЄ{Gx4y.]9h;;X C%{ ozϰ9ReZo@^\4wG"JaTXX\ ]3s#`9S'FuP(rJT5Tha8UX[ pEN ,^m/BbhsLB&٥jBEC%BrLg[ϵ6LuP\ǽ«Aӄ^Nrge 4 s췙dzɤM{V_lI|Q7PGC nfU,jP(T]<_eibM&?rΡ6 !dl򓫳e)FN#[Y?|T.J&7 'Փ8I>x5#sLj!|K ¹Uems)\ϟX2,^B87yh B-A2gkUp PYZli 4 ĺvn8+A/!Dg(Kߚ57MRQ_iC(126|vm E3F58Lq/{B.[MH3mS*@x\ G]LR;i i)Bq d)fIϔ/ A5}YbG~w,OloDt !_#q/[#f2:~)ሕ$ȡ|#h l+x(ϽiȄOlR=HBn'G Pz^Gz79HRuP;jRGuI<>mӽgckWq "@SΝ'*Pv|!E&JaKh`e}V)O'栚n'{*] ϒ9&Z ߥ]`IҮ 3 BW,*BuɁmB)IflfkQuƬ$d M.M˜~w;7vJL x=t(4;y Q6^Jq K,fP,B\葃cI^<^K*0-|  ^;Fc>@=x_*UXY)p\l/L'^;>1ٟ\ ++} i%jT1V-t)/u!MiPOHtC5&L)M;#]a j ۚC:bE=ָ{FvsOBV!g>Ȯ@ɕo^jij-P.{wJ?"7G[:C9߿a9g\]p /<4c kܪ{߽pW/L&m2}3ԭ=tT27hiNeI-j̹wϛ(Bar  |7 0 fz'T;zc2O0E|ekls5K.ԮnEVUIDAT)s>{[} 5J`hp{Y?z1k[Uk{/grߜhS5R=o.SBpO^rvă0&%gοɮ;OgN+L:H G}}M\3zkd-餸%48iUiGB͔,,XH(w;xkj3D1 Yeo]3Ra+ZF~mAQط6!Q|'d!B@LzZl*Jڒh>3d9`I,acU !xmpaeͮγkh;GJgz]Ҽ-n@Q VlmhI(!?bUQu^&kh1m)# Ә2я вBq^$zj hf$gN@jhJkpһW]2Ղ^ `pKv MPH- obB&.հeɶ9"&L&ft|.\Ur^5ƏNZrN p rr'!DkҺfmH3xٿ ` P'=3a+'}-Ximna_,K&kWYXQ7d~YDE5\@%ݶf%lFe;3D&zb{7{3 29ͦ/oұe w54;] sbjW|'Ksט!#C u4mI^{v+ϰm[@^e7~.'ϼ0#zh *_o{Z`XAq*܂ېbf1r kLըЄZ^AicPI~V |Y9ePl,gN)=q־b- Owmd}]8|p:{3S{r#mtvw3DgsY{z _yQ:7QW߮ᜠ/<a(7]T9[8 7s 2Xv%M*?GZ=`UВ- YHc9O$>{Rw$0t7X6hfQ8Cפ T5zX~S?\zw+w7=0_%[/u]r)`mUj@ΣZ*j mf ZiyfsZ^;ί<ȯ1m~aZIOw_|s.\_h&i/3|dE(ZCa BP r?D;爛Cv~ҵ94[LVi$mVd1w\kPP+tk3k0JnkuMs~4Ѻ1%ʕJuհXnTJ;iv:qڎmrܛ>fZZik*,E^bS $R k'?miS K/["}A?´HǮ?3_['%ꄺ EuaxkTI Cò+s suJI J=\kX]]eՉkԗ^#@83 AwW'nxwGOw7Km$q = 'q4!JPiUazngZ0 ,_rᎇ !x?8CPmO||O{wH%fitw) l0H&![e׵:J_DȒoU^BX`e\ N"r7iw&94eA`ş/ZabcoZ=ԐsЗX_-[zg#T({wqSGVi|{j̬ >8)e?xS3.comF~~-3п%>_{o7|\{l4]SGfϮA_=r_gl.<'ģзe/D{>hAQz:= g|r:PH%y%Am?[\lsޡTrG.-s 갋٨F[7KVпTp|7߲LJDi/3:A}wXrjme|'׭eIP UږI))ʾ^PH%C1[a:db kB1TH%CGv)%JR̝T2ak_;ԞJh]9ّ/rjvkBZClR(CuD"N<[%`-;!;6\@`;'-*L5?Y_Vӹзסsφ53w ˈm&-*Bqw8/ю;"$͗_{%B*-BmUqe8 |v^֜= _#d%XwrU-'&sUW0pn4ڞG*HI7,>*s jf_ӹm듄h{)a!,ӘC_FSQˊ$ XREkrJaPeF,*-J 8U`\3>fS5=DeVSq`]*jYDr[+? LZer' KQ@Z1)aBj #$Xs 7m!Uia3BX>U~~JI`Ѷ>Ü|g" @.KI$ jEK,o9릐wާj%1 qs/լrW!}vE{$J,+7I#FUc' }Gط-Uj==O"'^ Y\86k b$Dɀu/i"etpw`豿%h; >9=+ 7`苸H"\NõB*,m0Q$s{ se+dymtXD5rf$-{RSɖGz0 I$X \YXG >VK31_'f 8V$lLMk]УKp4>U]j+ri$D Il/*HVDIVq.#SI$|Mb=QDI$$H"KdEI$`EI$lF IENDB`Akira-0.0.16/akira-screenshot.png000066400000000000000000006226541410625726100166200ustar00rootroot00000000000000PNG  IHDR|Q.(DsBIT|d IDATxy#u?WUNOfSA@]EXVT@TdQ x,? _AEca{{;wRUd$S9_cU'sS@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDN*vl"""""""""lb7Xfz<QL g!"""""""""*w3&`/NDDDDDDDDD4e^nt+p\b\(ߊr|^qW+/`T鶫Tl1`R smOGDDDDDDDDD4[tzyWJr.m:t?fL\K%hζSm?U*}BDDDDDDDDDTl n.z^ q6mW^ kDz6AyQCb ҍНf+ꝧ[_zB|$/FNDDDDDDDDDDFFbRSmٴr ܉M7N8>>mp.Wr ҥ$ˍ ։fLtdY&g,yQ@9aT9sDDDDDDDDDD1s ڳY?mg{b..ADDDDDDDDD4ۥ D)Tm1L!|鉗S-˴] ։h$HOL`rО,U_ҡz\t9Ე<z6N.L~jtB' L SjϴlCDDDDDDDDDT'6~Y6hMFx Gq?T/K ՓFm!"""""""""2 S?? HT*/DϖaqM$lTȨ| k㉈('!UU{{{_Ku "գ{?]N{rV z.azt뮻o}[4MuzDDDDDDDDDDT,Ce(/}?O_E$TWq*PO ֑gU>&ѣ?ӷnBYDDDDDDDDDD$I0L]v ===[).~Fe'=u9PF' g}c1L'"""""""""*!Bhctf&ilBT;VxƳXⅈ躎!*CtLR)h^ꙔzImot CvIDDDDDDDDDD0:tedHrL3՝vyd.0 !l,BDDDDDDDDDTvDhTC$$M]sfDd!T%^GGH8P$IRnk*tFoOze?=,DL% Cu%&4$I? IC QI& KRLʺdS;=rbGG;:B躎~@UՂf4e8BdBuu5!27"""""""*<7YΛX%(d$^׀G'De_$J4$I8`X r[lE]Y\Cvލ~455Hu?Fz',|ƉhfH<qKrz1oF'[éLhaN;#VWEԵڠgë:FFFpl6K4ul هf+Vk(̝Jb=u,c횕%Bv1K!`[2lW;_ՠ Ʉ 8̅|P(17t] L 6+*+ 6X*Sp=^7wrB71񒛊,fUrKÇ moKe`ѢEEnYI0'TOUh{tZ' L@> pͳPsGG7e#:y] 2^} Ȳꪔ@P*Ju&4Z!wUQ"P5@dEBv!Ѭ '0`ֱzUe5v+8]8:4=0h @uuľEGJ݆%Khu!^a,jmƘFDj-UwNaNSfa%$L_لZעxz{ۿXqO~|!/xMOS1(+hA  aIM]Q;44J̙S;{4^|I:haqA̯kрAd8qEaXVBӴ; NjڿFu\)M3v_wO/.-u =v܉7 [nEOO8 h;@i8 8puuuذauY#Hm \4W sK&^fդt^BФ}Wpzڎ (QU0DA5-?c݇g|LC;3?4Ĉmum*pOf3̫EOvcӲ"[*0nƴ<jrm7B]-GE~v^/G{Y!AiF4 A/Zjj(5C͛4L=#D0e>}yGҀ)KxR_==E_χe˖dܿm-ؿ B!T^^IbtttA2P9)cΝذa~z#G`Tʕ+q@Q477cÆ ضm8VeX3=]\/5_TG%MJ:G !pEjFhܕ^q50=J׀*jZ\C?ZV8 igy3^0!>n?İjA{Ftqoa \8BP6=v{M]zEɷ\)s\L-A?zzd )0s"e_@ՠsn;mޜ/w 4J֨7D0j-v3hav90'LO&B0W8qcqGQPMӲ0ccc7bT #Au c 8EߺZ!2_EQP[[17 ܿ*@geUpZ`( 5MC H:x4MwdT^/v;Z[[cwtt`ǎhnnڵkpD2,χ^رk׮EKK t]Gkk+ ǃ>3駟O<1i͛k@J OlсzuFOO>+x$y|+_A}}}lSO=_~. W^y%6m4/c=V|_ဦiַ~+Sc'pVG ꍧ 8+89eƶ'䣡P{U8KTJd*V~HX\ kvjUup0ӯ66{t]oΟ xik>Jʴ|HQ~C=/gyflo[9r_܇iɇE~شiӤ]]]O+VL>ȘC=mlYGG^|E|j_DT}n*02~yBY5)xؘI*nfܿ5 ݆rM>er1歚:?҆:A-;%Z?_ʍλ*2oرc8x 6l ң-Zݻ,c޼yx'쫔]{lx;sh =*톆p>ANNvi'Oă>ACC```> n&46VvvjB7ppOv =,!,0ePwsJ*>vmx?6lؐ{_/.R<㨯/0=7|&@̌48LEwJpM{0q#hS)\r{0t={A~NRG!U5h?+uא^& t?a9Y;9zը/P۶mO,ى]2+o~{̛7_=VZt} mpg޽{Li~_x'ֆYo;Ci?u MrªsX!dC7ΑԄaDZ}+&^ߌZPMY>T:a%aı@CLT w8Ƕ~;BӼBQ!L&-7PB _ݿ:?lP&ڵkW^KM$pƪU`ZBfaʕ8x Z[[1<n&/7pWK-Uy_Bppе9a:1p$2ىK.ׯ0㩧\r%g?Æ \D&jiiASSo>+я~T;%$CC#sOaRuiwITO$^E)%r1k|Kj>1u޽5s!'#\I 4| *ϖK@G~a,^Z Xl00Ww0jԗ/l `˖-xއ]vgy&V\^xe?pbtto1i}m躎/8r~6 @$|qCEG>|(jkkqW_Ddwa g9ݑzؙL <=84淶L<+Kց^|mAf] }Iտ]}xœty09|D$T7ж~X+Q9=ss\u] ҍ+p=:Y,\p)o߾^xaV|OMY):t]]]B`Æ GSSSx?~MMM;w.ꆆcضmdYF[[/^lXwy'<\.WB<<%z&3&[`}t\qՅ}kG{{;㎒* 0μyaq79=Ʉf CzI=&}\pN͈BMi&.Cgg'uE"?9nX9"*?1YBOC r\ $(N;4m#I<^l6&sNտ~y1&$!!f\ h{6%yV+fڰuV߿n CCC'LV*믿>wJM@LXgAK=^x)"n06E#J.7Ono)s^sƷʟ`457ߞ IDATk|[GN5dXF/:sH7,p V~e. 0`|Ñj@ y^-{w\Tnz_ۛS֨/İ.ٗ+V񠥥@ff'aytt;::>SDZ >pVx0LQbeH BVWvuBr=bRI딮DssܿՂChN_GF[&FXL\rYq TUez:Gbpt%_t]a_P@U#a! !\ƽ K=_ӴXm6۔Ky ؾJ>>SI{{{\p>G e4\s̈́πY*ߍ.O4: 3-j]|N"".`…uǎWU|@}}to"oD~ui\@r`@U.w7 \%0{˰UsjOkk+$I¾}piߏGy^<{˖-{<%SDSXV7{ ˁJk@K -N&,T{Oo6%ko 7`j|4|\k;v]m\LK.nCX}ZK\Mr {ET IC pF%j$ԨߙF rCkԗjH ˻'M}hH]ޛn).I, z-ڜzpi,˄/DTD9$ucN#ÉgV,uTb*'e4zI( Nj:B=zF+2MvNӄgUj{%qh3zM>ta~kK1ڿ=I@}e;^|D [{%V.',0KaxgvkFJ D `ۡi\уoMMMػw//_ R򥱱1v?dYbD&-I_AQwyWAXV\p3G%-덉ӅꙔ1LBG}{5\) #3l:)r* pߋp8q*XЂ^T My֮ /0iذk]{:w`%$C(iy5~1Ck|So}Lwrt2_jG~"OTS?CX(2BV%jH&3j..M\(%V6mTVVbx7q!?SFl޽{bץtׯ_Պ^{-;_zjL&<쳨ī:Wl3hVi`@dXe&ѦlNAT/cAtzat@xYSEWdY$I? ߏc4+9-=6i@ªFD%K!L c#n̅Eʽ$__{N ZZbTD+E(B[[fҽwe] ?Y!#GpV!\y~J+s?!֮]FB!,XG[o!ZZZ`~!b?;w3l\?͛zԄ~FL6slv*//}Kwn-ߏ}yȃ6sXo= @.t񽀐YTA@/ż[Nx2ݶ}_Ɨe\zP]vʌ׿KNKp뭷7 .첂ߟTfVp"} Z m8hE5I)ꚦs+CCC hlQU%# êce^t]ǹ眉W_{$[o[uJ>eP^τ0jԗ !nV?įkh͆kW]uՔg)_Gywy'x≬;=tMe_|1֭[Yq-ߎ.]'Z " @IJ905R}UZ:c0[-РC$180Mտ†w}>z9p-*&hBJ ^4%NlƉn,ʊ X,\  add#lhiiχrnz C;0 ɣo|qRIXx1/^A e}ҥ/ ׋FLq+5mW ۫( ^y52Y_eeelEQpr`UEuǻzkoFfVkK.$IOZ$lը/%wqp8V|ҥx!2^x؈7'D(B(BUUՄZ~z7dY}޾ qE!CQ(눈fhL5f̳\S*0iQs;|DZNlV,P{1uv4 qmD"UaՁ/8b2_aLJzP}RUht`ZQ?o9I7 ),$?܋6ч믨G[S7@yP"mDEEE,𯫫B^X,曩@gg'jkkKrPO?O|Sor|N7,/WL˸$PsiYy-+By/"qud\auD Io?Z(/⇼_BVǯ.joJt:L{/G1gZT3>he}<5&eX[6ϛrzfDN*Y{W,_[~IbMlU's6{g M0)bG>tфߦ֬oP{Ug\X^~y\^EQ5.PWUȒ,5Fl;BľܙLIeTUȄea ^Q }49gPYQtnǒţ:Rfֿ" dqr .V A}Cn^-'~WTͨt srX(ߣ˥múubkdYFKKKl>hqՊJ8N #@$X:FFFP]]mX[駟"oc"abI,``@BIX uG!H M -P dؚM;07\.=t]g#0) dI$I'C̢2z3UI9A6=$A_u]/<װ3*R{KY(7ߜvv4o |sj|ըmhL[*rm WAr-<'ʭF}̩; Cf1^/H~2R\toLⴷ7 $Yh-'|$ 7} "_N UUp4 bpp. mmmp^,t0TgҲ`0;1OR͓*M|H69iARTa!d ZEKHɸ@dE+SCJv"ӡ 3xKÌJؔ)|ZZ@HU K4UTδ_f$IBmm OG)22e5sio1^;רUps"BY|B˿~c(˩E/e$@=^gNKflܸot]Gcc#vލ1̝;ͱ( z{{ىJX8|08㌒*W4::Z*-ɔ#ZY !j&{E^҄#:4-Ecc̒pP@ -i~ YD0@jB׷&j! PokH[KA)̢6ӟ3vUQ79q_Fȵh[9˥4J1k|J)Lަ뿑djQ *|L"*OSf YK7g+2kːTUN=ytDjKzz()7i4 $axwqAȲFl߾ ڽ}v,]xWn:HP(;e*-0(@=ل3;1ʀi$;v;•Qh( UiG68A U:0["/ׄ A_'G%x  jP鵸f|K0j-rLu]ǹ眉W_{##;R/Bm%=>قMC՞u܁*9l6#rf| sF[Lٵw,@t+EcccZxvl۱pG)T~޽N3v[3qedYFuuմۗQrmo!67ogēu*364تעjrLƦ[چF |#.Ō M*]&χrQYYMglҖRɄ(p:@gn:Wv[l,˱Ml* V⋱,rF+\wI\xLTG/',_񟦸fv?~RDE_`A~70]ѹEjqa!i< =M):eX}(2v;t:g/є ͟7p6X""B  f}=ZϼlʭDD]'\_m.|BTzOmgtR='#eTz@ NTYχ`0n3::rg|Dn7b"""""""*,cܹ@= ԁzb.C-J|IW>YWfNAC&"""""" U֛KI)@=W iFգaztTM0f:t"""""""*#e{N4-W+tq""""""""*r 3- C428eH;}C""""""")u[ؙ;h+dY6LDDDDDDDDDDe[j%_0)e!'S$"""""""""*Q mҜ7 @Ʉ0B=Q """"""""")][j#s[,^vQ,@ه C iKv+vSJr8@ko/rKhllj-vSf,I( ,  :-@])yUVAUUR'">+W)DDDD%T~F"</^ UX$AeL&Pq*TzFjbpt:48l68b7dvHD3f "ECupz dbND4Mf& fM!"""* 3ьADƒ tf$IRBDD9e91ǿk3Ŀq*E F8.vsʂlFmm-fhDDDDDDDDD 1|!P8F__\bVc;`uZa6maC4-6`ņ!bɒ%NNX!X12U@.gz>d;$"""""ŋQ__OSU& b>{V < J3&4U+nk^n{uzTlBv"sd @:UiK7! y MӰzĿ] wP80N't,L&8]&iV"DJ ׋dEC* 7`{;Bv <] 킀.X׽/AO$CU@O@sˢ wO@ux^tݟr+3yRv$kKzJJp~i:-0W$Bd)G$@D/G&NKzCD ٣4~{@RfZH3fV!UXX 8 sduZ"j`d nT($!QQmpZgX:Np:hZz]{ mXz)bt;%{x7 tQhAo}^ ˽^N^/ <^\N'̎,s!D,P.UbY$iB}""""""""*Y ao l. 2AUuEy ̂ `!ɊaMӠZ Ԭpx`v |I˲-h\(p饗xqw3 VH?Wh0vߤVąg? s&3<~٘/R,V%VF" ъRB  ! IR#L3H 9hбd!|UXU=;m އʞegZQDDDDDDt}Q\xᅸ'ԋ>3G׾F~`Xpi .(X=jχ??O|.-#*-2P|0:쁰"Qq&VXj~ˊ}~?Nb4FM@ǏdpB0M8/~TU;gh:HN ۍ+nuZa폟?#} #gX*>[QDDDDDDϣmRD]q8ty}}GQ__}cxgz8w!)UUo߾ݻwo,~fV0NYuE)F݆ rиvUnSmi/lSby-^~'e 9q# B5r Ȱd RHXu! 9C] :R&ڵk>򑏤9.I>loeYĠB 3h%i݆tH&69w3M l2С67av!ByFDk֬ks=7i!^{5^:\.\}ո+glٲGUW]nB!w} ܌^3cuEQ2~. N [\q1$ @1>]dYpZf賂|<:>{Ϲ8صk;ۦhC̙D:oT tA'Q"Ia᫾29l+feص];#L'c "00˗f_D*jP/Jgt{x=\+p}qo%%rj-._5K fggp7F#%p2wk>&־Zlt+9\/PJ[Y C~ s&Ge\WkYV7/SMDDDDD2e QQQ_Ld8q3gڕT h4Mxx8>(pnfÙ={6ѣG<==gx{{s_OOOqΝ;M.ǿbeP'NhW,;wfҥof2:.,\I^(g`hz~i< _wZLϮ%hSxx{zSZc6:ͭ]9teޏ)qg*TϬƃdbccڵC0gWt#}v"##KLxٳ;sfff;pqj׮رcnZIOOOO,x{{۝ǧXRQ.Ktt4cĈԽI咕ELL mڴX``#(L@U-a֬Yj7,,zf̘oy""""""""R?~5k͗_~Ijjyꩧ0`m;##h0K۹s'{-y9t̟?qƕs"S^K.{~G}???, ۶m#11 nVLӧO?G-hٲ%deeAzz:w&%%.]ʠA\gΜaƍz8pd:vHf͜DDDDDDDDشiƲe>~w֭[GNHHH`0`0HKK9s0hРbر7oN=l ٸq#s n:N|4nܘESDCN_VZnj38x mڴ!::k2c , &M" {=IKKc4lؐtf3...>}Z_>۳gd֯_믿NzDDDDDDDDM6a4yy衇شi-… ٺu+oח\V+۶m㮻O?ߒϒ%K5j?0Vڵs >3͛GPPÇٳDDDj*V\ɒ%KJo߾<Eaaav!ӧݛ;vw^%ԫ6m\1ަMr SNǑ#G c߾}ݻ^zqIy֭[G۶mfȐ!ݛ>}~``\;vn`>|ɓ'w^%EDDDDDDDѣ=zN:ѠA"##ٷoN"$$vl믿VZ Grr2K,̙3YW&==h"~anʮ]ݻ7׿غu+&L7Gf4nܘH&L֭[/[n7x۷_˟ ` TTcƌ!##7x{3rjYCHTTӦM?',,BRR-[vDӦMiӦ ,6m\EJ4hkY)͛7Ί+jFHHo۷ݝZja+|!:u@ǎ1 :t@ ?>}a֭@х7x#Fcl\999}񄤪0 L:X"ߘ>}wUTg? \]]mΒJڵ)(( ##\\\4iǎ#66kײo>}ݫr}qqq)*uV["hC=d۾TN:Ul`0eKl>}87b_o͝wɛoITT_}Uv/(TWjj*%ST!66ֶh=<<ܮ{`00m4rss駟sL>X>: uwww.ߺukYnDGGc2ر#wftԉ={p,Exxxp1.z'..cǎѮ];>8Lxyya2Xt:/’%K8}4iiim777t|ի[.[lΕ(*ҤIrss.w1 Y[b$_=;w槟~b̙|rj֬mfs͍W_}'kr7'<39rcDzj*>:uDdd$|ѣ_q1m4CDDDDDDDD*.={`0~wozI~<==y;d˖-|4hЀ'PNOlflݺ3h GyxW8AaÆ<3dggQJ_tЁ/YfQV-~m<<<~VRxzz{1sj?UKv\JX/i ?u7Ujjg{Q= DDDDDDDD>xJùJ%d:UսWJ/4%ZDDDDDDDDDDJA u;(.""""""""""b%EDDDDDDDDDD전P8/DPB]DDDDDDDDN:9;$PwJrr2iiifg#F`` k)ߪ:]򦄺)[:""""""""ՇTfooo%#шw([T+"""""""RޔPw*zӟiu@""""""""eC u;(.""""""""""bM.G̛7Xԩȑ#  33sw^BCC?իjeѢEl۶x 1b2Xp!xyy1dvj;nXXl o#)O>5];8)KJ_`Ϟ=|tޝ֭[h"222x,U'OVZ0j(-[s?SO_ۮ;|ٳAQNnʮ]{_~7fر:u_|>&M„ vȥTű+"""""RU\mrZ"<*r-Z_|d槟~QFN[,ƌC&M6lnnn8qqQ^=CnogŊL2GΝYv#n̝;ݻw3o<>9y$sX,-Zķ~dƍlܸa8T֭ILLdzjL&CдiS&MD޽;;v$66ӧOc1yRS4vEDDDDD2i$&M8psscȐ!={իW_mV >>>>={gd$%%q1l:t@\\\cVv/A8pKRvm Yx1QQQDGGӲeKXլY=zˑ#Gظq#999 8R}پqvMKGYxbFɈ#Xh7ngϞuxaZYp!#G_$))!|͛Ӯ];;b4:1Y,yḻl2 Yv-mڴ̙3ԬY84յkWn6RSSٹs'=SNeߟRuٸ~;~5U4zرVEջwo~G/_ΩSh׮5rXnݺË/h{@e+""""""ejbZˤ;wb2ʤkrR(^Zj`4 tx5kdo6'22CŮq]B\\f3,gWmyzzҷo_>s0`C7 Zsݝ>}8+""""""eiС̛7϶^$..@&MONN+Vs|ӯ_?lž={hӦ =z --?$$$иqcoPPP5kHHHsΘL&j׮MfͰZlذ8իG~pss+GQe˖qu={Xv->CU"QB/ټy3$%%tRFgϞɓ'9s ll63{ly.5",,cǎuuXLbcvѢEгgO.\H۶m(U?wq^xa[E{gΜ鐶+.]|rnfaa!III4l@v:t(Vt u])K-Z_//// ҥKcqM7xb֮]KͩW/2hтGyo6mڰb RRR1b&LӓݻEll,=͚5cڴifzO?֭[ywqrѥGH XV.]+<;vo!&&;?]v4Ņ'|Sr7sQ6o_|7۷gѢE<:u5k0gΜRSmڴرclْ{w4h;v:))W`0RE...9ѣGӯ_?rrr*e])kV}aZiժ_}-ZW^̚5'Or}Ypuue<3믿Ү];͛GHH5jO>aĈdzg6oތ`gϞw &$$7|+=z஻ѣ4lCE-W,RVP?Ç{ W^ IDATر+VТE TyjԨA߾}mǎ˝w+ԩSmӧ /Yr%f~ ~K#((xȑ#mۃvFXvSc0x7x嗙5k999|L0١]5])Kg͚5V"??)Sĉ;vC~~~oj'$$`Gnn.ڵ1 oCǣ>jk377b ZX(~]ҵkW۶hdڴii;00KY~=;Ă \|fvXr%xzz{@~-SǮHe3rHڵk <꫌3[+ b%}||dŎרQvE-W,RV@\\\.J_ǧB$?cz0IJLW""""""Rڷo ...nکeEO:E馛dݺuc[&;;(rrrؼy3UV9r[7l6k? V5k Rh=k׮,_{???5kf;|˜9sڵ+ݻwM6m>,^^^dggs8þ"+)+J8\_XjuͶ[o[oնݶ>gLs77bضyر#V"--\\\JI劥:QB]DDDDDDDD* hba̘1jՊVZg9B۶mWfMqH"dWWWg#PXXH~~~~54~4vEDDDDD*^ gf۶m8pP>3|}}HDxxmrurrrʪ0m瓔DPPCb4~KGcWDDDDDD*3g"R)($''drv8Qarww'((P,4~KOcWDDDDDDDzPB, !!!8;qꐐ)oz守P"""""""""""vPB]DDDDDDDDDDJDDDDDDDDDjM'""fA u;(.""""""""""b%EDDDDDDDDDD전P"""""""""""vPB]DDDDDDDDDDFg """"""""R5()+J8IMHŠH%1qDL&oߞ;tpwwa^$333f/_uV%K}vBBBx/E"""""""""DLL gϞZs疺ݷ~l6k׮nܹ۷ӪU+?8 lْoO?\>3>#8p&Msϱk.ZlɦM5kG(YKƷoߞ~MZUYYY]8 -Zo߾xxx />KZȮ]Xr%t֍1 ٓիWc6i֬!!!p j ٳg~)=p.O-]wEnn.ǎ_eÆ  wN>}.rq6hvޙ3g(vm͚59}eBj+̍7HAA_5 70z!"""H1Fڵ=zppa1bܼ<(((y涗  p>ψ%77J Kbb"mڴ)G۶m/jrq^P!''صDZ&ԏ?NBB{/`ƍ۷ ==B]o44hm۶Hpp0=zӳIDDDDDDDD~Zjc^}Uq<<|8=ʐ!C0xxxp OԩlذxZjEvv67n$77-[λ\ m۶,YSNvZΫ}T"S-g2qD.]ʌ3{};7$$)S_s!~ibccٽ{7&L]v矌=۷ӽ{r/R \؛m$W+ 6ZQFOӯ_?>>B&Mc՘L&FEyVpL;.%t3 l-]/\n@Ϯ5DbbbˋwyD&O̘1cԩ{aƌ >okײxbm_uIII;dСSdffK׮]TB#F`ܸqvh 2իWDDlz5ӍY7?3QWM(&'G""eaDFFݲ~kjoԨQWu~xMٳXe%|ay[{9s؄qѿn喫BYYYxyyK+` Px~߶ֿ,`h]ܾR-gN_>,_Ֆ >o{iHef86|l92 ൣnl`RXfRej\_+4\(|U}Z,ƏO˖-_ȑ#%Ԟ8/sUj6l`İuV;jԨAHHHsyZt҅Xbcc),,e˖BBB3f ))Iw&""rV+QQQԩS;w^ǏCdo%Kxwشi?)Ȱrąs|0=@Z+g?PDD4 >-Z ..ڵk`%åJ3իSO=ҥKy cܸq>8pom f̟?qa0֭-Z()_~뮻rJn+#F`ĉ̝;GҵkWbbb8|0-Gۿ?f"33@z)4i+)4|bccX,DFF2rH|}}ؽ{7-"##BwΰaJa̙xyy1k,`%۩SHHHW_Օ@ƍҥKY>V29ÝG`sW^ׅ%g.DDw١jP[[IOOh4+Ҹqc-[f۾p:t@8{,5jԸ(!/""Rѭ[>}ЦM̙Njs={6FaÆ;v!Cp7k'&&7x5jc^z%ϟ'ơ7 + ٳ([]m $55___|}}qww3Jtt47od24х19s??b]J5j //ؾ"" ^f9}VyZ1*M ujd2h+V`(KROKK+BPPddd`2lIRSSU|o&aaa;X[PfM233)((r(1zq qu=ƾ$?J6?F\K r}j֭4iҤX2W^]xkג 22ZjѺuk>3, VKҠAHKKF^Pp:4h(,,dʕ%LDD˖-bƚ5k޽eHeLk!/[,(~,Bk!ꅤ"""""""Ժu4hE;t~KnȐ!l޼Cr-JyIKK#00)Sƌ??G}HӦM4im۶1b<==i۶-zl'N?dx{{ӷo_~7n>?0>}гgϫyT"" 0.4OO{^7Ad 3Gj""""߭Jjǥ.o+~~ hCBD$66]:;Jg \؛md7x>. xW=t#}v"## nYly@"~@` ϯν_%ls_/hH%dLԯmGD^lIaHŧ"""""""""""vPB]DDDDDDDDDD*"""RM;;)-\*=='%jLZZfHڵqqqԻ{+&ߪ:]򦄺)[:""""""""Շ^Jfooo%#шw([T+"""""""RޔAs*zJgʕ+_ˋvq=PF GUn8L&S}O<^^###öѣY|ySjh"mFHHO<+>EʛիIHH੧ӓ~ 6лwo7olfل3`k#%% &?lI``m;55ɓ'yk;ʤ}Q`qhfڵߟ p6n믹m{?̗_~IݺuاǮ\~ӧGe۶mtعs'/r|Rxx8[[.'O.s?SO_W}ѣٳx@BBӧyǘ>l۾ KX4L̘1ѣG_+""""""eiǎvmرi֬Y|f}&-\{ b;̟?ٳgw^~9s&_}f~YbSL!""~ѹsg֮]{)R)h#G qqqw-nn˞ڵk:t8î]/iР`ҥԮ]B/^LTTѴl١VX~!~ðە[hڴ5//""""""RNW۷o͍5kf{sHH={d…mۖRsw8U4w̙iBE~gJ}([ʠM6;v-[2dcذatܙ=z~g6mbӦMLΫ̚7oܹs9r$#GdԪU#Fu4vEDDDDDr-aÆKaӝ޼( -[ХKN8K/D5ڵ+:t >>VZqRRR7߼ŤoߞEp)֬YC߾}DʘfAƍ%###/hذaO{(>-((xȑ#mۃvFXv+˚Ξ^l_\]]qgb4? IDATY8z(v !!͛7ΨQ@Z?N0cgQlvnęA۷IxxC-((`۶mܹǏPNnFnR%K#55,Ef3YYY%%NKK# ˧*pqqy0 (<^Xo[_\]fK-~}WE3˫N3+])Fnݺѭ[7grI`vw0iO/%El˖-^F{"ˋ'|aTjޅ WW+JϞ=!"dРACR u8f;;&e>(,,$??wwwgR4~4vEDDDDDDDʛf;@PPIII_fdONNYYY| rHLoh슈TJ;@hh(a2NT "44⠨*&PwBHH!!!E:$$5~0vEDؓ1Vm7qDUü?.~)z(iɿ "&N1cUw^ݟao񺝮c+o]B]$IRoqF˔'i; 8 8"h!atAb ۳_g-PTZ7 |b2$Q$I:ձR>Vhpg;3hGrDΣ^# 棃ĘN$uU$I$I$,%I$I$Ij uI$I$IB]$I$IvP$I$I$,%I$I$Ij uI$I$IB;$I$I$i?RqSO=ŬY9Ô)S$_f̘ ׾ĉu%I$I$IO0{lJJJ4i]㡇P(|ѣGwJ$I$I\,ԧOXp!555|`ӦMy睜x̟?ZLBcc#/2˗/gȐ!qi&qN?t,Xڵk6mƍ`Æ <30~x?x$O<V"JK/Q[[K2d̙pSYY;g5j?8v y }Y(Σ2,I$I$II,e˖-<̞=0 K( xlٲq2{lo?o<k׮Go}k 0c?+zraa0{:'Nd<|{c*xΝK:7'"JJJXl˖-_jܗT$I$Iz 8c?@ss3]vGnG}۷'?I.]7 ϟQGEcc#W]us>lü˔r+0|>O|u/~GyiӦiҥL<|#s=s=msg]y$I$I$WPߋ-++[o˗S__VmS=zKK G}4'N[ndĉ\tE{|:?x ƠAk+hۯ7x`yK$I$I-w*f◿%\\uU{A׾5~rE1o<_(v{~EE7o ϳm۶]@ؒ$I$Ieoo9sf7w\/PWWlj'ȑ#ٲe a d2<#Y|ֶ$I$Ix9K;z

5Ȟ~3R>oLqK 7om>DQD}}=UUUꬍ1$6s?w$i;5H䠿;RZfRG{8֤Թ2'9 @~{N|}m; Po 0`A=vo!I$I$IݏC%I$I$Ij uI$I$IB]$I$IvP$I$I$,%I$I$Ij uI$I$IB]$I$IvP$I$I$,%I$I$Ij uI$I$IB]$I$IvH@$I5amύMP9hl>@E@YxØjx@xOuab=5I$I$I}Ć& ] ^sBsZ--߯,éppJ-Ԕ\nI$I.,;@E]-[⎣NfذaAwIJ.]-g`М/^U= ӎgJ$Ia,;uhnnfԨQHׯgСX\uֱn:!z7;u,vqǑ$v_ 9DE7/G_6o.I$P7of̘1 4TKz0 Bq|>O*bҥ{mx#(^Xؼ V+z8Im pS˦fynV]0w2I$I;娨LERN᳓,wD|&QZ_}Di%ܾ(~|8ɴmqEl]e&.h4]XqU$2O>-s`gOK<w*I$Iڝ pqtW+XA֮͠Y @Wx˖>2BV-ibռ&ȥX=%H, ĝPRow :>4'ܿ& []$I uIx"6P_Z–~%QQQVɚ[\ҘM|-пÆ,Ekcy-9jLF=tn:q'\s';{x܉$I$B] "Gw2MM44lg yyNqҰ.N6WE@Iy2ĝ/ ٸ l^#C9UR5B.aClv4l )v 7[w5{5r |p|0:D$I2 .E~;3gdС\s5qq0*varW3y#,[)PS=xD@Ő$el\au].REl\YZJ(-ن؃ƭZo? aisBxx1iA:w"I$I}N.]? ϮNcԨQrn puロwvwrPYYwIH{ ;/$=ŋR(۶{Q(ȷF ٟUꕅny7RUQ2ݣ7oԇ0In:0͓~(r!|ix`!0ah܉$I$5;پ};/f񔗗+0g3t-r=p]w1dƎ˼yxᇹ; U(hmmo{ ' C*++ m߽()QqeXT*i;WDHJua TJڿ|Yg%v5=L<r O$I.b~:w7 ,8B}0dȐmSNeه?H$?Kuϒ9a loFe;w[ȷF(75*;>`vCZ럄G=W°$IXA6e֭,^C>M8p.۪ٸq!8;=Xhw;s9sX*_җX}ҥް/Jo iT` ^^'TWYɴnx˃Lz[f(Frl${zi-\vwU0m<<<4$Iz; =O8c9搏YYYIcc.ׯ3cÆȔf(++ek& aaFvP4 6ү&Ӆ;Ǒu۾#Xz5l-Zȑ#ؽya|GG?cVK.aQhll "Ϣk#6$XWoAux߾02W2↏vyH꾾|i҃5# 3N#I$P߃#G2~x^z%z!NV0env֯_σ>M7AE+V,‹. (.<%%" ![#S[>OYv?C&oYq"OCC+H$I,".Rn& /ysu?\.Fiu/}֬y~dhl.sۢ; lcDi-u]3uL.zHH3|Dz#Om۬bo$I:N&M/˶ߏ?]~?T555r-444P^^N"cX⥋5z4m;OК )4PΚEP>b8G g҄) L'_(P() T+S D,;ۣ-%I$u$ TVVAڧB@];Z[/cQR bRѿ60$S= }xn˖/ɤIS8rTm 4E{_e.N,]G =;$$Iz uIYjR$-\}-JJk)B$ I2?J=pأ9j455lRGhlncԨ ZMSS#-Md[qG <~S7΄kN"I$7PKrѤyQA ʫlOSʪWzEr??dy$nj;#G2l .Kf{$}#N"I$P6E]]d%-N5,[ץ;;r*+1id&M̖-Yt1<05#SZһ[YZ~˵಻Hgߒ$It,;@&B@2 l[y՟>^T=LvӦȚodbϟGM F9*xbҒ Mq'jKY@&I$ Ywꨭ$8=RSS Xl:jjj:$So<Wr;AAp؈6b$S \U%(+]SHjYw ]zEJ%I$< 0|p֮]… imm;NjժnsL&CMM Ç' Jջe>wn/L2zԑudQ$`jgRL~|pL?,$$Iz" !CeСqGQL$<|~(Dq' Q=ysP K$I:@H$Vxo;ͧN!I$'P$I 6OfǝB{Ypc)$I$4CWIN';ˇb늸 ;hDsBh8 l!ˢJEٰ9C,͓xB^ĐR$B]$=&ܿ0ڟ{50uDIz#^oiU?8?oeY+6+`Kam1 cLw\~w|DWuuBI7 uIw;IpL|tFF,KWv츿7!ߥ$IR7$IW+Nzby=$IP$I@?v!gǝ@$IROa.IAV/;#K`ӌH$Ij uI 'Oq!<7$Iz uI`)۳r=$I}P$I/5NjqY)$I$uw$INZwI$I]*$I|43V{ ]GګwVU\cݪwXqle$IR7`.It^y toe=;I3߮Ɨ)[QO"8v l aAc #i57tz%(xB9 $I}$I!rtzR pl%36F$1vrDΣ^# 棃ĘN$uΡ.It\̲ӾH$I uICF›qPGyM$I>B]$, qPGٖN!I$P$I:sŝ@m$IP$I:,=$I$IAzSI$I{c.ItVo;:H$I,%I[q'PGwI$IݕzfqG$Ihk!$ITrJ{1VZEMM }{>}zފ+̔)Shh(m^S$u\ њ|O%I$E>w\3o<̺uя~wi9b>1vX^O$u| ѲH$I|>7̰awKYYQ1c z!N=T***x9ScʕL2q/2dgqeeeas=NJ+8p gqm۶Q__ܹsٸq#ApwrW/rJJ xq1q8/$IڋV^/I$I$Ezj6n\VA_NE̟?-[ӟgy9sosR(پ};{/7xc_C466s͚5דrlذ(rw},[ sHɷI!;:Zir"I$=_֭[СCw^SSC*bs1='<7.ѣGS]]mƣ>۩cܹ|cL&Z\r /"DkiӦd3gcƌaΜ9 0;$I:Pe)G6%~I"I$i/d>`o߾f|@[N7nK.FnV/_N}}=lk IDAT7xm#Grt}*++cʔ)K\q̝;3<$uceiƝB<wI$IUlj?p4wsmƍoذrf͚/Kjkkꪫ୷P(h"nڮlz*VgN;NR$u!q'PGVwI$IU,+**xOs={?c9I&3ϰh"z)8ؼy3(3g?a2 ?0o7Vﬤ׳p¶m'Nw9#8.$INV{*I$i//Ї())ᡇ3%%%r)|eiӦӟM61~x.r0'niӦQWW@uu5_o~׾5RW^y%GunSwy[7|3$IN>dx ..$wuڪH$Il]t]t۷o voر|w+?* s\c'OWTTTJ/1c뮻:u*SN%RRRҶ=LH$8S;%IR[wu1q'$I]B}g>;P,w^tO72뮻7reQS%I30hc-%I$텅^.{0 ?Hmm-cƌו$IoⰸM=$I{1p@..}͊ >.}MIth 4ƝDSH$IڻD$IzD;:ʉH$IR$I!:=q'PG9Y$I$탅$I!:l QγP$I$I!pXSPVq$IԝYK$uG|;:]$I~XK$u;Gǝ@$IRwg.I. #:K$IڿT$uQvZlB.;!NS]]Ͱa 8RJ5;OǝDӓ!6%I$퇅Zn͌5t:wne :+˱n:֭[;$$@!;D*Q|$I$i,%͛3f  "?;+ Vwı|xۂQTh4Çglڴz+θN< .w q$IԓXK֭[پ};&L LEd &P__֭[8$iO,H:SJ#I$I:R7!+VNh|Ap 'b 0' C?ln~p յiiiH6m۾m6q ¡$tnK'5q$IXKЦM=z4d򀞗J=z46mdkƍ\s5̙3^xan&^x:M?ym۶;W^/ wqGzk5jK,aɒ%qǐNrw 3N!I$'꓋swi7̘1?;x`ϟ;!Yڰa7ñe]ֶ=r=p]w1dƎ˼yxᇹW_|>F*osտ |[S0˖-`ر1'e)R8(Bi IIT$IR7' _K :aÆGͺu5jA=7JQ__߱:1͛wپzjjjj2dH۶S2{}>---SRRB6% C>N?tg%I:y$|N";$IOot:(EQDYY^"ݗD"Akkk':6mڭܮfƍ|=jjjشid*VXŋ9374Gyc=?=\=vkɒ%m#ׯ_v|1c0f̘C*} R>$}3N!I$'su zn>oBUee%lkll_~|=s=pwsgsrp}1rH;;\$ 4] Nw >T/$IM>uT^|E TߔH$Xjƍ;655Q^޳#Fzj,%%%,Z#GxGM[zN?t?}l6˭zpyqyq8_s=2-[h-ĝo$q'$IB _?ϙ3g[jnnG9B}˖-=~.0env֯_σ>M7ݴkСaȯ~+.RRQH$H& 6]:)ï.y $}ˌ}*I$I' d2ɗ% gQ/LP8Eyי4iR'_=]wr| _`}fΜI&aڴiA#X|9͌13NC8_}j",7Ό;Iϧ_O;$IޢOBQ2 OnלQ3b*** eǩge[MM r ؾkBٳۮW^ɭJ"SԡT'Pz=Zq'ݾ|2N!I$7鳅ԝAȑ#Ylfbi(㾹\^xT*ȑ#{;<%L|emG}47xAOƿ 'ω;$I9OnQFQVVO<6IEA@E477l2x 5jTBG?w2]$IRgqԍUTTpӿ6nfmsҿ:( `.I=Џ΅ 3CҁNowI$I͕RRRB~fy0$HJ())WM"I}w΄CSCs>4=SynwI$IA@yy9qG$uØj.X-4=q'$I9d2R(⎢( dY2LQ$)#Nsr8YtI$I]:jkk]hhh6fQSS!$u̧VܣLy:|H9DD$IRP_Çgڵ,\ָt;V6d20|p0TZ*_? .< >q_we0pܐH$Ik,%W :CEd.>G; x.I$)UD$$|p\iqk3,%I$ǿH$Gg?'EKO >]<1q$IYK$ Ÿ? w}8%Lo5i{e\$I7P$IaSogC!Nvh\r4|$8Ө#/mDsBh8 l!eh8^XӉIzeQ%l؜![DPIh~ss ".B=VR~>c[︶Nꄒ$)n$I{σk<65ǝljqc#]h/8>:|oRkZ,~}VkvZG44$I&,%IztS" o!<,qjp`x"ѐD$IXK${_.<<{N9)ޠ8Z*殅v|ce)4NSjáPΦSFTZ1zڽuGxMe+|N!I1 uI.RO=wull?n pɎ¦&Xk`6o![=9?GIM%I(MAEJaDQ #owz;n=A|_{a# }OO2ls_~^6ʗ) #d$Zћwjg; T3jl;zt:z uI>*X|*cMŻeuA8]ɀ$w^k>a҂\$훅$i3Έ;#o7mM7o[c]V[1k05zg/FR\zU2yjii穧mjgZ'__wV=wI=L(ԟ~#HR7y#H=˥o}.Ѳ̠# "t 1cUw^ݟao񺝮UI. uI$IjB3휿iϟղVg?$]$I:ձX>vv=~Vkv$I$I$I$I$I$I$$I$I$I`.I$I$IR;XK$I$I$I$I$$I$I$I`.I$I$IR;Еnʝw+ >FeeeaR]]c-\_ל}\tE[$I$I>Sr9e˖Q[[K/"3f >ϳvZ~ٳgsQGuAzI$I$IRLh"-[ԩS~}.\yٲe |n+^x:Jjjjظq#sr0 yXx1C /_~q$I$I$9Okw}lܸ|+r- 6W_}f(b̙455}vn6fΜ ̙3o֭[w9vE?#w={67tW_}5۶mT%I$I$I굵?P~%puױ`zFA:w}$ yf͚E>,sSwu?OFK$I$Iz>3 W\_/̳>#<œ9s2dn4ɓ'/œ9s4iC aŊm-Yw}DQ˻$I$I$IO>$?Ї83x{KKK =-c|9spw9眳>oϕ~UWqim윓$I$I$u>3y饗s~OJ;v,崶rw83I~i<ݎ}'NyYv-O=^{-gs$I$I$u>Ss1|ߠw}TWW~aÆ|R~ӟtR8NO>v?o}[lݺ~tI\|]z$I$Ig|89ihhvsᬳ΢rI{mx̚5::͛7S^^Niiig$I$I$ Bm'HHϽ D@2$PVZBk&(-)%LL$I&$Yr@HO}D"YdT*CABT* }LA*I477.-!Ji6CRCRLxUkK TB@.#$-,k\Cߏu6ڵQ32 LZ[(--%JH$hii&ɐCmFYI aQ__ϠAhji&JR"Z) \moIsYK$PQC B+ CDX<ؖv" Z A[I%$ˆ Qk % ["(Ql#v;t$IdDy(BHa  / ;JOXdbdD24!rQ"u[D~?T "(Bx`츦a2ID0|X%!R( JICaY AP Aj1w*Ak3BMM?\+  XFBBk%3DDJr$Tl+ %4$ӄ/QDR *̤))+Y9-0$F4PNIIF *+̔rAYJ ++hظF#jɵ! [Y6o>\EII%[HdJHA˙B lk t2 /fi"J2iQd\k.B0A!,~TȷLKB>OAyiQt\>O"Hr90X|/$d+I: IDATsh V)bS1+8!9Cg@vue"AŜ!%o-Պo-f3@0yQ1!9f0$5;+X5 OW1c#[BbQv3ykb,xڪzMSsrz1qh-hL#1b^ڭub9Kkgwh'J{*hàF.u,TγT8g9:=ad5qa.lS9KNՂe_w=[!HJB3kw @Jg,U0dӤy*bJ` u0rd;FT8κK*@X,H&Mt$0$4MEJ{q,F~ΖxUUĨF1s:211$֓׍1# aVQH^wg Vs_,ya@ֵ'HI ]Q5ci3J^th2Fk!ԕD.9Q~s稪PUza"{|A/ނ`c*l>c\BKoY.8y~4u||1/]/5O4iҤI4&M4iҤIߴ*\%bEbF]h[So1YA:Ɠ`c&[4b1Eh$+ĨrdxVhx,bqz Z"Q oݒ3Vw{E!s.Py5qA=^u:*] Z'̽4uM^[$眃rlEXbLtw<|Id+v)eѝekDLc#NOb%M:c*AwXk8e)dZhk{Q`ZKe ڦ\s1oP59:͛7g99=m}QfmK۶0#Ŋmc{wlr$68=>! p%)g! ͘4_@*~m4iҤI&='I&M4iҤoR=/W/ U0҈{)l7R&a%g2f,L89k(=#%QmoլGR D[8爮 57z.(g16A=:(hFȂY1ޖJc QrVc#MȫJצ ~*:LJHUo-#\pa/rӅł8[A(; 5xkp10>&]rIm*K8">떝K;fs mتjnK`>P,w )&Պ5l-PG1J=˱gn矿ȭϝq.Oq:b$tNc,)z3XMo1I*eϐA3)&|k0(^$Ӂ ?9 1*%E5}(%85@6]@N [,HcuV1@YCS%DN؞sTu͡w9cR|u^%Jc`ƘҴ-:Ե2гyRE9,2 =[sՊq͛4m|Μnk*=}łeױ\-3g8>9!^!ۻ; ;fM 9|FQ?l1G8CumK @]gE}ҤI&M&C}ҤI&M4TbТ\bۦ&&EĨ NnqTք ^FQ#C> )q YцВd/^)} `IXխp2WTq9nYkWy /89`ͬuNOO|Лb+=Ɯ`[a(RASR` àhc5fl T8 %g50;.-кxIՒy)TX)jdܧAZkbi}m xɤ5Q⏲h;:RNdQڕpxx3IWUA= KU8rx&g3MW;BetXr||eX7nEtr|rSBѶ-gϞ:jgő-grc,K8rz|^.xՊM|ҤI&MMP4iҤI&M&N3`͍Q[jy Wጛӂb4(%*CzG*ki %x51q}`*bL4ʹ 䜉)S;LYv=xǜX:d/synył#.}yc:P A_9@80HQwKXTW8pcadl)@g3cJFD c Ιs&F5ޕ5n1U\4^*"8C(C} m/:Oɣ2ud i=04՞%3m \I6 r|X1qǬM:0c$T-;5F434M..q xd|EJ3Ut8Dss6s\x7b!p f;qyN Vł.\:$1U8=Q萔2;{b#{{acZ 9fM|ҤI&MMP4iҤI&MfUL 7B1 \#6 ƣ<}h)⥕n0SO@1׸+F_I_Һ $Mo)eks-UJ)Eƨ (XskJ:hhB9G50>`Lp_4_: )`D|@+0j33~RXozzi(A-1GLF)c1nϨCK;kJ[ 28gAŲj~`5 L:1TUK]{aZL[aLZvObyx[hO4vC~p0 $YsE n罢[ wTu@R7s AĐs"eـuBpg-I9B 5jXx1`VzrK<ėh'cQOTJlxzYsup.A{0Iʄ2q_SlŲߘޕ5: E0 !#&}M[f|vwvq}ױ=b{ڦ舝u]Yb1Tsf6Ĕr"GGGHfMېSd6q5ڶe\r\vvvY.W|>U gzQ D LSgL'M4iҤIz=+ n^5/| ׿k:lk_ZB_Ӻ|A~۾۾uN4iҤI1M I lHt4 C@ ҫqT`ϋ)MZJBLZHRY5Ǩ35q‌Y8j;NiL(cm~ R5ERpW9%膵ۭƒ5i T5Fr10Dr|YM.I\1 iG< ONc!*Ok0,qM<I ~Le`8`چ,@Pqbf!x@:5Hݡrigo-ԓSfȑkWBKDSU=1'viB3y]dqd\#7oQ9==m[ڶeRJ*(Z'ƸIb7|p69"d BĔ Gt Ťuj@[E#}OBQ*Nazo%E.,)M1s"1vSf1fpBJk|`mѾ.Du8 }OUzD MqIt ޖ伢2=({޼3ǟz,™=f._Dʙ1=!Tdtc:\?Y.8s^}89wèEMp||L:Vmrt0@;|EԤyG8{ *̱ӯzҤI&MJJC}>><1.5u~r-IlyO]q;o[[,KcF*9Hcrq$(cInc|ZG*rdI~=_B伱ټdx1c^W䬅90%aH1V5]X0KpSJxIQ$ǵ4Jk\o5`K*&JHdIXP+=ÃΝ;K#3rE0qHJKWEV}qi2 M<9gڶ1\Hv0H#YKʉ /kSOsiD]rrr|Xgo8:9$gaoPUc=0iҤI&M,5ovn~~|-̧>)z!Ξ=w~wō7G?ʫ^*>>|c:^W7c;wix:O|CX,|3_".\஻m4v]stt8|5y z+1F;e\vO|t]K_RF4iҤI&}#SBc%MaǬf/1բN 2jRduUZ<*k Ō_bIC&Z,bӮ?LN#Xb‡5? 0"70ީQo`t-Æ_ǂsض&K" Rւ)a_`j3n G8湵1QM%\@;d \aG$%Ģ$H8cz`Zd?u Sw9|г]7f\_ X=) Kcؙٟ%rAJs *vԵ"3K}"8樐,YP㬥rm8/ȕlry#;9X.d1Copb ;45]'1g-yE2R'Zڶ)`$3KC_A1TU Ru)l~}BO1*Ʀ]}GѤ})Eؔ:Ǿ$lϹ`0T."]^8sf-$fGP+0{AP$bdv"H) SyںXCJNO<$"<7I1tE]TU|CG|t}8 4mK#unpC 'Ǻ#vwv988DaSC?OT5[9Nj{ao=iҤI&Mgc=?+^wpwr=}w]~{3{x;#<w7__/9ԧ>?Zf9/3'?Iw""֏gn>[I)~r oo7~7yu&M4iҤIDeK̒$SdF|`F͂sX5)C1m=2 b'#}Xk8ǐr)gRNb@\)Bbӝ(Ʊ g g59ǂX# )pcc"KSp/A95%c%Iƈ['G)/uS܉ESrڍ\p9'Paa>qPٛ IDATf̺d5` xe #^RJu\{쵮u]) ><9À5L&DལrN8I)\H)2ϙϷ{{{gQP10PO=rEt[X-/'Zv]7ps.m; i8=:蘪cymL4iҤI&P>>.^aw}|so~3}ky'y[ʇ?a^W𒗼{ǹyG s~__xW^-oy ͭetX,xGg>K^XV vgΜG> O/ՓO>bMozwML4iҤIbE)P5jloLk4Mp?GyCy\//V_,_"GGG}շ|˷pw;Ǚ4iҤI&}%()0^$ő!VtV 9 xkL?*f%'Dˣ~;28h*|AjMԃ8My[B1*Y%flp)k܊d: oR֪u)yki䂳 Zk)xQ0KƎ#XAA"bV z-!)bǑG醁LLs)c'C9q8Tl 6eiP}YuPYGSUT.[)"'Gj g3vblNh-W.מH2緷O/;^ƍէ89X.O99>E8*WXǔ嵐KA-|ngs;GNQSLr`C(ؔDNjq_ղ{ڶe6$S_Lؑ}ٌdT8(:eCP-yvvv93"4[s5"y> ,Kq9Z熘Vv3˲E~GQxVgG:i0Ʋ\.NTqI1R׵^71ư53YIȧ F H87y+_7hgsnܼ) 845uS.:]pzrJhۖ{nL4iҤI&6wvvx"/^{{->3y&.]"1[[[k/~:r ]qzt ??˗׮]csz^wׯs>O׿ȏw|Uz֏\.qƗ}o;>(?Їx{ҤI&M,g)@Mc6bul99ER)%FM4ތ B$ޑڵfWSD-Űh"O(,\70AYUSb2BӔoZ)cRpdX&7 H"[t(cYCD*)|1#YnJ^5:~\b0N0VIdAz^1qI *eUzD@Hcg:Ȑ!HsZK<KUk8I#vNGLU\̙kDBͶuy|SD :GpV1:Պ>GF np.Ӎ#8rfhkrMK2'/ķ~f+VKn\FΉV g|=(2W^S*V[pBEJH)%㝣iX zvqX,Fh1i3}13_viҤI&MfԳPҗrpp>1\rn?s0lK^s|Cbgg{g4!^UWF~aO7ͺeߠ7 |y:O}^3u|#*>On~}0zի{rIL4iҤIfSIO#LJIȋ՚brA 璂򧵅CVzA@_RZh>f&o KE2`1sg8-%iiȢ&OT{Ƭq+k= qIA[iwHRc^t2decc2pٰ%K13y٩"I }o1)CR,&I? CAi8ɢ*LcDJR\bF)1!ˎ{b<;•vP5}|<}79Ez9;hȪxLnrb;HBP;G{`P p䘣crL킣!yq*bJ{;g\;0#O<Ε y髾'?p[~Ƒ4($5cT!l8uUӼn (ߔ{!E;+ ]w MKLZ 5KbLp>ptpei_)2rReM1)19֖cNZ`9G4xqJ< jkuCנ3ZsƗJ)caGc":MU#6#V59¶\zgϖTy95cc_89mͱΒ*H҄zΙNS׍왳&Eַgg7 U _—… O${ǯʯp]wq-l~9moZ]wK_R|z>x׼5_%x;╯|WMoz'>~~{e~o&韞I&M4X8Ζ\_4A uu.|ySD)ZH&$ tN$)`A_Q9Wb5>$s1"&LKJ4Z^ZUQLoK< ĶY@a!9BL .c@|Fѡ@NcA퀍z $&eS9C\QӃqs+&&j$SݨIR)18breeH?yrBGnF5l g,1E>P X-du`ibݻbB1}cŪq (c: *P񊗽pe38ᩧr.腜#q.V5O?]ӗPn޼Y|ٞ)D,LNm/~ϿU"_լk㦤VuV+&ˤIAurrϫ_oR&nIcɾHF9%-4p/ &4 Z9&M_T^c*?)OٖD# &]l1340Li DP$!D*++32qy^}΍D $ *¢9qv_L.ķ[8Ɓat/  WO,)i5azM[tƧ/z|aUsg>ǥHj[$uUp2~4UŃS9:t;qޢu,&SN.rS ^v۱z6k]˗/X̦xɼz~by}ڐ +NݕϊUeCX}Z9WLl%{v%naa-Qgum\9L Z^Vj\l'bvou=PוmWłIaד_03Rs]ݗfw.n|o)߳:zt:,e3s, gxqNtm"HJ E BӐb#>:I}~0m{,HV|>?gY뚺q|@J?ٜ/_f63c~~/c׮3lԨo~?5j_K+g쇏7獿L??I? f7}||إGٯB_ɄdF5jԨ:YY1n ll;\sޗ(R` FGLro]ƆQDܓYvζTr@1'PJH1S,"uc)pHo)"{TV=4P+$A& :3%FcgW8]TRX^,audzsse&#u熋2'XL[JR%;Eۭ;s_Mq8re&'K̙\C?}UeŞ9)1ZZU Ba57-"ԑRT_0,nJjKsW4l2eLQɨ9s{ v|t?8W3 IA`PJ(e޿GNtjb' IMւaΗc)CRDz]˭S//@L98:BQ~쌶n͆kF5jԨQF|j4G5jԨQl'ԝ]`Ԋ; ^[}V9YL =gjHD]RJYvǙ!Xg{7]d@]I\aGW=xChݠ%_04_MymoI8bTRXIµl+Ku u45*2 yRq@W=U8>C >2ve)`eyә?|wjbAB +! W \YRHY-U T%eb2R^m{N"3N$3gr2}Jc~~7Ԋ%})?5BYJ\3g>R6t{c2~j*<3o-@bSFDh1-_UafW Ĕ#%z}UJPYDQq sQ x3S63[RM2aأ1@oRn}.ر BekaRC%$L=e*Atn!%Z,<}7!bm,ha+ɭN,Ue8>>&xGt)בPU8!kYzc*(cC0Wu) Y7T @(JLZPbUNO7 US7>f2LsEH`=rmoos.Ϟa1_0/X-۞珸w(,TM vZmɚd^XݣF5jԨ/FC}ԨQF5*puRXjpQr}Z"ðEP 23 Ł.ftI^ ]!&Y`Xs!ض(\YK7ͩgIju0qwuQꍓ>VlU>fAcKDOzƛN ;\5aW&Kk&$ IDATjlhjfSjXu$>;?ǧbΤՁÙ1/T"i' hc;OS9shvkz`62Dw<{+xp6/>'prT8)7H17xRCCĘ)uMٰ*g2# w E1\%wƹ]Clj0LX,tMS>8B((7Z\Vj8'IJB-L& ý|{v Noߢ1uU g^]v[8Tuj-d'%'}:쐷o/xu}I]U><)1}&3ymGuzʫgO|ՔtwB۶ x #z7)k԰.f ׷UCKɨ]u]"`WbRѤ\0w1aq M*Efv;rN{KքU!5m`BzJj(xrRUCFCE?؀F#^0uBt:.벺%Dow|:(+rV4FnmeIT3!T4M- ͆3oq}.//XR7 CT^_9e~ 9'%łz+y5jԨQ QF5jԨ/䰤bQ3뉙孥RA8D,+$IҥTJ"^ f.\,~KMb)IkGŮjiM}B.!,0KtHq^VԖofJBQ_#)ߠl 6o1i4QScٱчlAU09J4z:4vh" pP9Ueƽ9.v<>Ny=c&\.Zwt݆v/ذh&Jɨ+8m[bpzzBJvT[LiUMJ vk )%+Ŏy|}b@Uy1%c~]&͔3m۲\.B Ef,躞v|~@z[G|~}Ūma^7<a L@ dFxJgb$ؽf+2)'p}YpȮ7 sVͩ'%-SFmEJ]W4zU`^와 d`nJJsac͛Ef'Mз.ub,wGGҒ|P=W4Ml6?,nLy$}znaT*M]}f%w~##sk~R?pXf}Dn[bV;jԨQFU4F5jԨQ_R+K:UJp>nCFYZzp!q].vلޒlm,gx I"@}QrLG:`uע:X|Mn.7DXjS]reH =p;;gǻ !aȆIْ ÛSs>8$[_ˊzzgK'3+.2J3f5)!5WY>eHWH;@Cu&\O'trk`vŋ p3rN 59f!'TuESW|CN)V d>krɄZ<] )vW\knMw|*ɑiJ(gGG,Wk{ĻbqxHV&Kmj@39d*1EBdIh@*t@RUCdTl8rBw2lݽgFn"9/tNP;Zy3̭^;S^U1C&SoXvt-ChAs"iovw v۽{.=>fۯ`wL )=BgZM_g-= O&6mK3pzvKP}6}?cŞuU9BٔQF5gH>jԨQF%.)Ydbl'3} ࠩ^&xNޛC)upӐ%+pj&:Evc P=⃥-soāĮ4[q+O,Fۗx9~zArBKC%9 ЕQ;WA3=aA#.&Rp@;#6={i@Tmo}v?G']@zdd&w=xNNxyyb:#odi?BUǧܚ͘T5]Ll@fU!8 ̜:4G28_)YmV\ãSN ^/Y_.{rĝ۷댜C^<}J۶lV+&̈́+߿ϼy*ܽǽas p.3#l$W1e3b2c>d-+E8P1~< =9L ל4UؗjN3Nf;22 F egr;gRbYqE38%DZ2OZ~,q? `i 1r&4D v_+ɄOK%n'u0a+gy}!mےsb:@>4͏y=jԨQFh5jԨQF}I;71!W"/ztk 㛂tmX#n޶n-12DUC,ZF2d3U͐.z-f3-&Ktʙ< +] 4hPHƁgR6Pp@Ҝc1 # !S= RBζt-Z: ћS y57f+YUn2Uԕ}msbm9[ش=z-Nđ ^IKIs5nK48ق{ ,8ϸ=s*P;ǢiңC@R!Exu9>Vx_ѥ'/)G9,4Cpxpȇ|X4)ɵ=1&&)jt6M'Opzzl>c\0G5jԨQ Q~*<} aIΨ{5j_,y7p)OOIj\B7vh $BO1nfm8)U3T)Njۆwh,ү{dn'KJKFTͨWl( Ĭ/VrZR]>׊ShNjɒ2<Ι%e(%)p`윐=>}IT,,KI[Ď'G?$nWTS ÀIK!bR=ܘ-$d#Hn"ήg[ANm%7zCL*xrAX/nTV> sG](H1r2vi9\A1}LlH^H9 {ǝ; ^ʰΗͩއRjHv'hŧl`џW׼/G_ʻo=Ds-~`^3l6z+u]#X79:O~<5jԨQ~v5F|+_֭[0ަo*c3ۊɾQ\w>va]^W)  aWzq Ž-RL=ۆ8 &YI,!Y{|o (f:C`p1%%C4C3JZ$c4L8C͈bPo]g~fK ޒYt3ט R8J t]Yd8%8QOʥx`cT +d#-| b!TP{t =Y`"G+o*d:#4N {Kҵ[hA3ٮl|ŻW%v/ׁWv5>x5a@j9z|Rk9nyc2r8Yo}N)'#u=c}qBfIJہfՔ~o=ۧH]ODΖD7HJ !biu㍗K~ڶj9K ,.fҮnFkCxf 12kl7[|?O_uNK~o 4 f9%_2YtzƉp|fjp||Bx5jԨQFlhtF)0 L(|>n]oip|_ "puykѭW?PŋܺsJxkn (tfCr#\bxs%N0K([PũFoνP4) Дs^fsL&=K[)7ϣr]tw`"Ƅݒxf-Oo_d}7r}uM]W~ Z@cu63(՚lzƵ3zԨQF{.ׯm۲3L8::tQy_ըQ~Rr!ɖ5Z` LI+uo;P3 wͅ,$qb5el` ق]K2\v:jfl@XY-mD,[3R&%3 TA3U9AI]@P7YoOHmGZP $+o_㭂ѱvJA2?:ucYjupZjWOTsn- ::}Id:ݶ ]Gv;_}=Ny_==9999f)^fd'9=aZQWW Qy IDATn ϠoZ>C>^]џeb]-*+AJn~^3ř}S)4_Rv'!8xg+<,G5SƇg+IKB }2=YWcڧص$؍5C%+z2`*!vo{o^ij`C-_t6Wo~N@#Co{޹0 tJhKzݶ,%?4 |5jԨQF,P/ÇTUU0 GCGnިQ?׾5Q)F3aG;73W}?(V,ʎniooygliڜ2s)pNJ%{ИA:.TE.pTqbKh+*Dgٗ8n}IٗTQKk]Y*[Cd4"~_@ے iEdQѶĻLFR>=]4A2hqGywd![%ᇄVZah7uw".dqtDH9_=>bw;]={N?D8*'̛P.|9 +nX)uy&da#j!{Ŧev|wuvӗxZr Aruq!I1m:<wl,7T+a3kHj[&%NNش+dB/$PWffD"tRLk1 Iz眩A`&t3$w\qî<)+v t-;>.-AG+LV%;C59;o~#IcBU/$3WW9<<,$1fBwR?R^#'1">tjV ^_SU|qrfY\.999e:2L̙zCv̦Sf9neU1t]O]UoG5jԨQ~ ϟZ_uBiܾ}??{ܹQF k>>k~߿t:Q~Z7lf5|õ*h7^YI )&.xT-],~GlC27R,Oۥ۝7 ?'3dߙ;3DwQws>\D7d SC55}$C@/dٔ\ n v;#8+l9Ϥp[NmIާa@BxoQv(}%H+CǔU >'#{Lk ah[ v Cf{Xǧ4UŶoB@1IRyU-ICzI¼jI/y5DQVѐ&jl:O/YpZ^-8bqxs޽wN,%'j_vK2 JhӐH=b\\b>&mu|JhVT 4xbۑ ]ѽ FzNvJh*T)mlrdR8lCbu RR9]1. &U*i2`o߬ݕ=T CG4mUMO>*`zUUTU1jԨ-C>#ܽ{??ؿ8x9χ~?Gh4GeT E,MB'Pr,.$z9Z{)~[ +|88%)cg2MZYΕRRR3ssJRXE` D ƌXٗ>d7 !Ӽ91CѾ\K{jIE#W/mZb& ]Ǟnxw,5jԨQF;C=̧~oo"///ſT5jԏUO<ᣏ>"?GGH}ԨQ?ϛ %,$5F~]. w"hOȕmW/ qdŗMP2NnXʖfxu;z)CgͽcݹAH ǰ}Fɐ4x1ߪR ||jE~Iɓa =&ld#GAĸ9bh_sVSIuː|ꃙ#xjݶ n4kFR@Z nH\:>\KWC;gyeLyŬj8d:CI<8(t9CbbxugMSW\Ym7LC$m&x:v]]!o *W\o"Ry9GG']ǟ WW8q?a]$ˮro9zT*nmMKmi@f$ Cf0f" k3t 4nk$JT=sޫkg hZ%UIy*gq?G?\p'%1rI3I"u]dޱin} 3xW!U׀PG۶f0wڬH^uK{'x/v~RJ ^-R0)'|)v)W}6X[8"B,E_+rkHDAƄUf3wK@J=;s='> >Ϯ&"\|0ѝ4'z3W^ q]&@Z'5"oR R\-3bE kyEq*hHjYIZ gHRX1[7uVdvQ5,-Yٚ ٛQMVȐ]1sY|VrxW% 24q&$  n&G$GbŤ$bR(bC m RW^z CCC>OX*Ν;իW]?=~#G?Q9w!.\۽˿:- W\S>,`wסTV4[JW;}{OIFdBX28.]LTa=ٜE36T64#b8̸x,v-5ٜAoܺkKOqC#] N̴)r)+v<'Ul]d;]`0`6_0pB^Ly+6gr8Nm+][ʋnT)C0 sA$f{;BV:{PJ]s%P е-45J驪f%TWPp+"J*øtɒMӬ5HJMUSUmRNUun=Ñ(Zfť54MJ麎|IBUS}y׸y]i,Kx jjp#9!°풶m9wӳݫW^zcg2zkb^ߍΝ;77۽ԷE/2׮][3ӝsگLKSⓟ$ʟɟsGz=2Smefc( |S5C{eGI.*X=Œb|K0 ŨSQʊnċT*-ƏUY]Pf`DA"u0X9fERpډ}-ffj+N`Ib筠Q9UaڶI&KN0A",Plp8$fX,ݦ<0mp:q<;ū45|7A}T crZw_`J1CZmׇvfs"9+U]{>IJ]2jV $$/h!T*u5X^| 8$"^ g;tQ¯KNW1b$ 2䶣Hgw:R,9{RԒf¬`iU_. >O v5M]_'.:)_y6F#vw]d.?|ޡ?{իW^OmR?S?[z;TU\~0>?/~0lɯggoW^ڵkyo>ϭ__>I___|_Ź-[K^~JbF"CI 0*dK? eEeUPŘ"R%^qʺRCXE,= ,T.TwC]4J9h >7)#0幮tPNkq M Bn[ m3ph&vJ%_* jVZ#9v&x6Fl&Ғɒ4] 8aٶawsAdͦ'8;=e>?|6%ws-kfW5ĉj" 8sLܶm)Y_ B <%Kf@u.FaEd\pAhq4ՀEڸ9>`t-ìUǻ#&•Y^l9%wwbgg3׮?'CT 18x>Xٔ{޲v^z_>9<< lFm+h|988x}__QUˋ/~~~GGy׻]]z׿G>53}L~w~o|)ׯ_͛\v_ԯ]f_zRz w8 $4cbjpgF?W%uL[FAC,͠_,6cB=Lk :}?v c%؀֏ YJ;%3Kʖ⯋H)UR{rp4+QdsΕ&&r⻄Ц68F/dRLC\X#=UhCkDCZdEJAԍ+,[vD\A$$ed8 Wzg@S"GdKϖ6(定2yqmm\蘔:rqh΢Y>яꫯ>1^ʛo??e^x^xsoʧ?i>OMk׮?wdk^r[z ^db+sbRVmْy!#QP7*~%R bJ*p9b "]-vwV,;ѵMӰ;[?8xƛ\xΦ3Fٜ k-=F c]zիWz /\zuvcdX3?3lnn~WqPyAy////Xַq}Ν߸qO~k͛7sxx}YS^ZɹDXUy ?L cᕬՄJ&L ⭴`ETx읢)*esaU9nVHMbPRgUccUq{Y- +6%WErFBUKjT;h#J -Jє 9$[BGJghͰ<XDt*V'S[o6KEͰaM4KʤH5+"֜u6q2NCE71P7S7,Z|J1pl 417-3 癨C_b<[*%`äV&vM޸'/^x+|}bȳO?|rxt˯^g{gG\taL&.]8)1; a6sp;_6NJFɱ+IG=hljV+k4ɪ\(Yq ]]5xNٸ!'+#B4yt3f p=Į"s@E2 N|a_Uri;0*X8J%.q֥P!jVC]߫qLuB -N8[ v &<|l>c<SW5҆c6&bd02|.99:fssn;ǽ999FQf1ċ[{իW^z@3766t_oI| _u]xzz0ԯ]}Tux?>~֫Ww간j)Lk\!G2Pu-bp Rڔ6f(jn)%c缱؝BN:*% I#d)ȗ,6W- !ؿ I5G=焧) lP[R;Ԑ f&-H ` cUs1?%cym`C 34*98R2 %힔* Y&LW>H]k藜Y,5s.R焪":%Gl[{ s2<ָ4;3J;R [UfUCp)' ݜjf3 ']^s&nx7sdws{36貣9g6144!tYdcɃŜGw9WМkʥ\x[w9Dž Œb\stry;ūO!p e @Ll[RRiaUPU^)i#"/t5%cs焔o m{\aGk M! GY3~bd沞Rjw" \AĘJ%RNPyI+,MyN+$Nu r?H߸To1NM&u{EAt.93_y+̗ Cvoo9zP\, 㾦+k٬?{իW^O"•+Wv>~:/Bʕ+})`^ߡ~w^;^/_楗^+_ '888~:W\9<<y饗tۼ^z#Taf"+t]n)f3Y=%3CUw%WhʋKfKBJ(Z3f|3ϝxr}c;C1ݱBB!BBBU1eAp<.  0,s 9w0ߓ=FdA *ƌ"N eO)yԸRJ-\ +5ԆA]sBu&i;tb4$5hOΐl!ie;m RUXq>'M&9>fֶ 76HRrAXȭ(W"97B9-xhjOJ6duHFx݋rbLNN,9;ÃΦzu}tTxxEflbmdcc^W'官+)9Rhg^.HpNqef+yRa;q8+UQC*QP0'l`c]+8HNhBKrn`'e=(74Y U@N#{b>M CDX? *jr0NZX, g%d)l;nzi)[e8QC\t9łAݰ\.8'K!'Ν?O۶ C?bww&zpcM6xp/ymtzl:g:wUw^zի;C`0OsM>/rE:űX,u/2/^4Mv/W^?o&nZSJ|3cغ$C.]*ɴ^z=Rhsfth.lbaRάsܘ{bJ:_՝:3SkT@!@e]n5"+ϒqBq}S9K޹ujNf* o}U*pɸ󎺮i Yyr^{uł9cd>"\`{kbALڶe4MSbّ)7_ŇSGիW^~X`'|-ݻ7M˥}`/;;;ޫW渚 \V?{K^bYYSr)͊:Ž&S-݊][!b veeZR)bMYS3hL8XRJHZ_%R- +nW6f}6Z >o'A`_6(Df@.j//-"] ( /Ŗ"ԍ7!ފ^mKily>[ Sc1)F4+}ooq-e˳>˥K~:o".'g6, esQIg ]gy)EwU- ĭ_5ӿe3y1LLlQb2Y1U]1咺**XpΌFCRk~`@S7\x۷oK|2#0TѝW^zíP}^u^fX_dMzȌp3XUkat9I"٥dF psI.4A2<1$l%ف$%3jK'g#^5V* ҧb/&%ii!};KKy -嫾qVvƳ0S *$KWq4F3oA o#K)h VoIp~s-3^{5HٸΡFc6$L*C f\LlJN4ZBДKOIweȠ٢ L~P2A @F5+=gj5Sà6,Ƽ@ؠJdBʸrGM{t޵8y٦/ft1 @8\<<98xxN˱(,k1ƺbz'f@LKJ. t58p2ՎadbI"'E`,fm\ 9ŠHphKRr$UhH(}pV4Ԗoj$MaޒOfAx`oLh3̺%NZ8'GU8>;}u_ٔބ\?}eR5Ȋ@st~fͶ\u7Wӟ{q/BWT")ҖpH6' % =nswf5}@_(.M97 f :eƽxͬ18Q'!&L9"đ%‘9*0ԉ.wTLA f-ݎׯ_suuEL4^oI)үO\!"\?} '-ZhѢEC}ѢE-Z U{ᤂ).$78 fX`Rܨ꾶F`ub3%Nm;|-f'%F$8혙{m&#&m/D7e?E" Qn&v3uƲlVX OKXQ>rO9p Gl9Eqñ#-̸sGhi¬6~zD*'V *μ׆jym`*HX-X2L *`aO}=G%b ZFWkN-pu\tӜY8=Ռ[nTaӫ ?y-'-0b(O>_+[;K^5x)j@-2MLWv4C8HN HѹC@ZA{NRnHZ}`RJ- ԮhHI)9vE}%BnIjm(9{ޯ5C̆53RO?ɟ`S3C}k%_3kĺn((_5c_urzvp8]N9K~{yjqy}8ݞpϤJH&^߳lnV=8pG-wNE-Zhѷ-ZhѢEo #:.6J'8G;:#BE4F:FjimIXЦ&Xbv:Kc@ŀ4*B+1@$SBUNnSɱ5f|V:ZVDȑNQBt̊easB"o/CAf*@P q_&g0˭ VGӤsan!s q3L! Sd0 cL2\Cit.ujJgn/)RɄF#ׄs,$$j T'z@Q_Ujx`yww=1qv"8N &6cA \|s}c)\]\??.O Iv\^\1B)n؀D噘QƉC29&C Y0|e4IhCf<Ӗ9>vΙ#ͽ ɄB-WhFD9S9mF}p@_16wwlNI!y񨚯PGd4Ht~{ >1w+M={::wr3j|/99pzzbt^= ;ՊW_ _bבbb:vT&R-hѢE-ZhѢE-Z:36#,n.*U/.un)"n"Cwri}4Q/E7 s )gΥUjqr[ U djK$07=- BP1rjLCOKΐPkhF=SiCAb+q$K{<8r~Vk|j3%&k=F$"EB{ԠL wG3VT *ikUۿbtɝa:7M=eOzr ]rLpNmZno!Fvt=֧6[;`6 ~m=;c?('W޽g{˼z 7wyus)-Q꒱V!BLzDq8[eiL#q-3-). cXSbGTѠ|UK3Q,iC~=SJNjlV _o(.a.8},f 8?ˋK)9g{,8YX, b CAWV|:"}߱[^g[]Z&V'w8==#ax'_|g^#hC1&$it+:bLWZnj:vDL<n:hԓ䅥#FpQSF H0̜-4Vg[witЌl%a V-9<k+Cc( dDȜn꯵ > Ӽ$!e͘Gf[UʌcW~E# %e"~m,gW7H$8*A"t Hh@R|;4:Xw[";ݽ z—A8GkÎg])@cdYq];|Elrww_~qrԏcwe~4 sfy9Á{2jeV5E"ZZ!s\|#1$JXP$:#WZ pL*VA]JLpt›fyj(*Zў1z/CGДb-H!Rf{^zE"UcG$JV_bx+Xo,J|>ݞq<Ч 9g/ݞ V!:g"'[pyj?w%H?7~;1R;j!SGL! T{ѢE-Zj1-ZhѢEPm3b*V] ``@fA ӣ!ooW n6-qR jXp<4tT1o( ;y"O̓DGSv>GSKM#ڎVhĸXu,VI ڒŰR!c1iErVK:6ZA}c]dwq%dB e#~T+Kh)PUKl[ + <:(i-\zϫ2 pzl?A+Q*$|2esL'|+~q}qa xw)ebp{"gg׿b0'rdunxrvAuD Lww(o^cS4t'*8ϼaa=G_ݼ䣓 &?S'dg)opys~W}0rޭ~]䔟՟3ܿ"}-jzllKQ#KZ*;@VP@ZZ )Fb3[ g A1A>G:>MD@KL )S!LSo=ᦶ\\\fԌz\ac'zxg'~'Q bdw2"t/uU~ W1!15gHV ?яl㒻WYOE-ZhѯC}ѢE-Z Α` 94ox7C@bf hq(nVu#W<Bh?7Nzi>9~Xv%6f{z8x#:M.sq5W}6~uf'wߟLw '9s38 ỗW\^\q?|{mb]x~u/>e:γȶ_cПOٽzgHD5%C(Jm7 j˙`tLvwn|\ŜIPѣ$ڒ9%R!4],: A#"̷=džCȚ9nfb$ Xʀ3_Pi1ZQޑLN= Dd4Ma0 #1qe [SNtk ݁t_suuuLɟnO9p{̌PhѢE-OZhѢE-Zjt-Ңn‡g̎9b[$BKAnӖBu3F7\g4rCE`LhƠ"c^4{7CcE]M f7fHPC3%x#]Yh|ECBmSfcx>͐fJn@|OnFNpvw JAƱ_Xa4T&e0б=.!`igG/Z⸥I _oX}3OjL%TH>SDHAUGFFbLiA& Ejfw H0S]3>yTZe;/wNNs]2LhQN8?/ "*HRS2C匪҇9%JcXuIQ3 Iаl0;rrrx)5R 0 #h5V ͆(_}^zٞ8vIUV꘴Ve(|lV+W_ԩp0ᰔ.ZhѢE-ZhѢEoL14ijr,5Ӧы͊ilsnC ĄTq|ZmFl[K l.N6MqjOD%qixO[w>i.Bo$q/V " 8q85伩x$~g8"K:ۿOȩXciiۛ ' IDAT¥ ;ee ۍFuG nQc#{ Zު'DzJ_rtӽ__qEt@Qd~b1*$f4UYmaV۳ZA#ՉU۞nQx8df#I"izGOOxKYS.N8n03?#/xS(cÁ>utg}G\eSWZ b(U'bl*$|u@ntD.rLSAb`*"pRHX`v|V0Mr[ PR"6`Fa@CLqɣo{+ X|HSu38/_fE49) vcYԆc.A jZQv.v]f>3WD 9Q}٭a]Wއ?goc('g\|rM}M"8Ukf󷱔9=Ys?j|A1/8|K1$bl(Ԍ.%OLjՆyiægn4j!T7lC-1%)#hbmCt|2T92F@T--34xyh >K5_C dH[AkRLZQ{ǜKB''=n1Dk:=}gCk oζ@`u//^rs{˳go[?!Z+77lVvPj RzF/ZhѢE~=-ZhѢEoZG!:c )u/&rhjn W XKF c6؝xļ@D:uI RWl-+}vҶ战` B>~U[%7KX rt[0`ƸHmvKKuVZk3q?EF71241_ R:ITuf*#W;`;06.zRBlŞ֊!MVjX-x9g} &ߦ0j~ww!_e`905");}<}]^PJbc|#|՚V.7k"J):T+c1~|"_9}︹lʯ>4?Zoys Ք0BUrNVDONy]9 3cb HVJ|5CUz@:čbV3OeЩ |5%/j'䔜2'''ZvuA,ZhѢE-ZhѢEo RJK1s:G -nH3 ы6574vCQXlŕpwз@pH?2**KG3\+6dD Wj+⸖`{17̓:ؒ@XѠnZ-D F/_OZm{nt>f7GYXѠݨ6O[HBR 4VRYK{O+βGI^J!u>$`aUU/ɷɂ@l{ q6+`gthݎ}U+} ֓v r_ |zqvrJZ ?K)l6R'n_{'PP(ej}Cfh~>T+Z+!}8^r׻RfJ չTy0wG^`R$u)y:=2.D1iC'_Cp&zFwUZ{RK[3aN{ 1e4dAZjT-kb?uB5 !QKo{0{\574KBl7^|fggg-*8V=qqy~ yhѢE-z3-ZhѢEof|"R@M:M$'4qnbتC{Ou (nbWmŢώx::$7p[Rsco d7AjiaZijDO;7]tfc~:9 &E(l}Ye羏^Hx_ *pz늌c}${!H 6kV 8@leaCBjٮ`}0䃧ω!BLu#}M</=-$G}X[qjEQ}b$'Ot1?%/3= +~_o8[mׇ+~Z1^'g}=no>n9XoSxo^>e{rBtu1c`FVNήx~_?Z=^(H<24!@-n:Eϴ{BL銈fLwG|u>1E.jfxKGYW?0W#t8r&; Ҟ3bᱬ5CK9 bGF٬9=ِ2Rq RfvT9V5!GzCU1W_sd70M H)9>R%w ^hѢEi1-ZhѢEPY 19F%9 :PO< m6%uIP=5Oي6C/')R)yZ8"p1=ac9bVD9 Z3u$+ tm,yRi ]}KԷ#X&3/P$>& 5GȄCdž `TZ#ƢJvR$L.`Yg" > e¦&7=uaBV, (b~sCh,G}(ȜƮoxZ l )* 6x`d+*wnϋwH2_}ͦ\Oxrz&'6]6j͚ON|`?~].=tMg~?9c->wk*L0tY'Uhpoiu(VRK[K)%ǬІOr4k襣S="[tf#$JFȹc˨ #x,NڐV*l:BK *AQ#uRZij;/5_0 n?W\\\KV]0LrjT*^hѢE0z-ZCo¢E2qFT0b6k0b^E+̼LGFG'܆oeBY-tl_MaQq3k+E9-ΈnnQ%7c7h Ԇ]51: M~Oz ){NofTRzEc)HRNǡ3૕v/RB )4w'ks$4MI!`RK&f:xhS{~Ԗ4G XJ+q[HÂs0m lNN#D ~sr fֻw>K='֫5Vb|Ƒ77|ڢE-ZhѯЛhѢEo>MXhQCKf{ WҰ,3E$jCX~nj<:Bi;Z?JkؕD0fG^ EtVZ #^X_Th`!ChZzhD;BL(ЂŚ)9fx@UJ3VECcviGX!%}֝bjΖDlت#u=1B>q݁"g7MmLpRbZѯV{0xzzwN'suSE}R{V!gyg~ꖏxRcJ3cJD3R7OVg0M7?)8|38XWx4{mp1 X1fG|N%P4uT V2#V}ph&?f ik[$Я:j-i"ƄiMaXmܼ2)9}zdƋ?vnoYu;ʋ7\_]yZhѢE-j0-ZhѢEdG3hn@!|W@h  nZWEbBn=A g-}Xgp,cy Gg@f{GP*0QGа)$|"S) )-&ꅘſۦB0dֆQ/Đ3OHa|knPêCJ lrY`BFѷ!&BpggF R=VFߝ!'ar.ϱ.6n<` (w"Sxz~s)є'[T~1聛/?Ք0N#fnZigccFXt?}uq%1D*)j3C3ʏ} $PVfl.5}93)FPA+ş' S>ѾY^bD+.wDZ 21<{^~%f#Z3 G+*r{wےn5j OƑɌ3}E-ZVhѢE-Zkӝ[z+(-9aRthBRl Jnsr&7E d"J "QEʼMkTG_U3bAڶ7~@H&O̗ydА5^+6zi`b Z`U]ni?Vٮ<>GӤX.4!)]J!ъ =q8b>hnD~xz~x }wYP ~$uUP/ZȂ2E7czA@P}Jf~-MuD9I"٦pBIhFKo_r7qWlSOWlb'ƻo 89Sl^?p=W؏Ll!jF@2w W||fwKBHP+V+1$JW@+&-)$ՙqlFJ D(b9Qa]b^_kSB`PsDJfתz4ٓ9UBlVv:oۼr4<"Pä3 wܽx`{vzszD6W77{6''w;ww1\_nrHʠ}j;{9j*xPrƕBNb纷,^ǔરqc;9ã!pQ՘S.^X-jz(vGD⒒39ܿK֋j+\ 7ヌ)ij!l-\->_q=}؊Ӫ5f~l7[V%8 R }qzr`Yn'W%G8L0^+c?^]>Emug_})=S VC<_9'%xö%MFBQo#6[_Gks̛ħ }/} 94MOX, ÈãG߄wYf͚5k;U>k֬Yf͚R&S=K IDAT\O,] V_MKgxw&9583R+UFQ4ej(5z\qCk4~`N=JԳX j hI6 Z K=Z1he)Ί#pXSR_by.beDK}qHI{=>Ox3^>ף2LCeY -GfOe# 兡m\yvL4Gh؛A3RZƃz{|.`ocN+LBF>|J߼0Zh-s%A.)1@ʅT27GOnpvD(Œkαж-o_} u'%qP3R:s)8gxbc-g\3{kJ}{yJ8bд~;|^ GLcTw[bV;?zw~;}&!|~/O>E۬V+rVRJbi ^] G݊GT3)Odͨid"G ',BÓ'\=[ g7dL/z qM; ׾eoZ,+["@wHhn^ YAbċC)C;tiH)ն M-:s"ٮ ź 4!ήݢZMZZ}q)&֔"6ţζ)"M5m/)QJ! Cݥg$ N 2W, b_zmWyCC*A3)er)|ŗHHNS5G޸&rZRR-DΙbQ f͚5k֬YfC}֬Yf͚5+sX!aw)T !+A5MB0cfkε<ƚ^1o^Ր4CB^swrL+[ZyX'bXcBb$c7r3n9ZDNvA9ۖtIYsNW\]]rIzngkX"V OC4ܽsS~U]zsm[-͵4פ>}B.9w& i=^E璵%)rji>bD޶¤~nC݉SΝ;Tsٝs/P )фhϐ7d-WvN{?zȢkiۆ30^Nw[...s݋/W_~W^?_ ,V+N'){vp||Lbm5k֬Yf=/Yf͚5k֬w ٌ" G2KP+Ͻ I,Y.2@eWt ⌛<WdRV5͚t UglҼN= ͔QF}ւS(d6 dy|WtpmkK7s['}w0jlƆQm)YAسSXԿNɒɰҴDf@lЈhAzJ.X*;KgУ#4D$ͬ:ۋ2Ykh{`׋(qg<%bqDrh5|Q922TV~Ş1Sro !vG4,-/~1>?5u  v 7oqԶl ǹes(ܺs{o$xzy!ywjwVlXqzBoksˇh))mTSWUXJE$Hp!D1'@X|)u;%<$-HQ\*MS.=m ^f$Xst|lt13yw(9:yK9^>xP-킶Z`^_̰WCwOlLXtK4Qjz}LBt ]puE-׻o=yk׾̿qRΜ3g͚5k֬YP͆Yf͚5k;TRM[KoUZ_ES(,۱)rb8V0õVdO>*{m\lf}qtR|} 6jlQX!}R9R#Lن2J5CUJm[hSg`xE=LW9\6^ -߆(ۦZj_+7Z1,: QI`F3\XA`s~n7&ʰ-C#ӥ+Ђ;Zj jR{Xtv>JVsA :Z|l("Į/.lx]q+0H--SB6[d#M@=xgüRf 蚆['t!0=²mqZXTp61arE)Xus|.7Oܽs7{[Ͽup (iYSg o~CǏ!MwUaf0y\~yv?zOx^-* )CI`6x]]vlNٶ̜M Tȹ*R3{ifLFb3E/]l4Ѷ!oɎ!.W;K碤qGyZ#T]]\r~Z?~eӴ WWW8=  c#|/TYtoлYf͚5A>k֬Yf͚NUVJ!h-5Kg#^j&šc2,ʞcOqmcWfbCLcM|f,jY+%,sMcۡJLzלqxD3&jWCPRBc5gk3"D2Em\Mh fH &;Zތs)#Ul@jUS Np%::0^$T6wF4>A0l.袵T@!vG#SFwƉ'j{ml~i? 4 oƶBRJ87GJ 7趷}X1,arI$]N6-wghX#['bdGB?4HEY@aF.-:M v6xkƳ oOӀ#:9]0NO9./T)ʹ΅"N& NℶsN5m{/1>ϥ"\5K5˳۠{wf;QjyKJeWud (|kf\ߨa'Tw=1i}0 ԺM;R 9eD%}x'Eж8\\\xiB Ͽy&^x8|;>9LpǏpky}5k֬Yf5U>18k֬Y9~?o̚5[\U1sq.SY݁7,xC%QEŊ0%xPK>ڭq zl C+iS뾚ːţ`DAWq٤ь=¥X*RELK 5鞲ߚ--PP3$T&Øf߹=<spX:2cR1)P¤u;ޘZ6"jqWnqE)甂t?-@1"݂"ӈ<٠Dۖ",e|(5;A!UlE K-޵f /lmP"SƊZ&ƙ&r?3r@'jIZ+'PBXvS7 a J!Bc7-n`JKr5"۱V~-ę[ fzub>ca)10wR'kbGo1#7Hj#YX.DAƁi0˦rr--ʣ94p&#n'-M^YҶݒ[wX8/_%nI}ߛ >n z r9%Bky_98MgrwUS9!;CM] Z,J]VJ[ #U+e?`v8a*HǑu rɤk֬Yf͚KhKExKq. TK-Pې bd"H5{{$3F:)mf) Tİ.3QÍ.ZrzQqvAW_]wE,I=qMcsAB5r\0nE**DPr}3~E)IIМxnq>"Ew=*JB=X-P5?[kF!lB 6pqLv +"l^)C.H QkpEa5Jq)۾lcux҄z`m0BDro\l]?Pˈwq7_r ,1a@n&{y999ޫr}Մ6 ِ)k=&EtH} MSJW>j|r( -vfC}ǐ4}kuϋWi"j% A,1X)"ue9yc\JΤ4!Nyyh[O#9r"&4"9GnKg؜~% QI9!E(9/v{8M{{_jsŭ[xRJaZK[? y֬Yf͚nѻPG~G'>u{x7^믿g>bZr)97xCNb{\$S44rq5TKJf`\5 *Es8FKR"j}M{GJIM6ƘnwU؈1u4YjCphMCVT\rzz6纏5q"॰lp.:Ta{)L@.#)ӴǴ˖R{NWǔ)9ZlEۂƒޢ߈Yf͚5kַun㭷:|}~~ {o}믿0'=~dg͚՞T5'-CpK6 \QJlD/[4MEGT\ S2y% =ӧن-:pF%e;ZnhI쀇 {h!ԕY }3e4'%XibSU0\R1]O>.\_;,61 1TÔ^ JJi2{4g'xE=_ٰJ"{=OnFvJ"@?$,;J-Y.dE'K(e}ٿM6)nmwm)R2 +]lhۖfOִ]Ǐҗ_9J1M,躖ﹼ͎gmYf͚5kֻ^:Cӟ4_o?q ݎ?Çhhx֬Yf͚5P\FZ[TR8Tk V0q)2bdASgMN*fpPj¼&P\-FeBUpntGßhM;M)Z)ɪ`o>q#Y AXP׈k1Yⵖ7#BႥΥdNhK bc1Po\vOb+hh#!DJʸ~gXՒZ׏_}ʸ)TqS>iHQ16N p-%ȢCCn{{ ̂4FCL9C\ EQh81G)#n]Euw4 M49S«rv-D[NX5JItkP׌}r6x<;gzybk}m|C/s9MMOӈä3U޹\RM+)A.ж3Q5s5穥QeE@yK[,%R:aJ)fg*pRR[bRPKq.Ro_bI_a N= mNϘDJD6`Lu7\@sjuskbibǸm2ϾbՆ?} suPf;wk8>^r}uŭ۷9;~5k֬Yf3?я)O>yԧ>g>>?>k֬of|LfW 9UQ1W ~w~t֬Yf͚5BRFFdzHb \RDԁkZ!),EmU=pE`IsK;+@՚SmB5kbMR"  UERV!I/j(k(^W='9%xCai(h!Av|A!Z5Pk+5.3&\|z&Cdg8d/qSA$rV f3U.a^Z= 8R·T|Bhm?i"4p\(PZok~[.p7 04bju*,K)1j" |Wx{w|ܸq6N㚮x7Ǒ劬 y˞5k֬Yf}{h6?ΟɟO}O~,K~~^z[kf͚5k֬wi3\ٗxMbR0)(=X©a*ԙ.tjgOxQK"5]hk-.a{"~E\ SSzP#:M O΋xLp44_@Ӓy`zҶ'4[jNLi+>Mт~HZZB* N<j|{H"fĶ39 []Anْ 26@(Sesw-r̞mO?A G+.Ͳ5NQ1ȼd#` mfhBÍ+yb(usӦCCϪiY66rt,bWE5*Iq)rbHDbEPL f=ٯ Kdۏgx/ӘA(Iqޑc4k[n3+}ag18=%b‹K!F{7݌5k֬Yf=|#ǺG}4|87(KYfv?3~[+trrޅY??=(HMB7 2R `bKW3ػ֊:k!U Q EqUwf\nРOEƝ3 f3{P7͈#D4X jI&ӄl!Okۧ8xKዝ;'웶 ys*ꦚJZQPkq`g 7S\2%8U5[s;$) ;甔v;ޡE)vH>EkKv.x-2JXH9;Zr/ukJ#9.Ɖ JJ6 Z6NXMږekq*< .n?qFJ#7Wk}~s"FOR^nq4qk}Jq`7 \̼nBޑ7WBvOO8;Z^ux׽1̥ᙩPor_㢄&RT #4RpL5mH5"h*;0]5tõTbo00^h_Μ!@M1RԩԊn]-D +:*a{Hk.b͆je:348R^!rbOidJ34;ocpvvF%>OͿ>]\\|waַVʬY 5M.?~m=7?ҜPGm[nݺލYf͚5k֬6$e4]k:\+-y_Hmxg%@Zz_QxW?98go_pŶ+8V9W`ϛ٘SdǑL~x6=wƓv|4lۗ_p9\9T2q5g$ " s=7s1%h%ӄKb90uZ(^ <.v{3.R|` s[Tq1 '#ϝ2I#l̀,_ cJ1k:XLPUoV>iFm$P>nt!ЪfNr)#O%gaqvN 1FRniBzU,I,cKXBGsTbA])l*F x>6t%MbIi""W܊a_r8)T3y;U̔!دav х e'rqrFɅ =?#\>9e0MfKOr):LVNkΑ? _;OJI*!D>|Cv4#O)5#P/{`|NvC@h?i;밍jԐ7rj EOzbH)s&@j%&J70 8Y,Vw;-wÇPruuE <9JZYxǀ25k֬Yfh6g͚5k֬Y^Qic6O’xӒ`omsCdfH-=8U}0ifT3-Pf- O#]3ǭԜ8jԖoVv3]]iImr1AjlӨW{dhC kMnu͓7R]+wt+"rѡq0` ı71}lPXJeciTQMZ %Ed1 (XB$]oK5Vؙ҄˞R&6lf)!tvO.MY =S-2eJD -a_U9z͋>.Cy~qw>"7\N,Ն(I\u1r*+rnoA`!U4KPԮ00=xVY!xV'k<<˟wIib\1nȥ[@aL+5#XΥm8Y욨f,~q-bÓv/tÉoD"[8c;Qm׭KԤڽ( jlqX%h{ ^]^"qB>ֆl)XbsG}zI)zZWD@8{X, \K4F+>C>Qkeqq]w/!_?5k֬Yfi6g͚5k֬Y^eY%U_41($hLK= l/t0VҊ%!F7l%!)4CDiCGܮBKͰVKKh Z rFe{g؜`W9/@vlޣΡ|LC1LRqb\xL-{$+ڐx6;!ul5d 5n-Z}f':n*JGO|8nl]ǘ3E(5wBOP:B-q|3nq촰^RufN!J.di|c~?Ϟ}{wwB9;e*7|#)S'}Ӌ"Q%;7yqs~rbI4Qs!#i^^q{{ Yף^>‹O?%F+C],ln!`+)=p>QA ZTJ3AvavKPY.=!Dr2ds>4ORJ8 "_ڱūU+Svwշ5 _y;^x 9 ve3 2yhϚ5k֬Y~&4f͚5k֬Yd3 8h6748pc +jAR9_h ApYK~*;rux *Tg(CT *Z͜62SCTSG8rq-/bKH+aMb}U4XHmftPHy쑪Nγ'%ccڏ{kpNWM;)ק|N`7x~{zgXdźxj;9כ=/Ҏ}!D݊ݔx2^QR"?y»?_:g~0v|;=cO5wNW<ߍ.bp ?Q|aJrܰImв)mT60(|t/{vNjiK{knqpr5>ML2Mn7ܿsλo}iϹX)Ǐ)gc`ȡH?̛Ag&r`wdQ)qe`T2Ncz<pm0A%\.CP3h̴vL []%է4j0|; ΩΏ`A&9|;N>Rd4PUEq] q }YOxN/e~G|OWwA<|siJ #'gg~ڏYf͚5k+P5k֬YfzU%oB3\1>Y۰(O nZ:pfKKV+:Kjb׊ ]|KohhwqŌv\VKU<R-Ůj13 D%*֢G^ ޸ыC[3Vu-H1F =Snș:BuVZK 0%CWBoD,ݏu|p1Z!c +BK'dvØA0$4thH9D+o,zzh!Wv*zA@^!dt?R[*)!-5FKw|ٸ١]Ɣ񝕚'₥׻p,jDq^\(V+ 54MСĮefƀ/ք\R7,G߷D-idSy_VX:eY<~x8O9iucǘ+ƊQy?>K_a*D]On^/}8V\}XA.SNlHljZ y\uPE@x415 eclH-?5O7<~AG+9j%>g9O#_ :45сo[zHcoH$>RZ+\qeoB޷Vi|KjZ~SRɆ]Q!Lݻ jhm;1D{cBr|jFp W =yݻw59Y קO?WW傇oE;pEߣjcw'xOU7S>ӔrZ }7-l'*f͚5k֬Y~& ^¬Yf׿YfJ BU*/D,Ջ6CefXj}U56zՆG: Qw/6!:.hRGuoNܱ4'W3kji Z[Q*jx1%C-] 9Wb MDv `\v'J 6]ڽz@aT)Y$ymïygCȱOW9k [g|dO#]PIђ?#>}|:NϸlxǬOOQegūR׆9C՚4%#-0PRB%ժ ->g͚5k֬Y~& o}[K5k֬W^777K5kֿŝf1C ^sU%XV=԰,uoXSsfUSZ&VSY7t#뼢-!oYΤBv@-$C3p0Ř'$h)ƪ Bx1zE[#|0F5L+A%gzH4x0TqQH7b?_+i߽Oc")S)ʄ#Qjմ?*\"RJdCB8ƔɅ_=/NX}޻#<\l-lv#SH9Kd yɾc-va#ʽ3ѽGl67,+-Z-B`}h>k֬Yfz C}֬Yf͚5EI3U0CX-a.LiujUˠB,f7ăsLbӂ$3 >xJʖ Lh >R:pf]ىN5 CbTk5箪aZZi`u*.HQ+ʔ,fbGO=uCꎺa1 xXZpZ8:[~'8:gE]Ez[7LkN^V* 5~X,/~vTxg}h\2*5WzYt4s60fe?QbX kkwHO?)^tDK#)':ڻ_fqú_bs˲, GS޼{>oXi {cn?!!xdGU1B.V*4]ALL>ش|+4=2sm9T!gjeʈ =Ӓjj Txm Tki<{{v(3{Ω*yDmsvx@U_rjCvv Pi[xCϿGKK# #N'0tl۟{֬Yf͚3P5k֬YfzE9FG X7LÁM-NAr::,J*~(1Ui 8ӌ@G-VV;\(~ Su,t6!qhl0 Umx@{Mh4ԸS짉ҝr!L8a$3~qx C͆^IR{KlC"Bm@8"RqNRQuv;bj/%͛Bàe=į|$Q" 4*'ggl;Ѧ IDATJ:n>ynntv7硅r"Z}q)>g͚5k֬YfC}֬Yf͚5Ua&VZ"GΒzHL7~wGץ"H3HR P+ŭdi9 bi\Q12-eJKZ' ybX C(P.Kq bez0S+K*bu켭ZУ>1Au،pA][A-[ap{g__ 3.ǹL춸@;4WH8 UoYHCݲv(3iE&NOtjou_{KnK3`S.$-t!Je칕"%5enoo8]pvnϘ3D r"Ob9,JʉVK7hl{l%i>p>|Xx=zX/O3ܹW>KY.liew\Â|&´!ֶ[fdžOrJ^!8O*X0zp\:ʼnch3k8شT{i+u*#b+Eĵ+׵ԗ:``׫ZR؋ Sy3%EZmvT[R)p (Zl׆,@ 1DO:JrRKm1}F^\2vx̞'1n)>ЭS{lϚ5k֬Y^}͆Yf͚5k+*gͤ @[qT5Jp-육pR:676zKҬy3Cf웽}D#٘VFP(5m2Nf5ZN0TPO,.ޡSBqhV=%KC8 GE d/>,q4P,=E8|7BI3ɖ omM"C6 Ch3  AEp!kރ8h ®9y ~"!m] T9 ]b{-GFџ[}rz( 3c^ QU-1F$*R%ĀFp:&Rˁ)ޡ ٕʙ %+q`[Fn#_K>'&sZ/{y6%nƉ ݒ3 |r\b+~wEN'noGw>jlb=,'q("KjdU*Ĕ 3;@:BtLˮs^cF4q@?0NO=)5a`jԁ=}‡/X)2NU)\O9{'%3MS;r`QՌb 2w KwC]T%"\GR]b$gyqrDPRz4ѵB1\Ab^tՊ!jSTBao2v7R:x砏<~u⠔sBlEʥrp{)%>S=p_rssz}BəaX5k֬Yfb6g͚5k֬Y^Yijn3S]528ԃ'}ĸc 5Ys0ŵ-fqŻfBL;A2CC}.ח%xtBK .9ʡH: Ն4cZB㼗j Z=SANVHZGz]oTq9j57|Em.4"FyUv=AܤJMrf2c|r{ă`'pNj;|(x ibrX2xiULݥum{8OOjOHZX,Q Mf"B~*ӎ!t+]GL9l:GO: _z1 '–2%b.,P".Wnw5_}M n~va&#n.v1 }BJlGEIܻV,z(.,Jiqׂͭxt!^k5S֗,9UPl7oXھqH`&k;;-ߞi)eBtV*783VR2݉k~s}}}<ּX._xv˯گq>c[ΎYf͚5'4f͚5k֬YDZ٧RS6j-%nFˆ8:s ǜqO)f3w ,}1ƜyuZU}/@7nPg@la{"؆ƒdmuc!}z#7Z̵6/rȬF7be~/9G9c7bR]tcE<$xuhV|DƔ6bYDbEl@BHDhʊD6,A-uSp1L25sb%=?TjY3@"^yӄ#G2B]|@e:TNB|4 P8dEiey*el2Sjm,* |@4'#\j4 [Q9ϴX ImZ±dT]:X8aΥ񈉫-fuzn5&cU9M!DTFcgy(*2m0Zd-`XI;Ιuiw8hkC;7MFPbN5>p-o Gl UIkYk7N1+hD Ӻ$X˰c)F'8 v(Mp1d&!P)m?VKN.XlZI4}b+iuHģD'[EUb*\Xu7xqb"&Ɖ]ʊYc]P4֔NpiFPidi,%udZ|\"JV%P/9ũYB|(%q!m; X[uukkf89GGGɴ%XnZ\| 67{D0$QF5j^s1a )lmF5jԨP+C,@@|U J*v1i4#_\MdOJD'W21Sd8!&J#}Z`!-8U{!)ɺLȅ'W)p>Wir!&q䋈YN`c)dЂGVX&xch@QrTsfmQ¸]ֳ6mex6!J{Ki8b xxtȖ*pUWBqT-؛kYJcg(%P,v(&gV,q[5rep@ER,%1͞`#&n^HIkO_ iYanDaglJ/3!yp3JAB,-8z}˂Rc.*\T!gW$VԻ u, (W (K9NU>xO]Wy)u {x/:v\E#>%knzx}bjF5jԨR/*C7%S}\lm/I_5jԨQF/JGRWabh>%[J_X"R|v !p%Fjj,̙3O=lGۨQFmyM6* ZŤMV2V\o|4WZ 2 P>n?$fZ* 3mV_ӲJ/w"Jj6 Kf O塕Αځ_wS9#!&T*m/Axdj1_TH]#. nxăOEn{W 'azTk#b,""=4&7&ht :=:-"IURyB+%d#r5Z6X"E@_ep|2ha1<.VYQ(JmW_Y;{'#Db iN^⸜3?9T-~Y`^]bCLk+X%'s 2󪠲nMUYVX)'E\pUkfS0f9.“GZfY=dz)Bݼpa.ejZma"b/kl]C$dK@+)>?$DO%E%zUPʒ[Fߜ<YFPRhG%4)Ѥ6I&< BDäa}aiw~8Nx9j|Q:@LtGbXjקt>"hYΞ=(Ij5QEc_DrnGtR0&#Ͻ5jԨQ^wKg>9zaooxk^W*˒~˗/?mS, nIjb ,\YdCh#jl Dqll; 06ؖ^ܢ|k1K{=adhjG\,=,,NMt&!=H;v+F{2(% Ɠb4upD8 ѢDPTں"&!!d iv ͑゗ɀs|&Ԁh e.a:bFc /&ošW1ў&Y$&ЕJ!NB< +䆯-a:ƾu#ᝇܠrtZ)<-Qa%eq< #Pl C ʊ(\vM̎(3CFq29Sps\8wquإ'rfs\>{#LäX0-hN35Kie9Ӫ(v,N+5aF"jg(U%3WqReh6ƝӜZ[k9/&(Mvr@0&MX!ɤ@yMC>P,9 666vVXkW=l>\gcs9 mԨQF}w7?<ϱ~g=z*Ϥcum_5^172Cx>5j]Wp 0oO^6(#P臉l ֎j$>#<*KH7h @!,'Jpf!]'7:ү+zp(Y$t7HVŮRz | ԱQE1Va>#'(~4住x@2|%8]:_߽C|Jtprx@]b9w5EQ`BkbQۭ:O~2}¥x6 kghVu!J |HJ΁Tw$i Kh딠_N`[%Ğ]4Ƙ՘Ie'@ZTJB1B }h2"2arB0T IDATafZeDS@kX, >FWŰd E#lo(x,X)ٔM<;+5jԨQF\&]WÏNMsӠKI2 QTĿ[K 19Q@%9 u,Ef<{7QJ_T9#Ξ=ˠӦi)eQE-[??_A|nعs;zSqZm8FU͹1U]398$v|}r+^Rݽ2v'#:6f2e3O)|J!6(ʣ;Pz2&dK{=ٔvˬ(Ped1G+Ͱ&_[̃>­3I_AFI[F Tk{,1OAeX`J2q3:So܁219.W @r 1EJʼnR>ĉ@4!j d"DVr<}@lQ"TR n!&6 zX \aF%v([\sހr{OspKocs}^e43;!n&|^}agȍW]Ϳw/?O6N'vU͵/c4czy 꼅u~hXŢ!\w:lnpR-4cq.Epr4:"9Vi1go~ Zz(.gl 0ඝk3vՂwPE14,eNؚN4ymm][`C`ۢNrPWlueFJ{ ЏK3<$dNɕ28Y%+\)Mjƹ&i)=2cRAqB%w]"݇X,)m."Dy`Vي:c%R4Z`vu||#A(c)vN!8ޡ pSk-~nCV~1|GjԨQF=E/ Chįj{W8O~^QFς7~G#iԨѳeJ.t,OIsQ omJ H8EK4₎f2A| 8! %H4_%rJ!*Xb>bMHHI&s1"wbzi{ޑ;$XB^b=aa:i Y*Y0y7X|PoTDxRhQS̾'Rد8^% 7*,bi@b3hw>{gV P%8yy,BkNFU hD uJPHmF2uNG.{L(mB1d}ct f&Uz+:V8?Tłr|xbrk yxvŰ݋ z=s\s~E]aZmBYp~|E;ϩE)xJՁGjᐍnhI`1*Эӽ5lYjQ9BQt;]Eڒ !(;SU5fXXzTuEU,rpe:>`w )u]mZ_1WK,).aT2>h>'"1!`u+l,TWVń'(Ais,W71(ajc(eJǢU|΃x+PFihEZz" ק+EIAU)U*YVXt"''@ߣblMB~xsp ~75jԨQ^t -B`>s>gըQ1;O5{l QF T61E.:bGZ&S{j7c]-:"eip3tYrȲ5/nG>sYdc_1-B@ZKjh^H'G2KSu,U Qے>$V,UX#@e#ULaAtEFTnpuT\ 6'd YwLC,BFt-ɴb1AS!/]3n(蘵^7gyEp1p1cTA &3Jc柿j}u;;<2ڥnqUx \8<`VZsfq3˅؛M4c}`:&sbfkU=)ΐL!.?;UMWY>D[e̼e|B<61t6oN%࣓f^DȌ,PxY wW5c|Qw/᫒PPZcDa:nBŇh/ |AWuLd&CP1&8A#FQW:s0J!MDs'M-ϥvBt j ^^$$Tyys:X"A•PH"9o]LR a/ON\"JԙlnmQb^2>sz49eUqNmb}}:fN=nz&ٍ5jԨQ^t Mx;:O|p |}wGկ~:FW(_W>{??s;;;};Eg>Ry睴Z-NNN؏~_@9>OO}h[xӛĝw ľ5zIR`AdwlEF@RA"*#Y,~@gy4 PT`+PGSUI+h$ba2.1&R#JbiU F(GԄ+ĴB:K3/xB*Xo4 DTac<͒g8Qm.Ļ,$NYvN j ~c0/=Ĕ| &ˍONЇc^jP ܣ: G{s3gYך:F0ֲ.^'b3C]{=]}U\cs`8.+׶8:9Co[N춨屓1@501YNd^o ֲ!ןh-c(\b{9vxɋX"Cyb6cUNե( N,#4VF]wtYvs~29zJhҢUM`/mxL?}tGOKTfRl},~Cu$u\Y} (qRFkTH4<~TJQB~UQiXjMnx@˕dUV\Xg1&KD\R^BK:D!ʤ"v&3blYr?62Q>M.CVV<ē ׆dFW휢(JF#vã#z*[=sF5jԨ^]w[>s9<]z׳:{?#o~7~u/}c_5x~}c oطӟrpppE~~Z7~angt<{87ʣ&_%`$cPD|uH;'(vF눟XB[l4#YɆ+I޸8ו<2NN!.d}EĎh{'tzW!P[!RЇF`k_5>nf;TeEx Wt[- )(&x[Ok׆tZ-Z,'7vk\(A-;C{ /TϧǴV-EUR, FSvYƍ8;dZK]U%.[[4f<GqGcj[|7[013wl,mwP@[e,)8{^ߤ5Wd&( αX,(˒m9u]3N(A v[W1=:-&L/SOhg9#M( aƇ8)RQ.,qD,"}pޡ#Oޡ%HVXvS+y#GJ*POtUG4NL%\DOcʒ,PJEk$1RxB&*>ۼ^ ~OH`0F;>z \xqD4ٌ;ngQF5j z/4G>w!"3gjR|+}[n~_5oۿc?3?my}wc G._K}xf ~뷰ɟɟ_e~w~;iorӿQ2I.DW+6V, 9%TcIm@nB+KiBD(!OYb{Ycːl ;Xt )y */,rC Q1s-PU-L]Pj%tւ u%RZ8jDkB&+ t PVVHފk$vS53T Z0&Rm3/l@TE.BP~+P;O6[ܰPgl:K;ӌ&MۧͧX:( (%>0zCjgɕ9r(m(\EpOeEjK=u]RU%#8:g9ֈ6CEʹz}֨knd4\2nJgpǥ}~bJ|N]3$L6TLUt;mN&p/a|O?c2ߍbv|&N,3 vwwۋ\Ted6gxMƊNw^ĝ k}\}d&KLq00zU&ZZi|'Sy 8%&d%+J %}~PFy5%_++序8>t\Jy]b׶أpljd^cw]QWeX[rlooS5VVcy4%V5բx<v Mg>}WqGw7oBOYרQF5BL;G>:'//a*<{lWUB`kk, 7pwsw}9 E/{8::?lmmq~/| 򱧣(vZ-ʲ{]wŏȏ ~PU??2?sw++o_2s~n5jVHB:MLp+!$yV+8A!EIP]O%dFKLtzpW~IIȘ@whIdMH4ժgq ffajSd&UMՃ,F F)v! x E,\&k1@JPl4ܽ įWyq4YWHELgPh΋tީSpi:klohuHpL]Bg="=P tbN21(YKЊnbr̼XsbdB7oIz'ٜnS(W]K Xt\}#NåKt[97>CEc%&ZN ^ /svΞa1_nꊃ]ֹ _[NcX`mMcƗ\~A\U,u!`ĠEh9Ӳ:.HbCĤ+Z &*HmW+SijkcR>J["'D|R8Vťjb@)W2 qR(6/q0`sQxʪ$[YaU߁5=GTeɩ-NoPLf… lnnq}rٳ?Ff9~,OXL]5jԨQF/ JBߚ˟> ]{O{{{與zw<|k_//PJ7x'3=[{gnonnrpp-{:5kkk׾{b>?OӫSnԨы@.BĮdh4>T1i. :V@Ī2b\CPZp֢TPIVw ԞU+jp( DVH MQU>Go|z戂ҁhh'S].2&t:JC`e|2y'BcmUcÈbgXgZ'{}ֲF 3~wp;b>ȕ.kY՛ۜtiѼ`Q(9T-cX%Mllle7L;ksn'i)M⪝w1zCv6p-ÓG#v/3)xeƣృh:6A,, 'BiZ򜬕2~DY,fǕ{*JqNQgS8<s 7pfcF#ZMa^Kp,9:!l v[\k.=uSLo%5{,yl%('ylSJaA^-4\kFĔx A,+4Rj{DI3Ivp3ɗJN1D(CYU=& 8WaX_`09>>fsc dYYS5CC 9:2ɘptu4,'˲gݨQF5zEg?4 ] IDATL|#/|;W[C=??`_"<V{w;Gyo}Uo;s+f o>7??-oy wu7tEQ?xiԨQ/+[6#:w &Xc᠒X PEEi LJT+tjJ'Dbi*9D&Yj pb9hJRZ9 VhdE<!^ Ti^/H1ՃI1%0˟}J b#3^DP΢jOXHۉR)|`8@mn xWʢYY;1j%~Z2?ĵڸv`4:oq,d]|A-k:[-ƘZfՂɄE]ȳNV.pirVdڠD:̋kk.^bm9ul2szh>R1O\p'm2z1~ uQwfܿw,^isdUQ0hZ!YQ@(ݶ ׆y1 `2l^ :;x6Tw:w/v9Et>Ĕ`>c7:ۧOᝧZyĻ<Ǚ[_ιn1K+4<E\Z9WT~Dκ aIyXu, {qFH-AZRUYޛJkar̬*\04Ĺ>mR+$.KBBX;_p5@BZ2>el3h Ty5]v]ˮrWJe授+V~hfx!pG,wk,a8WqӴ WOco{sg{7n0M.VPkiod^q-\zպak 5PX23~ԨQF5PNH__SOSO=>9gg6\.}-v7 t]GY|s{>(1Fnݺ)??̇?awuЇկo;oہK?g'ӿY~{8O>$~?1__8UU]lԨQ^Ԥp^I$0 Ij(9=]&~pw H$kQ2cCgމےXiL$ R؁.1pBI+hTbHI5BD2"E(2FiJ9pݰ9៌D-T]CQ>c'@ʘ -hbOq2DGR-K(,1E={ !ܸhTcQUI:<׃xBq=A f nyeI/rl3Gܨ uEQnp}erY!.Vk.ͧhIQsY-(ltՒ*,:̬Mpt}JQڂoa&3VMCYU _9:yOa 9h(l-ߜqvnzO< u.%0ܹ"&K!!%B߽|5ՆlErRS%VkW+|PϷ],h7s>tzW䘭}߳åK]J)'V %-67szy#=yoQ0֒H=!lR+CPjEisMϔ,ٝ@%Z)#\ e]I|KBiMB|R ]f1 6{ 500, s}^cwa` M`6Bzm!uM۶,OOtil}\ㅛ/Ҷnݺ6;;7'̾eQF5jk_ekM=??ɇ>o3?3<<˿̛&~~-oy g>d̻.Mv7h{{'|2#|;mTW^ի1??1byyݢ{__( O}c)???/,y5jԨW,7`I'\:S {!1 H.M%Ř Ժlӱ:3E)0&Mt.ch(Dɀ[q'$\ϹT)j@wh["b2l ǧp%g-C}&&l T2w<# C ]HQCiI!a>AG2$0i9C7xҋpJV,OH57[^K|>sK;`q\ȗn/ EaT5]gAQmoCD~:_iׯ/離 /ғO>>~~__~xFO||}/?7Guh~\2k? I9A-!~<C7!yalw 903㝌Q"V#9h ~?FTͥIcOC萔 0$F)ʌ 1!|HdH5׬2~&*MNK2Dq1 èH]ԺllKD\7 `AӒTZ]N1C\7HpP*\M^1c\q|vRGhU5, >>{&ζwk1`D"k.O؄RzخT$4c`u]EYr) : k,',9{Ua6T,E y4 S1b]ǦYghePܟ UU]l1/+:q])`k>gVUhєEׂIB<;ä^І.sߍ{_ᅛ/:R臡 ,[TUEp#lhJ)iSX蜃&]oVDӟМ-qJYB҉W"`> }c* `{Jyip){QDJhM_ `\y?b*6yrM֘ Ŧ Ἃ!bS "4_ٔ4O}<]QךGﻟ~{P7oBfawwU5jԨQ^o 3駟77~:?c?*?Op/nG>޾(Ez]>}]Vk3_WWOO]01}C(ٟzj<;ßٟSOۿ(x{^~G57 5jI"A*d<>˳YH"HL4e\P JF :s̃'s:;!_|Gr)FL~GkўR<Vk 4pӐ/u.kU6}@)bx17# M*l|#0ꥫ/B7>;Glpstrxfyb]la8>E]5"]pl MS*+ZRՆ wHL>xʺBB (;Dra^SaP[ؼ:%yɝ C\+J|h;4.(Ra bK00X˫ IuA-*RVt v< ;ezM fgSixEp-?P(tPn*Lꚝ6O<:O>[h]зFvE}Qc)QF5euY WmwfnzZk~裏}Z;w*G?NC'07c+k*"eH:O2**w$'`# )tCi~x|r2>D eM&j)b$%9BۜW|'uS"l+_{)W.x9Uy$cr&)S@UR2=8lKAAJ_ n] T3XLzJԤ%Hd 2I:'c'I{to{l\/"6v;!sZi='ªI1QL&T9i69nK{mNϖP5ՊɤE=aZNŻEQ|iZVj1Fkw9>>Dȿw>|T EYl6rߍѱNSI)٠5by@уZ4fvhx>Q}Z|ywN{%(ェ,'h(  Qb|f+p9̅!$|lS$XL糜GޓB;G2y F)$ĺmhn5Hu^tLBJԓ-jQF5jOwzM/} EF_>O<ķhoF\03Aa(dH T 3\(E a"Hs:JӆJs}(H.$1̐Aj$I.:D AINc @=x#_e̋ʘ * 2:FΡW An"I(y&E@iEHNHzBZuPhw%,HM u* 0d,,PeMm!-mBB ʂn`!d !_sDGTwܺu;wI%9?(S'm-Vo[Rmcή^BnZB6QC詬fbZU LJL Kф8]oи[f8J8\ !oZ6hmtGB[klQ#ڂ8^/Ѣ56ҬVʚ01=)ʢ`:1- 4¤ʥtMCQU}]O`^V vKsa *zE 7[Pmۣ$U%e^ow{ڶEkElNa,͆#GDŽ!)dl/2oNOQ<)C/@Is 5],`}6zc,Z#EPJr^<Ƙq/q8/ވ1kRz0QQ:!^LdēxdXqnuǘ$gyd{g`go!|(Qjچg>iGz#}Og\=Iu]Q8<|waԨQ 9DR6Ǒ`bҹa:U6%S"flǔ l4hC?9F%cx D !#'!aHYv-TLHm$gH̻C؈ S]BQ .Q@壃RޙLt)i&޺EZ$S"SyւRغE}lΠqcAD|$ir F5ztN<κ%h /RيprJZmNfr͆oA /se2GΚ)\tbٷ5vE=1$hz˶Ƭ Mἧ, 6 1%%P (Evq=+QϘ[`XeVYQ%-Ywg ƻe` )$#H M%aRD(jr(Y 3fDDaӷ4IUb('E1 A"XN 11+ф\>J4)PmK5y5ƖLv&<Ōww6|^0i הlI)BD f2 !caRr(k1Sʩ{km.JU*_CELE 8?rJHh=|O B 6kvfsy-?c{6=Wo{ B*Ke6Jj*^G5jԨQ7ݕk-J$"}}{߷{WF5jԨQRvNt梾Ȧ a΃s !EEh30R@wfz:烫AB$ 9 @CR:Or>C73Ic@PMÀ@*)r^2&,x@w[ ) 1DXB xat%aIz&6ȼFfSRסlE[B@*5i:̓u!uAyIR 19h^H$ZЩq%9etO*1uc1!ݸud2(@Ch(s64dgK*6!aI`Sq5?cV%l굢)#Ю7XR"*Ҧ#Y:(krֵ4ٌR)$*6MKYۖeJN*fi[1L ,=뚝EMz, B`sE>RM{*8| L+cd^*7{.SRye98c>unϪp舃ӟ&F軎ͅ>fԨQF5+ QF5jԨ6CJ)2 rBs=\SϦt{{|t:zRQӺLfCߵTN}{yՖf^l7(ggy=sz1~æpi 1u#p>%&raV$S,Otozy&UE \Y챻a^s<#$+Wi77rIhk5w!f)P<Ӳ`Rtg4y}T!Γ2C ň6&MgR iH!3}8 =Fkz }Q:o+_:d8$C.sڷ"IiR]{HhofD+k#\JbjIwxH:"k0><8D-]vG.9\ ѐǠX,i6+ }pLLAi +W3V+ǬY-9<:QɌ|-*vCYTedNT ʒ#bQ` Ӣ,KnӶ-D}#'8{ ޾v2ʽ7}̦3Jlͦ蹼Kaٜѵ-'ns3_`kNt ]_0+Ksu lgTxI]sϲ>9f{{b=vܦs=6ki6q#ƄV¤*I($~CbdBi-m|[:fC(PdhJJE`'3EI~2 ”Bkd4\EI`c.*J|!LPa-''L3 [/yӛ@J)׬d NUѵy(u]#sZqpY oz!n\#oxUU H"h{W}m5jԨQF}}28O+A~i~i]/IoTU˗/׮]͛|2*( vEi<__?kf[wԨQ^m%!U3 X: ؈ 儚x26zsɌX`M޿%t=(EO)2ýk`Z1 '\Jwd}GCE)lpg>촦(Jt UY$rE=gZLJm r$xfYy>Dn}@϶1 W c{RTl ?Iη٧;(dtI 7~[q%U }߂JlϧL[7$2`)Rbf+n\N- >bߣBC^q*Ph|fg6_A[jgvs<ҋe|kwT󒔠 NX lfTUM]0&NO5ɄĄ( wٗ?KN1/OUUc. mQ01 Efg#]~|wQ0.fz(};wx߾yͬ.[-L]kV\|Kׯq||BUkQF5국xC^N~f3?'ZB/"raO&W1ruo^c$ϺիWz꫸WQF$ +e(%O*>āMƖlp,>/ԃ=VI\|#Q%B̅."Ћ>"Z|ʥbL.<7b"1 !bNkIڐBƞdR*BAXEFĀ>LrihEI!!"!| t- * f?B:k]>dcl "))h{ Rt<[e#k4 uUA I I>'9NH!%Xw,2]@NWē3Ai̪d|(T=!U( M6`8 ]|"lZ$F#V:b:E!43b?ċXC d6Cb7NI6Z )l.||$.^ $bעR̘" ROӚ6Ae-lJ%ϞR儛5J+>gPFy&< ls{ԺnjQBQu.+GiP>ɔ]:$| xz\tǧ4zt{=[ ޣܻJi8:z"=V yj+VdD -jʠο'(=%se7錏I Q !aRh]ֆZihS$ ]X=ӝ)7"Ca|.El{ye ]г񞳦%J;Y0*V]-*('Sq:Dkꪢ2%J4w6`L$*CXVA3yGH6u̦S-ڎ;:!8n1++hh6͆YaWptrºpxpH uX[S.v&[1` ˬr|f÷=-'G<'8ĒX68}&[mRU2g(laNk4Ь,#h#={l[P?4'4! r; \sc-1FDfXqWA)WhɸM(QwkZ'Ekl6#I)9<0'rQn(5$pgX  %Dv9]H>$aEDtN*!sUIHL a0ٵ""Q:  M=BJֆ $$5eIF0s1M6UBꚔ.6TU7fb4n hޠ@QDC>#d 5d ⬀J_ LHMΫfm ԕK 1x3RDDф밢@,1 Th]a(ˊMc͞,ˮSUuWύF RQe1?Ap8v0HYH f4̼әd6.***2sYTxrޒ@64QTUMdfn|kkvHk5UsHyBIڏ41P;aα#g/5Mm9Ax❷pzt$ "//8w>{/ Ɣ1jZTxnxجl6]K3]=T񠅦X[#ET )o2PE(wVꜻJA3*d[d^=6+e.6-UBP#uVo0(8ei/ EžO"8g^LK)g.\6 rDq?)[nvÉnxqm@RE-Zhѯ?ʟ >mѢE-ZKjQ;jɽs=Z=Ao<r)h"H+ -tE ҹ,.+,,-ywNe*:%C8ú%Hl?* ffgC1s礭q!m>'j#e(.( sW(%n7ȐMI^xqa؟V3Vq8縿i*(hۖώx1xNE >cTUE$b;7 g#9 {u.'uLFޯ͹fn]\ hn&{9_Ho >J)tÉ˿iyGR(iDڶfGԒ)g^pBN> C׳Y9Mt/=GU `GY*XXӔ<;g֊jcdr“ӎ܏aZKfNDO\Wͥ*TMǑJ&Jݎ*z8QMn}bllꚫvNlh}`:`o^P7-O>sj \\}uҺnϓϞ|I mUncHP!7 77T1 |@|-A=z/~sb4MwܖLۮ9t9s<J퍧xlyw)#x4B0`ҕLiNR:Fbmȼz‰ Nq sԋ/ 3biEHiBwa{[[jwR~ծ8-(m"HVy;̔29'Ϳ6~15[?y918k7_}:VDp8ҬZ~ǣGΩE-Zh"b/ZhѢE}Q录bR }Pf39۸䌄 'RGfsUP ঄zAcvO)bfZ*`#{X1Vg<g3FaB@qfVB$8:Pҳ93F)!ulw#V ^P7n׬a7hC%ស4 IDATKP͞"&nOG BFq&nPWHVX(=>)sF{\[Í#*b5y 3J:uPyj #uL`EѓsAcӮμ3.x4xʔ\p:?:/EYZVDnZ^)՚e]!-<|ģ5OPi8tGnv;Gx&i '<%;o{zR5?~eb[7$29vL]sBN(\)Sm{f{fċ'V6̋;ܜl^QC8q<Y:^(%fN{n7s|^f&<3'jE(TůvG=7sGqPEhgsv=Y*$61 5U)>.!ir3KI_[B@q2 #)/#DYKb&\v\mO9v7ƁO5#g7@S;v\%qrN'|9endG82 /Ɓ1 Դ8rɬ5!ڹ^EC$ooRJx:w'~/!xBJokCô5tD,o+.PpX^uS[͂s\tCp_P*N3-Z 2T3>#^}bU=eߗk3)Lc%('?WnOGcd7-a"LqtuSpNRj[V5!C|ѢE-Zb/ZhѢE}A%> G3ec ?+!S)@dwB 3\Q\QJ1 sTlmbq>Ez\lА)S$ãVfB \w9}7 e s#[iYK&cRȐ'醁*^Ys'F3w;rz]`fc(H%B"v{i@5[ҿi SBT؊*ю3r&y?Tpa׌BQatBC>0Lo/ +ȉMhBSԡb{6}^Hج 笛*qb&yH*s*]t:~G4.k횛ݎO?!Vva'OtɋgHVV"HeY}`ZsJjM4JӶp@z-ÁX! NL}wp[Ai7'%?z0|.B0O猑>5yo'RWP x+G*Lt/0B*º;uV9Ed-45YpL@b0D34ĊI >[YP\v0i!@P}Ômے CӀ_P5 7& /4ɧ]oه?*WU|1zTqV4`iTJ!skis/w txy6.Ead8oha?S/50 }cekQ~WOJ#~o|+qs2V: #ʘz(L-||O?@n64 )e_ۼhѢE-\O-ZhѢE_Ps|4: AhU?H3FԛA.:n@y2TŢP11;Qfhk*4F;07 % !6q*hig}_!Σn”-uf{/`yU$AH.!1dH3xi[m^UT1&"4e$8mJ( P78?o-v,Ɖـ@-)'41L=:M%qH3ӧL&+ " .V8R`ɧd_S78WeDi#lPAJ̘kv][@7PƄ[7H *Cqd56L΅3'-i*NJ;BTuMelfp/^}dp5' |G"s;RΜ]^*J4LN;f$+C?1=} H*fMg4s֮خlj201ffZsp@|RG?~l\CFTW%-DM]4]7wP/ι{˝Pff~+'[C1r[ݿ'Ɨ%BpҦCKUx4Zo0}wz'}q$M"?я\_n֜m8;p<͋-ZhѢϵdhѢE-Z2Nad3$;nƦ"uۄR)CF8T)b)ӻPK;o#jbqs):wa$$A|@|o18PWb|p  yRJaB nG2#q$=XٓGb@ {;\2 u}Y5+B]3|>a%%8;K*0t=Þ}l@hηHQ᳧ ^x껛rSBɘM`xx M18vk~N`#f|I g5ShhE~3"ݗ!JQZ?:g_dƶ x>ODtuP_9j*vSOJ#NĆqǞvaWQ&>䗴#z;޾E3s~~x_GKuRxw=U[]=7_hѢE}A-ZhѢE_TE% KG-_&<3G)Yab]J[e 3ZTun~)3T)j8UJ"_I-^ %bktܛ_3/wf%C. 2%'Jcf3.S¥DAV Jdy?3*+ s;kCk^2\uĐ&Ajv{GYWISR5[;T3~ jw5>ʔ( J0sš6L)1 d4 "h3f@R :"}>?UڂHAq%qd7L\h=bFl!TН:P.(Eٜq<`L떳7pγOUb LGi7>/(]ohچWxq4RaUt*B4}4NXz{.r (%ɯ>Bګ]o|1eJfg[>S.W[_qQQpd\C$4xqUMΙМ]cf)36p)ߠ.X *dLgF^a; gUêiq2HS׌i…p \2{y 9nw=SQx'7]߃8VW5UPHɅUb<{\jZbUfU׶j FDS*IcF} ip>2Gp8|/[_>ty_R 0֛orNN'bx/k6 Wx10we^}s8NsaE-Zhi1-ZhѢEޒNPqv_|Prl{&cmAǭ@o :e3g:A*oA,R⌱=f9ڃfK6&[Q(D ̄/RY\@ 7uthI)C\3t\*gE ;%wЪ_gxTH Œ!+'Ȫ)_#. mDܬȹӈLzz+L8q5ܞ&EPq~rc"`Fd|uɆ/ h@q*U Z;ڮ Tp8U }o+bcҬZ^*&aKf育nZH]Wxqua< mwϥmR T===ypyA? \p1O V@{vvFVeޠ ȋӁu۲>{ vCk6uºڬy7Kn=4fA&V2M#iqEU4Cx|"\ܐRf;0M>W m4 .C}ѢE-ZkZ E-ZhѢ/,5G29 RE+(V "f3me(j`I7& IDATQ*$K@tN,GLHNi2sK;;+PLw㘋!aRxDo #9b8^/%+q߿KVމBz^JfROmjUөCd$ Z &ϡ-]OzԨ8THy;E<^2GFdL)އw9/J"sjqp<{T_6@ 9h. ]yCxAG[~w$x*η[joŦ1rbe4xdpL pSnU=l߇˛,ъPb0̃3SGUED3#4٬ l膁#$͊H݉gTgЪYl\<lc{Yna@L*mr:m[C {w<؞|OG<`SEӉbe¾FF BJZӴ5ۗib;B|4󹨒ljR ib+lu8kês̫[zJAD!RfLz(WUHE Z iʈX Vo:B T>V3jeJ;򁺪 s>iɓ \PVb놶m8?syu8 }v{FuLa]=վEچ)i|ѢE-Zb/ZhѢE}QĊ%U 089/;3ȣyyE礶.>Lf1·dsd{K|b.L}("Dz|q]psĀ r9?-׸ {dJ"DoJ"h HF{\(4"m3T- x=[x#*ƄSU3'qP nwƤ_m 3Dpú5Fع U%Ik9UI%cőgV~Kg93WՉ!BDc/sW,Ï5#rF$'ੜ׹i0\]\Ҹ?a6%U]%<F~'v~~va:v=먪UT@;ҍ#˗Hp8aVԎMwuB9eªs,n.3\й x(mCw`p8hs3KqE;C@Gi(QU:0cq eEC'..n8;۲^N.>*W mW3 _hѢE-Z4k1-ZhѢE*Z SKƏM0EdfjQGKfMk㝛s)f* y^ضJ f;z38K^sf:7'RvowEڐ3 N{_Ͳg)imlM e \L-pK}UsHq!j5AUm E'5,fd$=cS(.e`ft:ٮ_,\LPpI9ںC ub!B10C15ڶdR~(vH\aCS2h2!8 y&%rX-k9(+K9b,YN=;cZԔޛq%$,Yfvހ.F'BM=JWKR">'z"dʴ8{UgS {OOє( '4 @۵-\9<gԵ4fc>GRfRV8UVՊtʤ,yg(oP8rb ĜĘ~/"o#Zt(+0sp0]MD9 'g4ZvΐL>x ~Lu CQ3G2ҵW]*4SRNV+3Xܾs|__ꝷx3 f)cbRw;ֻ=ך+>"s^sr ןxi/M|?>G5jԨQP0?aԨQ?>QFw|0#W5AQq04 d)SLhdLE3S5{!Pj9^,8UC`φyL3}IeH K] 3)OPlJVЮ518$c_wCbp/Y2E~0<`M9$'u[X,X֌^%爥yJ&h;񾀶%u=2S[Ӫd v#- ! "H%܋`Jvnn8gP Q_@잪J;ތJPsbYqAB:In0Y)kh՚\Mi4ffEI,%=lʝش-IMo#m!f&er:9 ekP 8]9;;g]quy@Li5x6CEoĘN,Krʖjb6#kf߃zMzP@P\Y%w|m1| u-gmOUUϙ/E)I) #L R2yP"H0U@l7j‡`4y"fȗ,,20Ν99+YR"d^9+锜3Ms柿 >Ǔ=OSWMczÇY, o\'d9}|gIjnKUVۖot-QWx]8|ϻ8:91jzA3s S|ԨQFҿ CЇ0jԨQxݹs}Fe A8(.f.R>X9'q{j7lYoeC9 HK>IP.:г !P%znҘ3pd$SBUPAd ZXl t{$6ɰ7VԚѷq69[yJUs.R:9=2=_5&+>BGM 7 s]= U %cB3zQhM;PrbK! Mݷv)JKj@gjƺp#y4]mCHQzWSn̦S+q&Hd"Eih5IJ5 *]r eUw 5- p唪(imImG4l~G488?k;V ʢ"gRt)IU2j͖a2ێ9zdZ^_MtN8 &ʲ@l( }3)%7nDut]G+{" /dwQB3}ϋ΄"8ۍ2|h%GL8$ڭA)%op]\Re@HlffKPZpnx?]u0-X iZvyHXúxV8g|0 i{3U29*;siIoQ-P "/ 1 > =:97Rnbt #0) 3%=|AL NS뚓R ߷/X)^Z)x7%Q4Յ7@b2XTqzcC{c3 6H-"H2s>E]Bړ39Ec8 Ym`!æ\|hQe Ű^ԓ5T'4(mѶ7; 2ɏ4CS /8 H46 vME)}V(:`e n5dlK6>%9&~owB+q!1BQut"Pt)A9v[-BƞE=#P8OUvt$&z ǎjƱ86]C,},v8W>?gqZru4mÍnrv먽ݬش{B9sz*ł+'oݦo|-9מx <*3rtp+Wج.>7x#Țq⑔5|A{bf!Bi%9'ۡ<c>ʲ 3`[yxóSxG4&bv e٩]JJj u6|qZ޸&7x^[o329Xkӯ٬L'l6[2ХLYU]}9#>vu {^#??Pix9/Y.ƚ{j LWOݮo8zP)1|.5jԨQFh5jԨQFs̘9,U7[8ECD,Y=J_X%jȉ<fZ33]4S=+C+bI札Ӊ".Ltqv̀=#];gUIm?f)V` \ ~HV'Y" !H1K MSg8 H0c͌V!@>%D2iq[S rh ꠪` nHkp5ZY`n=<Vy|BJ G,ц0ZDÎ8\%%xrLz3RDCYp)yM2LJT{-D.(JiM/mY73g 0&a۾c6I}KA2NjoҬV!sX.YWjjiPp|pHQ"J8}*x-gmCRS϶l.6l/8X.Yy6 Lܿ|6'wpKV+{i&8bڷgxlU8O7pu^XGA;)%)u] ;5Q?t I>;.S)%R6ۃ3IAH1Ua)J*!xDW\ s"E(1c̗K֛u=%ͣF5jԨ5`ԨQF5Ꝫx}~.!8NOMbcOrxxHz(P8:9L״&S6mC ۢ``rl;y98=9 ٟ'g> !'J44gC5% ;2C"qCKTz p%\> 14 )'.R=à93UTs9> IDAT3uNP.ĮRHUi#||N!x~{F{MǟiF4[vx Gٯv2E=Q~j&UdCQF5jԨA>jԨQFNUi}4mHkop5-mm47緋MYܐNx*hlj>Z5?%4%[66G8.` Dv KQD39%$PCҬ["@/h0w; 2$K;t뮵!wvB!A")A@˂#bp,19{IPqȴF΢]㢀9G-eRq=&evw.;cZMXoxLk\ʖk)R$^Mni]1'SeY[w{.*ׯn^{|B( D<7^d2#5-fK N\/>^|=eooLj*RO ~U>X a35gY,3*.bk}8uZ;Pvϡ6,6ce2qq~_RW:y wAqCܸB"޸}~sc>Zpα{Oy5EJa8*]˼6 mדRd~?G5jԨQ`QF5j;U1 f K/;#J%4_A07)%qUO%.jK$ Uͬ Vp(+HĶ5X3],XYͼA@σtb}N+d2#w 3ʒ1]k8A.MASKf`5)gIu#g ZV YY-.-r" &"٣AsSҤqf眑E w%cLx)!Ӊw6GҸpaz6õ;r0TNV\I)R51fTEɶ2J)Ou -<,p9)D.g4%|gP=yg1wjW⌳gi{dl2tMKmw='<8{y߇>L3t}o1&}/ yy= mJ,sn<Anٜ]tFn;-HU<|0Nx3ϱi<L'S׼_DASs0?ޑb  ӹ IHx5kE3x/ĜĜh|h2d%gaRJˡ9% EQAU»89>D5k QٜN'5ڶ'Ŏ8=9!buq{_x7*Yp~~FUt]t:%Egk{m˴}KU6DTeP%EYu5|5jԨQޙ QF5jԨw, K)rH ސ(DP0ᒝH#*0p_dR#7%$ a(Ct&oof9)mѶzKk6IHYpoPW܁qS4\MCa{$bÁ#5;pd瑾C$K 0fZ Z;CփoR㺈8+yc) F9NA$T`4aԉvC)bvZzp "=mWJ$+ESXN'(ʮw6Txo3}<63)j͞IYQ%0@7'Cxɯ&~k \]0wm8RUvx+p22s ڒ}Do͠%0e@B G vb3)x$LmjəSLkt!=̺1qχ{qs%%g6l.qv{5fGZq޳\. =ْl.K<|(^Ϋ늫#ڶ"p i0gtgȱxyb>x~|IU=_q<( .ޡL=~Z! bh%'L#9sʈpxo)uâ8T#<ͨ=1z$"]V y+J{s8цo1|i;s(#ܽXs[\;>'~#8iI1r.KVno}EUr~+xug:>$d:'x1ؓL&S`4:Pg+\>ʲzA&:2G5jԨQok4G5jԨQީ%Cld'%0+Rq`,t)} J /* g0 ~0гs`>ٓ/9#HflI`XhD1N%uI΂OY/bF44)lhYZB1* t4%K;!JOɗ6>ZzwHѫh#ZhQ׌V7OcETT-Y/ޓ y(_-D?whi#]DJOVgx"d281sT5fnG5x%UUaCaƺɂ렏 <_C\8\P^DvߐN[Z(67Hs,3,bvzcKU.L'dU޼R o rčWi~O[pq N~%hMlFu(r4=NCw|łGt]K{R#xLo 琜)NQí䔭a՜ Ƀw 0>( yT$σ-VJg9[h8"߅RK!yٮ+n<8_&oȇ~ oS#l2!̫7yGӴE})#_A( )%^|Mˤp'Wc95&%8ҀѡйuМ黎dv#} 5jԨQF4F>1|$FAKROz@!fee9e9} It``[9)b&H ryC37 FRI1\GCI¾?R1jÏ dGʎqFpNޛf$[V`:юS%Ecܣ Qt ]A(l! 4 N{"RxK΋ڴv1[;MW 䄨!u덻lHU%v(BR+fspZH]^3'þa.y'H 8I mmdB.+d?Rx $, &eEjNztw~:a{ Çl.(g UQqx$mMg*E(eY!E H=~%=T,s-}78L~hÇh{+U(2E }49\.y{ǽ7nA"I)sppb:7=jevf#9͚=~؉ {eʃ2[LDɚÀ{( Ka혉)^2z{?s?٬P( am^z;n=;J3}IC=#aQ>`rG I)ប,2tpO~HLabw#)m4W5펟'w]si^|wr唛WO~cU :ab#ꚪ7Z3L׾sO=SO_'I999舺!(+Ʉc1i_s%UY}>G5jԨQ|'>oosӟ4/2ՊrIJ⥗^O}SrMɟW_9ǯʯ^?Sr^9g>K/qU~bzoO= l6ҨQF5 !n ŒMbao45jFm%{43b#`{RRęٌ^ *BNCAjGr|Gl¾C55kpy(p'?gK(,Ⱦ!uv NܶP 1sٲe^Ϩm PrQOg, c7/}4MG:5C887 6t5e 5 ՚rA |ĘLgL'[˾g2$8$v ݀=2əbxp>ɔB<펣S޺w'Ǽ͗r[ێ"})#-3(Hٿ3h6f9ΐ-eUx)#KʉB]ꌫ$#ɊGΆ8rX]q-z2W^eٰ<8ʵk5}?~o;?}KG?{y>v(e@w>sW~/~K/q7~xg9{p|Nx @#,)ʊŚ61'uM۴w EQBIwLsl"MP5jԨQF 3g/svvƇ?a%oo/gy۷oo&>9^{5>KKo7o|3*|/}K<Ӽɟ ̝;w ~=~?3/֨QKf#S}Ԩ>9qCN-ޝGYV9wi&AAH8%Bhhz8$&1DcƇDCbHDd$"$hC" @wWt=cD(jr[:V||`co&l*2M2ظZX7)FXZRթ:更M9Mx!2ڍl5.& 0M5k16ФRgTx ĮKACxb5JN#Sdm~l. amQnnR-v]6EXE| Aax%F)G>y:MHrc:^/)MDC`ƩjHn7[L^K{V ~k 4O3X"|L 4PH2Ď~XWQ^@9aʊ2!+۶ҙJ#jh!b& eUQhBn>D+Cy1E=4M4uDGeLLLଥio aeqe !r۲x UIǥn=&'b|~c0su4UCmklD:.45^Mg # IDATۻkl:6=(#!G]ASԧغu+_W_;;\~ o0/}KTK8cwn6g\qu[{/;vS?S5k~;'~>1x^_zGUUE%92""MDI9!\lbnq/LqleǪN_#lֆZK9Dceo`835S&cay #_a]t16u\vut:W%@k,?s!xc#ౙu34E+ rLsCov3 ҏ6߼'{ Ab` 9&'&t:z=2by+嘁)T"dR6Manu;7D|RشabϪ{}VnӤLc\2ֺC֥-Ѧ 2Ū6"'a^i/ Vc6zzyS801`,sYG]<~ԾT߸s֮;OR1390?`0IʄD_g.:yeu<WpuqQ"""r<''ٵk]t??G>nFp9`]8ln m3L{,;t:WooKn w=3 N=T.R:WU*ȷuv#]Dbj7,u6Lj1>EEgMU>(Bj"#fE:i nR7IƦnDh"5x5ŀM2TCbaBT5San-'PiPf P>t/0.'5Snr >ś!ԩ8j#cbE&Qb7&ũ4&semC:C]aG#LH]9lbqPS| .IJیT>mt4t&IQ:ۡ66Je>okmcHw1G` L bl;yi`Xb};ط8@eibsdiIX՘afҝY ed ^MS^=7(r0-Qt:Dvrl{q z~)X^^ &DS(r<)}~~ot{(#j>6l⎅;WtDYU G#fff803KlJ$@f6?mt4MރbII!D,9G4X"5EAB g0"4!sާWæ!fVy`x%E** RN,XlJ#.˱20)7@`ڜvxud.i<#3 q~C3gE`{͛.gߝw4 Si}`0ȱְ2ti|Cۡu """rԧ98WG?Qj;ؿ?!w+OLLg8C7|%zֳuַxnꫯkK. ox϶ms """ oƵ%}1١yr}*T̥cDMB quۙsWR~qm94m"hXh"):ڂ5X ѯFD&ocG2j򵍃Rκ1.}c;Xԥ |HƘ^&p1eBSBv@ʡZ2덵!snx4>bu %45.wĪ5mdOn8ҹmtM>[ Ɛ_8u$8kJ0>LLMۙSaoaAb@Jb.X3G,:aSU CĖ,1E23!-bo  ȋ4P:%EuĪY}Cl1E2FG U(:4eb!q ZbLg@19ESƓEC9.ٿ/YEf q3xb,//[n"ēc27MXس f8"VMա!Y]&ִwA_ uZc0biKVcHQ.1kY˱Bz[8YڬCkݐeڍ,G!s9tU"e:Efٺ( k]Lh`54Xc Y^YfqqAF1ш~@ߧ YX8HU5t:dE8%feرLU*hO~{~N;9.">Orǯ}8g}6Z.RnzGrꩧr 7׼5l߾ێ=/x/zы"""hPu);hY2Z!F-趎r a!:K͡ g DgSZZOC0Ra7@љwrMBHc\*Z ΦNl>3wSlRgn1U , EmT]*Y> u~ԭ,q ф6"Wc\bBM4)SAY}y|E0MC 83xƘ:m'")<1.S'xܶ>Yҹ>ei ph%bqb$B)Qfk3y+2Mߏi"Bz]6nYq`-鮃:c0Z|>`zd1ƑuqJ :NFa N*3t:C:E2(:&&ɋ1nC tc;̦IYx\,󌲬ػw/X uY1i x̖-[rwh4bQwdyNqvew,sTM2NTq&9l^ιԵo 6 .(2G,}n "bc3`,vkSGk7׊֤("/ȼMt} w7#tWicRIsut:reny3O0Ȳ ?.Xkt ֎ɲ205PLO+CvxlZ,"""QXP׾׾5s<1yғ[V"s~G~Wرێs)++1OOp5׬}~-o]zozӛ=K_ҷ/|!;vK/~__SNyNьm;xm2c" ա6mHE`I0<ì$@UN dML;oԬFRQ׬vqaLNmJnۤTज़19mv4L6&'T5&x,VnuE*uiZP/crvħu=GE`Rp_ݐH.Sq@C7Sge Qz1mz^͘O3i#w4imiYvum|\oیuY6=| bn&N[doRG>FC0y`=f"Z|6Dl^y zRFKSCcn=\px3]Nug xL^Ŷ~f߇1M6Qd9{hŸXKfSxUWvq<ڸO`nDHw<;t7K!2W:YӵcҦO {.1~&pβr=Q"MH}cla}dYӟ |ضm[u12i% e5wQd9 oح[9-|8j{yR[sd9𤪪!.Z`zz>t }e8p~O۽e"sssXk""]vqr#dzzp/AKMR\IGgb%}H.Ş\/&CECn!3Θ@!ug9. &kB0! !%eGc0&uR ZDc| Bbvh*(FdKڵELIM} !Imc }a`e%uؼH|9$4%l;1I - ϧά@n֦Ʀ"P9aܹڵM/cRzz$9̥Mh e@ p6HY_SN&o7uجb_\`rfL7ƧUcR\GcRB 6= Yd&Vkd.ufL'm!tR^ !'Z1ǐc0ѧ16u R749B`|C0&6n* WU۝߮;T)3<֮c4ĺNm1MA0}v%&h 8^ CY͏8@Pb4 D<0UL,~{WC! M yvMG0zw ӵ4Qrz~~NSS,.,4 oq]2.K$g wE ::.s371S  f1[QF#zyzeC,U%SSSԍmSMN{Mݰ@ebO]W uCPps:&&Y 8OD`׮gx`/hD"y11*.O-e+g;omf|2k1.Xsh]6۟WH_& .'Hk<5.1sZƒe~tbs6㬡nMn{lpYN:ؼ;ge Ƞ'I 2j#! @^ڵin훔eIel=f^'jj|hppi"""rdRA]DDDW2LfR,Ct)f4ڦcS5DvY3f_$ϰVOjgYƧm֓ ;g)i#Zr u ȽS7XBB:F A?ɀW`iYΛIN!1fI}X˜4:uHȈz<Ǔ6& 4Ӻu]ƤNx)D Mbʤ. S ksy3m8B/!`BΙ50\uCEu6ʚgG"`LƘ@$.2gGM%vC= CRwm;:&6-g-YK?j>mA.pY;G!"x V e׵<."""r9biȨoh׊R1e#% &er7ɱm:Ƙ!l5@S!C^7|iA:$p"Oqc1bL*,{6#N0Alnl.16 cmKQ24ݶYkb:w}e¨Lg\c ҹjO|,d)%M*V۔UML5[Rݻ<ˉ1b$v8`Et:#ﵜW|y~Bu#USNd:M 6OVc9,#U6_GR1,bYlhj0jw1KYmG5T^} ˘Nc9){,6FBUa*c\x!<3L0Ħ$4,1Eb h= ;=`{qugqY01H)?CF lPĪ=ַ=v(ju7ky1 RN3 jm>Ú8\JJw^tg#G Wķ16n# unׁcYP+rku̱PKƣ!K1-IGXMw Z\m7%p¾}sx|; " `iq` 'lgڳ YAf-LLL سw98ʪf0HySt:x,xO96oLxz4@Fw%d++ik_."""r_p/AD: 8r? |C^Ȇ\Ոu{spyw-"""!C]DDDDDDDDDDdTPYEDDDDDDDDDDQ{ ""G>{ """"""""ڣ

E]āxͅ^亾ptNjI],?kkt:ڵ8OoCFٸ^zV""""""""vcg#ncd8ru}>G .`ee;~`'>GbY""""""""zp/ڡ1^׭^QUZyѽ]#y\ve\xᅜ/o|#g ၇>W1yܷC=}4%\K^ nV൯}Cu+93ꪫx_mٱc_|1fffرcǺ _u?>ޮ.E/zCzܛnvm{կ{ώ;x_̯s't9k_Z1,,,pAN>dg=TKOk믿nݻws<377@UU൯}-׾;93 v#9y^Fk߷oԧ0x(9??g>vɩ#wF|s9;ve/F\z{^1E->l߾Wݻ / /p17|3o>1vܹܹ/~?9җoSN9%/y ?я7~lݺ^ǟٟs?sw`={<| _m>Orsq}Wֺ/|~뱮Z==]b<pyQU|;yxpyqW2?>>׵/""""""""-7ܗ}kkE}C ??u6mZ;#_:_~9Y/|nNõ^˙gIu{nwǽOFrZA^Ӟ4|+_a4=b G{i5>@_/шֲHd+??1""""""""q<5z~8}_3 sss|3n/3<믿Y^^[oy{;11g[ֻ}뭽{N;I:7񶷽__eΝ-oyXG{+ s/'<#֭[yG>{N;AE/zCs~cv]zH}7,9쳹 yOe*_~9nwc""""""""1uo#y[ 8y0j~~կ=~ΝFO#ȷ}|vv}sw9'> 癙[c~c ~s{طoy~#wѣQPx?A_|3|ZiFn 2wGeA}e~Ep%lmu꽹k]m޼Z܋H9yK_R^җ>, ^pܟý /[YopԵE ~op 7<ܧID6uYJDDDDDDDDG]ze?ֳY~~~؏þ&w%u‚Ƌ|Yz1o&HDDDDDDDDDD+hqc7ڐTvGEA1iaY+j^֚ASUιst*89eIQ#ǃ""""""""rTW=q"眣r1Ǭ==Xv_OUU2EQ077DZK@}0z0WDDDDDDDD]u8=5'{<{IƘz_wW|;?X' !uVn0JJ*j`0ukYǒEDDDDDDDDD :*ƿlbj,=$w#."""""""""r$;j ppcpGzm%f`lE07ݾnȠYߞ}[~%مOsDP_}ܜKΦﺗ\+ҿS7\x/tKG?q>헏߮oGzugڻB(G1n_k*kkVghex. m4Dz+ԣ1/~(=#_Jg;xF~uzLCz{Ots4 JvVhlz^JylP_t5ulKOj~%z}zM F^djKh(ߏ^X:zڝogGJ<% e_;X&Wg5q}4cڹcȑ/1/c)V*x}~ۮboW"5?Dems]v,K{z/g9l.3ԫȗzA_x~zjoG饬mGU2Q}8uY}m㈠>QD׆K}`ύV67[oqgYv; F`V=:>*CczgW^K;וov/1/egǿDA}KgW$ǃ4eZu:?WW]ڕle?:pGFQ\Kn_{tpψmGa_>F[/s^_8ٌFTz)>;(}?7IDAThDL=h}.umLGĔG6_JңqgˎBgir}o66_J_NWWc^xlWA=:G~ ~gٳztQ}Gsͼt8LZ>&z9gA}/>űuڱ-x_mϷfgQ؎wnvM^|0U7G״ە~Z?w=If(pG_u.b~ߏ{ޫ{ΜQA=:??Q}vm&*F?? c޿ץ&ڎ{ ׿f,ώG}-IgQ|]3.=w#zt^!vDzg8gWq/;}uO;~6Q|^# mҫ/s[GW_3|瑯g8Sw3|/?7BMIENDB`Akira-0.0.16/build-aux/000077500000000000000000000000001410625726100145235ustar00rootroot00000000000000Akira-0.0.16/build-aux/flatpak/000077500000000000000000000000001410625726100161455ustar00rootroot00000000000000Akira-0.0.16/build-aux/flatpak/com.github.akiraux.akira.json000066400000000000000000000054521410625726100236360ustar00rootroot00000000000000{ "app-id": "com.github.akiraux.akiraDevel", "runtime": "org.gnome.Platform", "runtime-version": "40", "sdk": "org.gnome.Sdk", "base": "io.elementary.BaseApp", "base-version": "juno-20.08", "command": "com.github.akiraux.akiraDevel", "cleanup": [ "/include", "/lib/pkgconfig", "/lib/debug", "/share/vala", "/man", "*.a", "*.la" ], "finish-args": [ "--share=ipc", "--socket=fallback-x11", "--socket=wayland", "--talk-name=org.gtk.vfs.*", "--filesystem=xdg-run/gvfs", "--filesystem=xdg-run/gvfsd" ], "modules": [{ "name": "goocanvas", "config-opts": ["--enable-python=no"], "build-options": { "make-install-args": [ "girdir=/app/share/gir-1.0", "typelibdir=/app/lib/girepository-1.0" ] }, "sources": [{ "type": "git", "url": "https://gitlab.gnome.org/GNOME/goocanvas", "branch": "goocanvas-3.0" }] }, { "name": "elementary-stylesheet", "buildsystem": "meson", "sources": [{ "type": "git", "url": "https://github.com/elementary/stylesheet.git", "commit": "3047efbfabe723e0b0f2b8ee3d53bed528be4b14" }], "modules": [{ "name": "sassc", "cleanup": [ "*" ], "sources": [{ "type": "git", "url": "https://github.com/sass/sassc.git", "tag": "3.6.1" }, { "type": "script", "dest-filename": "autogen.sh", "commands": [ "autoreconf -si" ] } ], "modules": [{ "name": "libsass", "cleanup": [ "*" ], "sources": [{ "type": "git", "url": "https://github.com/sass/libsass.git", "tag": "3.6.4" }, { "type": "script", "dest-filename": "autogen.sh", "commands": [ "autoreconf -si" ] } ] }] }] }, { "name": "elementary-icons", "buildsystem": "meson", "sources": [{ "type": "git", "url": "https://github.com/elementary/icons.git", "commit": "9e7ace3d6c1d1e3b5ea64012a371e46039bf044a" }], "modules": [{ "name": "xcursorgen", "cleanup": [ "*" ], "sources": [{ "type": "git", "url": "https://gitlab.freedesktop.org/xorg/app/xcursorgen.git", "tag": "xcursorgen-1.0.7" }] }] }, { "name": "akira", "buildsystem": "meson", "config-opts": [ "-Dprofile=development" ], "sources": [{ "type": "dir", "path": "../../" }] } ] } Akira-0.0.16/build-aux/meson/000077500000000000000000000000001410625726100156445ustar00rootroot00000000000000Akira-0.0.16/build-aux/meson/post_install.py000077500000000000000000000012571410625726100207410ustar00rootroot00000000000000#!/usr/bin/env python3 import os import subprocess install_prefix = os.environ['MESON_INSTALL_PREFIX'] schemadir = os.path.join(install_prefix, 'share/glib-2.0/schemas') if not os.environ.get('DESTDIR'): print('Compiling gsettings schemas...') subprocess.call(['glib-compile-schemas', schemadir]) print('Updating icon cache...') icon_cache_dir = os.path.join(install_prefix, 'share/icons/hicolor') subprocess.call(['gtk-update-icon-cache', '-qtf', icon_cache_dir]) print('Updating desktop database...') desktop_database_dir = os.path.join(install_prefix, 'share/applications') subprocess.call(['update-desktop-database', '-q', desktop_database_dir]) Akira-0.0.16/com.github.akiraux.akira.yml000066400000000000000000000014001410625726100201370ustar00rootroot00000000000000app-id: com.github.akiraux.akira runtime: io.elementary.Platform runtime-version: '6' sdk: io.elementary.Sdk command: com.github.akiraux.akira finish-args: - '--share=ipc' - '--socket=fallback-x11' - '--socket=wayland' # needed for perfers-color-scheme - '--system-talk-name=org.freedesktop.Accounts' - '--filesystem=home' - '--device=dri' modules: - name: goocanvas config-opts: - '--enable-python=no' build-options: make-install-args: - 'girdir=/app/share/gir-1.0' - 'typelibdir=/app/lib/girepository-1.0' sources: - type: git url: https://gitlab.gnome.org/GNOME/goocanvas branch: 'goocanvas-3.0' - name: akira buildsystem: meson sources: - type: dir path: . Akira-0.0.16/data/000077500000000000000000000000001410625726100135425ustar00rootroot00000000000000Akira-0.0.16/data/assets.gresource.xml000066400000000000000000000042511410625726100175650ustar00rootroot00000000000000 css/variables.css css/colors.css css/layout.css css/artboard.css css/layer.css css/headerbar.css css/option-panel.css css/dialogs.css assets/akira-banner.jpg css/stylesheet.css icons/hicolor/document-layout.svg icons/symbolic/document-layout-symbolic.svg icons/symbolic/layer-visible-symbolic.svg icons/symbolic/layer-hidden-symbolic.svg icons/symbolic/input-hash-symbolic.svg icons/symbolic/input-percentage-symbolic.svg icons/symbolic/input-pixel-symbolic.svg icons/symbolic/input-degrees-symbolic.svg icons/symbolic/shape-image-symbolic.svg icons/symbolic/shape-pencil-symbolic.svg icons/symbolic/shape-rectangle-symbolic.svg icons/symbolic/shape-triangle-symbolic.svg icons/symbolic/shape-circle-symbolic.svg icons/symbolic/shape-text-symbolic.svg Akira-0.0.16/data/assets/000077500000000000000000000000001410625726100150445ustar00rootroot00000000000000Akira-0.0.16/data/assets/akira-banner.jpg000066400000000000000000001714601410625726100201110ustar00rootroot00000000000000JFIF``C     C      d@dH @ `DA C 2D2c"H cd`Y$@ `2TH0 dȌ $@LQd! P P`,2dDFTH! &@2ebPb?n-:Yq B*),c B! U`2Bb 0$1 ($HP |vb,?cTK ^!7>=83y PC$D`0*FDD`$D2@ $T@C+"Q eR$`0=-r8\ÓԧsO)};6133[k"ekasRNVldHk=g(Uc!ÿ?5pͲmcOσLB:Ô`LeaLT&S@`T$;t퇩>ys}gXb*|]7<.z':L_ L] DB;gt,ws泳hV]dGn0:8si ]86's#LP",Q(serDPL@U$D0$#cӬ]E/;6-MG6]S"8ω˵ ׆X1ywl[]7׹k0"_#KhUoD/c}׾5?Nv5!@Y(}>|v;BmpEB -b`D " dH+z?{G_x:"`72ҷju;Yk:a_K>kl-R+Żj@Mk[;sc`L`l*E硑nϿS61;P L,q-efxF 2S(H LDc&H`2_>#w{zO]7?\0c7mcsWLn ku\l[9{:X/W%槶hW D;{prk9YtF1`+DL  H `0"d )H b&S ~}t+No.OL6EiQ;CNOL}}eV,VG֯o\Yur[ug\*d\!S`H @ DH@!"Ǝ<ڼSvYR1;os>ch|&qNҋio,[^=Ie|S?{}f{@ 9T1c) `LDeB 2D &!/.׋Ƕmu{ι!yuiTnuJN{7λm451y5ſ7n8F3-+ ޓVDb7|51z5QKq0YTՅ3hNL Vl3PҦ/^iMbGצ<&6MkcxsT ~13Zi#55X217؈ʢ%:'c*[:3s/><)TL'wߟ6ЙwOn:|kK͆NYO1M-'pK:j#_O CR9 j05 A2" Du Ax G\re/+FO߹uǗt$^̹J#3wVvQlR*@HFH\u}/_$DHb\dID ȔU"LS"HW$ $"$I @U)Ȁ-|uնd!g2XN oZY 8kC-W~Eྗb`|CB@"2#$#$2Ȉ!bC"2eq 2@D]_OkBq~sar:Kvu|>o~𮿒c׸hvwn>C c dP D`"%C$2 *2gb_z2^|/pZnjƢ}3QŒ'_>cn Wtsk/ Y P >CD! d D@`Hq|2_L^~.s~LxvlyNp]H@HA1/E쾗^|/[-bǢލJ>BC\ 22^̀ /0 &0{] \ᐗdE |/B]I k)/:!=1㚲ź}1@16 1!"027856@#3PC`p-o}^9wZj9>V]<̿PBmPGFJ]&+j5lyM^=שZ!@Co]y=>}P-oD`@@aZ)kf5}]c-۹tUU[kCխ};H}W0n5;}Pzyڡ6=@:?e*U+F"V@ۤMhpy>)͙ܲƛinvͥ,KR  k5xc⽌(0;h+ڽ1 B~ @j{znj#M4 T;,-1?$Kjhem]AJkZe uPg#G/PH>T>){7at?$)@.`>)L0W/$5_%ٷ!I!9cbWenJ+ލo`#`:سuM"GUz͵ȵJҖ͛Y5sm~VS%RM JSW֯P/g!sȮkcy_>5{C5s/ CB:-#IАf>.FN9dhY)tMi|/K~V-&޶~Ž}T?Xj%̨-$xAe]$7ˇhe/QG6~'jU0 ٛy`N*V!׊JXB05jMJc+X ~{嶅-XuG|_M$m ՚PlltecWo^e7Huh\׊ .(&."w7JULg鰺m:#qg侭Ջ\G ocZ"oTZ{@t'~}"PM-\١*C@ܤjWnwj}+ |C Կtcˆê\1WrF/|N*?nˌ'nq?Wc_yKqmG^s;"L9ѼU5Zjvpz5oqPN@:IoQe1Є}/Em6ڸi|$oיik2>B6YKDi/^~(,o@4Wڰ J\q{Q\&U3k$~Kq-kOř> Ed_'\p~qS`Әp詄(t!\35M,3W_t7 .܏<.e@b{> =??>+[Lb?ͭDɲڐ3EEɓl/m|~)RԷdhW. gXSlRҰWfBR^ڔy yꄠ5XNmG:h&v+WdL\Q2&zc|6K/V!ye)8S3˜}6fȶNuu8XgBa(iܙ uV{G ݹzхs/>h#F> =F?4!`c1X/Gui=¸^̽rFҒ& 2;)?n$Gi]*l(ԽBoD/^94<98[#a#3e`]QؤCZt! QY}M+otPꇴPOI[lf:|\Q *@5)# Y}k[|?N4% sLٽSR,4ޙA͚Ѯ^a)Ֆn]߄'ä+6ORrPaV^hIC:w^h7@FB4c <~y+V߸͏_H4v́j=W@mf"Ć$km=;zU;;T-˒z\rFQddQK6ԕ^XOdYRe.6\T]#icfU^[v^zuQMC[Dy_(|/ lܓ* ϥF=4ruD/ӄSӃט_n$njghy[, FNˤߵbAy[%Ҧ߇WW_%|u#eM)&ׂ1~iÚ/ ?e=·^hI2o}/>ykp1%#E?yMuMo9QiYInt-9uY~H,VSZm%= `KvTՐ1D'ySGb>o}>Q@es<1*iiaaiq͸tTzHBLI4$hȏf{)T=ǰ$zlq]ږO}wlM *b.ZUP*p)QװQu,'d?lJ>=@!دwk7Շ1jğ4Y%rl'eyXy-)iD^pE_$Ym@ *fҜ+(dt2+2E&0X<Ėc#| BLa&f`kizqbt[%9: wzD){Y<>x1 }k/IwQu7Knpefxq`tVai0NLf6VZ#͒іk'5ZSڰA5b nI!z"SvVbo+4Hmc[I~|ų){w)v&0W[n=(@PC54&D{ɪ glv&8'Vxh%b`cdlbv"hjD>UY{Nj,BU~믥pM(y jL#.񛸭)8p8ʔ [ꢘj١?O~B;nklla얢`,=V8`x5")* 0>T c$k@,RvB3|qsÖ.f}d؉ő1[= -鯦h+EA5P%g |16x[Z4Bn`F6. ƨ<l6Hir ,GH&^?wݽֻRd`%ÎB xbY.T4`F6[[+7>3I{=Ѡ;7LOޙN+Nr5{YLA,4#gԫ;B8>EKh}Ym VjלH?\dtudե y/K] !iW k8eC ^ oDHO=>xhIR_Ui@5f,VJJ89޼i!U-').MNmE X?cW+!e%>,Zm`D:Vh?'%>wA8G )RՁVmGG+4p>ހ#ze#㞟Z+vB5oғW':{6 tS N-hh֦֐0Z)}BƤ֦ IG)޳tN 6+ii%΢9BƃFK?F[=f5Sn KRDd GNn:+}>5whVm[dV/r~`RekxT*eHP/VիVRvCakiDn.tQUl %h4R@i+YySQ:9tz'9'KlcMBO:%]݅(#[_pd|flm |z_kem.K$u5!.MtJ5Jf4ZTt8xl -[;޷eAwutLXTHOVS :{8kjmW[)}ݸ (i4υ8˭-$~g6,5wJ{ofOʮu)p2D77V*0Nt;c_ 8զW"2]IIﭞ٠e97k]֬w ~wM,Ha:jD"u7UP%ڃ8U00[뒿Hh;?uDvNXd"Ir:>ȓnyj;q[.;(ydŷ % $U<@6|;s]$*+& Oo?gg’s &[5BSLԍS)Bp~X-2G]W]r)*zQfJ7򨖻m(vmn94!f=MHP5pزDVaMĆNt4'T=; 8FWJ٨-|h]yrw{^ʺm.3ٵطV7ʀ]NZۣJʻinn~]cQ·h8} 'qA[)\՗{?:k34q1w?$tuGօ_*tWw˫gV BΠ⇧W X矅Ors-qlސr|sRUec96 ȫXuG}m0L}]Ž@|Q6\mI}['ޯmA gL7 q* M\ft^짢O { TTyF_&>ZZ҄𭡾*FÿeoJ_AEc[M_[. w|5#VOwCLn({M1#*snJh$):VƼī5mʎ#4c_#^t v8Zݎ›u/Jؘ=r|-ƌzo5S H5e&4$'K;mqr_k\u4O*cKwH."rRulԶ:Joy{P %8iťdӋVi[W(}AXrKq5x61,}=N٫a4$<:N\)aNu. I5k~2JO^,ou`5:r~X79eiqS['0]oS[JʓHaOP`Io=*40[(dR +8&OLp8y֮rj²Gj{ksUPBz6Z>=fS~Niy:bۤmjdd9$7ו- mE*5nCE^$'d($q5my6]Aw?:ժՓ[£ 汏,Mѫ$^+m՗NRh:ڕi*C:ܼ*>y羿dLt(E^/11ߦxS8IN<l]X>bt? cPԠRphQ ,lQKn-2d0?)%FV &$P("qW G+R$)Hu)W/ G?}E k]<9phQUT#Ip/qÍָSҰ:ymVu=:Z귔r}WJo'A>U؎ Tl崒jdצ/e)=]V)z\NXV DFz(;NrGyڟ&Oyo7QK5"Xf>dNĎ aaD4 [w,OϬ1_TY(y?sS$*ZQV\dϰkWb{$K%䶓uҭlX,LV1O8xXGzDs5i) K  !1AQ"aq#2`BRbr03$%@PS 4Tp?ȹ!"&!%ՋhiFf@17Df{q®6e"]87voW*R0sepwNqDKuMN՗]mlb^XYCzhJ )$[P rWpUjBR=(is4W.A$u\$Ć%ViĔs҈}(_wj]F*:JrItW4`ZA u"΂MNV0*zj/o- t覭֦mV j:RaA?#0?!&hW,?b T<;A~Z{;tg\aڴĺ+| JJT"ZUA݄zNKۄQN0f}{a-B4>Qt:Dz1&.l5.哿+_CuPs^_gm%dĒhWj_xr^sZ1VzSǵn^&Hmcf0 [ꊒp?Pz;JFC^Q.'aYa-Bh~.w+T%X欎l.eI&Y;e7>p,ثd{O̫n}9Di;f0ےoîhTNY6JY'9U2!;6ԄKO.eI'3șkPA#6s ,=3zm`^&T2ڝt6NQ.a7"TFMQ74ia)EL>ٵ\B[]-Ju(> "E\ B( BJFzǕO)To$UyI #}*Gi&<UyyȬc!K/w;ٲ*&Ҧ0Q\aGَS]~9tc(te2h!CuMfUKZT#>T礔.mXGv@g6@<uutOq?ǚDVUy(Mf#C?wgE=B@*l,)k/>GrsY qQ9{;" k 5\yIM$.!*BѤU0Mm򉲛K}uM֝)t Fzف:]9,v ?z"TCX r)89C&9#3)ӭd0󼜪e=Cx&M0<,*Ϛ*kPYb|EUB?-"}J[W1˫,Ox\FwD>zPzƑN9w ;P4 };?h|O:vA8u=;JbLg;Ӧ֓rv~ȒMN&er-uCS"%%ZNztЕ;to#N).M|]4xZnJZ{7~*:dS,|ҧ:"E8.4m((^WO#Ig''wʊjtYϬorgSgQ y@TXjbMisM}FV 6Z"EJDŽOSfh<֖׺0 QG;U~3jwПE#duJMYuȸBmoEǓ©k 3 A"# WWX!#^94լk?Wk;R0,eX~ٟHYIi&C, %#p-q+1yM; '=\=PUE%Ԕ8}֪2M̷?]_e7)<7ĝ~>vZx_1TOVx:nZ( evWum˛wF27#$e|؞=(èT sOeL:2H%1"g $|Ѿ' NX\,>/ݻ)E/a XENfnxt_43ʑ[;?1-3Jۯ(iMP=FԚ~mVN)JN7vgQp2ߘMսG_ۨS r3hT9C*n{}DzI6q MKM#m*]FJwW%0v璂oG_nq훆aO0 eRm(,sHᵸ$Z5#ep׏ ĝa5)!b&gu3E]n3΃cs p -YDxE^Y>N3sC YWe):7j̝}&&gTeix;J F()P'(}߻l7u_pX?|ലk>FOC6A9oӞ#4x"FĎ1u/PSh_~^.b䤉nPr$VW4ny2u6D mm(\ĕe'(إxHg[✽Œ/0__FQSUjjj$ߖsR<ځ;[ L&.M1[ojIۧ5m5_%+)@ 3XN3 t~5(v7^>Е '%OH W*L&/dt="^15938nʺ4MwboIk1z9פh~~K-5)FλBR&(_j%Qװw^l'dJ_D= өsmB=[\ȤY|[ORM++gN蔘lKo`K3$ 9D 7!w@1+4'Mb"JYƚl\2s8C'f.!g3m=p!]tD;6s˱O_:Ww1x:ǥxkZsI* 9.x.b1xEm!Ta<h? ,)|x\.!SZ H 5'Z0$n"N8FxSv!Lk i%j V~(eDZgyAp,ScaZeLvȐqk$RO8O`Oq{Rg|7ǝR -H4QaB9.w+aHRUhr]IN%FNPl.Yu¬c [BsDŽzԃ9 ?2kFiNz(yIʊӾ,,Is"Rrk ><܄3-Vz9J !cT%Ch_IWR.]YM_dĴ4'SNL&mÛ?zaVhBٛr6.ާcHLc_~Pr ụ۬;"kM^eaC4:6G=y[IX| <@ TIy9uaj=GEh+XFʐ=hu`|a!+4qY(^/x8JLR.;%)ʒlaپbY^D>"KLS%߿,6z6QI1&RIbI Nҭ ("NdζQoxILvZNMU%l*]RAgmx#]k"*~뒜h۳%Zi;#s54*)A>W4sHR`A}DŽTY&UINٹzA (\EJ+V\U~ PT)tIGE7´NPx1GaLL$ fvBO>z*qm(d}۠xT|\~qĤ^肰wIoTfedzTwUI>U$ ]j^ me ēxVQ#\CW"LN*Ve6PZq)ڶQ#Rϩ6"VY򐻫}46\Jm`V5#Ry˷PN4}zZh4زF36ipbKõ~1F; uq=9nI:>o鯟pHd$Ƭ_FG9L353^Q`o!tԯZDHLr΢zXdI5q=:ȱ%jut-Yl SEZLCmĔ&Y#W1όa.Ef |w̧k&z_6 cwnbYVSl)E`*UlO$pP۞_/d-H@wB\YNRS%sUD#B9y:s-c#˩a7[1m0zcg6trll%djOL?j9yTޢkdG!V㰺dN;GA'= eYw_JIM|'NrC$&GN O۞?\Yɜfk\ddy`T*>!O"dB)Kr&Tۺ>lJ6%p I?NyM: W#Iz嶕՛9_No\MddӚ#O+_,xCcaٹv-i6xި9G ;iT#@*&ފfa-x!}0\@U(bP9#ʰ5|c 6*ҔHT ]sF`$A\O` i8K\d O B%z jGxb˕Ot}ЄdlkSwǁ$mI/_M*#C2$ )gfh:S"e&G;j~)6eOUhbO-ſMrmAg |h,ʕhM!EEĎ@0\%pG󭢉QHO7?\Yɜfk\NIZ; -v52 nph&(l犵֊\ ,dٲ 9raN+a&M>цrzUžВMe~敷Ot|8xK i,НP[#XvcxUFv0z8D\aD G)-E!J91ڈeaҪyR]Spp~- BlBJJƝ07(mx zbQK-kuBX 1jT.ba8ȯ&+'qÈP+ ފ'q.ыQEyN#TvCyM,q)p=uձcͩVL;`ҍ'$GѻWW&rqYXK#3{ky&l"|i4r{/kU2R^̢v$WFʈ ()cߧ2 q-FQ;b4(^oꕷi(W(tS ꞥ{|J5{sklqG&: wsK|9(뢅xu슧C[V* VcV?#0Q7rcQzU z@(ahm[w5 fΪwJ>RS iEks|*JSB ъC~c2LJ'-&մH:K.'Tk(%=p{ ][8Bƪ| [+jk:TT&Bd xiiLKL6Ps>~|ӹk2,Ngf&tZCW#VaԸ( ,&<${I?7Q [DژaWZaޔo;$O"?Gn?y:IGT<,s%őhfkfsAl;0+xpA^O5NHnvabOrn?f%r:UIA>j}m2))6<:A}nȠmqj\"gE`3f.M>I>8(ʜ^Jyᩉ (_5"g% T(NK;1pnPgu *MMn7&>Zo.TZ6˔c%`4sme#_L"`L. ^Y7lo\ThVC)^H`h'.J8ߞq+8e&>kn#|a7 gҼ`6+r-Uf A37W3^NJbd$㲢HNJMYɿ[턌+jz USN^5x<5mr@2TJBBS5jSJfaimIYKie" HHH 3/f[5"섧m *:I}dJ2`*Ol*D˸\sT((s֔Ҟ}wq~1Cj2thҠ(Cy·VQĘ"Lm9cmJ;D^EM=qI'S|kn0?i{:LVΖ"|>͞K!}0J6_i䥧^Hm͔P*a fu" NZ-;ELvsĜ.!ɶB1!KrQ\IS̩\p0%'^mWwSTWd"o(̠5:9#&P>^ a#Dho{tp2vo!c^Y}pS,6G2Ie|;l]H-Di%Q2{buBgeTYVtYLE#k/S7_.9{Tg͎Wgy=zsq1e([)GXK#bJ!(I.6<Royi%r}(MW e/G*q^8_m7PSjwчρfPD˲[ӦE4eKmӊa]jfIE8冒4lˌlum%m+6FLJ~7/S%+hR/vr -OU$l2P*zՊ18dCv ص2]K^Zvȿ6P͛6x:-'lK= 3ے*{" qcs3R,D/օrl\V63NNJ;ukstK]ƭ-κ* K rEG'AvT6JV\ӚFR x۫hIUDBst7J RI=uifoo: mM;o'x殬Vbu`z`I>φ&SH.,ԨԘ8wt~a+0c}\Gnj<@`;;xbkɦ/@W0) ]i=xxRtT;enL&QMuzNQ 2E2&4ؽrabUa&ERt%0ԪRBP!MO'N0.J]#O4VcLWU]qHW B袷 L;8BY&0Q8{N7.|f> αMq<A?![w!r]ǘKͥO pv%ʴexre)[.\riWSx՛&&aݶ$)e ̼%-hՀ@G/oOHm9 cڒAIE8֑Yf֓MN2Wt^9[.hݲ}zU7Cyen:9E6䳊"l' z2n\W'ٌ--&˲A~8sHd)z@ڨpmJCaϔ:uWCNzC9]&r]y sf,XvmEE`3eAvc'FbFږ)!ILHۅ~3Vř4ju%c mi4"M(j6z]g&͆SV۩WLHVɋ|.tq-b~i`>9?օiir@% +r!Z;hץM^~7o~n^w&%.a^nγ,!1Q0$3vyV]ṆD?16EhR%EqgeF-,sitL?_ǬfɻbimI55}u]ٻ„8T佽?!s3. }͝9_eZ2 <#G%11ˋlY6={ȫ`D|[1-CL}k(lkM2{>/VnϐS<@FyDŢ6UCsG$"^ 3i[pl;rWDGC@^ZN-r%i /U_S_sRo%\zN|ZqRt-O3v8T{Nk 6=CW*wtvę_/y?q}>ZK(TBPFY29`Fp_e*]R6 MRmH;vm~B=Ef]ɋMeB$7g'S༏4+3[Yg2)+f_]YVٮ0ϑ/dIM^nu K5Nk,=j:{m0BD R΍ i̹$li#geʼ+.גK$J;T!LBHRT(A7mZ<-Lj[Gl9H'ELpa=1Qb].eTT4w+T\y 1BU!/w RV\ښX58nʥPmm*LY\!u@Gtp Ge $8CY[n6x TB+ DxLmwZjFD?a-(Q ~m (5J5B<юkǮk>vӶՌN*X*$cӚNаgt7d2p,1Rɳgt|ɜn2Ji1#R ]YaKѷVm\fr_6z儡EC_D9D$nqs)ZnGG<ù/iqd:Д(7%- wLvK--WHQ#K.Μ?g:]#FMDԳ6֓Hbʝ(nIPh@$5bRP+gjL]sY[_ѻl͢(=[-ee,o))$ea;>_Y" Sf_Jʬҫ_%9 8Դƕ;vrDգoh]HUª a  몚JbUi 5rvB\2;6l v"/'[ }R j) q$)A$|\ 2YQϾ feՒ)5/G13?!G6nď#wR1lNh=b8̪n}d_L3lY3%yrLVLMJ7}P9L|yfSYEhJdȣQDſk;zbeˠn "Zаg4"e*V#?.ǘlgn=h1~ѓ{߷^\ԋ!sL%FY{TUN9=ى60%zW~(c?6$Tt#"26}ڪV͓0Z] ZyPŁk|ftVQ͵2_Fy+Q=rXYi HH*Ѷ VЩZ6h*<T _yO]\(iW=˺j53) @D_Egp0a}̌cH\|*DžM劔(nXzaɼJ\[WLN )BfKU+ACxlNd/y%<䏌g'+ѷ0L-hp[\/tx4Agz8zq8}<\3][5x.zG3QN+LJ !܊xĤL+ [8B'h5D쪨h1Z0RNY6i);bKZ; v͑V i䴁ܮPVe#ܦ.1PY7VFVޚARαO/8=S6cN~h{;"Zfz;zEE"-AءߓU89ci\M>.JPTiQ0[V a"qA漨L䛗ӱTk.hLŐ  M|F8EEԭ]=QrgEO52Y9M41|p} 5tw Ʈ{QOs-֍~ߟ2}->S#8NQNJSz}==IZǼsgw滢ꢜM^"'\Ӵr(n<¥@}l*Zq+h1. ~t<= . {ɶRyiOT`: `U*>r䔪R:S8ubH[Ϭ+HQ'̓' *>:Q.T;n;w3JEBj"iGAWQ:.)yPTՒ:p.AC*Naxh m?t@JF?%ÍaVj>Y2-XZ+5Cry^bPqY0O~|ۿފ7G돑Şי&.yxTAhX+[t*V~S鸑52̰/\Ò3vw Ҧu9͏hHJwf%2\rNٔ-;po =Z܍5j$4^hm5:i`pEll6s}S%^!iWGs));,}l?Tc~s">Uru+#bL'֣۴橱%&揺TdT}zg}Ded@VjA5y %Ovj}GR.{D6Գw.lZSaט+2k?cw3l϶6cT}\;G?nUIƮJ<Gukɯ>UlD|,O$OG2iVQ Ib&5w9%,~~1yG/E}Q{=ƀCY3ʻD*T?VܘkB|6t#,0;U ba2qTDb]{HNhM>R]nsiw H}V>p}b.{Quy7Smz5O&>[MZ+7nnCq򌢟Wqgɐ="t6h2:DȲfk=XB<$zP m[ GCͩ\' hha5sKS%(h(sM0CI7Fʙ{RQF2:UWFH<>vaGKhYmZ򜮗G*UuS&QmjVHNdڽԊW־jL&zRRŔk=D$17hJ8iCekTa M(> ֺ|hffRQ|W*Oos)Lk؎91F>TmW>A$Q_T|Ayo4ueIOM!y=9 '/}jvB2, )z65^*u^R+!1AQaq 0@P`?!)g%f龖) E }/cYCeerd.ư&'U7f-9(,`y l?xV^"? h6_9M +AyG^^rܾ%}&꾋H:`O?+L/g0XQ뾙Kb6]Nvfb*GHʿ3KarʿCv 5\b\>I՛R4h=oKC,o EWGl̝F(%\`}6tG05hт׻ }Kfr`?9.\+2@~Q4sq7gʼs_u>45[vPT>u{V,Q,L#OV[>NI?R72}µ)XS6:M}1P{{ws l__+\@ՋP'ǦEѻj;DL!1y WWkX8G?$EWUCPj|7- .߅˘$yokv;!MT]^?μ7WKZ 7ytU`Ƙȷ`J;x|DMO&9GymګҮJݔiurMH%3XEoU -7]F`~` n#̹{k@kO0 z|eҩǓxk^r! S Os{dUf!3]k@)͙_EqĿ@ Q+5ݶFȕp_=->D-)h )^cïKpDUXi)ö7AV>˪ojz,+|pv\!B} )HJc;6D]>H*#DM?}>ĸS3ЪͥdRs֜‡ rDs&q 75_5Gf [JMswc^x&Ў#^U K]x.k. SM&L`IzՆl+;*%\^*XR~$ wF }l+D_0JW{쒞 M y_xHKskMό`L+XoKt% ^ㄾ=Z0ws; } Br:7n I'ޝW2R(Znb=06`sB h&؇pHW U56vEv;)kX>7Bt>WVזq=ٞJa._EG_ v幂lu&{h5_՝ FuYQ 4>aF Ѓ sLi&Vox~kgj?15hS |+(mS?CHcJr4|<=5M^?mY>|8t_@6 }r(vڽ},]\J?}_ܣki,ҙ|(ſYOa A\*Æ*9"mS>p@UssC,s ﮏΙKMs0t| r̾LVO:U �EJ#s'0{Dt-'MCg}k L}ɔO3c<}Ӯt&bcSw ^D vmθapvzZ)x[hX.2 ȏCx+rF7`ڼj7[Yv,8S3 n<%uxHb@,/Ń5澔»FLqe9|ez @نbH_os~>$# ʚQljS.rc݃WASF%$ZE#mF6[^ɎѮ9B6gHsM_.3ȲCNSgo/{md{-BkxEF˗c=t,w#4f\>.2)g$2UV<~lACKߟS@u{!PQ@jGDp}j&_Ӫ;6Çz&BC 0`چIp,1o # ERGjuB\U+I\AYjmg(]IN. 'x/S!l:ļ F+/G*K>f LRot%HZCXݱf ~|@g.bxĢ%X:JKQ/0+fT 4] q3"Tx'DG&9^çʴ@B?1걤o˥qCz.N^pѫlOkwwTV Wg4ikNz.iNUh=te޲Ŝ:#x0F6 Ѓ+3>& -+B^3.4U\pR((v3Q$^O`S~7~`a"k߼WBuesKb 7w[kN."m4} 7p1q mZ/)/T_IojΉ"iL|B.U̩ՈXjrgEϦբ^K5fڿXJFDIewdHɴ)%;f?<&{_x5)K,fEǘj>;~x& /ڃ*n?6 4.bұ4:lctxk8jE͌[ 2߶`AF@\K._X aNo8-zzu澔D־fKц:V{ ]",hNj`_dsm5^13.>Y蕰+ȱA%aE5bbhl78Gp5M/B@-fE4;4p@ ͨ\pvZ~B~࢙>jA|gG3Kq Vc&{-ECWR1fӬDpPo6q]d݅%ݦbץ"/ѯ5^MzR_vw |'vG_Z\N$+[@wpm׹̦;XՄ?ZdM~>DJPk]~ O9ֿMbɞQ{1>U.Cb3{K3w(7]̴^~~Ym,^5Ĺ̹s$K.S2RW.z)9 " #IE/ɪ=̾72TKy:T5%oa1-Rx} x%d15:{99GAzɸpAx€Yly{FV?൨ʝ Ţ8jXUN ]Bt`|UӇ%dkϻ&%Y:;u{i0a w>9 1r|Uthj9 bTxjvXȰV Owfyi9Xo!@,afpvɄixkQ˝.,[|Y\Y3Lr|ZtJ+Nvղ)҃Y{@ՊDED>f" +#f$)^],x+59Ĺ$7ƅ^3* W#yt>uŠ:ʿq]5M 龲=p&1+N̥aAcСQuC"QΫZ܁ۮ}RxiHK3#=N]/ђ_RZ&SE0h9/ʲP- #Z ĀY.dS3B$Y7{yc[v+VEoDFOrA5+*~ P@o;Y&Orc/Д ƭ!3 UB<$0X̠\4^L82uYCR8xKX-W5[q ̷\C}.0/@;h1U, N*ይh& I2_Oe dfQ'H`@XޓkJB<9JhM(f5Ʉi lCKFzmY*Ёb;&cv_t퍒9k6ej#P`foXMXUO@4.!S JCֹeu&? 2)8īP- \K\/u),O9..N|.oH0-xǙYpmbA?3Iі|̏Vb `WKt(hYF!Ҟ߾!7Xd]ڂVe5vlf.kua€U>Ɨѡ9X{(.m.ޥpW' ŲQ$Pb -5 փDhKR 8{^H&C:n e Z/#+o1C+=!K_C:K<ܹrifMeM@hr3.wD殄glrכ 7\A{#\|%4u,ɬ 2ўm")|z?e5N 7ZD)˖tr2-+G[;k :1EqO0İBcY]OCB{hjr Cp_Tjbh\0{{_,qyiOR AVg:N3h7jyjq- //29ǯϮYeوbas&uZvປX z_J@[$ v8% VS;eɹ\gЕA% &t_Wx*8]!2ↆ̹U(?RXK>jcç_3,ܢ_U.\F|3=D LM8*p+N2Bs~I(]5N҃0#޾߹Io YP!+uT7&X/Ncpmt\>sɡΟeu} e |\ZJA[z/MZwd%Ç|c-K}G%yHF'`—O?yWs`.\Q=PsJܨ/ 8kpےTĿ㾧Pnnϖ)=Ӡ |AECչ-~PW'l1*p~؄ Rz.kù)EX VWY\4E35Ut)Yҥ2KBʬ6*^EU"hW-V6Ra\R[U'H`'G aVkS)-WgO I$H I@$ H$@  $@HI$I @H@ AA I  @ H  @@   HI@$ I$@$ $AH>`!@  I@H$A I $ILWgH  $@$I H$  0I $H $@( @fAI HI$Hyc, I|@@$$A$HA^H0 Hà A$H$A@HHA)qH$5 I  $@s3".$IjI$$H$ H I$y\@$L$H$I H IH $a( H܇i @$H$I  @ߨ~i $H$ $@ A+R2ʓuMHHA II$  ΆO^@>ֱA@$A $HI8Mqm~&A $A   H A0؎&#@ IHI q$fΝHH@A @$I$I 9+A@IAA I @$A99: $@@$I $AHe{Q= $$HA$@ @@&ʸ7$$@ II$I I@@ *>`A @A$A  A$THAI H$  I$$[  H@ A @I>j$H H $$8 A $H  ~  H@AHp@$HI I/$@R\-!1AQaq`0 @Pp?KK'DzP!Jn.ԍَ* ?zHI~X؇7e (̎m@o{Ni'ã $~2,ErCN:iPaKQw}Wr؄/5qtǶ݁uA6Yr]0GF84.-+z9QA t-sQmz߄ޙܤ"jI>ޤ/7=MMdQ|ɉ2'F;wQv쉮?rV lq!{Zm"Lx]41gaMҪ * 6f .K6]Dleu|(H9zf2v:J<{փ<_xx'"NۭO4S 5>#pxh3xDw3^>*2f(# iC@q.z p"hsWA@DUV8 ;d=vwwҲTfhuhiF2٨InZJMI { yD MI$'$Ҝo@3B Y$e%-KPS I:YJ|ڡ[_5ރkr_\FJjm|S1YH);P ]%ı4$4Lwgzd$9[=jr!^o$'zJaAu3RVrEW⅏CL  'Ehc?>G "\! cަ$I6ebhMM \JhRzg*Ly ǁPk }P!=f{Zl悖0ugw҇{'߱M&M)tI Y+ ?aԨG7\GޮP&ËG2E7DP[Apisjd,caWHgWU"y01f7];Ў{ PWj]cV :L<o5kv&'zp<ОvEPT cڍ_4Rs:xpe\,ol10"45HqO;=Y¬)sf"nQYPx:!j踞4$H{&%l@Vo)x>U6  # Ѩ/ը;21Bpܬ4ܿ2>p(zGTϑMܲ^6N9Ub1;\fC[-ߤQXH(HIp֎H(H %1q[gr`Z xlz㸩֕x1FO@-su/hUtˢAJ (}AOd#قx 7Z hV-(tjJDq/ [V1$ѼtMʹzU2FX;A ʑ"36CV]C>DK#ޞD35t#֠9oB~ſT`8bN`!ѡ\+"sV4 #YP6ȅ!v*"KLKTܛvj7mz髥9un,fޝ3q);PqH2xO5Q40Ҁ&Fp]O뿚q+S/;'ZFҳ4%gH* nh_/$?{0Ԑz:*=U./,8U J ׅ"Fޔ ԄfB%:ڣ:XWRԊSjU@t?mRLEO Lht"@]1;"=DZS:Q#/ ́0 S$y`!\BX5I^re)[mI8^,S JșV 6G!n [,\dbC|^(jiQI>zQe"GVRzO5tKzu/HӺq|FꓩX#%$&)5` NvdlEQ1j<5#Rhߚԑ'02SE`([/Jd9;e߈dmGњQ(j<5\%SNJ+GR=fq)/6D4IH])H%jZͺfҰ%Ww)J#OS؛IL45t/ҩpvzAZ#fAlD0԰7;f7^Xl`]1"ةPK|̼VBxR-9 NIRsR|;.kqҵJ4=z7I F8hkY?sԳ&I }A^ꢼy=OA|Ѡbz|b _G*MQ27c6UT+nX~*#.X}*ͬ|~8ҵQO$56L' >AsڗwAgKoT>> ּ?n1rB_Iv!Qm,'XvWe|t$An7c_Z4"6r$I mXdXA "Q‰(a^/F{Y[m,G ?c-!1AQaq`0@ Pp?"JF ([$C4,[Z&i˧SC[6{Rz +,`$BDKw-QFwKݟÊe|}F%4.ϹXlk*&k[F6S+a۴զD\#;6E@Eh^4ijZ`tsݷzC܆A3;P@ .ډlw /Yf oq'V/O+/lirlG$ {}@%\RσÈKs1 oljBeߍ 7֪z"hFIHP&5?P1u Axtk#N7"bMV.rhcvKdcMu4[_qd|}fWVenJ_5஭T*N2ab$$Dd)_= EcK<S*ULTl`C@F4!mIh!94?lTs@Kϓ#ƵFH]Ȟ Pe͌P"fJi|.=uc;UQɛ8(lҸ@L&-GR;2 MsIM 9 Tү)g܉nKVLWUAB FQݑo&vgA"DpDְw^$y?SP^Є5s!PH+2giLӸ/oS@VW[DBKE& o^sVZ[#P6*7O3L,!WPjl=)uE=r=;FfC# `IގHXmFA/X,80t -.7%6 \bD Sl>ҶF/2b_EaqvXQ DNڂ,,ztH s\`Yd `pg6SQx9LDL NMH9aMCh˱0`:h PGP+ QҜR?cjWnoV1 Y?Q@ƸF.X]5u@ ]Rw;Zb  g:W0?RmBq,1!Ѧ)]U7Hc[ә߲@^)$;[Rq֠2.{ڢ Dy1gUdqB J|k+C!dpUwVx"9 -er~}%# wfc1kxR_'hV;ӐdN\"-!dٚ-7 Kya \:E@lzV1oߥ;#:^lFS![1=EY8wko PJ*duhВuwZL U P%<6 ]"2.SZBW*QʴAgS֕%60OTZQrHz#e[ťpSe_Yk2o Q p5~ 3}[:P1J `5\Fdj-GEW5@PtImujHvqOZriEPGfa : 0gЛd +qFXmt2C ,5f HI@st)JI5WŞfj&OR :\Mlߣ QG'ޘDLP N*l60P"44VGP& v.%Ʀ}h>p$r306 3 G.i,\4l#W'uj3WE6?hw.iVڣfO#*t%rrkBC#q:P3Wa%fŕf")b`7ݿCO;B]u(@5Xh@pi9Fk_!6J7er/ͱ@.mƱ<3bSr=vMP!1_X$aj>QVO5ۮ/\!3ydkOYOlT+/)K`6ZUOje`x&_9䫝̥H,FKt #q.'ZҴT͗RVD^JD~/FYiTJ!G/(mLpnݍacy% X#zq~chdԈ ]vp_FK0}dn%<:Nj(~Ca^y^GnLgRLm@MxJGNG"hq#rt`M-2 uR?" /p93y`IQCzx t]pb&VY}Ódw"NJjIW3LIp @.fqz*%&)*nLFj2dg@ ji85 !PU@LK̯?ԃZ+!1AQaq 0@P`?iO3 It.2Q*Ƴ | o,,)݊j>%Qg""Ëh.x2%rܲlKy{ڇLℍZVYHj7/K nhtψf'_<3\XS9"rzi͓.q1\qkn ܪrТǮrbX1ԝJP`Lrj*TG0mkQJ0l,-,Gse\%R?2ޡcrKhەs yX2Q\ڜOĴiٲ!\2>6(8>%6^4 fZũ~ R_0y%ĸ*^%RA"J')_wAOȀ"ǹvd!0oK0. NIJW 94W|^g:U/XVw=(p!9H<gߙt3aV$a0ISӘjgD%Sl2ʸYC<+y/ S^n%{(l}1r-:_-Ao2cY5.;OL<˕=Jk# a%j ?DAI, p C؃@B/L6wl[?K-\baV3qG$dz0p,|&mj5>]MzfrҘ+!(X>27R4tVZL`\5UXQ2/R8Nf<lrY(QCG\psЭeQ!cSЌn\&o3].]KyA.͌; sn`Tfu]g.`uosW"UGgϓsG"q f+[^q/h dxB; |K5*rr&kwܿ2io"ԅ7,"Yc ¯k10'>6,v:bn~MwlM?s7pf3Ru̹u/lC~ ī+hWViô_^p)"X ɻ^X7~j5 J6' VO@a2Q4Q5X)i"pAK20_pR{>qkg}2 <\V]-v A4?b6]U{Er>wS{-qrຼK|RWЌ. w@ n_Olt9F nC5PŻeo0q}K}Kp}`0ť<ä@0ݙ ר (_D_;..s7^f `(׈4mtk<'ӿU,N1./xU C|z1pCQc5 }Hjc*p2}[vH6%7ܢ{pk&9e( L֕04|q?. + )>08ys,vp> [\u\3"ܺ7z}LJZ FٮѨ8Ywosw,q*`RۙnnOA^[X)̹?{fJ v_cgy5) 1Co^n, Bffm=˦} anebW?P%k4x_A 4|=~Wks_@`,+ϹtpBF Nn,meX--գjϢf9o5.ZhGeg-n]*Հܸ}cvMoeLe2"|@9bayشB WsPTbE~W}iS'*wXs..-# mdrFOB\2 =`xM q_xQV4pث$_IVNj__A9 ~5j7J* ]nf_xDe̛6UmoT8EⱵE.%eK z8{NCRBl hzqܑTqsVJR_jA)p* /s&Q="yT#@Jt1D/ބPۂAy~ %hL E(Ȧuu+xJ[VP_J< LuCE꡵1Z L,bp,W2j8%PVKZ%kӼR_+ UYc@{7[Jzĺjbt4^*n0ђd`ix.KXZhÚƎN2zl#B2t~s-T\eq+LK%Pj`d"f⌿?Xe$.-x;h[6'In||1h CAa/j]@]; HwNش P-4v _n@BD*tS%u~&DٙuĮ4.b [ =TUE&;郃Bj&?24!XbWy??ܾn 7>7K!.iz"191eS Q@P(.xp nC Fa-b](jkVwcsUA;xyvJ)hX<I,()h[>§hy^7//z섻IpV}H@)lZ$x@WFx`㨁SKaOe Pow3z/I ap51&ijPY  bABZw)r,*Qa3ThYc^W/90J\1,HKm}e. 6@D n\WADib'AY D71:$ X6*$$X4,Z(T6Vj7~eܮ*05DTk_YF*6"ڃ>pR+2LqZu-4,G!H{SbR– _ZVA&Jd=ʫ=.S b93-5R3c\F.2^n^j:"SU3-x8ߩg?iAzI- PKQ9}uhlxõ,3 lĠ+l6%8pk$"Gq# QI֟IQ}5?!bEgKU AE5?Nr\4c-Nim (DV OP0j6)sQZ,#r+1bc@tDƠVP)iq Rnrĝ*d$3 AvZ4KXk8w^u.sB7D~11C3#N;'.oC)整3K4z\nCU{e]I:)N?y"yoKy8(U;192Ū*.M䇚B_C847jn q[% ol`&O(b[Xc ?APئj Ve÷K ]̰ǏA0Ah I4\\*E6-4e7)ugߩش:.ya&?(.VQ8B)@(Yn{h V5U5>I g^؉yw!.-26yvjӁj`(e__TPv ҕeG2ѶQ c5BiCT>,ѢY̾ +A[D[VeeY3>zA^jT|FX!{b,yq9(F 2Fc|L_P.23#K\NC5hLӰ=25myR͹"E/)/V]8:HV(L/U[xVCQxju͹^ Xx!״࣐ Lp@!l.*0bĨN!6|z"{vSx#\kH %5CtkQ8O|0$ƷJ!V&osl㣼*)v5aKAC; y c!V;\#MU \ 䴦y1T 0PaUM2-5Ū7!qXnC-NTM@SAt hpɁYnC\ 5jU/ /,tQDm UN75) c9|_ qԻa4k|Fʲ^h4HG,m#1 mș5CA&h\Djmk!efC9[ B2Y.QUMڽqC ![TgQI[)@EWRo+"""(H(H2=UUX#( (weVWWIX\U[J2H7A`ѡ%,Kmc< .\#C(ROI p'XKCyY>P_,TaP݋yS \ NnQEU]qf yxˎ$YX%uB!lĽ麕*c^ CH"g"_C'% v8cá]սEYj72XڏfkH 7tLվTTf2Yȋ @ F#[)K]0.y+yAP(1bPʚhNFrL<aH}l(-%kPRPHZC ՛22J5H2K_Z.J"Ʉ-rMâd([5UŌ08ɕv {!^UpP~ z7`+ĺ37e$Ø9 7 bΟ1)`%^s..]á/;`ޛgr(8T-~-IH7, BT|GC-,FYp#XCsYmM6t̅1OAA{!0&gw̾ch  ;*%2gh p ۛ9P6gWEPG\ xS ( (v-M 娋bEš @ b6Qv]d[q ~Nw ]!4hQaZ.aN.vS*}:τh8p2+"TOkKA*m*U /<5 Z_w,gPYou(@ @0(uEJf$Ÿ\rG?)pF; bJix`:y(-vK<:Qh˗h` |Aw0/Y%Vޓ0-WgPˆPEew~ ?iWm[b*RkԳFM'% q1K<2j ^), ox;BEA-Z)#@CPaiJ&Q %5כrV$( ˌ@ih/4|BDF+_rb~7'ȒPc9Na9 -K0$0͸PQ' mUYih/% ;ᦣ8 Za5\eJ~ G>|@fќ F-e@Ģmaz OdUU>Q8zC%~ P>~¨'הXEb'mrg$˜:|˗b:~ ˗8&lV%4N|]K]H8eɘU?i¯K*oaɌ-Qo+źf).ŴI8ODk!|MCS)ThVoK̥,+TGH_jW7|䪒6-Wpzax0Uaaҕ,j!Y^m5 F;N˶ Ѧ EmmͶ뙃c1(>\Wڿ0ͧ*^3} qKWHbNNf/ G GwS7y'aW.uZz*&ǀ$sG/"CQbV⎕H]rP+x0DC5,vsBi(8EZɎ)ad-3`%S^сiEjpL'6'ѻ +I, JehRaQY_Խi5y en{)OcUD%f]PSVJc<TŻtM,;CU0X` 4MNtk \3Ȃ}kD-Kyʆjs(%:fnXeQcĸ&,,`Q S1/ @p#Tkj ʰx< f^c#ꨈu/ȎQJ nW(afvO"hJ4+kQ^G%+ɠx*R\ڏ+TtK{ j!h!UA3(pxa*b\ -> byMcļ!p? 5bO%#v4q} >+!ٖrԱd٘ &N%mq#W+̠U2Hܓ/UhדX4=PW?Ӱ\PWuw3x˕|*I@@fK똉I>dC @`BoӍ{6b&uͼÞVsBb 8, TbP3h`ş1E'cF2֏vG_̒^ķKd¼ ynʓ@ T\9nF#jӻZ2̶ 4J(; +XmKOW3FI5]իr;guFUU]ʒ-VR< yk4]C=Idy D+VLigbrEdE)yLfg奎|I ^Z!1HIV7ڎ3A$h#Bk6 V,tە\x@hTT !& r'p@ `[@!K`nvt.`qWԳv1Rܧ]kt2ȉEpfx`}+/в@[n\rx"!WO@BZЊ p_ַ0Zןbζ*NC,J穢 J^i"<2)o˹knR8<#=#C7mŭv`_\")hrFH4SSoVO/qZTl&.UE|9h˾" 3J{ia:ym/4"( @n hXeP\P-YnSܞLJQ#c6SR8 %pCVERK(.g[+dEhxIXO2 K%p*˩h،[Py]X*Ew @]Hܬ9f8!{ 2)r)h"/Ce' Kl iUL|V!u.$pJZܰ-E_fW1E3JqzbfpQH'eKFR6w6`(EbeྎY<2lN`S'2LuYk />Q.q 3D&d'igID\wMDBt}<yBf#ǘ,4⨔FnbNAoZTpTahC l!EY毫|jfe";0 jr"$ѓhQyWqn+y ^R^zKZ>v`&֙}1._r=ARkbBN k*"ut%0>MW< Yz.h/Z_22(:&e">rZJ [ ж8&{esF<pxGO3GH5TGg~Im].Ý=h^CJU}%֡XkR=/eM?z`Ob!)|A30 Wڂ+ekp6g'7rK_vȗg99@߯7TT<:6Jˌ1> q68kN! Yc M6B TC0[?fݏ.vQ M5vPzRc4ރ[V{Z%Ç>/&!hW LO_`RbWsZAw*F*3gĻt1&,sHW]J隦?RKƛ1/yy`Q~ao!3펓(ye9.YJhrR۹~ 6قjL-Ѷ5>}UޛġXhFieR:\3l`^]wi+DlX>{E8O;> BR?LRTzDAX0hRFх 䠑 >bdz7?p'pT^ *{!5;ث𔇃8@y);K,wK)o+b[>}+Pꀹ/ʄ8EF[ Hq!GЖ(s(-x>໚fĔ_y23VQ1mf ™\ q{!,@Ϙ rJK.FJi =&86wqKz :F`x/0mC?٩a, J kspZ7˹z0xG}KvAZ tr;Fxh`9ss8MϵBvK;no3EpVvP`,t:% bQy8[EK郜Km8zz*LdYM67=ubg_!b7 B J<\bPԯ]ߣ0SH~ K>} /8/`3GE\-f+q_K;:e;ehD=6&7PAtr7aV1ZzG*DWabjV­y.9 "$?ʲe%#$3_ 9@6e"h:l'Da%g ye/j7I,A}w/;rAy`AO %p591Fq/p cǛf^r.b.PNn"|/5LOjpUPNgeWW<_DITA)> qQFeq0`}%%?B?kD˖Qz>| mbZݑIz[A* kQpV QU,q,h`%e* jUUw9B =ܣ&ҳe ^%نS}A\`|.2+2%6J Ge,}6Sx:E̳O"m/sejPOf{ *\Caؔ| CA'Ѐ@?79zF;|1g8aDK>R"cP݄%dOm6f! AV Կ2p+('itΒ`")Qdh-3U-h aZЗZ~D3B{ |7Rcx01=%/sa2Pӷ'\Ķ(P۰'"әgM  ]OQ4k/ _Z(:Vr9x_ >^5De~ZXTGD C܇1сP#pʨppŪO4LJ8T~(kL'T/j8Uv¬5C_Nc_">0{Oaa4C>1p]B(?E5R*-iy+HL}+~_!R늈t&nL O#Cl_o @APP_ID@ CC0-1.0 GPL-3.0+ Akira

The Linux Design Tool

A modern UX Design Application for UI and UX Designers

⚠ WARNING! Akira is still under development and not ready for production. Missing features, random bugs, and black holes opening in your kitchen are to be expected.

Akira is a native Linux Design application built in Vala and Gtk. Akira focuses on offering a modern and fast approach to UI and UX Design, mainly targeting web and graphic designers. The main goal is to offer a valid and professional solution for designers who want to use Linux as their main OS.

Features Include:

  • Fully vector canvas for infinite resizing without quality loss
  • Smart option panel that shows the editable features of a selected item
  • Layers panel with easy Drag and Drop and smart ordering
  • Create Artboards to better organize your design iterations and views
  • Control the size and quality of exported images
  • Customizable icon set
  • And so much more…
@APP_ID@

elementary OS 6 Odin release

Performance improvements and Global colors library

  • Improved "Modes" detection (insert, select, transform).
  • Fixed Artboard label issues on zoom.
  • Improved Pixel Grid detection and z-index stack with other items.
  • Implemented editable zoom value.
  • Fix application activation when opening a new file.
  • Fix sizing issue when dropping images into the Canvas.
  • Implemented Global colors library.
  • Italian translation.

New Features and Bug Fixes

  • Complete rebuild of the Canvas library architecture.
  • Implemented Pixel Grid.
  • Customize color of Pixel Grid.
  • Implemented smart Snapping Guides.
  • Customize color and magnetic threshold of Snapping Guides.
  • Allow items resizing in all directions.
  • Add images via click and drag with the Image Tool.
  • Handle multiple Fills and Border colors for each item.
  • Allow scaling items from the center.
  • Enable dropping images on the canvas.
  • A lot of code improvements and optimization.

New Features and Bug Fixes

  • New color picker for Fills and Borders.
  • Zooming with mouse wheel follows the position of the cursor.
  • Fix loading Artboards background color when opening a file.
  • Fix numbering of newly created items.
  • Fix Gtk-CRITICAL warning when opening the Export Dialog.
  • Fix flipping items inside Artboards.
  • Fix crash when dropping flipped items inside Artboards.
  • General code improvements and optimization.

Bug fixes and Artboards improvements

  • Control Artboards background color.
  • Hide and Lock Artboards from the Layers panel.
  • Items inside Artboards are masked when extending outside the edges of the Artboard.
  • Fix items reordering with the layers panel drag and drop.
  • Fix random segfault at startup while setting accelerators.
  • Updated goocanvas vapi.

🚀 Experimental Alpha Release, say Hi to Akira!

  • Create Artboards and basic shapes
  • Manage the fill and border properties of shapes
  • Import images
  • Export custom areas, selections, and artboards
  • So many crashes and missing features you wouldn't believe, but hey, this is an experimental alpha…

🚀 Experimental Alpha Release, say Hi to Akira!

  • Create Artboards and basic shapes
  • Manage the fill and border properties of shapes
  • Import images
  • Export custom areas, selections, and artboards
  • So many crashes and missing features you wouldn't believe, but hey, this is an experimental alpha…

🚀 Experimental Alpha Release, say Hi to Akira!

  • Create Artboards and basic shapes
  • Manage the fill and border properties of shapes
  • Import images
  • Export custom areas, selections, and artboards
  • So many crashes and missing features you wouldn't believe, but hey, this is an experimental alpha…
https://raw.githubusercontent.com/akiraux/akira/master/data/screenshots/screenshot-1.png https://raw.githubusercontent.com/akiraux/akira/master/data/screenshots/screenshot-2.png https://raw.githubusercontent.com/akiraux/akira/master/data/screenshots/screenshot-3.png https://raw.githubusercontent.com/akiraux/akira/master/data/screenshots/screenshot-4.png @APP_ID@.desktop Alessandro Castellani https://github.com/akiraux/akira https://github.com/akiraux/akira/issues https://github.com/akiraux/akira/issues https://www.paypal.me/alecaddd castellani.ale@gmail.com @GETTEXT_PACKAGE@ ModernToolkit HighContrast HiDpiIcon none none none none none none none none none none none none none none none none none none none none none none none none none none none #3f3f3f #ffffff 15 pk_live_515yF9YDvXGakAYGJ74PQwmIwxs6xQrm0q0ULEAYO6vZyzsTIaOI40ZtDYj6qUGq6sjzCgwd25VQ4REbJob6pkB9r00tU1lgu6W Akira-0.0.16/data/com.github.akiraux.akira.desktop.in.in000066400000000000000000000003611410625726100227370ustar00rootroot00000000000000[Desktop Entry] Name=Akira GenericName=Akira App Comment=The Linux Design Tool Categories=Utility;Graphics; Exec=@EXECUTABLE@ Icon=@ICON_NAME@ Terminal=false Type=Application Keywords=Design;Web;UX;UI;Graphics; MimeType=application/x-akira; Akira-0.0.16/data/com.github.akiraux.akira.mime.xml000066400000000000000000000005161410625726100220040ustar00rootroot00000000000000 Akira Design File Akira-0.0.16/data/css/000077500000000000000000000000001410625726100143325ustar00rootroot00000000000000Akira-0.0.16/data/css/artboard.css000066400000000000000000000017221410625726100166440ustar00rootroot00000000000000.artboard { transition: all 240ms ease; background-color: shade (@bg_color, 1); } .artboard-name { transition: box-shadow 160ms ease; font-weight: bold; padding: 6px 10px; text-shadow: 0 1px 0 @bg_color; } .artboard .artboard-handle { border-bottom: 1px solid shade (@bg_color, 0.8); } .artboard.hover > grid > grid > .layer-action { opacity: 0.5; } .artboard:hover, .artboard:selected:hover { background-color: shade (@bg_color, 1); color: @fg_color; } .artboard:selected { box-shadow: inset 4px 0 0 @primary; } .artboard:selected, .artboard:selected .revealer-button image, .artboard:selected .layer-action image, .artboard:selected .artboard-container image { color: @fg_color; } /* Hovered */ .artboard.hovered:not(:selected) .artboard-handle { box-shadow: inset 0 0 0 2px @highlight; } .artboard-container { background-color: @bg_color; } .layer:last-child { border-bottom: 1px solid shade (@bg_color, 0.8); } Akira-0.0.16/data/css/colors.css000066400000000000000000000002371410625726100163470ustar00rootroot00000000000000.label-colors { color: alpha (@fg_color, 0.8); } .disabled { opacity: 0.5; } .border-bottom { border-bottom: 1px solid shade (@bg_color, 0.8); } Akira-0.0.16/data/css/dialogs.css000066400000000000000000000015271410625726100164730ustar00rootroot00000000000000.warning-message { background-color: alpha (@STRAWBERRY_300, 0.2); border: 1px solid @STRAWBERRY_500; border-radius: 4px; } .banner { background-color: @bg_color; background-image: url("/com/github/akiraux/akira/akira-banner.jpg"), linear-gradient( to bottom, shade(@bg_color, 1.02), shade(@bg_color, 0.98) ); background-position: center center; background-repeat: no-repeat; background-size: cover; border: 1px solid alpha(black, 0.15); border-radius: 6px; box-shadow: inset 0 0 0 1px alpha(white, 0.05), inset 0 1px 0 0 alpha(white, 0.45), inset 0 -1px 0 0 alpha(white, 0.15), 0 3px 2px -1px alpha(black, 0.15), 0 3px 5px alpha(black, 0.1); color: @fg_color; font-size: 32px; font-weight: 300; } Akira-0.0.16/data/css/headerbar.css000066400000000000000000000011721410625726100167620ustar00rootroot00000000000000.headerbar-label { font-size: 8pt; } .button-zoom { padding: 0 6px; } .button-zoom-start { border-top-right-radius: 0px; border-bottom-right-radius: 0px; } .button-zoom-end { border-top-left-radius: 0px; border-bottom-left-radius: 0px; } entry.input-zoom { padding: 3px 8px 4px; margin: 6px; } .linked-flat button { background-color: shade (@bg_color, 1); } .export-titlebar { padding: 0; } /* Temporary elementary OS 6 stylesheet fixes */ button.flat:disabled { background-color: transparent; box-shadow: none; border: none; } popover.menu stack { padding: 6px 10px; } Akira-0.0.16/data/css/layer.css000066400000000000000000000031751410625726100161660ustar00rootroot00000000000000/* initial status */ .layer { transition: all 240ms ease; } .layer.transparent { opacity: 0.5; } /* selected status */ .layer, .layer:selected { background-color: @base_color; } .layer:selected { box-shadow: inset 4px 0 0 @primary; } .layer:selected image, .layer:selected button { background-color: transparent; color: @fg_color; } /* zebra */ .layer.even, .layer.even:focus, .layer.even:selected { background-color: shade (@bg_color, 1); } /* Hovered */ .layer.hovered:not(:selected), .layer.even.hovered:not(:selected) { box-shadow: inset 0 0 0 2px @highlight; } /* label */ .layer label, .layer:selected label { color: @fg_color; padding: 8px 0; } /* actions */ .layer-action { border: none; background: transparent; padding: 0 2px; opacity: 0; box-shadow: none; } .layer.hover > grid > .layer-action, .layer.hover > grid > grid > .layer-action { opacity: 0.5; } .layer.hover > grid > .layer-action:hover, .layer-action:hover { opacity: 1; } .layer-action.show { opacity: 0.5; } .layer-action image, .layer-action { color: @fg_color; } /* revealer */ .layer .revealer-button { border-bottom: none; } .revealer-button { padding: 0 8px; border-radius: 0; border: none; box-shadow: none; background: transparent; } .revealer-button image { transition: all 160ms ease-in-out; } .revealer-button.closed image { -gtk-icon-transform: rotate(-90deg); } /* group */ .group-container { background-color: @bg_color; } .group-container .layer { padding-left: 15px; } /* drag and drop */ .grid-motion { background-color: @primary; } Akira-0.0.16/data/css/layout.css000066400000000000000000000043621410625726100163660ustar00rootroot00000000000000.main-canvas { background-color: alpha (@fg_color, 0.05); } .sidebar-l { background-color: shade (@bg_color, 0.95); border-right: 1px solid shade (@bg_color, 0.9); } .sidebar-r { background-color: shade (@bg_color, 0.95); border-left: 1px solid shade (@bg_color, 0.9); } .layers-panel { background-color: alpha (@base_color, 0.7); } .sidebar-export-header { background-color: shade (@bg_color, 0.95); border-radius: 4px 0 0 0; } .sidebar-export { background-color: shade (@bg_color, 0.95); border-radius: 0 0 0 4px; } .color-picker { padding: 8px 5px; } .color-grid flowboxchild { background-color: transparent; } .color-picker label { font-size: 9pt; font-weight: bold; color: @fg_color; } .popover-toggler { padding: 3px; margin: 3px; } .popover-list row { padding: 3px; } .popover-list row:selected, .popover-list row:selected:hover { background-color: shade (@base_color, 0.85); color: shade (@fg_color, 0.7); } .popover-list row:hover { background-color: shade (@base_color, 0.9); } .alignment-box { background-color: alpha (@base_color, 0.7); border-bottom: 1px solid shade (@bg_color, 0.8); padding: 3px; } .alignment-box separator { border-right: none; } .button-rounded { border-radius: 50%; padding-left: 3px; padding-right: 3px; } .color-picker-button { border-radius: 0 3px 3px 0; border-left: none; } .group-title { font-size: 9pt; font-weight: 600; color: alpha (@fg_color, 0.9); } .entry-label { font-size: 8pt; font-weight: bold; color: alpha (@fg_color, 0.8); } .linked entry { padding: 3px 5px; border-left-width: 1px; border-radius: 2.5px; } .panel-separator { border: none; } .input-button { padding: 0 2pt; margin: 0; } .input-button.up { margin-bottom: -2pt; } .input-button.down { margin-top: -2pt; } paned > separator { min-width: 1px; margin-right: 0; margin-left: 0; } .export-panel { background-color: @bg_color; } .export-panel flowboxchild:focus { background-color: transparent; } .export-filename { background: none; border: none; box-shadow: none; } .export-info { color: alpha (@fg_color, 0.7); font-size: 0.85em; } Akira-0.0.16/data/css/option-panel.css000066400000000000000000000022471410625726100174560ustar00rootroot00000000000000.option-panel { background-color: alpha (@base_color, 0.7); border-top: 1px solid shade (@bg_color, 0.7); border-bottom: 1px solid shade (@bg_color, 0.7); } .option-panel label { padding: 9px; font-size: 9pt; font-weight: bold; color: @fg_color; } .option-panel button { margin-right: 6px; border-radius: 50%; } .fills-list { background: transparent; } .bg-pattern { background-image: /* tint image */ linear-gradient(to right, rgba(192, 192, 192, 0.75), rgba(192, 192, 192, 0.75)), /* checkered effect */ linear-gradient(to right, black 50%, white 50%), linear-gradient(to bottom, black 50%, white 50%); background-blend-mode: normal, difference, normal; background-size: 8px 8px; } .selected-color-container { border-radius: 4px 0 0 4px; } button.selected-color { border-radius: 3px 0 0 3px; border: 1px solid; } .saved-color-button { border-radius: 4px; } /* spin button */ .sidebar-l spinbutton.horizontal button.down, .sidebar-l spinbutton.horizontal button.up { -gtk-icon-transform: scale(0.7); padding: 0 1px; } Akira-0.0.16/data/css/stylesheet.css000066400000000000000000000004351410625726100172370ustar00rootroot00000000000000/* akira stylesheet */ @import url("css/variables.css"); @import url("css/colors.css"); @import url("css/layout.css"); @import url("css/artboard.css"); @import url("css/headerbar.css"); @import url("css/layer.css"); @import url("css/option-panel.css"); @import url("css/dialogs.css"); Akira-0.0.16/data/css/variables.css000066400000000000000000000001411410625726100170100ustar00rootroot00000000000000@define-color primary #ffa90e; @define-color secondary #feba13; @define-color highlight #41c9fd; Akira-0.0.16/data/icons/000077500000000000000000000000001410625726100146555ustar00rootroot00000000000000Akira-0.0.16/data/icons/128x128/000077500000000000000000000000001410625726100156125ustar00rootroot00000000000000Akira-0.0.16/data/icons/128x128/com.github.akiraux.akira.png000066400000000000000000000243621410625726100231170ustar00rootroot00000000000000PNG  IHDRimO,sBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org< IDATx}i$uޗGUQ}MϵsbO,$E$) %PX!$-C2[!.:,[u00Ya!I@X.؝>L>gf_Duee̯˗/3 ~p5MMNND"{9QBN)Bt!B)Eq򄐒8E0o޼y4"֨K"otڳg#hD:I$EQ5s8研BQض !ǁpraBa>ͯ͗333_d227Ro;c؃􁾾>F.,˂m۰, u]H)!RJB@)!0P1bu7\{9Ͽp/otcfسo߾?>44b0MJa4jp#I)|4MC$A(i( XYY)ϭͅ ` {#A 311񁩩GFGG'$ @PiB4[|jT0RP(]Df1???sƍgggg? z#@Ç722BRTL;PiVu;|(bc+_|˳833c' +NwLLL|СCL:l Vҳ]I ہ( RB*/^|ƍZXXx]wF$iھcǎѣGz|| @2j|Ç?vBd28hP0Q5s~Bp.]˗/agnQ$L8uԟ>}#ud٦}N0ܫU>bu199~O8>V(.T* Խ{'O.Y^^zۮkގtٶ\.]޽{#mlll\v].hAJ;v7U KnH݀ՋqQ.a&&''tG!IPhߩS>uVUszkNx۞ "ap%T^)ê[Z|'I RAٳgR\RmЮHw{, LVRo"2&̋xhw`?̽c9wQ nfq[X,B4LMMݡ(\*rH;)N'N yVmU{ L,0ٗx `^{Va.  FmWT cBp0&M5$244ةS뮻f(J^B`lPث.kA [ EQ+򝐠jH4Yq0999iCrBPѬmNO:uܿrsk*Lݽ]?REє *l`5Xa0j:PXRzn?۶166bP(|T*mD-Rѻs:J#Wp!2)b C\G`&7f*Ox.f4Je||BKP  b@]4&cX('U6MX  K[*لI'Np&Ip8ɑsPܔ$F$@} "3 jj@[Զp84188PJrtcHtR:|[r,@h'=>=:p'`G`P(AU0 l:d( vW1 U*=_BÎ MNNĉRR z 0J YTqPnJO ( T6kTss$; øf_R`%B{~Lu4)L/v#%쉔0PT \3€{ ޙ}x8]pvBX,F'''?'N9|Jw:]LDuAX`_\`ĩJR\qۖu7_K).tRh$ HR FRL:GFfC@2XP#KO-\$ 8^ǘ^zc/mCJ={< `(Vۓi2mvԩ"ݨ;@=s5OP.'T@ѷ\OeTFNii"L9>>`z$n2.XVqoQc4i|" dӚmnO4M躎T*cj54M!qd1n0cE6~qr,=%6XU֘jけ_v|K)84m̏4::x, Jn<_;ޤjխNc!(*o#vMD"y؏AbH䭡Pցu*N ڌM5&U5}i0hU l`<^ `=:tJmPHmV}Qcp7 2O)XuSa J5@Ǧz*n>) x$P)bC\@⺡ EʁZzF"TZ9D"q$LUߡjlg5fÀ޹4@x]|LVnܬxZmPUUDTU=iZ;}Nfᾡlٍ̚KOЪy׾][[Kw]s~"DF}n3m?>^5SK-<sЉnht@HЙq7 ؉@Ʌ`Gy]Fa@xe%'ۉBt ꘿U4{H;f"Q_8q''rV o}2onq!r]#/鴯S#"[PUu@ M)QF^?:Ė#DQp_3(Qgs 6ph|DG ͤKz5 Yf@`?\9[ U^ qUb<n6t!?l?o?MKo3ObdK=;Q?sAu׋Fb'fbVHԽaR 6<͒ցsi<1*&11RvnG t4`UnPU57HQU㢙PET¢/nV|\x'zv7n3M1 2!؀y(?ڣFP~ޠu \6 XnV7MXNԭ9!$J)CtzJSW"? ljyV0nr.` DC=4EA8wL>OLpBȖԭRqA>n`M ;D<<9SDz9oV[(wl{6>F)9˗F&{׋ 0p|JlS3P2 Th@ z.>-B oM&fIâRRnz|z˜΀~7 ~@b Op5/kX( H i0JPN<bЉO!D !Jy|x;F'n-v˰:1V7xEso'CWWťȥE^㷀e _#`$0p5W7'4>@ `T?U-sG&;) -gF2x`㙦8xd^ zU}k(4[er*Ś뺏j¨[rvL;BmF8My; skvj\!n۶(v0Kw ZƷ4Ӻ)z5pXZ;`j vtV:5r`=>Rd_7׷ۡuV/L&sٲ,zV]G(š h?eoKpWDZ$9_\ Y#nukf?~(WTp S^ۧB`Yf/RnYr 1H}G  % w )q6+k6 A pJԳnU,NYP,78iF|vOط'M=k!TPUZY {kGP2M n~l sbo2 㪧Ȧ(P`-o@Tuxri'49aFr*H odȽygxǵeC6> p6w7% @`AЪN}%8k)H&"0%6M8[2ڎo9t: fy@5O>_@%! ~[7>B#[J댚#Ub:teOH84_0+tɿn[:%pϣb{y+:j VXsBT*8LoZQ/im010 ܳgϿD"1^ %z{PVs p^_ Wv uCkÈbu|F8_T*v,} Rxk | ( I_-..~vccK~z+hYVf``iT^s&[e\&8a5BA(B(v蓯?a+Ͼ6Յ=TEb~#W;]Q309(k׮}̶횃$۶X-}}}- R7ώ3ګotWP{#$)3pv)VcUaSCUsf]_JM0*7hHD<}aJ u2E3P{k9WM]fQ$"P\ t357'Qvh-?og!sukv0z1񴅱tղk}jYcS{Q}s)~P(L D"P<$M:ܴ* TR|AS-lX!PUpg}2ӯqy1衆UÎKx ^rh[ff(L&(Mx@þ ,`e`E)! ~o9_~|m6XfmSf Xu&/%`&*SU76gZz 29,ol)O l__;cP+ijB%>h1 =uoZY;;O~ 9sVn)Rx( J՟%74\_mVQ|O:j5('wv72֯bd! p-_~\Z_W{<n:t:ۧߟc!da'~91_8msss5=ӌ(0]oKU12>^b zhiGW.iqh]cZYK7\hsˉD5MS\4LjfsȺ{4MNɗ*91mDks]x=6/)GB2==a|o[aPh*Lg,p3YLzo,_2)(ꦷ,AZV2_N!i2̋Ro177OhUtxch4D,KS{|WwڋS`PmS`7܎|+_m X*>ymmmzff?X:z&-PJK[4;LN:q}sWcpu7D{Eaܯ}3rW9Cd򔿗e, (W,!j~p8\s缙U[ԬҚ t_p?yGӊlllx|4Yu(J7U1p[օ1kF˟\,˺Dޣ7i<섶zVSUW~?xڵkY֫S+V*y۶cpxt7djf@\(333d [R,JE] B<6"te TUa7ooG|>bwhFw-oFo$UUi!:U3nb au]?*m*@rvvo_Mg|Iv'N e477CнP63&~U[H(⟦{'J~7G(z顇wy*\U c]֌cIDATYCQ{ѨҭD ׍*aJ>RnBEQD\LI)]BHWʑv:==Mc1F}R2!#h4*xo~fqqێҫ7;qϿO>\ʤRk39Ӈ~k-r۶)qi !\K2??MWN$ZUUhBPfu?ٿBUJ\EQ\q\8#p8, ǎsUy]?diiE"&d0q( 1Ƅ,9tl. Bp8Uo "\e9zөT$p).Եm[0\۶]ι([Th4K*D׵~'Ձ4MUuŶmxP]U(1U !TJ @YYYI߼y󝚦=J~_8bA4PJ+_ݻw d!BXlu-JDZ؊XrيF'?I>Xe Q:CBPsN5 ~ƍ_XXx_<;BT*@;70K(y+ϟc^ACPJmUUm˲BS*N"pΝ;׵`_wqL&IbY4 BNV*R*ST|>yuuM!sU7v;?mԭ+ f&yEӴ/x+ᰁ`BlؚYs{nn?߳vO}HXb1EJY;Bf-lfxiii8C)Gףcg7nɗU`Ţ[,o !ΧRo̅ኔA䇣Ѩ}{ߩDΜ9Equ]EJe1QRU|ӝ12Lbyyy2Ͽ5 G#S8j,,!`1J)8研4May4d2:RJGJaTUUm!* Ugb ,Nnҙ3g‚iB(s^*9R*18r !QJZb}}}X,u]p8<UUPUʟx ~H)aY6,˂eYea0.J__ju]1!B+pkxO9rT*//흂Ӯ$#fy8抢p493Ƹm\Q8N,ds%d,//' È1۶]9O+kRB”R&peCwǴm;8:cl^QH$2iZ~xx89 !RB\B8s0q]ס8:8e9Hat>sL^NtKRJO|r9%x< pɅLTU=B}W&P!W뺴T*iB!$UU˄q(K\Mlι+D”R ϣ%E)eY(-n(rLt8.ӟ[ӊnOmzz˒$s(TQwmr !K8u]" 1'JyJJdIqjg)POR?3\u5 Ùr>4 zS8Μ9Ci*לB2ƨiĶmB)qH$n/6rι,Kp8,LӔ UUqqTUuGFF[Co :QUŋ*9x 4\.G HHF,KKK2JɑyEy\n.?jWIENDB`Akira-0.0.16/data/icons/128x128/com.github.akiraux.akira.svg000066400000000000000000000706341410625726100231350ustar00rootroot00000000000000 image/svg+xml Akira-0.0.16/data/icons/128x128/com.github.akiraux.akiraDevel.svg000066400000000000000000000633451410625726100241160ustar00rootroot00000000000000 image/svg+xml Akira-0.0.16/data/icons/16x16/000077500000000000000000000000001410625726100154425ustar00rootroot00000000000000Akira-0.0.16/data/icons/16x16/com.github.akiraux.akira.svg000066400000000000000000001414521410625726100227620ustar00rootroot00000000000000 image/svg+xml Akira-0.0.16/data/icons/16x16/com.github.akiraux.akiraDevel.svg000066400000000000000000001474731410625726100237530ustar00rootroot00000000000000 image/svg+xml Akira-0.0.16/data/icons/24x24/000077500000000000000000000000001410625726100154405ustar00rootroot00000000000000Akira-0.0.16/data/icons/24x24/com.github.akiraux.akira.svg000066400000000000000000001602341410625726100227570ustar00rootroot00000000000000 image/svg+xml Akira-0.0.16/data/icons/24x24/com.github.akiraux.akiraDevel.svg000066400000000000000000001662711410625726100237460ustar00rootroot00000000000000 image/svg+xml Akira-0.0.16/data/icons/32x32/000077500000000000000000000000001410625726100154365ustar00rootroot00000000000000Akira-0.0.16/data/icons/32x32/com.github.akiraux.akira.svg000066400000000000000000001357021410625726100227570ustar00rootroot00000000000000 image/svg+xml Akira-0.0.16/data/icons/32x32/com.github.akiraux.akiraDevel.svg000066400000000000000000001440151410625726100237340ustar00rootroot00000000000000 image/svg+xml Akira-0.0.16/data/icons/48x48/000077500000000000000000000000001410625726100154545ustar00rootroot00000000000000Akira-0.0.16/data/icons/48x48/com.github.akiraux.akira.svg000066400000000000000000001430361410625726100227740ustar00rootroot00000000000000 image/svg+xml Akira-0.0.16/data/icons/48x48/com.github.akiraux.akiraDevel.svg000066400000000000000000001441211410625726100237500ustar00rootroot00000000000000 image/svg+xml Akira-0.0.16/data/icons/64x64/000077500000000000000000000000001410625726100154505ustar00rootroot00000000000000Akira-0.0.16/data/icons/64x64/com.github.akiraux.akira.svg000066400000000000000000001360431410625726100227700ustar00rootroot00000000000000 image/svg+xml Akira-0.0.16/data/icons/64x64/com.github.akiraux.akiraDevel.svg000066400000000000000000001407261410625726100237530ustar00rootroot00000000000000 image/svg+xml Akira-0.0.16/data/icons/hicolor/000077500000000000000000000000001410625726100163145ustar00rootroot00000000000000Akira-0.0.16/data/icons/hicolor/document-layout.svg000077500000000000000000000225001410625726100221700ustar00rootroot00000000000000 image/svg+xml Akira-0.0.16/data/icons/symbolic/000077500000000000000000000000001410625726100164765ustar00rootroot00000000000000Akira-0.0.16/data/icons/symbolic/document-layout-symbolic.svg000077500000000000000000000143541410625726100242010ustar00rootroot00000000000000 image/svg+xml Akira-0.0.16/data/icons/symbolic/input-degrees-symbolic.svg000066400000000000000000000062541410625726100236200ustar00rootroot00000000000000 image/svg+xml Akira-0.0.16/data/icons/symbolic/input-hash-symbolic.svg000066400000000000000000000021141410625726100231140ustar00rootroot00000000000000 image/svg+xml Akira-0.0.16/data/icons/symbolic/input-percentage-symbolic.svg000066400000000000000000000044731410625726100243200ustar00rootroot00000000000000 image/svg+xml Akira-0.0.16/data/icons/symbolic/input-pixel-symbolic.svg000066400000000000000000000046641410625726100233260ustar00rootroot00000000000000 image/svg+xml Akira-0.0.16/data/icons/symbolic/layer-hidden-symbolic.svg000066400000000000000000000113041410625726100234020ustar00rootroot00000000000000 image/svg+xml eye eye Created with Sketch. Akira-0.0.16/data/icons/symbolic/layer-visible-symbolic.svg000066400000000000000000000047631410625726100236170ustar00rootroot00000000000000 image/svg+xml Akira-0.0.16/data/icons/symbolic/shape-circle-symbolic.svg000066400000000000000000000066771410625726100234150ustar00rootroot00000000000000 image/svg+xml shapes Akira-0.0.16/data/icons/symbolic/shape-image-symbolic.svg000066400000000000000000000140131410625726100232150ustar00rootroot00000000000000 image/svg+xml pic pic Created with Sketch. Akira-0.0.16/data/icons/symbolic/shape-pencil-symbolic.svg000066400000000000000000000120561410625726100234120ustar00rootroot00000000000000 image/svg+xml pencil pencil Created with Sketch. Akira-0.0.16/data/icons/symbolic/shape-rectangle-symbolic.svg000066400000000000000000000034321410625726100241020ustar00rootroot00000000000000 image/svg+xml Akira-0.0.16/data/icons/symbolic/shape-text-symbolic.svg000066400000000000000000000040031410625726100231150ustar00rootroot00000000000000 image/svg+xml text text Created with Sketch. Akira-0.0.16/data/icons/symbolic/shape-triangle-symbolic.svg000066400000000000000000000067631410625726100237550ustar00rootroot00000000000000 image/svg+xml shapes shapes Created with Sketch. Akira-0.0.16/data/meson.build000066400000000000000000000046441410625726100157140ustar00rootroot00000000000000assets_dir = join_paths(akira_datadir, 'pixmaps', application_id) install_data( 'assets/akira-banner.jpg', install_dir: assets_dir ) icon_sizes = ['16', '24', '32', '48', '64', '128'] icons_dir = join_paths(akira_datadir, 'icons', 'hicolor') foreach size : icon_sizes install_data( join_paths('icons', size + 'x' + size, application_id + '.svg'), install_dir: join_paths(icons_dir, size + 'x' + size, 'apps') ) install_data( join_paths('icons', size + 'x' + size, application_id + '.svg'), install_dir: join_paths(icons_dir, size + 'x' + size + '@2', 'apps') ) install_data( join_paths('icons', size + 'x' + size, application_id + '.svg'), install_dir: join_paths(icons_dir, size + 'x' + size, 'mimetypes') ) endforeach install_data( 'icons/128x128/' + meson.project_name() + '.svg', rename: application_id + '.svg', install_dir: join_paths(icons_dir, 'scalable', 'apps') ) desktop_file_conf = configuration_data() desktop_file_conf.set('ICON_NAME', application_id) desktop_file_conf.set('EXECUTABLE', application_id) desktop_file = i18n.merge_file( input: configure_file( input: meson.project_name() + '.desktop.in.in', output: '@BASENAME@', configuration: desktop_file_conf ), output: application_id + '.desktop', po_dir: join_paths(meson.source_root(), 'po'), type: 'desktop', install: true, install_dir: join_paths(akira_datadir, 'applications') ) if desktop_file_validate.found() test( 'validate-desktop', desktop_file_validate, args: [ desktop_file.full_path() ] ) endif appdata_file_conf = configuration_data() appdata_file_conf.set('APP_ID', application_id) appdata_file_conf.set('GETTEXT_PACKAGE', application_id) appdata_file = i18n.merge_file( input: configure_file( input: meson.project_name() + '.appdata.xml.in.in', output: '@BASENAME@', configuration: appdata_file_conf ), output: application_id + '.appdata.xml', po_dir: join_paths(meson.source_root(), 'po'), install: true, install_dir: join_paths(akira_datadir, 'metainfo') ) if appstream_util.found() test( 'validate-appdata', appstream_util, args: [ 'validate-relax', '--nonet', appdata_file.full_path() ] ) endif install_data( meson.project_name() + '.mime.xml', install_dir: join_paths(akira_datadir, 'mime', 'packages') ) subdir('schemas') Akira-0.0.16/data/schemas/000077500000000000000000000000001410625726100151655ustar00rootroot00000000000000Akira-0.0.16/data/schemas/com.github.akiraux.akira.gschema.xml.in000066400000000000000000000174611410625726100245230ustar00rootroot00000000000000 '0.0.0' The currently installed version. The currently installed version of Akira, updated only after the user launched the app. This is used to know when to trigger the Release Dialog. 360 The saved horizontal position of the window. The saved horizontal position of the window. 360 The vertical position width of the window. The saved vertical position of the window. 1024 The saved width of the window. The saved width of the window. 768 The saved height of the window. The saved height of the window. 804 The saved width of the right panel. The saved width of the right panel containing the MainCanvas and RightSidebar. 220 The saved width of the left panel. The saved width of the left panel. Must be greater than 220, or it will not take effect. false Use dark theme Switch between Light and Dark theme. true Show button labels Show or Hide the button labels to slim the UI. false Use Symbolic Icons Allow user to choose between normal and symbolic icons in HeaderBar. false Invert Panels Order Allow user to choose between default and inverted panels order. '#888888' Default Grid Color. The default color of the pixel grid. true Enable Snapping Guides Allow user to enable or disable the snapping guides when moving items. '#ff0000' Default Snaps Color. The default color of the snapping guides. 4 Default Snaps Sensitivity. The default sensitivity of the snapping threshold. '#CCCCCC' Default Shape Color. The default color of a newly created shape. true Add Border on Shape Creation Enable the addition of the border style when creating a new shape. 1 Default Border Width. The default width of the border for a newly created shape. '#AAAAAA' Default Border Color. The default color of the border for a newly created shape. false Auto Reopen latest file Automatically reopen the latest file on startup. [] Recently opened files Keep track of the 10 most recently opened files. '' Default export folder. The default folder where exported images will be saved. 1000 The saved width of the export dialog. The saved width of the export dialog. 600 The saved height of the export dialog. The saved height of the export dialog. 300 The saved position of the export left panel. The saved position of the left panel in the export dialog. 100 The quality value for exporting JPG images. The quality value for exporting JPG images in the export dialog. 0 The compression value for exporting PNG images. The compression value for exporting PNG images in the export dialog. 'png' The format type for exporting images. The format type for exporting images in the export dialog. 1 The scaled resolution for exporting images. The scaled resolution for exporting images in the export dialog. true The alpha setting for exporting PNG images. The alpha setting for exporting PNG images in the export dialog. [] The list of global colors Keep track of the colors saved by the user and available in every document file. Akira-0.0.16/data/schemas/meson.build000066400000000000000000000006141410625726100173300ustar00rootroot00000000000000schemas_conf = configuration_data() schemas_conf.set('SCHEMA_ID', application_id) schemas_conf.set('SCHEMA_PATH', schema_path) schemas_conf.set('GETTEXT_PACKAGE', gettext_package) configure_file( input: meson.project_name() + '.gschema.xml.in', output: application_id + '.gschema.xml', configuration: schemas_conf, install_dir: join_paths(akira_datadir, 'glib-2.0', 'schemas') ) Akira-0.0.16/data/screenshots/000077500000000000000000000000001410625726100161025ustar00rootroot00000000000000Akira-0.0.16/data/screenshots/screenshot-1.png000066400000000000000000006226541410625726100211420ustar00rootroot00000000000000PNG  IHDR|Q.(DsBIT|d IDATxy#u?WUNOfSA@]EXVT@TdQ x,? _AEca{{;wRUd$S9_cU'sS@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDN*vl"""""""""lb7Xfz<QL g!"""""""""*w3&`/NDDDDDDDDD4e^nt+p\b\(ߊr|^qW+/`T鶫Tl1`R smOGDDDDDDDDD4[tzyWJr.m:t?fL\K%hζSm?U*}BDDDDDDDDDTl n.z^ q6mW^ kDz6AyQCb ҍНf+ꝧ[_zB|$/FNDDDDDDDDDDFFbRSmٴr ܉M7N8>>mp.Wr ҥ$ˍ ։fLtdY&g,yQ@9aT9sDDDDDDDDDD1s ڳY?mg{b..ADDDDDDDDD4ۥ D)Tm1L!|鉗S-˴] ։h$HOL`rО,U_ҡz\t9Ე<z6N.L~jtB' L SjϴlCDDDDDDDDDT'6~Y6hMFx Gq?T/K ՓFm!"""""""""2 S?? HT*/DϖaqM$lTȨ| k㉈('!UU{{{_Ku "գ{?]N{rV z.azt뮻o}[4MuzDDDDDDDDDDT,Ce(/}?O_E$TWq*PO ֑gU>&ѣ?ӷnBYDDDDDDDDDD$I0L]v ===[).~Fe'=u9PF' g}c1L'"""""""""*!Bhctf&ilBT;VxƳXⅈ躎!*CtLR)h^ꙔzImot CvIDDDDDDDDDD0:tedHrL3՝vyd.0 !l,BDDDDDDDDDTvDhTC$$M]sfDd!T%^GGH8P$IRnk*tFoOze?=,DL% Cu%&4$I? IC QI& KRLʺdS;=rbGG;:B躎~@UՂf4e8BdBuu5!27"""""""*<7YΛX%(d$^׀G'De_$J4$I8`X r[lE]Y\Cvލ~455Hu?Fz',|ƉhfH<qKrz1oF'[éLhaN;#VWEԵڠgë:FFFpl6K4ul هf+Vk(̝Jb=u,c횕%Bv1K!`[2lW;_ՠ Ʉ 8̅|P(17t] L 6+*+ 6X*Sp=^7wrB71񒛊,fUrKÇ moKe`ѢEEnYI0'TOUh{tZ' L@> pͳPsGG7e#:y] 2^} Ȳꪔ@P*Ju&4Z!wUQ"P5@dEBv!Ѭ '0`ֱzUe5v+8]8:4=0h @uuľEGJ݆%Khu!^a,jmƘFDj-UwNaNSfa%$L_لZעxz{ۿXqO~|!/xMOS1(+hA  aIM]Q;44J̙S;{4^|I:haqA̯kрAd8qEaXVBӴ; NjڿFu\)M3v_wO/.-u =v܉7 [nEOO8 h;@i8 8puuuذauY#Hm \4W sK&^fդt^BФ}Wpzڎ (QU0DA5-?c݇g|LC;3?4Ĉmum*pOf3̫EOvcӲ"[*0nƴ<jrm7B]-GE~v^/G{Y!AiF4 A/Zjj(5C͛4L=#D0e>}yGҀ)KxR_==E_χe˖dܿm-ؿ B!T^^IbtttA2P9)cΝذa~z#G`Tʕ+q@Q477cÆ ضm8VeX3=]\/5_TG%MJ:G !pEjFhܕ^q50=J׀*jZ\C?ZV8 igy3^0!>n?İjA{Ftqoa \8BP6=v{M]zEɷ\)s\L-A?zzd )0s"e_@ՠsn;mޜ/w 4J֨7D0j-v3hav90'LO&B0W8qcqGQPMӲ0ccc7bT #Au c 8EߺZ!2_EQP[[17 ܿ*@geUpZ`( 5MC H:x4MwdT^/v;Z[[cwtt`ǎhnnڵkpD2,χ^رk׮EKK t]Gkk+ ǃ>3駟O<1i͛k@J OlсzuFOO>+x$y|+_A}}}lSO=_~. W^y%6m4/c=V|_ဦiַ~+Sc'pVG ꍧ 8+89eƶ'䣡P{U8KTJd*V~HX\ kvjUup0ӯ66{t]oΟ xik>Jʴ|HQ~C=/gyflo[9r_܇iɇE~شiӤ]]]O+VL>ȘC=mlYGG^|E|j_DT}n*02~yBY5)xؘI*nfܿ5 ݆rM>er1歚:?҆:A-;%Z?_ʍλ*2oرc8x 6l ң-Zݻ,c޼yx'쫔]{lx;sh =*톆p>ANNvi'Oă>ACC```> n&46VvvjB7ppOv =,!,0ePwsJ*>vmx?6lؐ{_/.R<㨯/0=7|&@̌48LEwJpM{0q#hS)\r{0t={A~NRG!U5h?+uא^& t?a9Y;9zը/P۶mO,ى]2+o~{̛7_=VZt} mpg޽{Li~_x'ֆYo;Ci?u MrªsX!dC7ΑԄaDZ}+&^ߌZPMY>T:a%aı@CLT w8Ƕ~;BӼBQ!L&-7PB _ݿ:?lP&ڵkW^KM$pƪU`ZBfaʕ8x Z[[1<n&/7pWK-Uy_Bppе9a:1p$2ىK.ׯ0㩧\r%g?Æ \D&jiiASSo>+я~T;%$CC#sOaRuiwITO$^E)%r1k|Kj>1u޽5s!'#\I 4| *ϖK@G~a,^Z Xl00Ww0jԗ/l `˖-xއ]vgy&V\^xe?pbtto1i}m躎/8r~6 @$|qCEG>|(jkkqW_Ddwa g9ݑzؙL <=84淶L<+Kց^|mAf] }Iտ]}xœty09|D$T7ж~X+Q9=ss\u] ҍ+p=:Y,\p)o߾^xaV|OMY):t]]]B`Æ GSSSx?~MMM;w.ꆆcضmdYF[[/^lXwy'<\.WB<<%z&3&[`}t\qՅ}kG{{;㎒* 0μyaq79=Ʉf CzI=&}\pN͈BMi&.Cgg'uE"?9nX9"*?1YBOC r\ $(N;4m#I<^l6&sNտ~y1&$!!f\ h{6%yV+fڰuV߿n CCC'LV*믿>wJM@LXgAK=^x)"n06E#J.7Ono)s^sƷʟ`457ߞ IDATk|[GN5dXF/:sH7,p V~e. 0`|Ñj@ y^-{w\Tnz_ۛS֨/İ.ٗ+V񠥥@ff'aytt;::>SDZ >pVx0LQbeH BVWvuBr=bRI딮DssܿՂChN_GF[&FXL\rYq TUez:Gbpt%_t]a_P@U#a! !\ƽ K=_ӴXm6۔Ky ؾJ>>SI{{{\p>G e4\s̈́πY*ߍ.O4: 3-j]|N"".`…uǎWU|@}}to"oD~ui\@r`@U.w7 \%0{˰UsjOkk+$I¾}piߏGy^<{˖-{<%SDSXV7{ ˁJk@K -N&,T{Oo6%ko 7`j|4|\k;v]m\LK.nCX}ZK\Mr {ET IC pF%j$ԨߙF rCkԗjH ˻'M}hH]ޛn).I, z-ڜzpi,˄/DTD9$ucN#ÉgV,uTb*'e4zI( Nj:B=zF+2MvNӄgUj{%qh3zM>ta~kK1ڿ=I@}e;^|D [{%V.',0KaxgvkFJ D `ۡi\уoMMMػw//_ R򥱱1v?dYbD&-I_AQwyWAXV\p3G%-덉ӅꙔ1LBG}{5\) #3l:)r* pߋp8q*XЂ^T My֮ /0iذk]{:w`%$C(iy5~1Ck|So}Lwrt2_jG~"OTS?CX(2BV%jH&3j..M\(%V6mTVVbx7q!?SFl޽{bץtׯ_Պ^{-;_zjL&<쳨ī:Wl3hVi`@dXe&ѦlNAT/cAtzat@xYSEWdY$I? ߏc4+9-=6i@ªFD%K!L c#n̅Eʽ$__{N ZZbTD+E(B[[fҽwe] ?Y!#GpV!\y~J+s?!֮]FB!,XG[o!ZZZ`~!b?;w3l\?͛zԄ~FL6slv*//}Kwn-ߏ}yȃ6sXo= @.t񽀐YTA@/ż[Nx2ݶ}_Ɨe\zP]vʌ׿KNKp뭷7 .첂ߟTfVp"} Z m8hE5I)ꚦs+CCC hlQU%# êce^t]ǹ眉W_{$[o[uJ>eP^τ0jԗ !nV?įkh͆kW]uՔg)_Gywy'x≬;=tMe_|1֭[Yq-ߎ.]'Z " @IJ905R}UZ:c0[-РC$180Mտ†w}>z9p-*&hBJ ^4%NlƉn,ʊ X,\  add#lhiiχrnz C;0 ɣo|qRIXx1/^A e}ҥ/ ׋FLq+5mW ۫( ^y52Y_eeelEQpr`UEuǻzkoFfVkK.$IOZ$lը/%wqp8V|ҥx!2^x؈7'D(B(BUUՄZ~z7dY}޾ qE!CQ(눈fhL5f̳\S*0iQs;|DZNlV,P{1uv4 qmD"UaՁ/8b2_aLJzP}RUht`ZQ?o9I7 ),$?܋6ч믨G[S7@yP"mDEEE,𯫫B^X,曩@gg'jkkKrPO?O|Sor|N7,/WL˸$PsiYy-+By/"qud\auD Io?Z(/⇼_BVǯ.joJt:L{/G1gZT3>he}<5&eX[6ϛrzfDN*Y{W,_[~IbMlU's6{g M0)bG>tфߦ֬oP{Ug\X^~y\^EQ5.PWUȒ,5Fl;BľܙLIeTUȄea ^Q }49gPYQtnǒţ:Rfֿ" dqr .V A}Cn^-'~WTͨt srX(ߣ˥múubkdYFKKKl>hqՊJ8N #@$X:FFFP]]mX[駟"oc"abI,``@BIX uG!H M -P dؚM;07\.=t]g#0) dI$I'C̢2z3UI9A6=$A_u]/<װ3*R{KY(7ߜvv4o |sj|ըmhL[*rm WAr-<'ʭF}̩; Cf1^/H~2R\toLⴷ7 $Yh-'|$ 7} "_N UUp4 bpp. mmmp^,t0TgҲ`0;1OR͓*M|H69iARTa!d ZEKHɸ@dE+SCJv"ӡ 3xKÌJؔ)|ZZ@HU K4UTδ_f$IBmm OG)22e5sio1^;רUps"BY|B˿~c(˩E/e$@=^gNKflܸot]Gcc#vލ1̝;ͱ( z{{ىJX8|08㌒*W4::Z*-ɔ#ZY !j&{E^҄#:4-Ecc̒pP@ -i~ YD0@jB׷&j! PokH[KA)̢6ӟ3vUQ79q_Fȵh[9˥4J1k|J)Lަ뿑djQ *|L"*OSf YK7g+2kːTUN=ytDjKzz()7i4 $axwqAȲFl߾ ڽ}v,]xWn:HP(;e*-0(@=ل3;1ʀi$;v;•Qh( UiG68A U:0["/ׄ A_'G%x  jP鵸f|K0j-rLu]ǹ眉W_{##;R/Bm%=>قMC՞u܁*9l6#rf| sF[Lٵw,@t+EcccZxvl۱pG)T~޽N3v[3qedYFuuմۗQrmo!67ogēu*364تעjrLƦ[چF |#.Ō M*]&χrQYYMglҖRɄ(p:@gn:Wv[l,˱Ml* V⋱,rF+\wI\xLTG/',_񟦸fv?~RDE_`A~70]ѹEjqa!i< =M):eX}(2v;t:g/є ͟7p6X""B  f}=ZϼlʭDD]'\_m.|BTzOmgtR='#eTz@ NTYχ`0n3::rg|Dn7b"""""""*,cܹ@= ԁzb.C-J|IW>YWfNAC&"""""" U֛KI)@=W iFգaztTM0f:t"""""""*#e{N4-W+tq""""""""*r 3- C428eH;}C""""""")u[ؙ;h+dY6LDDDDDDDDDDe[j%_0)e!'S$"""""""""*Q mҜ7 @Ʉ0B=Q """"""""")][j#s[,^vQ,@ه C iKv+vSJr8@ko/rKhllj-vSf,I( ,  :-@])yUVAUUR'">+W)DDDD%T~F"</^ UX$AeL&Pq*TzFjbpt:48l68b7dvHD3f "ECupz dbND4Mf& fM!"""* 3ьADƒ tf$IRBDD9e91ǿk3Ŀq*E F8.vsʂlFmm-fhDDDDDDDDD 1|!P8F__\bVc;`uZa6maC4-6`ņ!bɒ%NNX!X12U@.gz>d;$"""""ŋQ__OSU& b>{V < J3&4U+nk^n{uzTlBv"sd @:UiK7! y MӰzĿ] wP80N't,L&8]&iV"DJ ׋dEC* 7`{;Bv <] 킀.X׽/AO$CU@O@sˢ wO@ux^tݟr+3yRv$kKzJJp~i:-0W$Bd)G$@D/G&NKzCD ٣4~{@RfZH3fV!UXX 8 sduZ"j`d nT($!QQmpZgX:Np:hZz]{ mXz)bt;%{x7 tQhAo}^ ˽^N^/ <^\N'̎,s!D,P.UbY$iB}""""""""*Y ao l. 2AUuEy ̂ `!ɊaMӠZ Ԭpx`v |I˲-h\(p饗xqw3 VH?Wh0vߤVąg? s&3<~٘/R,V%VF" ъRB  ! IR#L3H 9hбd!|UXU=;m އʞegZQDDDDDDt}Q\xᅸ'ԋ>3G׾F~`Xpi .(X=jχ??O|.-#*-2P|0:쁰"Qq&VXj~ˊ}~?Nb4FM@ǏdpB0M8/~TU;gh:HN ۍ+nuZa폟?#} #gX*>[QDDDDDDϣmRD]q8ty}}GQ__}cxgz8w!)UUo߾ݻwo,~fV0NYuE)F݆ rиvUnSmi/lSby-^~'e 9q# B5r Ȱd RHXu! 9C] :R&ڵk>򑏤9.I>loeYĠB 3h%i݆tH&69w3M l2С67av!ByFDk֬ks=7i!^{5^:\.\}ո+glٲGUW]nB!w} ܌^3cuEQ2~. N [\q1$ @1>]dYpZf賂|<:>{Ϲ8صk;ۦhC̙D:oT tA'Q"Ia᫾29l+feص];#L'c "00˗f_D*jP/Jgt{x=\+p}qo%%rj-._5K fggp7F#%p2wk>&־Zlt+9\/PJ[Y C~ s&Ge\WkYV7/SMDDDDD2e QQQ_Ld8q3gڕT h4Mxx8>(pnfÙ={6ѣG<==gx{{s_OOOqΝ;M.ǿbeP'NhW,;wfҥof2:.,\I^(g`hz~i< _wZLϮ%hSxx{zSZc6:ͭ]9teޏ)qg*TϬƃdbccڵC0gWt#}v"##KLxٳ;sfff;pqj׮رcnZIOOOO,x{{۝ǧXRQ.Ktt4cĈԽI咕ELL mڴX``#(L@U-a֬Yj7,,zf̘oy""""""""R?~5k͗_~Ijjyꩧ0`m;##h0K۹s'{-y9t̟?qƕs"S^K.{~G}???, ۶m#11 nVLӧO?G-hٲ%deeAzz:w&%%.]ʠA\gΜaƍz8pd:vHf͜DDDDDDDDشiƲe>~w֭[GNHHH`0`0HKK9s0hРbر7oN=l ٸq#s n:N|4nܘESDCN_VZnj38x mڴ!::k2c , &M" {=IKKc4lؐtf3...>}Z_>۳gd֯_믿NzDDDDDDDDM6a4yy衇شi-… ٺu+oח\V+۶m㮻O?ߒϒ%K5j?0Vڵs >3͛GPPÇٳDDDj*V\ɒ%KJo߾<Eaaav!ӧݛ;vw^%ԫ6m\1ަMr SNǑ#G c߾}ݻ^zqIy֭[G۶mfȐ!ݛ>}~``\;vn`>|ɓ'w^%EDDDDDDDѣ=zN:ѠA"##ٷoN"$$vl믿VZ Grr2K,̙3YW&==h"~anʮ]ݻ7׿غu+&L7Gf4nܘH&L֭[/[n7x۷_˟ ` TTcƌ!##7x{3rjYCHTTӦM?',,BRR-[vDӦMiӦ ,6m\EJ4hkY)͛7Ί+jFHHo۷ݝZja+|!:u@ǎ1 :t@ ?>}a֭@х7x#Fcl\999}񄤪0 L:X"ߘ>}wUTg? \]]mΒJڵ)(( ##\\\4iǎ#66kײo>}ݫr}qqq)*uV["hC=d۾TN:Ul`0eKl>}87b_o͝wɛoITT_}Uv/(TWjj*%ST!66ֶh=<<ܮ{`00m4rss駟sL>X>: uwww.ߺukYnDGGc2ر#wftԉ={p,Exxxp1.z'..cǎѮ];>8Lxyya2Xt:/’%K8}4iiim777t|ի[.[lΕ(*ҤIrss.w1 Y[b$_=;w槟~b̙|rj֬mfs͍W_}'kr7'<39rcDzj*>:uDdd$|ѣ_q1m4CDDDDDDDD*.={`0~wozI~<==y;d˖-|4hЀ'PNOlflݺ3h GyxW8AaÆ<3dggQJ_tЁ/YfQV-~m<<<~VRxzz{1sj?UKv\JX/i ?u7Ujjg{Q= DDDDDDDD>xJùJ%d:UսWJ/4%ZDDDDDDDDDDJA u;(.""""""""""b%EDDDDDDDDDD전P8/DPB]DDDDDDDDN:9;$PwJrr2iiifg#F`` k)ߪ:]򦄺)[:""""""""ՇTfooo%#шw([T+"""""""RޔPw*zӟiu@""""""""eC u;(.""""""""""bM.G̛7Xԩȑ#  33sw^BCC?իjeѢEl۶x 1b2Xp!xyy1dvj;nXXl o#)O>5];8)KJ_`Ϟ=|tޝ֭[h"222x,U'OVZ0j(-[s?SO_ۮ;|ٳAQNnʮ]{_~7fر:u_|>&M„ vȥTű+"""""RU\mrZ"<*r-Z_|d槟~QFN[,ƌC&M6lnnn8qqQ^=CnogŊL2GΝYv#n̝;ݻw3o<>9y$sX,-Zķ~dƍlܸa8T֭ILLdzjL&CдiS&MD޽;;v$66ӧOc1yRS4vEDDDDD2i$&M8psscȐ!={իW_mV >>>>={gd$%%q1l:t@\\\cVv/A8pKRvm Yx1QQQDGGӲeKXլY=zˑ#Gظq#999 8R}پqvMKGYxbFɈ#Xh7ngϞuxaZYp!#G_$))!|͛Ӯ];;b4:1Y,yḻl2 Yv-mڴ̙3ԬY84յkWn6RSSٹs'=SNeߟRuٸ~;~5U4zرVEջwo~G/_ΩSh׮5rXnݺË/h{@e+""""""ejbZˤ;wb2ʤkrR(^Zj`4 tx5kdo6'22CŮq]B\\f3,gWmyzzҷo_>s0`C7 Zsݝ>}8+""""""eiС̛7϶^$..@&MONN+Vs|ӯ_?lž={hӦ =z --?$$$иqcoPPP5kHHHsΘL&j׮MfͰZlذ8իG~pss+GQe˖qu={Xv->CU"QB/ټy3$%%tRFgϞɓ'9s ll63{ly.5",,cǎuuXLbcvѢEгgO.\H۶m(U?wq^xa[E{gΜ鐶+.]|rnfaa!III4l@v:t(Vt u])K-Z_//// ҥKcqM7xb֮]KͩW/2hтGyo6mڰb RRR1b&LӓݻEll,=͚5cڴifzO?֭[ywqrѥGH XV.]+<;vo!&&;?]v4Ņ'|Sr7sQ6o_|7۷gѢE<:u5k0gΜRSmڴرclْ{w4h;v:))W`0RE...9ѣGӯ_?rrr*e])kV}aZiժ_}-ZW^̚5'Or}Ypuue<3믿Ү];͛GHH5jO>aĈdzg6oތ`gϞw &$$7|+=z஻ѣ4lCE-W,RVP?Ç{ W^ IDATر+VТE TyjԨA߾}mǎ˝w+ԩSmӧ /Yr%f~ ~K#((xȑ#mۃvFXvSc0x7x嗙5k999|L0١]5])Kg͚5V"??)Sĉ;vC~~~oj'$$`Gnn.ڵ1 oCǣ>jk377b ZX(~]ҵkW۶hdڴii;00KY~=;Ă \|fvXr%xzz{@~-SǮHe3rHڵk <꫌3[+ b%}||dŎרQvE-W,RV@\\\.J_ǧB$?cz0IJLW""""""Rڷo ...nکeEO:E馛dݺuc[&;;(rrrؼy3UV9r[7l6k? V5k Rh=k׮,_{???5kf;|˜9sڵ+ݻwM6m>,^^^dggs8þ"+)+J8\_XjuͶ[o[oնݶ>gLs77bضyر#V"--\\\JI劥:QB]DDDDDDDD* hba̘1jՊVZg9B۶mWfMqH"dWWWg#PXXH~~~~54~4vEDDDDD*^ gf۶m8pP>3|}}HDxxmrurrrʪ0m瓔DPPCb4~KGcWDDDDDD*3g"R)($''drv8Qarww'((P,4~KOcWDDDDDDDzPB, !!!8;qꐐ)oz守P"""""""""""vPB]DDDDDDDDDDJDDDDDDDDDjM'""fA u;(.""""""""""b%EDDDDDDDDDD전P"""""""""""vPB]DDDDDDDDDDFg """"""""R5()+J8IMHŠH%1qDL&oߞ;tpwwa^$333f/_uV%K}vBBBx/E"""""""""DLL gϞZs疺ݷ~l6k׮nܹ۷ӪU+?8 lْoO?\>3>#8p&Msϱk.ZlɦM5kG(YKƷoߞ~MZUYYY]8 -Zo߾xxx />KZȮ]Xr%t֍1 ٓիWc6i֬!!!p j ٳg~)=p.O-]wEnn.ǎ_eÆ  wN>}.rq6hvޙ3g(vm͚59}eBj+̍7HAA_5 70z!"""H1Fڵ=zppa1bܼ<(((y涗  p>ψ%77J Kbb"mڴ)G۶m/jrq^P!''صDZ&ԏ?NBB{/`ƍ۷ ==B]o44hm۶Hpp0=zӳIDDDDDDDD~Zjc^}Uq<<|8=ʐ!C0xxxp OԩlذxZjEvv67n$77-[λ\ m۶,YSNvZΫ}T"S-g2qD.]ʌ3{};7$$)S_s!~ibccٽ{7&L]v矌=۷ӽ{r/R \؛m$W+ 6ZQFOӯ_?>>B&Mc՘L&FEyVpL;.%t3 l-]/\n@Ϯ5DbbbˋwyD&O̘1cԩ{aƌ >okײxbm_uIII;dСSdffK׮]TB#F`ܸqvh 2իWDDlz5ӍY7?3QWM(&'G""eaDFFݲ~kjoԨQWu~xMٳXe%|ay[{9s؄qѿn喫BYYYxyyK+` Px~߶ֿ,`h]ܾR-gN_>,_Ֆ >o{iHef86|l92 ൣnl`RXfRej\_+4\(|U}Z,ƏO˖-_ȑ#%Ԟ8/sUj6l`İuV;jԨAHHHsyZt҅Xbcc),,e˖BBB3f ))Iw&""rV+QQQԩS;w^ǏCdo%Kxwشi?)Ȱrąs|0=@Z+g?PDD4 >-Z ..ڵk`%åJ3իSO=ҥKy cܸq>8pom f̟?qa0֭-Z()_~뮻rJn+#F`ĉ̝;GҵkWbbb8|0-Gۿ?f"33@z)4i+)4|bccX,DFF2rH|}}ؽ{7-"##BwΰaJa̙xyy1k,`%۩SHHHW_Օ@ƍҥKY>V29ÝG`sW^ׅ%g.DDw١jP[[IOOh4+Ҹqc-[f۾p:t@8{,5jԸ(!/""Rѭ[>}ЦM̙Njs={6FaÆ;v!Cp7k'&&7x5jc^z%ϟ'ơ7 + ٳ([]m $55___|}}qww3Jtt47od24х19s??b]J5j //ؾ"" ^f9}VyZ1*M ujd2h+V`(KROKK+BPPddd`2lIRSSU|o&aaa;X[PfM233)((r(1zq qu=ƾ$?J6?F\K r}j֭4iҤX2W^]xkג 22ZjѺuk>3, VKҠAHKKF^Pp:4h(,,dʕ%LDD˖-bƚ5k޽eHeLk!/[,(~,Bk!ꅤ"""""""Ժu4hE;t~KnȐ!l޼Cr-JyIKK#00)Sƌ??G}HӦM4im۶1b<==i۶-zl'N?dx{{ӷo_~7n>?0>}гgϫyT"" 0.4OO{^7Ad 3Gj""""߭Jjǥ.o+~~ hCBD$66]:;Jg \؛md7x>. xW=t#}v"## nYly@"~@` ϯν_%ls_/hH%dLԯmGD^lIaHŧ"""""""""""vPB]DDDDDDDDDD*"""RM;;)-\*=='%jLZZfHڵqqqԻ{+&ߪ:]򦄺)[:""""""""Շ^Jfooo%#шw([T+"""""""RޔAs*zJgʕ+_ˋvq=PF GUn8L&S}O<^^###öѣY|ySjh"mFHHO<+>EʛիIHH੧ӓ~ 6лwo7olfل3`k#%% &?lI``m;55ɓ'yk;ʤ}Q`qhfڵߟ p6n믹m{?̗_~IݺuاǮ\~ӧGe۶mtعs'/r|Rxx8[[.'O.s?SO_W}ѣٳx@BBӧyǘ>l۾ KX4L̘1ѣG_+""""""eiǎvmرi֬Y|f}&-\{ b;̟?ٳgw^~9s&_}f~YbSL!""~ѹsg֮]{)R)h#G qqqw-nn˞ڵk:t8î]/iР`ҥԮ]B/^LTTѴl١VX~!~ðە[hڴ5//""""""RNW۷o͍5kf{sHH={d…mۖRsw8U4w̙iBE~gJ}([ʠM6;v-[2dcذatܙ=z~g6mbӦMLΫ̚7oܹs9r$#GdԪU#Fu4vEDDDDDr-aÆKaӝ޼( -[ХKN8K/D5ڵ+:t >>VZqRRR7߼ŤoߞEp)֬YC߾}DʘfAƍ%###/hذaO{(>-((xȑ#mۃvFXv+˚Ξ^l_\]]qgb4? IDATY8z(v !!͛7ΨQ@Z?N0cgQlvnęA۷IxxC-((`۶mܹǏPNnFnR%K#55,Ef3YYY%%NKK# ˧*pqqy0 (<^Xo[_\]fK-~}WE3˫N3+])Fnݺѭ[7grI`vw0iO/%El˖-^F{"ˋ'|aTjޅ WW+JϞ=!"dРACR u8f;;&e>(,,$??wwwgR4~4vEDDDDDDDʛf;@PPIII_fdONNYYY| rHLoh슈TJ;@hh(a2NT "44⠨*&PwBHH!!!E:$$5~0vEDؓ1Vm7qDUü?.~)z(iɿ "&N1cUw^ݟao񺝮c+o]B]$IRoqF˔'i; 8 8"h!atAb ۳_g-PTZ7 |b2$Q$I:ձR>Vhpg;3hGrDΣ^# 棃ĘN$uU$I$I$,%I$I$Ij uI$I$IB]$I$IvP$I$I$,%I$I$Ij uI$I$IB;$I$I$i?RqSO=ŬY9Ô)S$_f̘ ׾ĉu%I$I$IO0{lJJJ4i]㡇P(|ѣGwJ$I$I\,ԧOXp!555|`ӦMy睜x̟?ZLBcc#/2˗/gȐ!qi&qN?t,Xڵk6mƍ`Æ <30~x?x$O<V"JK/Q[[K2d̙pSYY;g5j?8v y }Y(Σ2,I$I$II,e˖-<̞=0 K( xlٲq2{lo?o<k׮Go}k 0c?+zraa0{:'Nd<|{c*xΝK:7'"JJJXl˖-_jܗT$I$Iz 8c?@ss3]vGnG}۷'?I.]7 ϟQGEcc#W]us>lü˔r+0|>O|u/~GyiӦiҥL<|#s=s=msg]y$I$I$WPߋ-++[o˗S__VmS=zKK G}4'N[ndĉ\tE{|:?x ƠAk+hۯ7x`yK$I$I-w*f◿%\\uU{A׾5~rE1o<_(v{~EE7o ϳm۶]@ؒ$I$Ieoo9sf7w\/PWWlj'ȑ#ٲe a d2<#Y|ֶ$I$Ix9K;z

5Ȟ~3R>oLqK 7om>DQD}}=UUUꬍ1$6s?w$i;5H䠿;RZfRG{8֤Թ2'9 @~{N|}m; Po 0`A=vo!I$I$IݏC%I$I$Ij uI$I$IB]$I$IvP$I$I$,%I$I$Ij uI$I$IB]$I$IvP$I$I$,%I$I$Ij uI$I$IB]$I$IvH@$I5amύMP9hl>@E@YxØjx@xOuab=5I$I$I}Ć& ] ^sBsZ--߯,éppJ-Ԕ\nI$I.,;@E]-[⎣NfذaAwIJ.]-g`М/^U= ӎgJ$Ia,;uhnnfԨQHׯgСX\uֱn:!z7;u,vqǑ$v_ 9DE7/G_6o.I$P7of̘1 4TKz0 Bq|>O*bҥ{mx#(^Xؼ V+z8Im pS˦fynV]0w2I$I;娨LERN᳓,wD|&QZ_}Di%ܾ(~|8ɴmqEl]e&.h4]XqU$2O>-s`gOK<w*I$Iڝ pqtW+XA֮͠Y @Wx˖>2BV-ibռ&ȥX=%H, ĝPRow :>4'ܿ& []$I uIx"6P_Z–~%QQQVɚ[\ҘM|-пÆ,Ekcy-9jLF=tn:q'\s';{x܉$I$B] "Gw2MM44lg yyNqҰ.N6WE@Iy2ĝ/ ٸ l^#C9UR5B.aClv4l )v 7[w5{5r |p|0:D$I2 .E~;3gdС\s5qq0*varW3y#,[)PS=xD@Ő$el\au].REl\YZJ(-ن؃ƭZo? aisBxx1iA:w"I$I}N.]? ϮNcԨQrn puロwvwrPYYwIH{ ;/$=ŋR(۶{Q(ȷF ٟUꕅny7RUQ2ݣ7oԇ0In:0͓~(r!|ix`!0ah܉$I$5;پ};/f񔗗+0g3t-r=p]w1dƎ˼yxᇹ; U(hmmo{ ' C*++ m߽()QqeXT*i;WDHJua TJڿ|Yg%v5=L<r O$I.b~:w7 ,8B}0dȐmSNeه?H$?Kuϒ9a loFe;w[ȷF(75*;>`vCZ럄G=W°$IXA6e֭,^C>M8p.۪ٸq!8;=Xhw;s9sX*_җX}ҥް/Jo iT` ^^'TWYɴnx˃Lz[f(Frl${zi-\vwU0m<<<4$Iz; =O8c9搏YYYIcc.ׯ3cÆȔf(++ek& aaFvP4 6ү&Ӆ;Ǒu۾#Xz5l-Zȑ#ؽya|GG?cVK.aQhll "Ϣk#6$XWoAux߾02W2↏vyH꾾|i҃5# 3N#I$P߃#G2~x^z%z!NV0env֯_σ>M7AE+V,‹. (.<%%" ![#S[>OYv?C&oYq"OCC+H$I,".Rn& /ysu?\.Fiu/}֬y~dhl.sۢ; lcDi-u]3uL.zHH3|Dz#Om۬bo$I:N&M/˶ߏ?]~?T555r-444P^^N"cX⥋5z4m;OК )4PΚEP>b8G g҄) L'_(P() T+S D,;ۣ-%I$u$ TVVAڧB@];Z[/cQR bRѿ60$S= }xn˖/ɤIS8rTm 4E{_e.N,]G =;$$Iz uIYjR$-\}-JJk)B$ I2?J=pأ9j455lRGhlncԨ ZMSS#-Md[qG <~S7΄kN"I$7PKrѤyQA ʫlOSʪWzEr??dy$nj;#G2l .Kf{$}#N"I$P6E]]d%-N5,[ץ;;r*+1id&M̖-Yt1<05#SZһ[YZ~˵಻Hgߒ$It,;@&B@2 l[y՟>^T=LvӦȚodbϟGM F9*xbҒ Mq'jKY@&I$ Ywꨭ$8=RSS Xl:jjj:$So<Wr;AAp؈6b$S \U%(+]SHjYw ]zEJ%I$< 0|p֮]… imm;NjժnsL&CMM Ç' Jջe>wn/L2zԑudQ$`jgRL~|pL?,$$Iz" !CeСqGQL$<|~(Dq' Q=ysP K$I:@H$Vxo;ͧN!I$'P$I 6OfǝB{Ypc)$I$4CWIN';ˇb늸 ;hDsBh8 l!ˢJEٰ9C,͓xB^ĐR$B]$=&ܿ0ڟ{50uDIz#^oiU?8?oeY+6+`Kam1 cLw\~w|DWuuBI7 uIw;IpL|tFF,KWv츿7!ߥ$IR7$IW+Nzby=$IP$I@?v!gǝ@$IROa.IAV/;#K`ӌH$Ij uI 'Oq!<7$Iz uI`)۳r=$I}P$I/5NjqY)$I$uw$INZwI$I]*$I|43V{ ]GګwVU\cݪwXqle$IR7`.It^y toe=;I3߮Ɨ)[QO"8v l aAc #i57tz%(xB9 $I}$I!rtzR pl%36F$1vrDΣ^# 棃ĘN$uΡ.It\̲ӾH$I uICF›qPGyM$I>B]$, qPGٖN!I$P$I:sŝ@m$IP$I:,=$I$IAzSI$I{c.ItVo;:H$I,%I[q'PGwI$IݕzfqG$Ihk!$ITrJ{1VZEMM }{>}zފ+̔)Shh(m^S$u\ њ|O%I$E>w\3o<̺uя~wi9b>1vX^O$u| ѲH$I|>7̰awKYYQ1c z!N=T***x9ScʕL2q/2dgqeeeas=NJ+8p gqm۶Q__ܹsٸq#ApwrW/rJJ xq1q8/$IڋV^/I$I$Ezj6n\VA_NE̟?-[ӟgy9sosR(پ};{/7xc_C466s͚5דrlذ(rw},[ sHɷI!;:Zir"I$=_֭[СCw^SSC*bs1='<7.ѣGS]]mƣ>۩cܹ|cL&Z\r /"DkiӦd3gcƌaΜ9 0;$I:Pe)G6%~I"I$i/d>`o߾f|@[N7nK.FnV/_N}}=lk IDAT7xm#Grt}*++cʔ)K\q̝;3<$uceiƝB<wI$IUlj?p4wsmƍoذrf͚/Kjkkꪫ୷P(h"nڮlz*VgN;NR$u!q'PGVwI$IU,+**xOs={?c9I&3ϰh"z)8ؼy3(3g?a2 ?0o7Vﬤ׳p¶m'Nw9#8.$INV{*I$i//Ї())ᡇ3%%%r)|eiӦӟM61~x.r0'niӦQWW@uu5_o~׾5RW^y%GunSwy[7|3$IN>dx ..$wuڪH$Il]t]t۷o voر|w+?* s\c'OWTTTJ/1c뮻:u*SN%RRRҶ=LH$8S;%IR[wu1q'$I]B}g>;P,w^tO72뮻7reQS%I30hc-%I$텅^.{0 ?Hmm-cƌו$IoⰸM=$I{1p@..}͊ >.}MIth 4ƝDSH$IڻD$IzD;:ʉH$IR$I!:=q'PG9Y$I$탅$I!:l QγP$I$I!pXSPVq$IԝYK$uG|;:]$I~XK$u;Gǝ@$IRwg.I. #:K$IڿT$uQvZlB.;!NS]]Ͱa 8RJ5;OǝDӓ!6%I$퇅Zn͌5t:wne :+˱n:֭[;$$@!;D*Q|$I$i,%͛3f  "?;+ Vwı|xۂQTh4Çglڴz+θN< .w q$IԓXK֭[پ};&L LEd &P__֭[8$iO,H:SJ#I$I:R7!+VNh|Ap 'b 0' C?ln~p յiiiH6m۾m6q ¡$tnK'5q$IXKЦM=z4d򀞗J=z46mdkƍ\s5̙3^xan&^x:M?ym۶;W^/ wqGzk5jK,aɒ%qǐNrw 3N!I$'꓋swi7̘1?;x`ϟ;!Yڰa7ñe]ֶ=r=p]w1dƎ˼yxᇹW_|>F*osտ |[S0˖-`ر1'e)R8(Bi IIT$IR7' _K :aÆGͺu5jA=7JQ__߱:1͛wپzjjjj2dH۶S2{}>---SRRB6% C>N?tg%I:y$|N";$IOot:(EQDYY^"ݗD"Akkk':6mڭܮfƍ|=jjjشid*VXŋ9374Gyc=?=\=vkɒ%m#ׯ_v|1c0f̘C*} R>$}3N!I$'su zn>oBUee%lkll_~|=s=pwsgsrp}1rH;;\$ 4] Nw >T/$IM>uT^|E TߔH$Xjƍ;655Q^޳#Fzj,%%%,Z#GxGM[zN?t?}l6˭zpyqyq8_s=2-[h-ĝo$q'$IB _?ϙ3g[jnnG9B}˖-=~.0env֯_σ>M7ݴkСaȯ~+.RRQH$H& 6]:)ï.y $}ˌ}*I$I' d2ɗ% gQ/LP8Eyי4iR'_=]wr| _`}fΜI&aڴiA#X|9͌13NC8_}j",7Ό;Iϧ_O;$IޢOBQ2 OnלQ3b*** eǩge[MM r ؾkBٳۮW^ɭJ"SԡT'Pz=Zq'ݾ|2N!I$7鳅ԝAȑ#Ylfbi(㾹\^xT*ȑ#{;<%L|emG}47xAOƿ 'ω;$I9OnQFQVVO<6IEA@E477l2x 5jTBG?w2]$IRgqԍUTTpӿ6nfmsҿ:( `.I=Џ΅ 3CҁNowI$I͕RRRB~fy0$HJ())WM"I}w΄CSCs>4=SynwI$IA@yy9qG$uØj.X-4=q'$I9d2R(⎢( dY2LQ$)#Nsr8YtI$I]:jkk]hhh6fQSS!$u̧VܣLy:|H9DD$IRP_Çgڵ,\ָt;V6d20|p0TZ*_? .< >q_we0pܐH$Ik,%W :CEd.>G; x.I$)UD$$|p\iqk3,%I$ǿH$Gg?'EKO >]<1q$IYK$ Ÿ? w}8%Lo5i{e\$I7P$IaSogC!Nvh\r4|$8Ө#/mDsBh8 l!eh8^XӉIzeQ%l؜![DPIh~ss ".B=VR~>c[︶Nꄒ$)n$I{σk<65ǝljqc#]h/8>:|oRkZ,~}VkvZG44$I&,%IztS" o!<,qjp`x"ѐD$IXK${_.<<{N9)ޠ8Z*殅v|ce)4NSjáPΦSFTZ1zڽuGxMe+|N!I1 uI.RO=wull?n pɎ¦&Xk`6o![=9?GIM%I(MAEJaDQ #owz;n=A|_{a# }OO2ls_~^6ʗ) #d$Zћwjg; T3jl;zt:z uI>*X|*cMŻeuA8]ɀ$w^k>a҂\$훅$i3Έ;#o7mM7o[c]V[1k05zg/FR\zU2yjii穧mjgZ'__wV=wI=L(ԟ~#HR7y#H=˥o}.Ѳ̠# "t 1cUw^ݟao񺝮UI. uI$IjB3휿iϟղVg?$]$I:ձX>vv=~Vkv$I$I$I$I$I$I$$I$I$I`.I$I$IR;XK$I$I$I$I$$I$I$I`.I$I$IR;Еnʝw+ >FeeeaR]]c-\_ל}\tE[$I$I>Sr9e˖Q[[K/"3f >ϳvZ~ٳgsQGuAzI$I$IRLh"-[ԩS~}.\yٲe |n+^x:Jjjjظq#sr0 yXx1C /_~q$I$I$9Okw}lܸ|+r- 6W_}f(b̙455}vn6fΜ ̙3o֭[w9vE?#w={67tW_}5۶mT%I$I$I굵?P~%puױ`zFA:w}$ yf͚E>,sSwu?OFK$I$Iz>3 W\_/̳>#<œ9s2dn4ɓ'/œ9s4iC aŊm-Yw}DQ˻$I$I$IO>$?Ї83x{KKK =-c|9spw9眳>oϕ~UWqim윓$I$I$u>3y饗s~OJ;v,崶rw83I~i<ݎ}'NyYv-O=^{-gs$I$I$u>Ss1|ߠw}TWW~aÆ|R~ӟtR8NO>v?o}[lݺ~tI\|]z$I$Ig|89ihhvsᬳ΢rI{mx̚5::͛7S^^Niiig$I$I$ Bm'HHϽ D@2$PVZBk&(-)%LL$I&$Yr@HO}D"YdT*CABT* }LA*I477.-!Ji6CRCRLxUkK TB@.#$-,k\Cߏu6ڵQ32 LZ[(--%JH$hii&ɐCmFYI aQ__ϠAhji&JR"Z) \moIsYK$PQC B+ CDX<ؖv" Z A[I%$ˆ Qk % ["(Ql#v;t$IdDy(BHa  / ;JOXdbdD24!rQ"u[D~?T "(Bx`츦a2ID0|X%!R( JICaY AP Aj1w*Ak3BMM?\+  XFBBk%3DDJr$Tl+ %4$ӄ/QDR *̤))+Y9-0$F4PNIIF *+̔rAYJ ++hظF#jɵ! [Y6o>\EII%[HdJHA˙B lk t2 /fi"J2iQd\k.B0A!,~TȷLKB>OAyiQt\>O"Hr90X|/$d+I: IDATsh V)bS1+8!9Cg@vue"AŜ!%o-Պo-f3@0yQ1!9f0$5;+X5 OW1c#[BbQv3ykb,xڪzMSsrz1qh-hL#1b^ڭub9Kkgwh'J{*hàF.u,TγT8g9:=ad5qa.lS9KNՂe_w=[!HJB3kw @Jg,U0dӤy*bJ` u0rd;FT8κK*@X,H&Mt$0$4MEJ{q,F~ΖxUUĨF1s:211$֓׍1# aVQH^wg Vs_,ya@ֵ'HI ]Q5ci3J^th2Fk!ԕD.9Q~s稪PUza"{|A/ނ`c*l>c\BKoY.8y~4u||1/]/5O4iҤI4&M4iҤIߴ*\%bEbF]h[So1YA:Ɠ`c&[4b1Eh$+ĨrdxVhx,bqz Z"Q oݒ3Vw{E!s.Py5qA=^u:*] Z'̽4uM^[$眃rlEXbLtw<|Id+v)eѝekDLc#NOb%M:c*AwXk8e)dZhk{Q`ZKe ڦ\s1oP59:͛7g99=m}QfmK۶0#Ŋmc{wlr$68=>! p%)g! ͘4_@*~m4iҤI&='I&M4iҤoR=/W/ U0҈{)l7R&a%g2f,L89k(=#%QmoլGR D[8爮 57z.(g16A=:(hFȂY1ޖJc QrVc#MȫJצ ~*:LJHUo-#\pa/rӅł8[A(; 5xkp10>&]rIm*K8">떝K;fs mتjnK`>P,w )&Պ5l-PG1J=˱gn矿ȭϝq.Oq:b$tNc,)z3XMo1I*eϐA3)&|k0(^$Ӂ ?9 1*%E5}(%85@6]@N [,HcuV1@YCS%DN؞sTu͡w9cR|u^%Jc`ƘҴ-:Ե2гyRE9,2 =[sՊq͛4m|Μnk*=}łeױ\-3g8>9!^!ۻ; ;fM 9|FQ?l1G8CumK @]gE}ҤI&M&C}ҤI&M4TbТ\bۦ&&EĨ NnqTք ^FQ#C> )q YцВd/^)} `IXխp2WTq9nYkWy /89`ͬuNOO|Лb+=Ɯ`[a(RASR` àhc5fl T8 %g50;.-кxIՒy)TX)jdܧAZkbi}m xɤ5Q⏲h;:RNdQڕpxx3IWUA= KU8rx&g3MW;BetXr||eX7nEtr|rSBѶ-gϞ:jgő-grc,K8rz|^.xՊM|ҤI&MMP4iҤI&M&N3`͍Q[jy Wጛӂb4(%*CzG*ki %x51q}`*bL4ʹ 䜉)S;LYv=xǜX:d/synył#.}yc:P A_9@80HQwKXTW8pcadl)@g3cJFD c Ιs&F5ޕ5n1U\4^*"8C(C} m/:Oɣ2ud i=04՞%3m \I6 r|X1qǬM:0c$T-;5F434M..q xd|EJ3Ut8Dss6s\x7b!p f;qyN Vł.\:$1U8=Q萔2;{b#{{acZ 9fM|ҤI&MMP4iҤI&MfUL 7B1 \#6 ƣ<}h)⥕n0SO@1׸+F_I_Һ $Mo)eks-UJ)Eƨ (XskJ:hhB9G50>`Lp_4_: )`D|@+0j33~RXozzi(A-1GLF)c1nϨCK;kJ[ 28gAŲj~`5 L:1TUK]{aZL[aLZvObyx[hO4vC~p0 $YsE n罢[ wTu@R7s AĐs"eـuBpg-I9B 5jXx1`VzrK<ėh'cQOTJlxzYsup.A{0Iʄ2q_SlŲߘޕ5: E0 !#&}M[f|vwvq}ױ=b{ڦ舝u]Yb1Tsf6Ĕr"GGGHfMېSd6q5ڶe\r\vvvY.W|>U gzQ D LSgL'M4iҤIz=+ n^5/| ׿k:lk_ZB_Ӻ|A~۾۾uN4iҤI1M I lHt4 C@ ҫqT`ϋ)MZJBLZHRY5Ǩ35q‌Y8j;NiL(cm~ R5ERpW9%膵ۭƒ5i T5Fr10Dr|YM.I\1 iG< ONc!*Ok0,qM<I ~Le`8`چ,@Pqbf!x@:5Hݡrigo-ԓSfȑkWBKDSU=1'viB3y]dqd\#7oQ9==m[ڶeRJ*(Z'ƸIb7|p69"d BĔ Gt Ťuj@[E#}OBQ*Nazo%E.,)M1s"1vSf1fpBJk|`mѾ.Du8 }OUzD MqIt ޖ伢2=({޼3ǟz,™=f._Dʙ1=!Tdtc:\?Y.8s^}89wèEMp||L:Vmrt0@;|EԤyG8{ *̱ӯzҤI&MJJC}>><1.5u~r-IlyO]q;o[[,KcF*9Hcrq$(cInc|ZG*rdI~=_B伱ټdx1c^W䬅90%aH1V5]X0KpSJxIQ$ǵ4Jk\o5`K*&JHdIXP+=ÃΝ;K#3rE0qHJKWEV}qi2 M<9gڶ1\Hv0H#YKʉ /kSOsiD]rrr|Xgo8:9$gaoPUc=0iҤI&M,5ovn~~|-̧>)z!Ξ=w~wō7G?ʫ^*>>|c:^W7c;wix:O|CX,|3_".\஻m4v]stt8|5y z+1F;e\vO|t]K_RF4iҤI&}#SBc%MaǬf/1բN 2jRduUZ<*k Ō_bIC&Z,bӮ?LN#Xb‡5? 0"70ީQo`t-Æ_ǂsض&K" Rւ)a_`j3n G8湵1QM%\@;d \aG$%Ģ$H8cz`Zd?u Sw9|г]7f\_ X=) Kcؙٟ%rAJs *vԵ"3K}"8樐,YP㬥rm8/ȕlry#;9X.d1Copb ;45]'1g-yE2R'Zڶ)`$3KC_A1TU Ru)l~}BO1*Ʀ]}GѤ})Eؔ:Ǿ$lϹ`0T."]^8sf-$fGP+0{AP$bdv"H) SyںXCJNO<$"<7I1tE]TU|CG|t}8 4mK#unpC 'Ǻ#vwv988DaSC?OT5[9Nj{ao=iҤI&Mgc=?+^wpwr=}w]~{3{x;#<w7__/9ԧ>?Zf9/3'?Iw""֏gn>[I)~r oo7~7yu&M4iҤIDeK̒$SdF|`F͂sX5)C1m=2 b'#}Xk8ǐr)gRNb@\)Bbӝ(Ʊ g g59ǂX# )pcc"KSp/A95%c%Iƈ['G)/uS܉ESrڍ\p9'Paa>qPٛ IDATf̺d5` xe #^RJu\{쵮u]) ><9À5L&DལrN8I)\H)2ϙϷ{{{gQP10PO=rEt[X-/'Zv]7ps.m; i8=:蘪cymL4iҤI&P>>.^aw}|so~3}ky'y[ʇ?a^W𒗼{ǹyG s~__xW^-oy ͭetX,xGg>K^XV vgΜG> O/ՓO>bMozwML4iҤIbE)P5jloLk4Mp?GyCy\//V_,_"GGG}շ|˷pw;Ǚ4iҤI&}%()0^$ő!VtV 9 xkL?*f%'Dˣ~;28h*|AjMԃ8My[B1*Y%flp)k܊d: oR֪u)yki䂳 Zk)xQ0KƎ#XAA"bV z-!)bǑG醁LLs)c'C9q8Tl 6eiP}YuPYGSUT.[)"'Gj g3vblNh-W.מH2緷O/;^ƍէ89X.O99>E8*WXǔ嵐KA-|ngs;GNQSLr`C(ؔDNjq_ղ{ڶe6$S_Lؑ}ٌdT8(:eCP-yvvv93"4[s5"y> ,Kq9Z熘Vv3˲E~GQxVgG:i0Ʋ\.NTqI1R׵^71ư53YIȧ F H87y+_7hgsnܼ) 845uS.:]pzrJhۖ{nL4iҤI&6wvvx"/^{{->3y&.]"1[[[k/~:r ]qzt ??˗׮]csz^wׯs>O׿ȏw|Uz֏\.qƗ}o;>(?Їx{ҤI&M,g)@Mc6bul99ER)%FM4ތ B$ޑڵfWSD-Űh"O(,\70AYUSb2BӔoZ)cRpdX&7 H"[t(cYCD*)|1#YnJ^5:~\b0N0VIdAz^1qI *eUzD@Hcg:Ȑ!HsZK<KUk8I#vNGLU\̙kDBͶuy|SD :GpV1:Պ>GF np.Ӎ#8rfhkrMK2'/ķ~f+VKn\FΉV g|=(2W^S*V[pBEJH)%㝣iX zvqX,Fh1i3}13_viҤI&MfԳPҗrpp>1\rn?s0lK^s|Cbgg{g4!^UWF~aO7ͺeߠ7 |y:O}^3u|#*>On~}0zի{rIL4iҤIfSIO#LJIȋ՚brA 璂򧵅CVzA@_RZh>f&o KE2`1sg8-%iiȢ&OT{Ƭq+k= qIA[iwHRc^t2decc2pٰ%K13y٩"I }o1)CR,&I? CAi8ɢ*LcDJR\bF)1!ˎ{b<;•vP5}|<}79Ez9;hȪxLnrb;HBP;G{`P p䘣crL킣!yq*bJ{;g\;0#O<Ε y髾'?p[~Ƒ4($5cT!l8uUӼn (ߔ{!E;+ ]w MKLZ 5KbLp>ptpei_)2rReM1)19֖cNZ`9G4xqJ< jkuCנ3ZsƗJ)caGc":MU#6#V59¶\zgϖTy95cc_89mͱΒ*H҄zΙNS׍왳&Eַgg7 U _—… O${ǯʯp]wq-l~9moZ]wK_R|z>x׼5_%x;╯|WMoz'>~~{e~o&韞I&M4X8Ζ\_4A uu.|ySD)ZH&$ tN$)`A_Q9Wb5>$s1"&LKJ4Z^ZUQLoK< ĶY@a!9BL .c@|Fѡ@NcA퀍z $&eS9C\QӃqs+&&j$SݨIR)18breeH?yrBGnF5l g,1E>P X-du`ibݻbB1}cŪq (c: *P񊗽pe38ᩧr.腜#q.V5O?]ӗPn޼Y|ٞ)D,LNm/~ϿU"_լk㦤VuV+&ˤIAurrϫ_oR&nIcɾHF9%-4p/ &4 Z9&M_T^c*?)OٖD# &]l1340Li DP$!D*++32qy^}΍D $ *¢9qv_L.ķ[8Ɓat/  WO,)i5azM[tƧ/z|aUsg>ǥHj[$uUp2~4UŃS9:t;qޢu,&SN.rS ^v۱z6k]˗/X̦xɼz~by}ڐ +NݕϊUeCX}Z9WLl%{v%naa-Qgum\9L Z^Vj\l'bvou=PוmWłIaד_03Rs]ݗfw.n|o)߳:zt:,e3s, gxqNtm"HJ E BӐb#>:I}~0m{,HV|>?gY뚺q|@J?ٜ/_f63c~~/c׮3lԨo~?5j_K+g쇏7獿L??I? f7}||إGٯB_ɄdF5jԨ:YY1n ll;\sޗ(R` FGLro]ƆQDܓYvζTr@1'PJH1S,"uc)pHo)"{TV=4P+$A& :3%FcgW8]TRX^,audzsse&#u熋2'XL[JR%;Eۭ;s_Mq8re&'K̙\C?}UeŞ9)1ZZU Ba57-"ԑRT_0,nJjKsW4l2eLQɨ9s{ v|t?8W3 IA`PJ(e޿GNtjb' IMւaΗc)CRDz]˭S//@L98:BQ~쌶n͆kF5jԨQF|j4G5jԨQl'ԝ]`Ԋ; ^[}V9YL =gjHD]RJYvǙ!Xg{7]d@]I\aGW=xChݠ%_04_MymoI8bTRXIµl+Ku u45*2 yRq@W=U8>C >2ve)`eyә?|wjbAB +! W \YRHY-U T%eb2R^m{N"3N$3gr2}Jc~~7Ԋ%})?5BYJ\3g>R6t{c2~j*<3o-@bSFDh1-_UafW Ĕ#%z}UJPYDQq sQ x3S63[RM2aأ1@oRn}.ر BekaRC%$L=e*Atn!%Z,<}7!bm,ha+ɭN,Ue8>>&xGt)בPU8!kYzc*(cC0Wu) Y7T @(JLZPbUNO7 US7>f2LsEH`=rmoos.Ϟa1_0/X-۞珸w(,TM vZmɚd^XݣF5jԨ/FC}ԨQF5*puRXjpQr}Z"ðEP 23 Ł.ftI^ ]!&Y`Xs!ض(\YK7ͩgIju0qwuQꍓ>VlU>fAcKDOzƛN ;\5aW&Kk&$ IDATjlhjfSjXu$>;?ǧbΤՁÙ1/T"i' hc;OS9shvkz`62Dw<{+xp6/>'prT8)7H17xRCCĘ)uMٰ*g2# w E1\%wƹ]Clj0LX,tMS>8B((7Z\Vj8'IJB-L& ý|{v Noߢ1uU g^]v[8Tuj-d'%'}:쐷o/xu}I]U><)1}&3ymGuzʫgO|ՔtwB۶ x #z7)k԰.f ׷UCKɨ]u]"`WbRѤ\0w1aq M*Efv;rN{KքU!5m`BzJj(xrRUCFCE?؀F#^0uBt:.벺%Dow|:(+rV4FnmeIT3!T4M- ͆3oq}.//XR7 CT^_9e~ 9'%łz+y5jԨQ QF5jԨ/䰤bQ3뉙孥RA8D,+$IҥTJ"^ f.\,~KMb)IkGŮjiM}B.!,0KtHq^VԖofJBQ_#)ߠl 6o1i4QScٱчlAU09J4z:4vh" pP9Ueƽ9.v<>Ny=c&\.Zwt݆v/ذh&Jɨ+8m[bpzzBJvT[LiUMJ vk )%+Ŏy|}b@Uy1%c~]&͔3m۲\.B Ef,躞v|~@z[G|~}Ūma^7<a L@ dFxJgb$ؽf+2)'p}YpȮ7 sVͩ'%-SFmEJ]W4zU`^와 d`nJJsac͛Ef'Mз.ub,wGGҒ|P=W4Ml6?,nLy$}znaT*M]}f%w~##sk~R?pXf}Dn[bV;jԨQFU4F5jԨQ_R+K:UJp>nCFYZzp!q].vلޒlm,gx I"@}QrLG:`uע:X|Mn.7DXjS]reH =p;;gǻ !aȆIْ ÛSs>8$[_ˊzzgK'3+.2J3f5)!5WY>eHWH;@Cu&\O'trk`vŋ p3rN 59f!'TuESW|CN)V d>krɄZ<] )vW\knMw|*ɑiJ(gGG,Wk{ĻbqxHV&Kmj@39d*1EBdIh@*t@RUCdTl8rBw2lݽgFn"9/tNP;Zy3̭^;S^U1C&SoXvt-ChAs"iovw v۽{.=>fۯ`wL )=BgZM_g-= O&6mK3pzvKP}6}?cŞuU9BٔQF5gH>jԨQF%.)Ydbl'3} ࠩ^&xNޛC)upӐ%+pj&:Evc P=⃥-soāĮ4[q+O,Fۗx9~zArBKC%9 ЕQ;WA3=aA#.&Rp@;#6={i@Tmo}v?G']@zdd&w=xNNxyyb:#odi?BUǧܚ͘T5]Ll@fU!8 ̜:4G28_)YmV\ãSN ^/Y_.{rĝ۷댜C^<}J۶lV+&̈́+߿ϼy*ܽǽas p.3#l$W1e3b2c>d-+E8P1~< =9L ל4UؗjN3Nf;22 F egr;gRbYqE38%DZ2OZ~,q? `i 1r&4D v_+ɄOK%n'u0a+gy}!mےsb:@>4͏y=jԨQFh5jԨQF}I;71!W"/ztk 㛂tmX#n޶n-12DUC,ZF2d3U͐.z-f3-&Ktʙ< +] 4hPHƁgR6Pp@Ҝc1 # !S= RBζt-Z: ћS y57f+YUn2Uԕ}msbm9[ش=z-Nđ ^IKIs5nK48ق{ ,8ϸ=s*P;ǢiңC@R!Exu9>Vx_ѥ'/)G9,4Cpxpȇ|X4)ɵ=1&&)jt6M'Opzzl>c\0G5jԨQ Q~*<} aIΨ{5j_,y7p)OOIj\B7vh $BO1nfm8)U3T)Njۆwh,ү{dn'KJKFTͨWl( Ĭ/VrZR]>׊ShNjɒ2<Ι%e(%)p`윐=>}IT,,KI[Ď'G?$nWTS ÀIK!bR=ܘ-$d#Hn"ήg[ANm%7zCL*xrAX/nTV> sG](H1r2vi9\A1}LlH^H9 {ǝ; ^ʰΗͩއRjHv'hŧl`џW׼/G_ʻo=Ds-~`^3l6z+u]#X79:O~<5jԨQ~v5F|+_֭[0ަo*c3ۊɾQ\w>va]^W)  aWzq Ž-RL=ۆ8 &YI,!Y{|o (f:C`p1%%C4C3JZ$c4L8C͈bPo]g~fK ޒYt3ט R8J t]Yd8%8QOʥx`cT +d#-| b!TP{t =Y`"G+o*d:#4N {Kҵ[hA3ٮl|ŻW%v/ׁWv5>x5a@j9z|Rk9nyc2r8Yo}N)'#u=c}qBfIJہfՔ~o=ۧH]ODΖD7HJ !biu㍗K~ڶj9K ,.fҮnFkCxf 12kl7[|?O_uNK~o 4 f9%_2YtzƉp|fjp||Bx5jԨQFlhtF)0 L(|>n]oip|_ "puykѭW?PŋܺsJxkn (tfCr#\bxs%N0K([PũFoνP4) Дs^fsL&=K[)7ϣr]tw`"Ƅݒxf-Oo_d}7r}uM]W~ Z@cu63(՚lzƵ3zԨQF{.ׯm۲3L8::tQy_ըQ~Rr!ɖ5Z` LI+uo;P3 wͅ,$qb5el` ق]K2\v:jfl@XY-mD,[3R&%3 TA3U9AI]@P7YoOHmGZP $+o_㭂ѱvJA2?:ucYjupZjWOTsn- ::}Id:ݶ ]Gv;_}=Ny_==9999f)^fd'9=aZQWW Qy IDATn ϠoZ>C>^]џeb]-*+AJn~^3ř}S)4_Rv'!8xg+<,G5SƇg+IKB }2=YWcڧص$؍5C%+z2`*!vo{o^ij`C-_t6Wo~N@#Co{޹0 tJhKzݶ,%?4 |5jԨQF,P/ÇTUU0 GCGnިQ?׾5Q)F3aG;73W}?(V,ʎniooygliڜ2s)pNJ%{ИA:.TE.pTqbKh+*Dgٗ8n}IٗTQKk]Y*[Cd4"~_@ے iEdQѶĻLFR>=]4A2hqGywd![%ᇄVZah7uw".dqtDH9_=>bw;]={N?D8*'̛P.|9 +nX)uy&da#j!{Ŧev|wuvӗxZr Aruq!I1m:<wl,7T+a3kHj[&%NNش+dB/$PWffD"tRLk1 Iz眩A`&t3$w\qî<)+v t-;>.-AG+LV%;C59;o~#IcBU/$3WW9<<,$1fBwR?R^#'1">tjV ^_SU|qrfY\.999e:2L̙zCv̦Sf9neU1t]O]UoG5jԨQ~ ϟZ_uBiܾ}??{ܹQF k>>k~߿t:Q~Z7lf5|õ*h7^YI )&.xT-],~GlC27R,Oۥ۝7 ?'3dߙ;3DwQws>\D7d SC55}$C@/dٔ\ n v;#8+l9Ϥp[NmIާa@BxoQv(}%H+CǔU >'#{Lk ah[ v Cf{Xǧ4UŶoB@1IRyU-ICzI¼jI/y5DQVѐ&jl:O/YpZ^-8bqxs޽wN,%'j_vK2 JhӐH=b\\b>&mu|JhVT 4xbۑ ]ѽ FzNvJh*T)mlrdR8lCbu RR9]1. &U*i2`o߬ݕ=T CG4mUMO>*`zUUTU1jԨ-C>#ܽ{??ؿ8x9χ~?Gh4GeT E,MB'Pr,.$z9Z{)~[ +|88%)cg2MZYΕRRR3ssJRXE` D ƌXٗ>d7 !Ӽ91CѾ\K{jIE#W/mZb& ]Ǟnxw,5jԨQF;C=̧~oo"///ſT5jԏUO<ᣏ>"?GGH}ԨQ?ϛ %,$5F~]. w"hOȕmW/ qdŗMP2NnXʖfxu;z)CgͽcݹAH ǰ}Fɐ4x1ߪR ||jE~Iɓa =&ld#GAĸ9bh_sVSIuː|ꃙ#xjݶ n4kFR@Z nH\:>\KWC;gyeLyŬj8d:CI<8(t9CbbxugMSW\Ym7LC$m&x:v]]!o *W\o"Ry9GG']ǟ WW8q?a]$ˮro9zT*nmMKmi@f$ Cf0f" k3t 4nk$JT=sޫkg hZ%UIy*gq?G?\p'%1rI3I"u]dޱin} 3xW!U׀PG۶f0wڬH^uK{'x/v~RJ ^-R0)'|)v)W}6X[8"B,E_+rkHDAƄUf3wK@J=;s='> >Ϯ&"\|0ѝ4'z3W^ q]&@Z'5"oR R\-3bE kyEq*hHjYIZ gHRX1[7uVdvQ5,-Yٚ ٛQMVȐ]1sY|VrxW% 24q&$  n&G$GbŤ$bR(bC m RW^z CCC>OX*Ν;իW]?=~#G?Q9w!.\۽˿:- W\S>,`wסTV4[JW;}{OIFdBX28.]LTa=ٜE36T64#b8̸x,v-5ٜAoܺkKOqC#] N̴)r)+v<'Ul]d;]`0`6_0pB^Ly+6gr8Nm+][ʋnT)C0 sA$f{;BV:{PJ]s%P е-45J驪f%TWPp+"J*øtɒMӬ5HJMUSUmRNUun=Ñ(Zfť54MJ麎|IBUS}y׸y]i,Kx jjp#9!°풶m9wӳݫW^zcg2zkb^ߍΝ;77۽ԷE/2׮][3ӝsگLKSⓟ$ʟɟsGz=2Smefc( |S5C{eGI.*X=Œb|K0 ŨSQʊnċT*-ƏUY]Pf`DA"u0X9fERpډ}-ffj+N`Ib筠Q9UaڶI&KN0A",Plp8$fX,ݦ<0mp:q<;ū45|7A}T crZw_`J1CZmׇvfs"9+U]{>IJ]2jV $$/h!T*u5X^| 8$"^ g;tQ¯KNW1b$ 2䶣Hgw:R,9{RԒf¬`iU_. >O v5M]_'.:)_y6F#vw]d.?|ޡ?{իW^OmR?S?[z;TU\~0>?/~0lɯggoW^ڵkyo>ϭ__>I___|_Ź-[K^~JbF"CI 0*dK? eEeUPŘ"R%^qʺRCXE,= ,T.TwC]4J9h >7)#0幮tPNkq M Bn[ m3ph&vJ%_* jVZ#9v&x6Fl&Ғɒ4] 8aٶawsAdͦ'8;=e>?|6%ws-kfW5ĉj" 8sLܶm)Y_ B <%Kf@u.FaEd\pAhq4ՀEڸ9>`t-ìUǻ#&•Y^l9%wwbgg3׮?'CT 18x>Xٔ{޲v^z_>9<< lFm+h|988x}__QUˋ/~~~GGy׻]]z׿G>53}L~w~o|)ׯ_͛\v_ԯ]f_zRz w8 $4cbjpgF?W%uL[FAC,͠_,6cB=Lk :}?v c%؀֏ YJ;%3Kʖ⯋H)UR{rp4+QdsΕ&&r⻄Ц68F/dRLC\X#=UhCkDCZdEJAԍ+,[vD\A$$ed8 Wzg@S"GdKϖ6(定2yqmm\蘔:rqh΢Y>яꫯ>1^ʛo??e^x^xsoʧ?i>OMk׮?wdk^r[z ^db+sbRVmْy!#QP7*~%R bJ*p9b "]-vwV,;ѵMӰ;[?8xƛ\xΦ3Fٜ k-=F c]zիWz /\zuvcdX3?3lnn~WqPyAy////Xַq}Ν߸qO~k͛7sxx}YS^ZɹDXUy ?L cᕬՄJ&L ⭴`ETx읢)*esaU9nVHMbPRgUccUq{Y- +6%WErFBUKjT;h#J -Jє 9$[BGJghͰ<XDt*V'S[o6KEͰaM4KʤH5+"֜u6q2NCE71P7S7,Z|J1pl 417-3 癨C_b<[*%`äV&vM޸'/^x+|}bȳO?|rxt˯^g{gG\taL&.]8)1; a6sp;_6NJFɱ+IG=hljV+k4ɪ\(Yq ]]5xNٸ!'+#B4yt3f p=Į"s@E2 N|a_Uri;0*X8J%.q֥P!jVC]߫qLuB -N8[ v &<|l>c<SW5҆c6&bd02|.99:fssn;ǽ999FQf1ċ[{իW^z@3766t_oI| _u]xzz0ԯ]}Tux?>~֫Ww간j)Lk\!G2Pu-bp Rڔ6f(jn)%c缱؝BN:*% I#d)ȗ,6W- !ؿ I5G=焧) lP[R;Ԑ f&-H ` cUs1?%cym`C 34*98R2 %힔* Y&LW>H]k藜Y,5s.R焪":%Gl[{ s2<ָ4;3J;R [UfUCp)' ݜjf3 ']^s&nx7sdws{36貣9g6144!tYdcɃŜGw9WМkʥ\x[w9Dž Œb\stry;ūO!p e @Ll[RRiaUPU^)i#"/t5%cs焔o m{\aGk M! GY3~bd沞Rjw" \AĘJ%RNPyI+,MyN+$Nu r?H߸To1NM&u{EAt.93_y+̗ Cvoo9zP\, 㾦+k٬?{իW^O"•+Wv>~:/Bʕ+})`^ߡ~w^;^/_楗^+_ '888~:W\9<<y饗tۼ^z#Taf"+t]n)f3Y=%3CUw%WhʋKfKBJ(Z3f|3ϝxr}c;C1ݱBB!BBBU1eAp<.  0,s 9w0ߓ=FdA *ƌ"N eO)yԸRJ-\ +5ԆA]sBu&i;tb4$5hOΐl!ie;m RUXq>'M&9>fֶ 76HRrAXȭ(W"97B9-xhjOJ6duHFx݋rbLNN,9;ÃΦzu}tTxxEflbmdcc^W'官+)9Rhg^.HpNqef+yRa;q8+UQC*QP0'l`c]+8HNhBKrn`'e=(74Y U@N#{b>M CDX? *jr0NZX, g%d)l;nzi)[e8QC\t9łAݰ\.8'K!'Ν?O۶ C?bww&zpcM6xp/ymtzl:g:wUw^zի;C`0OsM>/rE:űX,u/2/^4Mv/W^?o&nZSJ|3cغ$C.]*ɴ^z=Rhsfth.lbaRάsܘ{bJ:_՝:3SkT@!@e]n5"+ϒqBq}S9K޹ujNf* o}U*pɸ󎺮i Yyr^{uł9cd>"\`{kbALڶe4MSbّ)7_ŇSGիW^~X`'|-ݻ7M˥}`/;;;ޫW渚 \V?{K^bYYSr)͊:Ž&S-݊][!b veeZR)bMYS3hL8XRJHZ_%R- +nW6f}6Z >o'A`_6(Df@.j//-"] ( /Ŗ"ԍ7!ފ^mKily>[ Sc1)F4+}ooq-e˳>˥K~:o".'g6, esQIg ]gy)EwU- ĭ_5ӿe3y1LLlQb2Y1U]1咺**XpΌFCRk~`@S7\x۷oK|2#0TѝW^zíP}^u^fX_dMzȌp3XUkat9I"٥dF psI.4A2<1$l%ف$%3jK'g#^5V* ҧb/&%ii!};KKy -嫾qVvƳ0S *$KWq4F3oA o#K)h VoIp~s-3^{5HٸΡFc6$L*C f\LlJN4ZBДKOIweȠ٢ L~P2A @F5+=gj5Sà6,Ƽ@ؠJdBʸrGM{t޵8y٦/ft1 @8\<<98xxN˱(,k1ƺbz'f@LKJ. t58p2ՎadbI"'E`,fm\ 9ŠHphKRr$UhH(}pV4Ԗoj$MaޒOfAx`oLh3̺%NZ8'GU8>;}u_ٔބ\?}eR5Ȋ@st~fͶ\u7Wӟ{q/BWT")ҖpH6' % =nswf5}@_(.M97 f :eƽxͬ18Q'!&L9"đ%‘9*0ԉ.wTLA f-ݎׯ_suuEL4^oI)үO\!"\?} '-ZhѢEC}ѢE-Z U{ᤂ).$78 fX`Rܨ꾶F`ub3%Nm;|-f'%F$8혙{m&#&m/D7e?E" Qn&v3uƲlVX OKXQ>rO9p Gl9Eqñ#-̸sGhi¬6~zD*'V *μ׆jym`*HX-X2L *`aO}=G%b ZFWkN-pu\tӜY8=Ռ[nTaӫ ?y-'-0b(O>_+[;K^5x)j@-2MLWv4C8HN HѹC@ZA{NRnHZ}`RJ- ԮhHI)9vE}%BnIjm(9{ޯ5C̆53RO?ɟ`S3C}k%_3kĺn((_5c_urzvp8]N9K~{yjqy}8ݞpϤJH&^߳lnV=8pG-wNE-Zhѷ-ZhѢEo #:.6J'8G;:#BE4F:FjimIXЦ&Xbv:Kc@ŀ4*B+1@$SBUNnSɱ5f|V:ZVDȑNQBt̊easB"o/CAf*@P q_&g0˭ VGӤsan!s q3L! Sd0 cL2\Cit.ujJgn/)RɄF#ׄs,$$j T'z@Q_Ujx`yww=1qv"8N &6cA \|s}c)\]\??.O Iv\^\1B)n؀D噘QƉC29&C Y0|e4IhCf<Ӗ9>vΙ#ͽ ɄB-WhFD9S9mF}p@_16wwlNI!y񨚯PGd4Ht~{ >1w+M={::wr3j|/99pzzbt^= ;ՊW_ _bבbb:vT&R-hѢE-ZhѢE-Z:36#,n.*U/.un)"n"Cwri}4Q/E7 s )gΥUjqr[ U djK$07=- BP1rjLCOKΐPkhF=SiCAb+q$K{<8r~Vk|j3%&k=F$"EB{ԠL wG3VT *ikUۿbtɝa:7M=eOzr ]rLpNmZno!Fvt=֧6[;`6 ~m=;c?('W޽g{˼z 7wyus)-Q꒱V!BLzDq8[eiL#q-3-). cXSbGTѠ|UK3Q,iC~=SJNjlV _o(.a.8},f 8?ˋK)9g{,8YX, b CAWV|:"}߱[^g[]Z&V'w8==#ax'_|g^#hC1&$it+:bLWZnj:vDL<n:hԓ䅥#FpQSF H0̜-4Vg[witЌl%a V-9<k+Cc( dDȜn꯵ > Ӽ$!e͘Gf[UʌcW~E# %e"~m,gW7H$8*A"t Hh@R|;4:Xw[";ݽ z—A8GkÎg])@cdYq];|Elrww_~qrԏcwe~4 sfy9Á{2jeV5E"ZZ!s\|#1$JXP$:#WZ pL*VA]JLpt›fyj(*Zў1z/CGДb-H!Rf{^zE"UcG$JV_bx+Xo,J|>ݞq<Ч 9g/ݞ V!:g"'[pyj?w%H?7~;1R;j!SGL! T{ѢE-Zj1-ZhѢEPm3b*V] ``@fA ӣ!ooW n6-qR jXp<4tT1o( ;y"O̓DGSv>GSKM#ڎVhĸXu,VI ڒŰR!c1iErVK:6ZA}c]dwq%dB e#~T+Kh)PUKl[ + <:(i-\zϫ2 pzl?A+Q*$|2esL'|+~q}qa xw)ebp{"gg׿b0'rdunxrvAuD Lww(o^cS4t'*8ϼaa=G_ݼ䣓 &?S'dg)opys~W}0rޭ~]䔟՟3ܿ"}-jzllKQ#KZ*;@VP@ZZ )Fb3[ g A1A>G:>MD@KL )S!LSo=ᦶ\\\fԌz\ac'zxg'~'Q bdw2"t/uU~ W1!15gHV ?яl㒻WYOE-ZhѯC}ѢE-Z Α` 94ox7C@bf hq(nVu#W<Bh?7Nzi>9~Xv%6f{z8x#:M.sq5W}6~uf'wߟLw '9s38 ỗW\^\q?|{mb]x~u/>e:γȶ_cПOٽzgHD5%C(Jm7 j˙`tLvwn|\ŜIPѣ$ڒ9%R!4],: A#"̷=džCȚ9nfb$ Xʀ3_Pi1ZQޑLN= Dd4Ma0 #1qe [SNtk ݁t_suuuLɟnO9p{̌PhѢE-OZhѢE-Zjt-Ңn‡g̎9b[$BKAnӖBu3F7\g4rCE`LhƠ"c^4{7CcE]M f7fHPC3%x#]Yh|ECBmSfcx>͐fJn@|OnFNpvw JAƱ_Xa4T&e0б=.!`igG/Z⸥I _oX}3OjL%TH>SDHAUGFFbLiA& Ejfw H0S]3>yTZe;/wNNs]2LhQN8?/ "*HRS2C匪҇9%JcXuIQ3 Iаl0;rrrx)5R 0 #h5V ͆(_}^zٞ8vIUV꘴Ve(|lV+W_ԩp0ᰔ.ZhѢE-ZhѢEoL14ijr,5Ӧы͊ilsnC ĄTq|ZmFl[K l.N6MqjOD%qixO[w>i.Bo$q/V " 8q85伩x$~g8"K:ۿOȩXciiۛ ' IDAT¥ ;ee ۍFuG nQc#{ Zު'DzJ_rtӽ__qEt@Qd~b1*$f4UYmaV۳ZA#ՉU۞nQx8df#I"izGOOxKYS.N8n03?#/xS(cÁ>utg}G\eSWZ b(U'bl*$|u@ntD.rLSAb`*"pRHX`v|V0Mr[ PR"6`Fa@CLqɣo{+ X|HSu38/_fE49) vcYԆc.A jZQv.v]f>3WD 9Q}٭a]Wއ?goc('g\|rM}M"8Ukf󷱔9=Ys?j|A1/8|K1$bl(Ԍ.%OLjՆyiægn4j!T7lC-1%)#hbmCt|2T92F@T--34xyh >K5_C dH[AkRLZQ{ǜKB''=n1Dk:=}gCk oζ@`u//^rs{˳go[?!Z+77lVvPj RzF/ZhѢE~=-ZhѢEoZG!:c )u/&rhjn W XKF c6؝xļ@D:uI RWl-+}vҶ战` B>~U[%7KX rt[0`ƸHmvKKuVZk3q?EF71241_ R:ITuf*#W;`;06.zRBlŞ֊!MVjX-x9g} &ߦ0j~ww!_e`905");}<}]^PJbc|#|՚V.7k"J):T+c1~|"_9}︹lʯ>4?Zoys Ք0BUrNVDONy]9 3cb HVJ|5CUz@:čbV3OeЩ |5%/j'䔜2'''ZvuA,ZhѢE-ZhѢEo RJK1s:G -nH3 ы6574vCQXlŕpwз@pH?2**KG3\+6dD Wj+⸖`{17̓:ؒ@XѠnZ-D F/_OZm{nt>f7GYXѠݨ6O[HBR 4VRYK{O+βGI^J!u>$`aUU/ɷɂ@l{ q6+`gthݎ}U+} ֓v r_ |zqvrJZ ?K)l6R'n_{'PP(ej}Cfh~>T+Z+!}8^r׻RfJ չTy0wG^`R$u)y:=2.D1iC'_Cp&zFwUZ{RK[3aN{ 1e4dAZjT-kb?uB5 !QKo{0{\574KBl7^|fggg-*8V=qqy~ yhѢE-z3-ZhѢEof|"R@M:M$'4qnbتC{Ou (nbWmŢώx::$7p[Rsco d7AjiaZijDO;7]tfc~:9 &E(l}Ye羏^Hx_ *pz늌c}${!H 6kV 8@leaCBjٮ`}0䃧ω!BLu#}M</=-$G}X[qjEQ}b$'Ot1?%/3= +~_o8[mׇ+~Z1^'g}=no>n9XoSxo^>e{rBtu1c`FVNήx~_?Z=^(H<24!@-n:Eϴ{BL銈fLwG|u>1E.jfxKGYW?0W#t8r&; Ҟ3bᱬ5CK9 bGF٬9=ِ2Rq RfvT9V5!GzCU1W_sd70M H)9>R%w ^hѢEi1-ZhѢEPY 19F%9 :PO< m6%uIP=5Oي6C/')R)yZ8"p1=ac9bVD9 Z3u$+ tm,yRi ]}KԷ#X&3/P$>& 5GȄCdž `TZ#ƢJvR$L.`Yg" > e¦&7=uaBV, (b~sCh,G}(ȜƮoxZ l )* 6x`d+*wnϋwH2_}ͦ\Oxrz&'6]6j͚ON|`?~].=tMg~?9c->wk*L0tY'Uhpoiu(VRK[K)%ǬІOr4k襣S="[tf#$JFȹc˨ #x,NڐV*l:BK *AQ#uRZij;/5_0 n?W\\\KV]0LrjT*^hѢE0z-ZCo¢E2qFT0b6k0b^E+̼LGFG'܆oeBY-tl_MaQq3k+E9-ΈnnQ%7c7h Ԇ]51: M~Oz ){NofTRzEc)HRNǡ3૕v/RB )4w'ks$4MI!`RK&f:xhS{~Ԗ4G XJ+q[HÂs0m lNN#D ~sr fֻw>K='֫5Vb|Ƒ77|ڢE-ZhѯЛhѢEo>MXhQCKf{ WҰ,3E$jCX~nj<:Bi;Z?JkؕD0fG^ EtVZ #^X_Th`!ChZzhD;BL(ЂŚ)9fx@UJ3VECcviGX!%}֝bjΖDlت#u=1B>q݁"g7MmLpRbZѯV{0xzzwN'suSE}R{V!gyg~ꖏxRcJ3cJD3R7OVg0M7?)8|38XWx4{mp1 X1fG|N%P4uT V2#V}ph&?f ik[$Я:j-i"ƄiMaXmܼ2)9}zdƋ?vnoYu;ʋ7\_]yZhѢE-j0-ZhѢEdG3hn@!|W@h  nZWEbBn=A g-}Xgp,cy Gg@f{GP*0QGа)$|"S) )-&ꅘſۦB0dֆQ/Đ3OHa|knPêCJ lrY`BFѷ!&BpggF R=VFߝ!'ar.ϱ.6n<` (w"Sxz~s)є'[T~1聛/?Ք0N#fnZigccFXt?}uq%1D*)j3C3ʏ} $PVfl.5}93)FPA+ş' S>ѾY^bD+.wDZ 21<{^~%f#Z3 G+*r{wےn5j OƑɌ3}E-ZVhѢE-Zkӝ[z+(-9aRthBRl Jnsr&7E d"J "QEʼMkTG_U3bAڶ7~@H&O̗ydА5^+6zi`b Z`U]ni?Vٮ<>GӤX.4!)]J!ъ =q8b>hnD~xz~x }wYP ~$uUP/ZȂ2E7czA@P}Jf~-MuD9I"٦pBIhFKo_r7qWlSOWlb'ƻo 89Sl^?p=W؏Ll!jF@2w W||fwKBHP+V+1$JW@+&-)$ՙqlFJ D(b9Qa]b^_kSB`PsDJfתz4ٓ9UBlVv:oۼr4<"Pä3 wܽx`{vzszD6W77{6''w;ww1\_nrHʠ}j;{9j*xPrƕBNb纷,^ǔરqc;9ã!pQ՘S.^X-jz(vGD⒒39ܿK֋j+\ 7ヌ)ij!l-\->_q=}؊Ӫ5f~l7[V%8 R }qzr`Yn'W%G8L0^+c?^]>Emug_})=S VC<_9'%xö%MFBQo#6[_Gks̛ħ }/} 94MOX, ÈãG߄wYf͚5k;U>k֬Yf͚R&S=K IDAT\O,] V_MKgxw&9583R+UFQ4ej(5z\qCk4~`N=JԳX j hI6 Z K=Z1he)Ί#pXSR_by.beDK}qHI{=>Ox3^>ף2LCeY -GfOe# 兡m\yvL4Gh؛A3RZƃz{|.`ocN+LBF>|J߼0Zh-s%A.)1@ʅT27GOnpvD(Œkαж-o_} u'%qP3R:s)8gxbc-g\3{kJ}{yJ8bд~;|^ GLcTw[bV;?zw~;}&!|~/O>E۬V+rVRJbi ^] G݊GT3)Odͨid"G ',BÓ'\=[ g7dL/z qM; ׾eoZ,+["@wHhn^ YAbċC)C;tiH)ն M-:s"ٮ ź 4!ήݢZMZZ}q)&֔"6ţζ)"M5m/)QJ! Cݥg$ N 2W, b_zmWyCC*A3)er)|ŗHHNS5G޸&rZRR-DΙbQ f͚5k֬YfC}֬Yf͚5+sX!aw)T !+A5MB0cfkε<ƚ^1o^Ր4CB^swrL+[ZyX'bXcBb$c7r3n9ZDNvA9ۖtIYsNW\]]rIzngkX"V OC4ܽsS~U]zsm[-͵4פ>}B.9w& i=^E璵%)rji>bD޶¤~nC݉SΝ;Tsٝs/P )фhϐ7d-WvN{?zȢkiۆ30^Nw[...s݋/W_~W^?_ ,V+N'){vp||Lbm5k֬Yf=/Yf͚5k֬w ٌ" G2KP+Ͻ I,Y.2@eWt ⌛<WdRV5͚t UglҼN= ͔QF}ւS(d6 dy|WtpmkK7s['}w0jlƆQm)YAسSXԿNɒɰҴDf@lЈhAzJ.X*;KgУ#4D$ͬ:ۋ2Ykh{`׋(qg<%bqDrh5|Q922TV~Ş1Sro !vG4,-/~1>?5u  v 7oqԶl ǹes(ܺs{o$xzy!ywjwVlXqzBoksˇh))mTSWUXJE$Hp!D1'@X|)u;%<$-HQ\*MS.=m ^f$Xst|lt13yw(9:yK9^>xP-킶Z`^_̰WCwOlLXtK4Qjz}LBt ]puE-׻o=yk׾̿qRΜ3g͚5k֬YP͆Yf͚5k;TRM[KoUZ_ES(,۱)rb8V0õVdO>*{m\lf}qtR|} 6jlQX!}R9R#Lن2J5CUJm[hSg`xE=LW9\6^ -߆(ۦZj_+7Z1,: QI`F3\XA`s~n7&ʰ-C#ӥ+Ђ;Zj jR{Xtv>JVsA :Z|l("Į/.lx]q+0H--SB6[d#M@=xgüRf 蚆['t!0=²mqZXTp61arE)Xus|.7Oܽs7{[Ͽup (iYSg o~CǏ!MwUaf0y\~yv?zOx^-* )CI`6x]]vlNٶ̜M Tȹ*R3{ifLFb3E/]l4Ѷ!oɎ!.W;K碤qGyZ#T]]\r~Z?~eӴ WWW8=  c#|/TYtoлYf͚5A>k֬Yf͚NUVJ!h-5Kg#^j&šc2,ʞcOqmcWfbCLcM|f,jY+%,sMcۡJLzלqxD3&jWCPRBc5gk3"D2Em\Mh fH &;Zތs)#Ul@jUS Np%::0^$T6wF4>A0l.袵T@!vG#SFwƉ'j{ml~i? 4 oƶBRJ87GJ 7趷}X1,arI$]N6-wghX#['bdGB?4HEY@aF.-:M v6xkƳ oOӀ#:9]0NO9./T)ʹ΅"N& NℶsN5m{/1>ϥ"\5K5˳۠{wf;QjyKJeWud (|kf\ߨa'Tw=1i}0 ԺM;R 9eD%}x'Eж8\\\xiB Ͽy&^x8|;>9LpǏpky}5k֬Yf5U>18k֬Y9~?o̚5[\U1sq.SY݁7,xC%QEŊ0%xPK>ڭq zl C+iS뾚ːţ`DAWq٤ь=¥X*RELK 5鞲ߚ--PP3$T&Øf߹=<spX:2cR1)P¤u;ޘZ6"jqWnqE)甂t?-@1"݂"ӈ<٠Dۖ",e|(5;A!UlE K-޵f /lmP"SƊZ&ƙ&r?3r@'jIZ+'PBXvS7 a J!Bc7-n`JKr5"۱V~-ę[ fzub>ca)10wR'kbGo1#7Hj#YX.DAƁi0˦rr--ʣ94p&#n'-M^YҶݒ[wX8/_%nI}ߛ >n z r9%Bky_98MgrwUS9!;CM] Z,J]VJ[ #U+e?`v8a*HǑu rɤk֬Yf͚KhKExKq. TK-Pې bd"H5{{$3F:)mf) Tİ.3QÍ.ZrzQqvAW_]wE,I=qMcsAB5r\0nE**DPr}3~E)IIМxnq>"Ew=*JB=X-P5?[kF!lB 6pqLv +"l^)C.H QkpEa5Jq)۾lcux҄z`m0BDro\l]?Pˈwq7_r ,1a@n&{y999ޫr}Մ6 ِ)k=&EtH} MSJW>j|r( -vfC}ǐ4}kuϋWi"j% A,1X)"ue9yc\JΤ4!Nyyh[O#9r"&4"9GnKg؜~% QI9!E(9/v{8M{{_jsŭ[xRJaZK[? y֬Yf͚nѻPG~G'>u{x7^믿g>bZr)97xCNb{\$S44rq5TKJf`\5 *Es8FKR"j}M{GJIM6ƘnwU؈1u4YjCphMCVT\rzz6纏5q"॰lp.:Ta{)L@.#)ӴǴ˖R{NWǔ)9ZlEۂƒޢ߈Yf͚5kַun㭷:|}~~ {o}믿0'=~dg͚՞T5'-CpK6 \QJlD/[4MEGT\ S2y% =ӧن-:pF%e;ZnhI쀇 {h!ԕY }3e4'%XibSU0\R1]O>.\_;,61 1TÔ^ JJi2{4g'xE=_ٰJ"{=OnFvJ"@?$,;J-Y.dE'K(e}ٿM6)nmwm)R2 +]lhۖfOִ]Ǐҗ_9J1M,躖ﹼ͎gmYf͚5kֻ^:Cӟ4_o?q ݎ?Çhhx֬Yf͚5P\FZ[TR8Tk V0q)2bdASgMN*fpPj¼&P\-FeBUpntGßhM;M)Z)ɪ`o>q#Y AXP׈k1Yⵖ7#BႥΥdNhK bc1Po\vOb+hh#!DJʸ~gXՒZ׏_}ʸ)TqS>iHQ16N p-%ȢCCn{{ ̂4FCL9C\ EQh81G)#n]Euw4 M49S«rv-D[NX5JItkP׌}r6x<;gzybk}m|C/s9MMOӈä3U޹\RM+)A.ж3Q5s5穥QeE@yK[,%R:aJ)fg*pRR[bRPKq.Ro_bI_a N= mNϘDJD6`Lu7\@sjuskbibǸm2ϾbՆ?} suPf;wk8>^r}uŭ۷9;~5k֬Yf3?я)O>yԧ>g>>?>k֬of|LfW 9UQ1W ~w~t֬Yf͚5BRFFdzHb \RDԁkZ!),EmU=pE`IsK;+@՚SmB5kbMR"  UERV!I/j(k(^W='9%xCai(h!Av|A!Z5Pk+5.3&\|z&Cdg8d/qSA$rV f3U.a^Z= 8R·T|Bhm?i"4p\(PZok~[.p7 04bju*,K)1j" |Wx{w|ܸq6N㚮x7Ǒ劬 y˞5k֬Yf}{h6?ΟɟO}O~,K~~^z[kf͚5k֬wi3\ٗxMbR0)(=X©a*ԙ.tjgOxQK"5]hk-.a{"~E\ SSzP#:M O΋xLp44_@Ӓy`zҶ'4[jNLi+>Mт~HZZB* N<j|{H"fĶ39 []Anْ 26@(Sesw-r̞mO?A G+.Ͳ5NQ1ȼd#` mfhBÍ+yb(usӦCCϪiY66rt,bWE5*Iq)rbHDbEPL f=ٯ Kdۏgx/ӘA(Iqޑc4k[n3+}ag18=%b‹K!F{7݌5k֬Yf=|#ǺG}4|87(KYfv?3~[+trrޅY??=(HMB7 2R `bKW3ػ֊:k!U Q EqUwf\nРOEƝ3 f3{P7͈#D4X jI&ӄl!Okۧ8xKዝ;'웶 ys*ꦚJZQPkq`g 7S\2%8U5[s;$) ;甔v;ޡE)vH>EkKv.x-2JXH9;Zr/ukJ#9.Ɖ JJ6 Z6NXMږekq*< .n?qFJ#7Wk}~s"FOR^nq4qk}Jq`7 \̼nBޑ7WBvOO8;Z^ux׽1̥ᙩPor_㢄&RT #4RpL5mH5"h*;0]5tõTbo00^h_Μ!@M1RԩԊn]-D +:*a{Hk.b͆je:348R^!rbOidJ34;ocpvvF%>OͿ>]\\|waַVʬY 5M.?~m=7?ҜPGm[nݺލYf͚5k֬6$e4]k:\+-y_Hmxg%@Zz_QxW?98go_pŶ+8V9W`ϛ٘SdǑL~x6=wƓv|4lۗ_p9\9T2q5g$ " s=7s1%h%ӄKb90uZ(^ <.v{3.R|` s[Tq1 '#ϝ2I#l̀,_ cJ1k:XLPUoV>iFm$P>nt!ЪfNr)#O%gaqvN 1FRniBzU,I,cKXBGsTbA])l*F x>6t%MbIi""W܊a_r8)T3y;U̔!دav х e'rqrFɅ =?#\>9e0MfKOr):LVNkΑ? _;OJI*!D>|Cv4#O)5#P/{`|NvC@h?i;밍jԐ7rj EOzbH)s&@j%&J70 8Y,Vw;-wÇPruuE <9JZYxǀ25k֬Yfh6g͚5k֬Y^Qic6O’xӒ`omsCdfH-=8U}0ifT3-Pf- O#]3ǭԜ8jԖoVv3]]iImr1AjlӨW{dhC kMnu͓7R]+wt+"rѡq0` ı71}lPXJeciTQMZ %Ed1 (XB$]oK5Vؙ҄˞R&6lf)!tvO.MY =S-2eJD -a_U9z͋>.Cy~qw>"7\N,Ն(I\u1r*+rnoA`!U4KPԮ00=xVY!xV'k<<˟wIib\1nȥ[@aL+5#XΥm8Y욨f,~q-bÓv/tÉoD"[8c;Qm׭KԤڽ( jlqX%h{ ^]^"qB>ֆl)XbsG}zI)zZWD@8{X, \K4F+>C>Qkeqq]w/!_?5k֬Yfi6g͚5k֬Y^eY%U_41($hLK= l/t0VҊ%!F7l%!)4CDiCGܮBKͰVKKh Z rFe{g؜`W9/@vlޣΡ|LC1LRqb\xL-{$+ڐx6;!ul5d 5n-Z}f':n*JGO|8nl]ǘ3E(5wBOP:B-q|3nq촰^RufN!J.di|c~?Ϟ}{wwB9;e*7|#)S'}Ӌ"Q%;7yqs~rbI4Qs!#i^^q{{ Yף^>‹O?%F+C],ln!`+)=p>QA ZTJ3AvavKPY.=!Dr2ds>4ORJ8 "_ڱūU+Svwշ5 _y;^x 9 ve3 2yhϚ5k֬Y~&4f͚5k֬Yd3 8h6748pc +jAR9_h ApYK~*;rux *Tg(CT *Z͜62SCTSG8rq-/bKH+aMb}U4XHmftPHy쑪Nγ'%ccڏ{kpNWM;)ק|N`7x~{zgXdźxj;9כ=/Ҏ}!D݊ݔx2^QR"?y»?_:g~0v|;=cO5wNW<ߍ.bp ?Q|aJrܰImв)mT60(|t/{vNjiK{knqpr5>ML2Mn7ܿsλo}iϹX)Ǐ)gc`ȡH?̛Ag&r`wdQ)qe`T2Ncz<pm0A%\.CP3h̴vL []%է4j0|; ΩΏ`A&9|;N>Rd4PUEq] q }YOxN/e~G|OWwA<|siJ #'gg~ڏYf͚5k+P5k֬YfzU%oB3\1>Y۰(O nZ:pfKKV+:Kjb׊ ]|KohhwqŌv\VKU<R-Ůj13 D%*֢G^ ޸ыC[3Vu-H1F =Snș:BuVZK 0%CWBoD,ݏu|p1Z!c +BK'dvØA0$4thH9D+o,zzh!Wv*zA@^!dt?R[*)!-5FKw|ٸ١]Ɣ񝕚'₥׻p,jDq^\(V+ 54MСĮefƀ/ք\R7,G߷D-idSy_VX:eY<~x8O9iucǘ+ƊQy?>K_a*D]On^/}8V\}XA.SNlHljZ y\uPE@x415 eclH-?5O7<~AG+9j%>g9O#_ :45сo[zHcoH$>RZ+\qeoB޷Vi|KjZ~SRɆ]Q!Lݻ jhm;1D{cBr|jFp W =yݻw59Y קO?WW傇oE;pEߣjcw'xOU7S>ӔrZ }7-l'*f͚5k֬Y~& ^¬Yf׿YfJ BU*/D,Ջ6CefXj}U56zՆG: Qw/6!:.hRGuoNܱ4'W3kji Z[Q*jx1%C-] 9Wb MDv `\v'J 6]ڽz@aT)Y$ymïygCȱOW9k [g|dO#]PIђ?#>}|:NϸlxǬOOQegūR׆9C՚4%#-0PRB%ժ ->g͚5k֬Y~& o}[K5k֬W^777K5kֿŝf1C ^sU%XV=԰,uoXSsfUSZ&VSY7t#뼢-!oYΤBv@-$C3p0Ř'$h)ƪ Bx1zE[#|0F5L+A%gzH4x0TqQH7b?_+i߽Oc")S)ʄ#Qjմ?*\"RJdCB8ƔɅ_=/NX}޻#<\l-lv#SH9Kd yɾc-va#ʽ3ѽGl67,+-Z-B`}h>k֬Yfz C}֬Yf͚5EI3U0CX-a.LiujUˠB,f7ăsLbӂ$3 >xJʖ Lh >R:pf]ىN5 CbTk5箪aZZi`u*.HQ+ʔ,fbGO=uCꎺa1 xXZpZ8:[~'8:gE]Ez[7LkN^V* 5~X,/~vTxg}h\2*5WzYt4s60fe?QbX kkwHO?)^tDK#)':ڻ_fqú_bs˲, GS޼{>oXi {cn?!!xdGU1B.V*4]ALL>ش|+4=2sm9T!gjeʈ =Ӓjj Txm Tki<{{v(3{Ω*yDmsvx@U_rjCvv Pi[xCϿGKK# #N'0tl۟{֬Yf͚3P5k֬YfzE9FG X7LÁM-NAr::,J*~(1Ui 8ӌ@G-VV;\(~ Su,t6!qhl0 Umx@{Mh4ԸS짉ҝr!L8a$3~qx C͆^IR{KlC"Bm@8"RqNRQuv;bj/%͛Bàe=į|$Q" 4*'ggl;Ѧ IDATJ:n>ynntv7硅r"Z}q)>g͚5k֬YfC}֬Yf͚5Ua&VZ"GΒzHL7~wGץ"H3HR P+ŭdi9 bi\Q12-eJKZ' ybX C(P.Kq bez0S+K*bu켭ZУ>1Au،pA][A-[ap{g__ 3.ǹL춸@;4WH8 UoYHCݲv(3iE&NOtjou_{KnK3`S.$-t!Je칕"%5enoo8]pvnϘ3D r"Ob9,JʉVK7hl{l%i>p>|Xx=zX/O3ܹW>KY.liew\Â|&´!ֶ[fdžOrJ^!8O*X0zp\:ʼnch3k8شT{i+u*#b+Eĵ+׵ԗ:``׫ZR؋ Sy3%EZmvT[R)p (Zl׆,@ 1DO:JrRKm1}F^\2vx̞'1n)>ЭS{lϚ5k֬Y^}͆Yf͚5k+*gͤ @[qT5Jp-육pR:676zKҬy3Cf웽}D#٘VFP(5m2Nf5ZN0TPO,.ޡSBqhV=%KC8 GE d/>,q4P,=E8|7BI3ɖ omM"C6 Ch3  AEp!kރ8h ®9y ~"!m] T9 ]b{-GFџ[}rz( 3c^ QU-1F$*R%ĀFp:&Rˁ)ޡ ٕʙ %+q`[Fn#_K>'&sZ/{y6%nƉ ݒ3 |r\b+~wEN'noGw>jlb=,'q("KjdU*Ĕ 3;@:BtLˮs^cF4q@?0NO=)5a`jԁ=}‡/X)2NU)\O9{'%3MS;r`QՌb 2w KwC]T%"\GR]b$gyqrDPRz4ѵB1\Ab^tՊ!jSTBao2v7R:x砏<~u⠔sBlEʥrp{)%>S=p_rssz}BəaX5k֬Yfb6g͚5k֬Y^Yijn3S]528ԃ'}ĸc 5Ys0ŵ-fqŻfBL;A2CC}.ח%xtBK .9ʡH: Ն4cZB㼗j Z=SANVHZGz]oTq9j57|Em.4"FyUv=AܤJMrf2c|r{ă`'pNj;|(x ibrX2xiULݥum{8OOjOHZX,Q Mf"B~*ӎ!t+]GL9l:GO: _z1 '–2%b.,P".Wnw5_}M n~va&#n.v1 }BJlGEIܻV,z(.,Jiqׂͭxt!^k5S֗,9UPl7oXھqH`&k;;-ߞi)eBtV*783VR2݉k~s}}}<ּX._xv˯گq>c[ΎYf͚5'4f͚5k֬YDZ٧RS6j-%nFˆ8:s ǜqO)f3w ,}1ƜyuZU}/@7nPg@la{"؆ƒdmuc!}z#7Z̵6/rȬF7be~/9G9c7bR]tcE<$xuhV|DƔ6bYDbEl@BHDhʊD6,A-uSp1L25sb%=?TjY3@"^yӄ#G2B]|@e:TNB|4 P8dEiey*el2Sjm,* |@4'#\j4 [Q9ϴX ImZ±dT]:X8aΥ񈉫-fuzn5&cU9M!DTFcgy(*2m0Zd-`XI;Ιuiw8hkC;7MFPbN5>p-o Gl UIkYk7N1+hD Ӻ$X˰c)F'8 v(Mp1d&!P)m?VKN.XlZI4}b+iuHģD'[EUb*\Xu7xqb"&Ɖ]ʊYc]P4֔NpiFPidi,%udZ|\"JV%P/9ũYB|(%q!m; X[uukkf89GGGɴ%XnZ\| 67{D0$QF5j^s1a )lmF5jԨP+C,@@|U J*v1i4#_\MdOJD'W21Sd8!&J#}Z`!-8U{!)ɺLȅ'W)p>Wir!&q䋈YN`c)dЂGVX&xch@QrTsfmQ¸]ֳ6mex6!J{Ki8b xxtȖ*pUWBqT-؛kYJcg(%P,v(&gV,q[5rep@ER,%1͞`#&n^HIkO_ iYanDaglJ/3!yp3JAB,-8z}˂Rc.*\T!gW$VԻ u, (W (K9NU>xO]Wy)u {x/:v\E#>%knzx}bjF5jԨR/*C7%S}\lm/I_5jԨQF/JGRWabh>%[J_X"R|v !p%Fjj,̙3O=lGۨQFmyM6* ZŤMV2V\o|4WZ 2 P>n?$fZ* 3mV_ӲJ/w"Jj6 Kf O塕Αځ_wS9#!&T*m/Axdj1_TH]#. nxăOEn{W 'azTk#b,""=4&7&ht :=:-"IURyB+%d#r5Z6X"E@_ep|2ha1<.VYQ(JmW_Y;{'#Db iN^⸜3?9T-~Y`^]bCLk+X%'s 2󪠲nMUYVX)'E\pUkfS0f9.“GZfY=dz)Bݼpa.ejZma"b/kl]C$dK@+)>?$DO%E%zUPʒ[Fߜ<YFPRhG%4)Ѥ6I&< BDäa}aiw~8Nx9j|Q:@LtGbXjקt>"hYΞ=(Ij5QEc_DrnGtR0&#Ͻ5jԨQ^wKg>9zaooxk^W*˒~˗/?mS, nIjb ,\YdCh#jl Dqll; 06ؖ^ܢ|k1K{=adhjG\,=,,NMt&!=H;v+F{2(% Ɠb4upD8 ѢDPTں"&!!d iv ͑゗ɀs|&Ԁh e.a:bFc /&ošW1ў&Y$&ЕJ!NB< +䆯-a:ƾu#ᝇܠrtZ)<-Qa%eq< #Pl C ʊ(\vM̎(3CFq29Sps\8wquإ'rfs\>{#LäX0-hN35Kie9Ӫ(v,N+5aF"jg(U%3WqReh6ƝӜZ[k9/&(Mvr@0&MX!ɤ@yMC>P,9 666vVXkW=l>\gcs9 mԨQF}w7?<ϱ~g=z*Ϥcum_5^172Cx>5j]Wp 0oO^6(#P臉l ֎j$>#<*KH7h @!,'Jpf!]'7:ү+zp(Y$t7HVŮRz | ԱQE1Va>#'(~4住x@2|%8]:_߽C|Jtprx@]b9w5EQ`BkbQۭ:O~2}¥x6 kghVu!J |HJ΁Tw$i Kh딠_N`[%Ğ]4Ƙ՘Ie'@ZTJB1B }h2"2arB0T IDATafZeDS@kX, >FWŰd E#lo(x,X)ٔM<;+5jԨQF\&]WÏNMsӠKI2 QTĿ[K 19Q@%9 u,Ef<{7QJ_T9#Ξ=ˠӦi)eQE-[??_A|nعs;zSqZm8FU͹1U]398$v|}r+^Rݽ2v'#:6f2e3O)|J!6(ʣ;Pz2&dK{=ٔvˬ(Ped1G+Ͱ&_[̃>­3I_AFI[F Tk{,1OAeX`J2q3:So܁219.W @r 1EJʼnR>ĉ@4!j d"DVr<}@lQ"TR n!&6 zX \aF%v([\sހr{OspKocs}^e43;!n&|^}agȍW]Ϳw/?O6N'vU͵/c4czy 꼅u~hXŢ!\w:lnpR-4cq.Epr4:"9Vi1go~ Zz(.gl 0ඝk3vՂwPE14,eNؚN4ymm][`C`ۢNrPWlueFJ{ ЏK3<$dNɕ28Y%+\)Mjƹ&i)=2cRAqB%w]"݇X,)m."Dy`Vي:c%R4Z`vu||#A(c)vN!8ޡ pSk-~nCV~1|GjԨQF=E/ Chįj{W8O~^QFς7~G#iԨѳeJ.t,OIsQ omJ H8EK4₎f2A| 8! %H4_%rJ!*Xb>bMHHI&s1"wbzi{ޑ;$XB^b=aa:i Y*Y0y7X|PoTDxRhQS̾'Rد8^% 7*,bi@b3hw>{gV P%8yy,BkNFU hD uJPHmF2uNG.{L(mB1d}ct f&Uz+:V8?Tłr|xbrk yxvŰ݋ z=s\s~E]aZmBYp~|E;ϩE)xJՁGjᐍnhI`1*Эӽ5lYjQ9BQt;]Eڒ !(;SU5fXXzTuEU,rpe:>`w )u]mZ_1WK,).aT2>h>'"1!`u+l,TWVń'(Ais,W71(ajc(eJǢU|΃x+PFihEZz" ק+EIAU)U*YVXt"''@ߣblMB~xsp ~75jԨQ^t -B`>s>gըQ1;O5{l QF T61E.:bGZ&S{j7c]-:"eip3tYrȲ5/nG>sYdc_1-B@ZKjh^H'G2KSu,U Qے>$V,UX#@e#ULaAtEFTnpuT\ 6'd YwLC,BFt-ɴb1AS!/]3n(蘵^7gyEp1p1cTA &3Jc柿j}u;;<2ڥnqUx \8<`VZsfq3˅؛M4c}`:&sbfkU=)ΐL!.?;UMWY>D[e̼e|B<61t6oN%࣓f^DȌ,PxY wW5c|Qw/᫒PPZcDa:nBŇh/ |AWuLd&CP1&8A#FQW:s0J!MDs'M-ϥvBt j ^^$$Tyys:X"A•PH"9o]LR a/ON\"JԙlnmQb^2>sz49eUqNmb}}:fN=nz&ٍ5jԨQ^t Mx;:O|p |}wGկ~:FW(_W>{??s;;;};Eg>Ry睴Z-NNN؏~_@9>OO}h[xӛĝw ľ5zIR`AdwlEF@RA"*#Y,~@gy4 PT`+PGSUI+h$ba2.1&R#JbiU F(GԄ+ĴB:K3/xB*Xo4 DTac<͒g8Qm.Ļ,$NYvN j ~c0/=Ĕ| &ˍONЇc^jP ܣ: G{s3gYך:F0ֲ.^'b3C]{=]}U\cs`8.+׶8:9Co[N춨屓1@501YNd^o ֲ!ןh-c(\b{9vxɋX"Cyb6cUNե( N,#4VF]wtYvs~29zJhҢUM`/mxL?}tGOKTfRl},~Cu$u\Y} (qRFkTH4<~TJQB~UQiXjMnx@˕dUV\Xg1&KD\R^BK:D!ʤ"v&3blYr?62Q>M.CVV<ē ׆dFW휢(JF#vã#z*[=sF5jԨ^]w[>s9<]z׳:{?#o~7~u/}c_5x~}c oطӟrpppE~~Z7~angt<{87ʣ&_%`$cPD|uH;'(vF눟XB[l4#YɆ+I޸8ו<2NN!.d}EĎh{'tzW!P[!RЇF`k_5>nf;TeEx Wt[- )(&x[Ok׆tZ-Z,'7vk\(A-;C{ /TϧǴV-EUR, FSvYƍ8;dZK]U%.[[4f<GqGcj[|7[013wl,mwP@[e,)8{^ߤ5Wd&( αX,(˒m9u]3N(A v[W1=:-&L/SOhg9#M( aƇ8)RQ.,qD,"}pޡ#Oޡ%HVXvS+y#GJ*POtUG4NL%\DOcʒ,PJEk$1RxB&*>ۼ^ ~OH`0F;>z \xqD4ٌ;ngQF5j z/4G>w!"3gjR|+}[n~_5oۿc?3?my}wc G._K}xf ~뷰ɟɟ_e~w~;iorӿQ2I.DW+6V, 9%TcIm@nB+KiBD(!OYb{Ycːl ;Xt )y */,rC Q1s-PU-L]Pj%tւ u%RZ8jDkB&+ t PVVHފk$vS53T Z0&Rm3/l@TE.BP~+P;O6[ܰPgl:K;ӌ&MۧͧX:( (%>0zCjgɕ9r(m(\EpOeEjK=u]RU%#8:g9ֈ6CEʹz}֨knd4\2nJgpǥ}~bJ|N]3$L6TLUt;mN&p/a|O?c2ߍbv|&N,3 vwwۋ\Ted6gxMƊNw^ĝ k}\}d&KLq00zU&ZZi|'Sy 8%&d%+J %}~PFy5%_++序8>t\Jy]b׶أpljd^cw]QWeX[rlooS5VVcy4%V5բx<v Mg>}WqGw7oBOYרQF5BL;G>:'//a*<{lWUB`kk, 7pwsw}9 E/{8::?lmmq~/| 򱧣(vZ-ʲ{]wŏȏ ~PU??2?sw++o_2s~n5jVHB:MLp+!$yV+8A!EIP]O%dFKLtzpW~IIȘ@whIdMH4ժgq ffajSd&UMՃ,F F)v! x E,\&k1@JPl4ܽ įWyq4YWHELgPh΋tީSpi:klohuHpL]Bg="=P tbN21(YKЊnbr̼XsbdB7oIz'ٜnS(W]K Xt\}#NåKt[97>CEc%&ZN ^ /svΞa1_nꊃ]ֹ _[NcX`mMcƗ\~A\U,u!`ĠEh9Ӳ:.HbCĤ+Z &*HmW+SijkcR>J["'D|R8Vťjb@)W2 qR(6/q0`sQxʪ$[YaU߁5=GTeɩ-NoPLf… lnnq}rٳ?Ff9~,OXL]5jԨQF/ JBߚ˟> ]{O{{{與zw<|k_//PJ7x'3=[{gnonnrpp-{:5kkk׾{b>?OӫSnԨы@.BĮdh4>T1i. :V@Ī2b\CPZp֢TPIVw ԞU+jp( DVH MQU>Go|z戂ҁhh'S].2&t:JC`e|2y'BcmUcÈbgXgZ'{}ֲF 3~wp;b>ȕ.kY՛ۜtiѼ`Q(9T-cX%Mllle7L;ksn'i)M⪝w1zCv6p-ÓG#v/3)xeƣృh:6A,, 'BiZ򜬕2~DY,fǕ{*JqNQgS8<s 7pfcF#ZMa^Kp,9:!l v[\k.=uSLo%5{,yl%('ylSJaA^-4\kFĔx A,+4Rj{DI3Ivp3ɗJN1D(CYU=& 8WaX_`09>>fsc dYYS5CC 9:2ɘptu4,'˲gݨQF5zEg?4 ] IDATL|#/|;W[C=??`_"<V{w;Gyo}Uo;s+f o>7??-oy wu7tEQ?xiԨQ/+[6#:w &Xc᠒X PEEi LJT+tjJ'Dbi*9D&Yj pb9hJRZ9 VhdE<!^ Ti^/H1ՃI1%0˟}J b#3^DP΢jOXHۉR)|`8@mn xWʢYY;1j%~Z2?ĵڸv`4:oq,d]|A-k:[-ƘZfՂɄE]ȳNV.pirVdڠD:̋kk.^bm9ul2szh>R1O\p'm2z1~ uQwfܿw,^isdUQ0hZ!YQ@(ݶ ׆y1 `2l^ :;x6Tw:w/v9Et>Ĕ`>c7:ۧOᝧZyĻ<Ǚ[_ιn1K+4<E\Z9WT~Dκ aIyXu, {qFH-AZRUYޛJkar̬*\04Ĺ>mR+$.KBBX;_p5@BZ2>el3h Ty5]v]ˮrWJe授+V~hfx!pG,wk,a8WqӴ WOco{sg{7n0M.VPkiod^q-\zպak 5PX23~ԨQF5PNH__SOSO=>9gg6\.}-v7 t]GY|s{>(1Fnݺ)??̇?awuЇկo;oہK?g'ӿY~{8O>$~?1__8UU]lԨQ^Ԥp^I$0 Ij(9=]&~pw H$kQ2cCgމےXiL$ R؁.1pBI+hTbHI5BD2"E(2FiJ9pݰ9៌D-T]CQ>c'@ʘ -hbOq2DGR-K(,1E={ !ܸhTcQUI:<׃xBq=A f nyeI/rl3Gܨ uEQnp}erY!.Vk.ͧhIQsY-(ltՒ*,:̬Mpt}JQڂoa&3VMCYU _9:yOa 9h(l-ߜqvnzO< u.%0ܹ"&K!!%B߽|5ՆlErRS%VkW+|PϷ],h7s>tzW䘭}߳åK]J)'V %-67szy#=yoQ0֒H=!lR+CPjEisMϔ,ٝ@%Z)#\ e]I|KBiMB|R ]f1 6{ 500, s}^cwa` M`6Bzm!uM۶,OOtil}\ㅛ/Ҷnݺ6;;7'̾eQF5jk_ekM=??ɇ>o3?3<<˿̛&~~-oy g>d̻.Mv7h{{'|2#|;mTW^ի1??1byyݢ{__( O}c)???/,y5jԨW,7`I'\:S {!1 H.M%Ř Ժlӱ:3E)0&Mt.ch(Dɀ[q'$\ϹT)j@wh["b2l ǧp%g-C}&&l T2w<# C ]HQCiI!a>AG2$0i9C7xҋpJV,OH57[^K|>sK;`q\ȗn/ EaT5]gAQmoCD~:_iׯ/離 /ғO>>~~__~xFO||}/?7Guh~\2k? I9A-!~<C7!yalw 903㝌Q"V#9h ~?FTͥIcOC萔 0$F)ʌ 1!|HdH5׬2~&*MNK2Dq1 èH]ԺllKD\7 `AӒTZ]N1C\7HpP*\M^1c\q|vRGhU5, >>{&ζwk1`D"k.O؄RzخT$4c`u]EYr) : k,',9{Ua6T,E y4 S1b]ǦYghePܟ UU]l1/+:q])`k>gVUhєEׂIB<;ä^І.sߍ{_ᅛ/:R臡 ,[TUEp#lhJ)iSX蜃&]oVDӟМ-qJYB҉W"`> }c* `{Jyip){QDJhM_ `\y?b*6yrM֘ Ŧ Ἃ!bS "4_ٔ4O}<]QךGﻟ~{P7oBfawwU5jԨQ^o 3駟77~:?c?*?Op/nG>޾(Ez]>}]Vk3_WWOO]01}C(ٟzj<;ßٟSOۿ(x{^~G57 5jI"A*d<>˳YH"HL4e\P JF :s̃'s:;!_|Gr)FL~GkўR<Vk 4pӐ/u.kU6}@)bx17# M*l|#0ꥫ/B7>;Glpstrxfyb]la8>E]5"]pl MS*+ZRՆ wHL>xʺBB (;Dra^SaP[ؼ:%yɝ C\+J|h;4.(Ra bK00X˫ IuA-*RVt v< ;ezM fgSixEp-?P(tPn*Lꚝ6O<:O>[h]зFvE}Qc)QF5euY WmwfnzZk~裏}Z;w*G?NC'07c+k*"eH:O2**w$'`# )tCi~x|r2>D eM&j)b$%9BۜW|'uS"l+_{)W.x9Uy$cr&)S@UR2=8lKAAJ_ n] T3XLzJԤ%Hd 2I:'c'I{to{l\/"6v;!sZi='ªI1QL&T9i69nK{mNϖP5ՊɤE=aZNŻEQ|iZVj1Fkw9>>Dȿw>|T EYl6rߍѱNSI)٠5by@уZ4fvhx>Q}Z|ywN{%(ェ,'h(  Qb|f+p9̅!$|lS$XL糜GޓB;G2y F)$ĺmhn5Hu^tLBJԓ-jQF5jOwzM/} EF_>O<ķhoF\03Aa(dH T 3\(E a"Hs:JӆJs}(H.$1̐Aj$I.:D AINc @=x#_e̋ʘ * 2:FΡW An"I(y&E@iEHNHzBZuPhw%,HM u* 0d,,PeMm!-mBB ʂn`!d !_sDGTwܺu;wI%9?(S'm-Vo[Rmcή^BnZB6QC詬fbZU LJL Kф8]oи[f8J8\ !oZ6hmtGB[klQ#ڂ8^/Ѣ56ҬVʚ01=)ʢ`:1- 4¤ʥtMCQU}]O`^V vKsa *zE 7[Pmۣ$U%e^ow{ڶEkElNa,͆#GDŽ!)dl/2oNOQ<)C/@Is 5],`}6zc,Z#EPJr^<Ƙq/q8/ވ1kRz0QQ:!^LdēxdXqnuǘ$gyd{g`go!|(Qjچg>iGz#}Og\=Iu]Q8<|waԨQ 9DR6Ǒ`bҹa:U6%S"flǔ l4hC?9F%cx D !#'!aHYv-TLHm$gH̻C؈ S]BQ .Q@壃RޙLt)i&޺EZ$S"SyւRغE}lΠqcAD|$ir F5ztN<κ%h /RيprJZmNfr͆oA /se2GΚ)\tbٷ5vE=1$hz˶Ƭ Mἧ, 6 1%%P (Evq=+QϘ[`XeVYQ%-Ywg ƻe` )$#H M%aRD(jr(Y 3fDDaӷ4IUb('E1 A"XN 11+ф\>J4)PmK5y5ƖLv&<Ōww6|^0i הlI)BD f2 !caRr(k1Sʩ{km.JU*_CELE 8?rJHh=|O B 6kvfsy-?c{6=Wo{ B*Ke6Jj*^G5jԨQ7ݕk-J$"}}{߷{WF5jԨQRvNt梾Ȧ a΃s !EEh30R@wfz:烫AB$ 9 @CR:Or>C73Ic@PMÀ@*)r^2&,x@w[ ) 1DXB xat%aIz&6ȼFfSRסlE[B@*5i:̓u!uAyIR 19h^H$ZЩq%9etO*1uc1!ݸud2(@Ch(s64dgK*6!aI`Sq5?cV%l굢)#Ю7XR"*Ҧ#Y:(krֵ4ٌR)$*6MKYۖeJN*fi[1L ,=뚝EMz, B`sE>RM{*8| L+cd^*7{.SRye98c>unϪp舃ӟ&F軎ͅ>fԨQF5+ QF5jԨ6CJ)2 rBs=\SϦt{{|t:zRQӺLfCߵTN}{yՖf^l7(ggy=sz1~æpi 1u#p>%&raV$S,Otozy&UE \Y챻a^s<#$+Wi77rIhk5w!f)P<Ӳ`Rtg4y}T!Γ2C ň6&MgR iH!3}8 =Fkz }Q:o+_:d8$C.sڷ"IiR]{HhofD+k#\JbjIwxH:"k0><8D-]vG.9\ ѐǠX,i6+ }pLLAi +W3V+ǬY-9<:QɌ|-*vCYTedNT ʒ#bQ` Ӣ,KnӶ-D}#'8{ ޾v2ʽ7}̦3Jlͦ蹼Kaٜѵ-'ns3_`kNt ]_0+Ksu lgTxI]sϲ>9f{{b=vܦs=6ki6q#ƄV¤*I($~CbdBi-m|[:fC(PdhJJE`'3EI~2 ”Bkd4\EI`c.*J|!LPa-''L3 [/yӛ@J)׬d NUѵy(u]#sZqpY oz!n\#oxUU H"h{W}m5jԨQF}}28O+A~i~i]/IoTU˗/׮]͛|2*( vEi<__?kf[wԨQ^m%!U3 X: ؈ 儚x26zsɌX`M޿%t=(EO)2ýk`Z1 '\Jwd}GCE)lpg>촦(Jt UY$rE=gZLJm r$xfYy>Dn}@϶1 W c{RTl ?Iη٧;(dtI 7~[q%U }߂JlϧL[7$2`)Rbf+n\N- >bߣBC^q*Ph|fg6_A[jgvs<ҋe|kwT󒔠 NX lfTUM]0&NO5ɄĄ( wٗ?KN1/OUUc. mQ01 Efg#]~|wQ0.fz(};wx߾yͬ.[-L]kV\|Kׯq||BUkQF5국xC^N~f3?'ZB/"raO&W1ruo^c$ϺիWz꫸WQF$ +e(%O*>āMƖlp,>/ԃ=VI\|#Q%B̅."Ћ>"Z|ʥbL.<7b"1 !bNkIڐBƞdR*BAXEFĀ>LrihEI!!"!| t- * f?B:k]>dcl "))h{ Rt<[e#k4 uUA I I>'9NH!%Xw,2]@NWē3Ai̪d|(T=!U( M6`8 ]|"lZ$F#V:b:E!43b?ċXC d6Cb7NI6Z )l.||$.^ $bעR̘" ROӚ6Ae-lJ%ϞR儛5J+>gPFy&< ls{ԺnjQBQu.+GiP>ɔ]:$| xz\tǧ4zt{=[ ޣܻJi8:z"=V yj+VdD -jʠο'(=%se7錏I Q !aRh]ֆZihS$ ]X=ӝ)7"Ca|.El{ye ]г񞳦%J;Y0*V]-*('Sq:Dkꪢ2%J4w6`L$*CXVA3yGH6u̦S-ڎ;:!8n1++hh6͆YaWptrºpxpH uX[S.v&[1` ˬr|f÷=-'G<'8ĒX68}&[mRU2g(laNk4Ь,#h#={l[P?4'4! r; \sc-1FDfXqWA)WhɸM(QwkZ'Ekl6#I)9<0'rQn(5$pgX  %Dv9]H>$aEDtN*!sUIHL a0ٵ""Q:  M=BJֆ $$5eIF0s1M6UBꚔ.6TU7fb4n hޠ@QDC>#d 5d ⬀J_ LHMΫfm ԕK 1x3RDDф밢@,1 Th]a(ˊMc͞,ˮSUuWύF RQe1?Ap8v0HYH f4̼әd6.***2sYTxrޒ@64QTUMdfn|kkvHk5UsHyBIڏ41P;aα#g/5Mm9Ax❷pzt$ "//8w>{/ Ɣ1jZTxnxجl6]K3]=T񠅦X[#ET )o2PE(wVꜻJA3*d[d^=6+e.6-UBP#uVo0(8ei/ EžO"8g^LK)g.\6 rDq?)[nvÉnxqm@RE-Zhѯ?ʟ >mѢE-ZKjQ;jɽs=Z=Ao<r)h"H+ -tE ҹ,.+,,-ywNe*:%C8ú%Hl?* ffgC1s礭q!m>'j#e(.( sW(%n7ȐMI^xqa؟V3Vq8縿i*(hۖώx1xNE >cTUE$b;7 g#9 {u.'uLFޯ͹fn]\ hn&{9_Ho >J)tÉ˿iyGR(iDڶfGԒ)g^pBN> C׳Y9Mt/=GU `GY*XXӔ<;g֊jcdr“ӎ܏aZKfNDO\Wͥ*TMǑJ&Jݎ*z8QMn}bllꚫvNlh}`:`o^P7-O>sj \\}uҺnϓϞ|I mUncHP!7 77T1 |@|-A=z/~sb4MwܖLۮ9t9s<J퍧xlyw)#x4B0`ҕLiNR:Fbmȼz‰ Nq sԋ/ 3biEHiBwa{[[jwR~ծ8-(m"HVy;̔29'Ϳ6~15[?y918k7_}:VDp8ҬZ~ǣGΩE-Zh"b/ZhѢE}Q录bR }Pf39۸䌄 'RGfsUP ঄zAcvO)bfZ*`#{X1Vg<g3FaB@qfVB$8:Pҳ93F)!ulw#V ^P7n׬a7hC%ស4 IDATKP͞"&nOG BFq&nPWHVX(=>)sF{\[Í#*b5y 3J:uPyj #uL`EѓsAcӮμ3.x4xʔ\p:?:/EYZVDnZ^)՚e]!-<|ģ5OPi8tGnv;Gx&i '<%;o{zR5?~eb[7$29vL]sBN(\)Sm{f{fċ'V6̋;ܜl^QC8q<Y:^(%fN{n7s|^f&<3'jE(TůvG=7sGqPEhgsv=Y*$61 5U)>.!ir3KI_[B@q2 #)/#DYKb&\v\mO9v7ƁO5#g7@S;v\%qrN'|9endG82 /Ɓ1 Դ8rɬ5!ڹ^EC$ooRJx:w'~/!xBJokCô5tD,o+.PpX^uS[͂s\tCp_P*N3-Z 2T3>#^}bU=eߗk3)Lc%('?WnOGcd7-a"LqtuSpNRj[V5!C|ѢE-Zb/ZhѢE}A%> G3ec ?+!S)@dwB 3\Q\QJ1 sTlmbq>Ez\lА)S$ãVfB \w9}7 e s#[iYK&cRȐ'醁*^Ys'F3w;rz]`fc(H%B"v{i@5[ҿi SBT؊*ю3r&y?Tpa׌BQatBC>0Lo/ +ȉMhBSԡb{6}^Hج 笛*qb&yH*s*]t:~G4.k횛ݎO?!Vva'OtɋgHVV"HeY}`ZsJjM4JӶp@z-ÁX! NL}wp[Ai7'%?z0|.B0O猑>5yo'RWP x+G*Lt/0B*º;uV9Ed-45YpL@b0D34ĊI >[YP\v0i!@P}Ômے CӀ_P5 7& /4ɧ]oه?*WU|1zTqV4`iTJ!skis/w txy6.Ead8oha?S/50 }cekQ~WOJ#~o|+qs2V: #ʘz(L-||O?@n64 )e_ۼhѢE-\O-ZhѢE_Ps|4: AhU?H3FԛA.:n@y2TŢP11;Qfhk*4F;07 % !6q*hig}_!Σn”-uf{/`yU$AH.!1dH3xi[m^UT1&"4e$8mJ( P78?o-v,Ɖـ@-)'41L=:M%qH3ӧL&+ " .V8R`ɧd_S78WeDi#lPAJ̘kv][@7PƄ[7H *Cqd56L΅3'-i*NJ;BTuMelfp/^}dp5' |G"s;RΜ]^*J4LN;f$+C?1=} H*fMg4s֮خlj201ffZsp@|RG?~l\CFTW%-DM]4]7wP/ι{˝Pff~+'[C1r[ݿ'Ɨ%BpҦCKUx4Zo0}wz'}q$M"?я\_n֜m8;p<͋-ZhѢϵdhѢE-Z2Nad3$;nƦ"uۄR)CF8T)b)ӻPK;o#jbqs):wa$$A|@|o18PWb|p  yRJaB nG2#q$=XٓGb@ {;\2 u}Y5+B]3|>a%%8;K*0t=Þ}l@hηHQ᳧ ^x껛rSBɘM`xx M18vk~N`#f|I g5ShhE~3"ݗ!JQZ?:g_dƶ x>ODtuP_9j*vSOJ#NĆqǞvaWQ&>䗴#z;޾E3s~~x_GKuRxw=U[]=7_hѢE}A-ZhѢE_TE% KG-_&<3G)Yab]J[e 3ZTun~)3T)j8UJ"_I-^ %bktܛ_3/wf%C. 2%'Jcf3.S¥DAV Jdy?3*+ s;kCk^2\uĐ&Ajv{GYWISR5[;T3~ jw5>ʔ( J0sš6L)1 d4 "h3f@R :"}>?UڂHAq%qd7L\h=bFl!TН:P.(Eٜq<`L떳7pγOUb LGi7>/(]ohچWxq4RaUt*B4}4NXz{.r (%ɯ>Bګ]o|1eJfg[>S.W[_qQQpd\C$4xqUMΙМ]cf)36p)ߠ.X *dLgF^a; gUêiq2HS׌i…p \2{y 9nw=SQx'7]߃8VW5UPHɅUb<{\jZbUfU׶j FDS*IcF} ip>2Gp8|/[_>ty_R 0֛orNN'bx/k6 Wx10we^}s8NsaE-Zhi1-ZhѢEޒNPqv_|Prl{&cmAǭ@o :e3g:A*oA,R⌱=f9ڃfK6&[Q(D ̄/RY\@ 7uthI)C\3t\*gE ;%wЪ_gxTH Œ!+'Ȫ)_#. mDܬȹӈLzz+L8q5ܞ&EPq~rc"`Fd|uɆ/ h@q*U Z;ڮ Tp8U }o+bcҬZ^*&aKf育nZH]Wxqua< mwϥmR T===ypyA? \p1O V@{vvFVeޠ ȋӁu۲>{ vCk6uºڬy7Kn=4fA&V2M#iqEU4Cx|"\ܐRf;0M>W m4 .C}ѢE-ZkZ E-ZhѢ/,5G29 RE+(V "f3me(j`I7& IDATQ*$K@tN,GLHNi2sK;;+PLw㘋!aRxDo #9b8^/%+q߿KVމBz^JfROmjUөCd$ Z &ϡ-]OzԨ8THy;E<^2GFdL)އw9/J"sjqp<{T_6@ 9h. ]yCxAG[~w$x*η[joŦ1rbe4xdpL pSnU=l߇˛,ъPb0̃3SGUED3#4٬ l膁#$͊H݉gTgЪYl\<lc{Yna@L*mr:m[C {w<؞|OG<`SEӉbe¾FF BJZӴ5ۗib;B|4󹨒ljR ib+lu8kês̫[zJAD!RfLz(WUHE Z iʈX Vo:B T>V3jeJ;򁺪 s>iɓ \PVb놶m8?syu8 }v{FuLa]=վEچ)i|ѢE-Zb/ZhѢE}QĊ%U 089/;3ȣyyE礶.>Lf1·dsd{K|b.L}("Dz|q]psĀ r9?-׸ {dJ"DoJ"h HF{\(4"m3T- x=[x#*ƄSU3'qP nwƤ_m 3Dpú5Fع U%Ik9UI%cőgV~Kg93WՉ!BDc/sW,Ï5#rF$'ੜ׹i0\]\Ҹ?a6%U]%<F~'v~~va:v=먪UT@;ҍ#˗Hp8aVԎMwuB9eªs,n.3\й x(mCw`p8hs3KqE;C@Gi(QU:0cq eEC'..n8;۲^N.>*W mW3 _hѢE-Z4k1-ZhѢE*Z SKƏM0EdfjQGKfMk㝛s)f* y^ضJ f;z38K^sf:7'RvowEڐ3 N{_Ͳg)imlM e \L-pK}UsHq!j5AUm E'5,fd$=cS(.e`ft:ٮ_,\LPpI9ںC ub!B10C15ڶdR~(vH\aCS2h2!8 y&%rX-k9(+K9b,YN=;cZԔޛq%$,Yfvހ.F'BM=JWKR">'z"dʴ8{UgS {OOє( '4 @۵-\9<gԵ4fc>GRfRV8UVՊtʤ,yg(oP8rb ĜĘ~/"o#Zt(+0sp0]MD9 'g4ZvΐL>x ~Lu CQ3G2ҵW]*4SRNV+3Xܾs|__ꝷx3 f)cbRw;ֻ=ך+>"s^sr ןxi/M|?>G5jԨQP0?aԨQ?>QFw|0#W5AQq04 d)SLhdLE3S5{!Pj9^,8UC`φyL3}IeH K] 3)OPlJVЮ518$c_wCbp/Y2E~0<`M9$'u[X,X֌^%爥yJ&h;񾀶%u=2S[Ӫd v#- ! "H%܋`Jvnn8gP Q_@잪J;ތJPsbYqAB:In0Y)kh՚\Mi4ffEI,%=lʝش-IMo#m!f&er:9 ekP 8]9;;g]quy@Li5x6CEoĘN,Krʖjb6#kf߃zMzP@P\Y%w|m1| u-gmOUUϙ/E)I) #L R2yP"H0U@l7j‡`4y"fȗ,,20Ν99+YR"d^9+锜3Ms柿 >Ǔ=OSWMczÇY, o\'d9}|gIjnKUVۖot-QWx]8|ϻ8:91jzA3s S|ԨQFҿ CЇ0jԨQxݹs}Fe A8(.f.R>X9'q{j7lYoeC9 HK>IP.:г !P%znҘ3pd$SBUPAd ZXl t{$6ɰ7VԚѷq69[yJUs.R:9=2=_5&+>BGM 7 s]= U %cB3zQhM;PrbK! Mݷv)JKj@gjƺp#y4]mCHQzWSn̦S+q&Hd"Eih5IJ5 *]r eUw 5- p唪(imImG4l~G488?k;V ʢ"gRt)IU2j͖a2ێ9zdZ^_MtN8 &ʲ@l( }3)%7nDut]G+{" /dwQB3}ϋ΄"8ۍ2|h%GL8$ڭA)%op]\Re@HlffKPZpnx?]u0-X iZvyHXúxV8g|0 i{3U29*;siIoQ-P "/ 1 > =:97Rnbt #0) 3%=|AL NS뚓R ߷/X)^Z)x7%Q4Յ7@b2XTqzcC{c3 6H-"H2s>E]Bړ39Ec8 Ym`!æ\|hQe Ű^ԓ5T'4(mѶ7; 2ɏ4CS /8 H46 vME)}V(:`e n5dlK6>%9&~owB+q!1BQut"Pt)A9v[-BƞE=#P8OUvt$&z ǎjƱ86]C,},v8W>?gqZru4mÍnrv먽ݬش{B9sz*ł+'oݦo|-9מx <*3rtp+Wج.>7x#Țq⑔5|A{bf!Bi%9'ۡ<c>ʲ 3`[yxóSxG4&bv e٩]JJj u6|qZ޸&7x^[o329Xkӯ٬L'l6[2ХLYU]}9#>vu {^#??Pix9/Y.ƚ{j LWOݮo8zP)1|.5jԨQFh5jԨQFs̘9,U7[8ECD,Y=J_X%jȉ<fZ33]4S=+C+bI札Ӊ".Ltqv̀=#];gUIm?f)V` \ ~HV'Y" !H1K MSg8 H0c͌V!@>%D2iq[S rh ꠪` nHkp5ZY`n=<Vy|BJ G,ц0ZDÎ8\%%xrLz3RDCYp)yM2LJT{-D.(JiM/mY73g 0&a۾c6I}KA2NjoҬV!sX.YWjjiPp|pHQ"J8}*x-gmCRS϶l.6l/8X.Yy6 Lܿ|6'wpKV+{i&8bڷgxlU8O7pu^XGA;)%)u] ;5Q?t I>;.S)%R6ۃ3IAH1Ua)J*!xDW\ s"E(1c̗K֛u=%ͣF5jԨ5`ԨQF5Ꝫx}~.!8NOMbcOrxxHz(P8:9L״&S6mC ۢ``rl;y98=9 ٟ'g> !'J44gC5% ;2C"qCKTz p%\> 14 )'.R=à93UTs9> IDAT3uNP.ĮRHUi#||N!x~{F{MǟiF4[vx Gٯv2E=Q~j&UdCQF5jԨA>jԨQFNUi}4mHkop5-mm47緋MYܐNx*hlj>Z5?%4%[66G8.` Dv KQD39%$PCҬ["@/h0w; 2$K;t뮵!wvB!A")A@˂#bp,19{IPqȴF΢]㢀9G-eRq=&evw.;cZMXoxLk\ʖk)R$^Mni]1'SeY[w{.*ׯn^{|B( D<7^d2#5-fK N\/>^|=eooLj*RO ~U>X a35gY,3*.bk}8uZ;Pvϡ6,6ce2qq~_RW:y wAqCܸB"޸}~sc>Zpα{Oy5EJa8*]˼6 mדRd~?G5jԨQ`QF5j;U1 f K/;#J%4_A07)%qUO%.jK$ Uͬ Vp(+HĶ5X3],XYͼA@σtb}N+d2#w 3ʒ1]k8A.MASKf`5)gIu#g ZV YY-.-r" &"٣AsSҤqf眑E w%cLx)!Ӊw6GҸpaz6õ;r0TNV\I)R51fTEɶ2J)Ou -<,p9)D.g4%|gP=yg1wjW⌳gi{dl2tMKmw='<8{y߇>L3t}o1&}/ yy= mJ,sn<Anٜ]tFn;-HU<|0Nx3ϱi<L'S׼_DASs0?ޑb  ӹ IHx5kE3x/ĜĜh|h2d%gaRJˡ9% EQAU»89>D5k QٜN'5ڶ'Ŏ8=9!buq{_x7*Yp~~FUt]t:%Egk{m˴}KU6DTeP%EYu5|5jԨQޙ QF5jԨw, K)rH ސ(DP0ᒝH#*0p_dR#7%$ a(Ct&oof9)mѶzKk6IHYpoPW܁qS4\MCa{$bÁ#5;pd瑾C$K 0fZ Z;CփoR㺈8+yc) F9NA$T`4aԉvC)bvZzp "=mWJ$+ESXN'(ʮw6Txo3}<63)j͞IYQ%0@7'Cxɯ&~k \]0wm8RUvx+p22s ڒ}Do͠%0e@B G vb3)x$LmjəSLkt!=̺1qχ{qs%%g6l.qv{5fGZq޳\. =ْl.K<|(^Ϋ늫#ڶ"p i0gtgȱxyb>x~|IU=_q<( .ޡL=~Z! bh%'L#9sʈpxo)uâ8T#<ͨ=1z$"]V y+J{s8цo1|i;s(#ܽXs[\;>'~#8iI1r.KVno}EUr~+xug:>$d:'x1ؓL&S`4:Pg+\>ʲzA&:2G5jԨQok4G5jԨQީ%Cld'%0+Rq`,t)} J /* g0 ~0гs`>ٓ/9#HflI`XhD1N%uI΂OY/bF44)lhYZB1* t4%K;!JOɗ6>ZzwHѫh#ZhQ׌V7OcETT-Y/ޓ y(_-D?whi#]DJOVgx"d281sT5fnG5x%UUaCaƺɂ렏 <_C\8\P^DvߐN[Z(67Hs,3,bvzcKU.L'dU޼R o rčWi~O[pq N~%hMlFu(r4=NCw|łGt]K{R#xLo 琜)NQí䔭a՜ Ƀw 0>( yT$σ-VJg9[h8"߅RK!yٮ+n<8_&oȇ~ oS#l2!̫7yGӴE})#_A( )%^|Mˤp'Wc95&%8ҀѡйuМ黎dv#} 5jԨQF4F>1|$FAKROz@!fee9e9} It``[9)b&H ryC37 FRI1\GCI¾?R1jÏ dGʎqFpNޛf$[V`:юS%Ecܣ Qt ]A(l! 4 N{"RxK΋ڴv1[;MW 䄨!u덻lHU%v(BR+fspZH]^3'þa.y'H 8I mmdB.+d?Rx $, &eEjNztw~:a{ Çl.(g UQqx$mMg*E(eY!E H=~%=T,s-}78L~hÇh{+U(2E }49\.y{ǽ7nA"I)sppb:7=jevf#9͚=~؉ {eʃ2[LDɚÀ{( Ka혉)^2z{?s?٬P( am^z;n=;J3}IC=#aQ>`rG I)ប,2tpO~HLabw#)m4W5펟'w]si^|wr唛WO~cU :ab#ꚪ7Z3L׾sO=SO_'I999舺!(+Ʉc1i_s%UY}>G5jԨQ|'>oosӟ4/2ՊrIJ⥗^O}SrMɟW_9ǯʯ^?Sr^9g>K/qU~bzoO= l6ҨQF5 !n ŒMbao45jFm%{43b#`{RRęٌ^ *BNCAjGr|Gl¾C55kpy(p'?gK(,Ⱦ!uv NܶP 1sٲe^Ϩm PrQOg, c7/}4MG:5C887 6t5e 5 ՚rA |ĘLgL'[˾g2$8$v ݀=2əbxp>ɔB<펣S޺w'Ǽ͗r[ێ"})#-3(Hٿ3h6f9ΐ-eUx)#KʉB]ꌫ$#ɊGΆ8rX]q-z2W^eٰ<8ʵk5}?~o;?}KG?{y>v(e@w>sW~/~K/q7~xg9{p|Nx @#,)ʊŚ61'uM۴w EQBIwLsl"MP5jԨQF 3g/svvƇ?a%oo/gy۷oo&>9^{5>KKo7o|3*|/}K<Ӽɟ ̝;w ~=~?3/֨QKf#S}Ԩ>9qCN-ޝGYV9wi&AAH8%Bhhz8$&1DcƇDCbHDd$"$hC" @wWt=cD(jr[:V||`co&l*2M2ظZX7)FXZRթ:更M9Mx!2ڍl5.& 0M5k16ФRgTx ĮKACxb5JN#Sdm~l. amQnnR-v]6EXE| Aax%F)G>y:MHrc:^/)MDC`ƩjHn7[L^K{V ~k 4O3X"|L 4PH2Ď~XWQ^@9aʊ2!+۶ҙJ#jh!b& eUQhBn>D+Cy1E=4M4uDGeLLLଥio aeqe !r۲x UIǥn=&'b|~c0su4UCmklD:.45^Mg # IDATۻkl:6=(#!G]ASԧغu+_W_;;\~ o0/}KTK8cwn6g\qu[{/;vS?S5k~;'~>1x^_zGUUE%92""MDI9!\lbnq/LqleǪN_#lֆZK9Dceo`835S&cay #_a]t16u\vut:W%@k,?s!xc#ౙu34E+ rLsCov3 ҏ6߼'{ Ab` 9&'&t:z=2by+嘁)T"dR6Manu;7D|RشabϪ{}VnӤLc\2ֺC֥-Ѧ 2Ū6"'a^i/ Vc6zzyS801`,sYG]<~ԾT߸s֮;OR1390?`0IʄD_g.:yeu<WpuqQ"""r<''ٵk]t??G>nFp9`]8ln m3L{,;t:WooKn w=3 N=T.R:WU*ȷuv#]Dbj7,u6Lj1>EEgMU>(Bj"#fE:i nR7IƦnDh"5x5ŀM2TCbaBT5San-'PiPf P>t/0.'5Snr >ś!ԩ8j#cbE&Qb7&ũ4&semC:C]aG#LH]9lbqPS| .IJیT>mt4t&IQ:ۡ66Je>okmcHw1G` L bl;yi`Xb};ط8@eibsdiIX՘afҝY ed ^MS^=7(r0-Qt:Dvrl{q z~)X^^ &DS(r<)}~~ot{(#j>6l⎅;WtDYU G#fff803KlJ$@f6?mt4MރbII!D,9G4X"5EAB g0"4!sާWæ!fVy`x%E** RN,XlJ#.˱20)7@`ڜvxud.i<#3 q~C3gE`{͛.gߝw4 Si}`0ȱְ2ti|Cۡu """rԧ98WG?Qj;ؿ?!w+OLLg8C7|%zֳuַxnꫯkK. ox϶ms """ oƵ%}1١yr}*T̥cDMB quۙsWR~qm94m"hXh"):ڂ5X ѯFD&ocG2j򵍃Rκ1.}c;Xԥ |HƘ^&p1eBSBv@ʡZ2덵!snx4>bu %45.wĪ5mdOn8ҹmtM>[ Ɛ_8u$8kJ0>LLMۙSaoaAb@Jb.X3G,:aSU CĖ,1E23!-bo  ȋ4P:%EuĪY}Cl1E2FG U(:4eb!q ZbLg@19ESƓEC9.ٿ/YEf q3xb,//[n"ēc27MXس f8"VMա!Y]&ִwA_ uZc0biKVcHQ.1kY˱Bz[8YڬCkݐeڍ,G!s9tU"e:Efٺ( k]Lh`54Xc Y^YfqqAF1ш~@ߧ YX8HU5t:dE8%feرLU*hO~{~N;9.">Orǯ}8g}6Z.RnzGrꩧr 7׼5l߾ێ=/x/zы"""hPu);hY2Z!F-趎r a!:K͡ g DgSZZOC0Ra7@љwrMBHc\*Z ΦNl>3wSlRgn1U , EmT]*Y> u~ԭ,q ф6"Wc\bBM4)SAY}y|E0MC 83xƘ:m'")<1.S'xܶ>Yҹ>ei ph%bqb$B)Qfk3y+2Mߏi"Bz]6nYq`-鮃:c0Z|>`zd1ƑuqJ :NFa N*3t:C:E2(:&&ɋ1nC tc;̦IYx\,󌲬ػw/X uY1i x̖-[rwh4bQwdyNqvew,sTM2NTq&9l^ιԵo 6 .(2G,}n "bc3`,vkSGk7׊֤("/ȼMt} w7#tWicRIsut:reny3O0Ȳ ?.Xkt ֎ɲ205PLO+CvxlZ,"""QXP׾׾5s<1yғ[V"s~G~Wرێs)++1OOp5׬}~-o]zozӛ=K_ҷ/|!;vK/~__SNyNьm;xm2c" ա6mHE`I0<ì$@UN dML;oԬFRQ׬vqaLNmJnۤTज़19mv4L6&'T5&x,VnuE*uiZP/crvħu=GE`Rp_ݐH.Sq@C7Sge Qz1mz^͘O3i#w4imiYvum|\oیuY6=| bn&N[doRG>FC0y`=f"Z|6Dl^y zRFKSCcn=\px3]Nug xL^Ŷ~f߇1M6Qd9{hŸXKfSxUWvq<ڸO`nDHw<;t7K!2W:YӵcҦO {.1~&pβr=Q"MH}cla}dYӟ |ضm[u12i% e5wQd9 oح[9-|8j{yR[sd9𤪪!.Z`zz>t }e8p~O۽e"sssXk""]vqr#dzzp/AKMR\IGgb%}H.Ş\/&CECn!3Θ@!ug9. &kB0! !%eGc0&uR ZDc| Bbvh*(FdKڵELIM} !Imc }a`e%uؼH|9$4%l;1I - ϧά@n֦Ʀ"P9aܹڵM/cRzz$9̥Mh e@ p6HY_SN&o7uجb_\`rfL7ƧUcR\GcRB 6= Yd&Vkd.ufL'm!tR^ !'Z1ǐc0ѧ16u R749B`|C0&6n* WU۝߮;T)3<֮c4ĺNm1MA0}v%&h 8^ CY͏8@Pb4 D<0UL,~{WC! M yvMG0zw ӵ4Qrz~~NSS,.,4 oq]2.K$g wE ::.s371S  f1[QF#zyzeC,U%SSSԍmSMN{Mݰ@ebO]W uCPps:&&Y 8OD`׮gx`/hD"y11*.O-e+g;omf|2k1.Xsh]6۟WH_& .'Hk<5.1sZƒe~tbs6㬡nMn{lpYN:ؼ;ge Ƞ'I 2j#! @^ڵin훔eIel=f^'jj|hppi"""rdRA]DDDW2LfR,Ct)f4ڦcS5DvY3f_$ϰVOjgYƧm֓ ;g)i#Zr u ȽS7XBB:F A?ɀW`iYΛIN!1fI}X˜4:uHȈz<Ǔ6& 4Ӻu]ƤNx)D Mbʤ. S ksy3m8B/!`BΙ50\uCEu6ʚgG"`LƘ@$.2gGM%vC= CRwm;:&6-g-YK?j>mA.pY;G!"x V e׵<."""r9biȨoh׊R1e#% &er7ɱm:Ƙ!l5@S!C^7|iA:$p"Oqc1bL*,{6#N0Alnl.16 cmKQ24ݶYkb:w}e¨Lg\c ҹjO|,d)%M*V۔UML5[Rݻ<ˉ1b$v8`Et:#ﵜW|y~Bu#USNd:M 6OVc9,#U6_GR1,bYlhj0jw1KYmG5T^} ˘Nc9){,6FBUa*c\x!<3L0Ħ$4,1Eb h= ;=`{qugqY01H)?CF lPĪ=ַ=v(ju7ky1 RN3 jm>Ú8\JJw^tg#G Wķ16n# unׁcYP+rku̱PKƣ!K1-IGXMw Z\m7%p¾}sx|; " `iq` 'lgڳ YAf-LLL سw98ʪf0HySt:x,xO96oLxz4@Fw%d++ik_."""r_p/AD: 8r? |C^Ȇ\Ոu{spyw-"""!C]DDDDDDDDDDdTPYEDDDDDDDDDDQ{ ""G>{ """"""""ڣ

E]āxͅ^亾ptNjI],?kkt:ڵ8OoCFٸ^zV""""""""vcg#ncd8ru}>G .`ee;~`'>GbY""""""""zp/ڡ1^׭^QUZyѽ]#y\ve\xᅜ/o|#g ၇>W1yܷC=}4%\K^ nV൯}Cu+93ꪫx_mٱc_|1fffرcǺ _u?>ޮ.E/zCzܛnvm{կ{ώ;x_̯s't9k_Z1,,,pAN>dg=TKOk믿nݻws<377@UU൯}-׾;93 v#9y^Fk߷oԧ0x(9??g>vɩ#wF|s9;ve/F\z{^1E->l߾Wݻ / /p17|3o>1vܹܹ/~?9җoSN9%/y ?я7~lݺ^ǟٟs?sw`={<| _m>Orsq}Wֺ/|~뱮Z==]b<pyQU|;yxpyqW2?>>׵/""""""""-7ܗ}kkE}C ??u6mZ;#_:_~9Y/|nNõ^˙gIu{nwǽOFrZA^Ӟ4|+_a4=b G{i5>@_/шֲHd+??1""""""""q<5z~8}_3 sss|3n/3<믿Y^^[oy{;11g[ֻ}뭽{N;I:7񶷽__eΝ-oyXG{+ s/'<#֭[yG>{N;AE/zCs~cv]zH}7,9쳹 yOe*_~9nwc""""""""1uo#y[ 8y0j~~կ=~ΝFO#ȷ}|vv}sw9'> 癙[c~c ~s{طoy~#wѣQPx?A_|3|ZiFn 2wGeA}e~Ep%lmu꽹k]m޼Z܋H9yK_R^җ>, ^pܟý /[YopԵE ~op 7<ܧID6uYJDDDDDDDDG]ze?ֳY~~~؏þ&w%u‚Ƌ|Yz1o&HDDDDDDDDDD+hqc7ڐTvGEA1iaY+j^֚ASUιst*89eIQ#ǃ""""""""rTW=q"眣r1Ǭ==Xv_OUU2EQ077DZK@}0z0WDDDDDDDD]u8=5'{<{IƘz_wW|;?X' !uVn0JJ*j`0ukYǒEDDDDDDDDD :*ƿlbj,=$w#."""""""""r$;j ppcpGzm%f`lE07ݾnȠYߞ}[~%مOsDP_}ܜKΦﺗ\+ҿS7\x/tKG?q>헏߮oGzugڻB(G1n_k*kkVghex. m4Dz+ԣ1/~(=#_Jg;xF~uzLCz{Ots4 JvVhlz^JylP_t5ulKOj~%z}zM F^djKh(ߏ^X:zڝogGJ<% e_;X&Wg5q}4cڹcȑ/1/c)V*x}~ۮboW"5?Dems]v,K{z/g9l.3ԫȗzA_x~zjoG饬mGU2Q}8uY}m㈠>QD׆K}`ύV67[oqgYv; F`V=:>*CczgW^K;וov/1/egǿDA}KgW$ǃ4eZu:?WW]ڕle?:pGFQ\Kn_{tpψmGa_>F[/s^_8ٌFTz)>;(}?7IDAThDL=h}.umLGĔG6_JңqgˎBgir}o66_J_NWWc^xlWA=:G~ ~gٳztQ}Gsͼt8LZ>&z9gA}/>űuڱ-x_mϷfgQ؎wnvM^|0U7G״ە~Z?w=If(pG_u.b~ߏ{ޫ{ΜQA=:??Q}vm&*F?? c޿ץ&ڎ{ ׿f,ώG}-IgQ|]3.=w#zt^!vDzg8gWq/;}uO;~6Q|^# mҫ/s[GW_3|瑯g8Sw3|/?7BMIENDB`Akira-0.0.16/data/screenshots/screenshot-2.png000066400000000000000000005742641410625726100211460ustar00rootroot00000000000000PNG  IHDR|Q.(DsBIT|d IDATxy|?|;؉'!@ -G t(,- _ZZ(.mn ~m)ڴ.I[ $Gn,E%Y5lGb{f4G,3@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD4ERs>i6ͳYφy6"""""""""`F31m&"""""""""fT>SN"""""""""" 9u /)awA"gMxflR<ݶdRR B ӎ޶P;L3Հ{:xC|S9~&wJ6BL1-XgX>}2$'"""""""""tt4$K`9AzFDDDDDDDDDDsI6Uzlk1bdleTms#Mgi)@=vZI[hZ>-az9>v"""""""""ĦZ%tsL\әP4~y:!:GeO6FO'X7Ow4zߧ{LOtl|5㦃:tFS-d >mS#uDDDDDDDDDDY&u'  :TG>0} ]N.qR-K;T,}|8X˲ψ@=陆驂d_S'ղtn}9@=az|LFݨDDDDDDDDDDQ#ӁṎ3!`P}F=UpH\&vНftd]bCt u ճ3L-d4L cEtS >r?LN]whP(ԍ3az$XƇJG/jpL6tkOg.0@Z7X,,$}JʧzGHGGGi0@ tuk$\OVi|M}ө(@O4hlyHnX,78[WXh0 Aua """"""""""!IdYl(wޭ|! #zlmu`bnɖgDNƤO%Lttܨtf`YrB!DDDDDDDDDDy$uv|]7A?& ,덟tZ{N:PDf!BP8,l6j2\'""""""&>MU?=Q3*PNDXgNN$LX,Xx1fǔeVZS> BhooG `N4,3P?8q"""""UbDo8M4=r9B=YTIPMTdՊJWl =NxС湥 h"B!AÏ( rD%IBCC<jiIK+dY8|h+g{)?-}EN|ecDWdN;R`'0{}"I2v`X  108Wp[,`(^,˰kko(XKsdg=nݻs3J :Ly+/J$j:Y;HQnZ^EK*P|܃A;x;:~8DF'f6!DӔL1&de\|!^:/^}ߦr?^'!@x =1`Jc-dqB'N2wRBsbXq;d9|1z}سg/=ۍvd5 鈆csIm]Jx8ٖI+JµW?XyB@jB6f +V-Ɗ/k"{[ Oh2s9i^:4MÇRl)A\3D@v$\FkGaG:+=~>""YN(E9<z'U/!iWhU%zw`\J(/E]ښhy&I;֮= x10ЗƆ%g-Ʋ:h![Z\sƁr ? 遼UI¸5M7U`~|ܱ3[`lv'6BT麎+bÊWfu{vPП}&:Z[[< `X( T}ryE8cчϗzfX%e. d_V46T2d?;־{B'ݒ$ 6-G-JmZu@Du-'`-bnU?:oeuSD5!`jvhENT݂UU8_x5^ME`AUt 7<:\..`-jjꄿO]$Tcڵزe < 9j]E58w# `QM :<`{..li)yB!7ֿF$i 6sNe]{wz#+Ku+VFCC.]Ç.i {+l2[bϞ=s5Tv'/ʟOV'=DGu IrE1b,KhYzVz8iv 2|믻Jw4 R 騬-3œ*WU\|ime|4E>nF/Dը.FOo07n6cYK :h{O?3A}s)Lnu}}]jY3Jvn?Śj&QRDDAWdH PU7)5 '4T`CޜeM &a+2𦮮MMMط/Dk~ Q?Mz;5?`~whjZv.ljĩS8xp?ku}}[$axx e6 o˖-C=Z~\tEXf ;wb'? EQQ[[z<<8kɥKR$*m|=Gɗt!(cb ZӉ_I !ԆdOt+Nl3*̋pףC'մ]O-/t^G ig!1Yn]Kz1W~nv*PR߂" c6 i; P= 0r>[ EQ¥]&B gAw&y'R$*JBGE%ee^bJ,VkKE!`~cP'FwS|>|<|`,lf݆Z k #* T[noZyjCKbhK[p|monCY| k!߀aDWQVWos"!_EQܼǏyL'o˪+ja(UFgRU~?ѩ4m18_z~躎v{ʕ+p߻{^twwʕ+Q[[ ]Q__._/T7t =܌4X9^5ԓ #aI/L$1 έ.o) s[) -g5' MdLəB:˩( ֯_>w000] x?ۦZEӟ4裏AQs=x'fV4[5*W[Ljۣ( װdI˸u%%%()Eyw(R.J:^aFSr@ ČP_pA5fUPx[۔nkR@1<@H3.`a.רC=]~7cٲe<>JJDF[^/\_aر#>C%K#ED3^nðL{- zY1 #a)d4MaGYYy_ݿn5Îyw}صkWZo|??K.n@? Ozzz71:arBRLDҿ 2&4ik 'Q]TP{gCj| }FdR{iEr ASn\<=Ncj}wp&4_c {`{?}{9j łu_|…XzuZx'in&7Hfaݺuxg3n9=7LOlݺ;v /B%S&jA7{!md!UGoH!dq{ńz0acA$zWgWLX]YrPMYa6'&[=TCZ,Lp.:]dhfBuU02 E0Cwu!.XQ~YervSo|{r L&z)m6g8![!$MmP0WlEmu=:tmzꨙ_:2lЀ͛7cr͆}cx'yfZ_=v5z(++Cww7z{{QZZ%K /Lx9RY23f W{ ls;PpFeF*r'6v">l)3d?%K:u+vw6  x,F`ٲe?7|p`p8x@(OS<(//GOOO= !ψr[=fB~=鉄f eyL)vs&"#%<ٱ;wET644p୷ފ.{qw^|E<(..}݇>hNMqF:f!F%r?ϯe\٫wl6#;]`W`ʷOT[ĄF$EloHWV,2G PmB6 tzZuXd`iv?!`u:+4vƵR"l6}lI  ׿3MόO<׎ ۫buPSdѹ)!WNV+_{w#?/Xw`6iߏ(8p~ax<[n׾5,[ hmmc=UU;w4/~ɓ'qucLqzIuSy0 s1B}z:@\s ~b`BX#Pt5;uIe F!TML;`JӸYdp###e(..lt}(O~bxx'׿ǏI[6\'JVYqr3T}h& INCPmkhgljmo! 55IhYT!{oA()"IRZ|F]eaY.x=h׭7 eוFL Rlقx+W͛f?e]UUqw"8a}kK. 7܀-[o6> K,-[ B?Á{wqs1DU1BOAz!NT \0;Є}M$Iuchh&_sY1r7lIjK'z ʔ IDAT6l046MT[`zgղhMvG}>шt9n& >(*yrBu+tkth(n.&5۴iS0-n$b w8B¹瞋%K׿5?eeeя~wy'/-~pϔ02a~]^t {*q¯ c%LY(a7Ono!N5e0ۋO2dtjzq$IzWY=e"Uf+LQ@^i" D,Yoo5wᰦQOEfS_3$.jjjf8|)$Ip77783jlc;v@UU;]]]x`2022R`_(BL3 $x:{aӰ$ud!AnXW董n5;T3M1!A> ooeűӽ(+)I;Puǎ73I/.z{p@HPp!aP^*4/+bl6۸o_E\jFd]~I,XQVVɄ?NdcK.KTO=~:1!{!Hvn|LJطodYƲeOnéSS[@d7Pj$ WdTE@F!W?dI.FÆIIWN!d޽xG8u]W+kn o%>M\7kėoFg_6c)A@XmyQr@=ɦ`[S{q˙ߋo.dhobZ} B.sKwi\ta֤a`DNYe45Wnjh?v #{jӲQf\B]8nE&ߍKߜh/8rGMpp)l- TUp"ɉas&IC1at?(F7绬V8{ []l)':pI>/QJ S]J^wBM A聢Ōn'O6emA$u%YY \QubT/o;$0KC!p 6g`M aۡiZt"ɷ/۶m|q:ˢCe8NX,(`0X0?BuƆ 0|x^ p8ƗGR7nzm ≐wRO,}Gy8|0֯_IxGp뭷N#`_' vd"i6K\ߟ$A4n/u \"XǏ녤a ec{{iN9+ϊx[^dֳ?ޖˡ( Z.ǡrBi* fs˚duu:}*;ɖLKIQՊX Q԰}U E ͛q7bdd>Xo>^/.];;vhmO|?l2u]xG[o! ӟ4FFFpW#It@`J$$*0A~}ԛ6HVUTa;ah+w,ː$ 'Ovރ0ke.k0|*,U`$Xe&HGp;{9\%Qz˜;t 4F[Ǟ=֎{u>dI5_>Z^u~|S0K bBQ=C:Fٳ Պ|3A0F'%+ !, V+۱a~ٳ'ꌻ ԧPTT'N00d_3:=4Qh.gk;=>>>/zKh}t}[kЅc޿"(a%݁nzL)]MMB:gDo_:}Yh?Oظqc׭[2Kַ뮻/+~bvBL@r j*m{qș&ؗ"퍌4 [UZk$"QJJ,.:S3]e\rksqNe8OR{ynk|4?NeunZo{].@ҵ !Rd2P!a [{6Ϗ֨3#(K0(${/oodc=J^$SO=~O?4. ۧZߏ[n=6nM_[nGs<8p@tD4LG @HSu{1tm,5"DAEZNP63V 4% BC#8rN< { P?I#`34V Z Q]=:zb׸$ÕNDQ,I  bppǎGGGGLopft:K t8*<)ܯ&%jI P;v쀪Xh>Oj" AUU|>FJ B|u& 6 $axW r@QQя~~?kmLD' ~,s&X:#ѓ]?9y^_[UUQ^^^XOj/Pq{hZ䔡Fk:GS=JfE}s } рeI55\3i8+ƍsԪ=z4ziw n!  f~۶mضm[#Gonӧ3ɏ[!IjB^EQuPeU`h;~--Kq躖˱R+2] ή4]^Y<}2hLsLefm,Yɐt\*@H {6YNvm@oo/\.JKKvBii)*++p8:JKKQ\\Rl۶ VN~qO7Dkk+*++5 I^x<3X,$ @& s@FOSqI``(L=*Ӓ`lƲ*z]g?4l ~_FkIZ\Ӂ(U A abD&|.qr %Xpbhpa$$œeylĿGQ/ND}u3FG9WTT````0Z%bAEE|c(,^M MII >{^wl2X2ƿ%0I|JT%6.j2PUU5n(JD{Ni!tuD#BO;n2"~ij >![qB p_\ _>ϤmII  nQv=~nwQ[Έ5c+1m]vvl%IJ޹^%Ok;͊Eਆ=pY$,\\3wnA" n{da:|t='fMi[֨߹PZVdYFeeeu}}V ,,g Og}]]4MCee劎g B4^ {\H}$~}-q:Qdc`7;A{wg9 ^J K' ~2Z?w&B#2~m\z饨B}}}tNP(ǃhvYсz+g\\+rA⫐d#C6}3 UIq_sU9| ZEKH^jh h80s?:4u1$:(M),ipRʡKAUM:aL7jb6xk_~o=I%}Wv{9BFD$k06RLԜ=2mo>M*gB-5F}HAD4EId2 2:5/PGH'fZFgm.mmHFnohv$DRSxN>|qo9ѫ`N+Xx1֬YN|ő#G r<])'aƛbYAwd33dN*50 ?}|x-ASS#̒P@@ -"g_vBQw/bW( a'~\;&%>#3.; `鲳p^ھ0m3L](\5)rlը'"8"ɑdXs=ҝ'$;gJ3q83hz1Z6q2 ԇG ?~k/ $ϓZ83Ү˱lTϫiǯ=7]SA@ `;T1L 9;9%E%_WYۗQ\m.uo"""JN5 V{ڷ!4XB\.gڷq=*ֿrPP3k9B#۳?mgP!$|#פ οާ,0C?7Gɲ#GСC$ ,# " FAȲa<3Qs8Lj͂ 5PlŜ %I›GTl?3m"nFF^ }.Af9<9XHwc0x=p`36EQtuu.'RDaZ .L>4 ;iI6iWMpik鲳2TۛIyMDDDYOaP ҟ\a7Ut7Ú]{ lUrS}tgؿ*9> q{|)$I; {8+3rNI`Y6+6߷oohc@=Y[tAR'|Og`ggr:?]xq%C% P̋i_,"g8@t\uF&Zs/Ѥ+^ƿ1 Iث?Œo*Y>'c{5KL2gxEQpȑ>s37?ؿ?=HݧckAߧZ6B>Y`Wl*I5ۜR0!U㛈Ria(k^dg,J&^K4U[|SAh"""""""U6I>.@}2:IZA_5}CDDDDDDD4K$zgDQz7#:hr2>!QR3:5:P֝/2nDDDDDDDDDDDTxqnehii&""""""""""JQTffM8|""""""""""Jh7(LiHvDDDDDDDDDDDi(IIB:QocC؜w\`B 3dM""""""""""JBQgl)(u"QU@n QNjBYh|cfZ> xz*0P'"ߏA̛7/M!""""" ׋ؠ,%Iz1nvML  ԉNeHđDDDDD4gD>sQwF$DDDDD4D>1S"ʩjjW1""""""""" 3>B~Pe$If3l6[bDDDDDDDDDq~?(--eI4 !vgm>'<&tɆ*\۸nֆdFFFP\\lq*%x8+fS>$!V(Bii), u4 !r044@}6VXX]AIl . ⲔlY՘XXS!-fSQ}6]v5 b߯H#D؋UKN.\/7m!C}"""""Bd21L'ʀ$I0LLLMJ 89XXј0r=pބ;T vhpado9!@mE‚sm^)RpKYaX(vF̸Iڑ-qޣeoāEI z_:]c;iTU$):uB 0#ٕȦ)he?< ۦ ̜%NAdť2`hp4FQZ0<4 rY=P^^^|K>t:^-,혬-0u4y(/|``VqQ-KbYȘD#\E"'"""""""ܚ@(ofl.ϻb\HX~%$[1\j`@tU@4Mnvbhn'0G^hXH$G{ބeY6xDN!,+?mG.BM!ĸu Nݬ&c!ekͼ>cO,xaIg~L2y>XG!f牞Arl#Fh@C̉5YѾumԭE'mw4=툌Ox #h" f``EEEi3 ^{-6mǃD?Ʉ;wbXb~l6K_݋G/Fqq1^|EX,\}hiiݻ O|V;vʕ+q9'XV\{ػw/Z[[qw[V#U[h^__//RD6'u`6uЍr3*vی (Ă /m sdߢDct:~>nfg*HeyDFNUn%Մk@b>vQVVrrgW^y%[l] @uu5.]|cΝxGP]]SNꪫb, ~_`xxXh~a躎w}]tQ|l~;ƿ$QP(i[ IсիWc?~xƵ@=2h좸0L@@Q)ɒ9ab Ā" `9Rw l]zO;>MӰg:u w}7y~g?ٸ466⦛nO?{?8~N3i;qL֖z w}7vލ!>}KzvCd9Dr  #A9!gI+)avbp '}|n\s:ΡCt]waÆ:vԩѣG_V\*x%$$hE]PUr塞iqRu:_Ul6|GLu"t&Y6%$Ӿ R@jj~+`ܠ2qJyUrjZq$8L>Uڋ+r+RcH5Pjn7onۅu6]9t`߾}1cwﮞ={Zjמ={h" >\u?s^2 jܸqʒ?Kӵ`Ȑ֭['Ţ={sΚ2eRSS:bg}{W7|s/suٳeӦM;}K^e5åOxs$cǼ˅v n6 I$OI\msͼTsj9W!//ǒiii:w頤$8MMR9B(9P\xk>+!!*Ç+ r%%%f͚崏yխ[WgΜћoK`0OEоSSS/żRRR*+IJIIqe**믿^[VddE 6\YrrrW`hΝ%=#")CR [օ*)[\ϻ}U.]m۶)22RYYY%PTꞞ Ξ= 7N#ٳG4}tM:ԯ__W4x`\5/_nUԨQ2p7pBCC }TN8qB˗/l.pN8p ~BO#FP\\"""zK7x´u~;QA}Wj޼y8p@C )**P̙3$ooofM>]!!!ڼy:u꤁jرrqq{ァݻW'N?>LUzuI:7 9r1r jU5`=:t3&*GӵpBÞPWFN:qZne2d0O˖-ձcGK>|z-͟?_AtaիWOsFgj^߯h(pK*22RAAAS^R൵lRZbRSS%IVҍ7ިPUȎ;.P߱cG9ESqTɒ/ԩm;PϞ=uI:uJ^{kڴizꩧnݺђ%K4{l=ڼyE}/ZH'Nбc4cƌjL5Fh=?~ =@4iMj˖-:t/誫w~ZӦMӉ'=z~z;C9999r$SN ʕ+5h =3ѣe2駟jر{a5h@7+((Hn6͙3ЄzZ$IgϞ>]v2̚5K+W,/YfcDCN_>?~\'OfS&M$I۷o$p3ŢFm۶OVԠAm۶M<}޼yjժ }mZZ5l0}7kV#FP5۷+++K}Q_ǏW׮]%/[zeTΝ{˖-Z߿N>mOرcڰa:tDC т hڷoyngΜY෎K,Qff^u8<*k֬jo_ _~,q5k޾b uUCաC4c I҉'4qD_VΝ_k…{n=gSFF*ŢzH7|B?1r¾ۅf!S+mJpE^fEL&pɒ,ENdZƍ;;(V@@vM<=e2ݕv1//%) @fV_(\\\^]'///:u1l۶mg$Y$eHJya˺Y%eKIʹwyT*V*]Ν+===]qom Gvvv KKRBBB헓L˪{m6)|$p u@BP$p ugj5ZR:g ABX,eeef9; 777yzz:;r<(O$Kbf ù"eeeͭeٔ"RߒaT$KAVVNB+L_6M>>>JLLIIo1w l6\]]IFV"AU rJsP$p uMIˑhԠAg}^Z55Jmڴщ'駟ߠpذaj߾***Y*{9j04tPuAԱcǜq ~X7n\)G,P#<<\=zʕ+uVIҘ1c秷zK}꥗^lu]ؔ)StY͜9Sz74x`eeez-ժUK'Oָqt]kU׽{wIիIѣ5|{º[n_h5/5GGVZiΜ9jٲΝKſ*2],.79^$<K;wT``F)xܹ_d$ըQC׫h<ܹsu}R $I׬Yw^oںuڶm[XJjԨQj׮F#FWk֨Q,ѨC[nN(ݺu֭[լY3EDDH!?%껰+=G=<<4`͘1CԊ+i&իDsPڴi_|Q/Znp2ydee)22RСCuI-_}ڰaEVUO>RRR$I~~~|$I VhhmVxJkՀta+""BgΜ [oU۷ݻgUQ\sZh}[ ,f+Q߅_9Z^=+..~mԢES\]@Y;vL>fݫ?X6lPtt@EFFJf̘!Ţu[oU6m4o<ߚ8qݵn:]رƏ/ʽo߾TD$0 {w}W:uҠAԡCBG-f;Cw}W˗/dRΝuر2QѪ_bbbd5lPfY}?zUV%NJYVYr)Ut9j6sN :TUGyc+ sP ڶm+K~ݫ_~EcǎUZdɒ奷zKoK:ꫯΝ;*66V#F(22~N޽eZn:XBԨQ#]wu8prrrn:}jԨ9b"{ |vڥR3 @?ӵxb{oUV3<1cK6lٳK=˕E駟;g0jNz9ꫯ꥗^R~{/卹 (K[V޽"ͦ}þ|zWK%xIRJJJʼnrsst>9~wM62L̴ܹ^jjǎMS~OOOOw}E, %y]Vk׮gee'(1ݨ0!!A7tSܹS,%Sٓ#G,~;Kx;V>>>JKK!st>>ܹStW+--MEdfQZjSjɚ;wK:toذa󽽽qٳGӦMw<---~E, %c*L2}ܸq矝*Kє'әcl6l6EGG;hZt1m޼YEv_%ooou]&Irڶm+IQ&M(,Iz^sӧ~rB|B(Eu+(qZh~1Ţ'xBƍѣuI:0nzW.///}7h^DB(%ƍ+bի?þGٟ?# TRRg6<9smtw_fY6(:P *ʽyi^FQbbb5i^=WbbCcJ@EFBFYVF gR`Vvʥ*]HzezYZzԡCӺHE ^ L&KrrrSaZJJJd**2o0wW^ZWvv(z)0L2 :w5* (///yzz*33)oR.@y#^ 233e4PPʪBB[9U PިH8: \L8: H8: HWgT|e?f̘2@Y!G䗛|P1Pf͒$)11Q[neZKԯ233Ya^W>}z`uM7̙3u2p5+D꣏>?hر%w„ ڵk)DX0WWW_xo^3gԖ-[׷ " u o>JRRR4uTίGjҥʺؿKb{ Vj^իWW׮]ոqc#I뭿:y~7^Z&I 4Phhu&ժ_~E?ECܹs^5j 8J& ^yկ__\]]5tPhB'OֱcGiϞ='$$D /oVԼysyzz*22~dRFݻwo^jZw:Fƍ5j(]}2LnVj6uIdL&5nX۷o7ƶm.껨8&SRRVJ&6l͛/g}&I۷ZW^\\\t{}VVϟ/I2ڵ6mXOJOO/K@o*66V7p^x}PJJbbb4iҤ|&g֭5c =s3g7n)S؏l_|mMK*2μN!SXV%$$qWI&i:rS7LzW5ra\2.74f̘R իWWbbbY-<++qo7xbg^>>>JKKWm۶$ I2/lY6lI6I9n< x^c^EOBT[VNtR?[ 4uӺuti;M"ҥ:wiӦ]/ 6bQlll9EW2իWL[N@%T uܹBMxWn2]Ξ={YcF͙3GъVhh6m;v+μrpUE~Ə:k׮ѣtԩ|zzzjʔ)2 t5ko߮LzrqqQ-4}t5iIW3 СԦͥյkWլYK(q[ǎs=ٳgnPvPXV=Q֭u)}JNNvvh@+:YfߡjժUk׮rJ.88X Zvn_c&Mg};CӮ]ԦM5h@}ъ+#Ij֬,///%%%oѣG%I޺մiS ?ZxW]ݻ-[o4^u+""BSfffu%) @uܹseZe6/nk hʕ_VLKҚ5kf+;;;Fۧݻ> 6hÆ Pjjjp%֠ATV|\N-\P'Nt~!VݻӺukP۶m5zhM6M>|N>_|QԻwo9R$)..NٳgUZ5M8Q;wԿ[` >}26lXvUW)666_mSNW^*Y%R@2p]#ͦ׫cǎY~_l"˺? cbbf͚W-ZЊ+dZeZ?*((^:&>>^199Y _AAAZrl6rrr/233eee,@WeW馛nRj/l6VXaOD9sơ[l6WJKKSVVXNNfW8}rsst~~|}}c̔{6ėb!@kڴi2O]w$]|VWRRffOWΝSF7xCqqq'|1%{)c:uj֬)(*IS_ u*9CP_^N]-N PMpv***J{'+%%EջzNo>]vO>Zdl6z쩓'O*..NuQFF}y˖-UnB'!!A'OTO?h4[n)sرcٳV\)uY?R?;e۷#PHPZp_߮$iW{iʏƍxի5|p]Zbo.ժuTjՔ?^6f޼y;4eȑ#$޽[4i233o>mܸkTDDNtj׮].X@C eZam?gK^g #@[Rpl(j^$uQM>=_K/$IڵkW=i k[~}OJJ|Phr>[Q|*2<<<+ҧV;///yժ0\,>>g G]g @Bl68; W|p| $KbQVVl6CA)0 rssC)ʣ]t;; WcZQ3P/E6M2.u'r$++Knnn/ͦY,Jd s ^ /www%^alQbbbOJ2K P5P/6M$#+ WW*Q[T˳+٦}Ξ g g "#ɤCn$)%%E6mW_}4j('v*fᇊ%Ѡ]bR|poTt$ԁ2`24}tթS'_v֭[kҤI$ =ݓ#0P...JuRTt}@IT馛f :uJ7o땓 u :Tuс̙35kPpp O>ɑﯱc*!!A?;&I R.]ԡCJLLtrz9[Իw|mӦMl.򘷷ٳ7o n${d$>М9st_ ѣGGsq8Pٹjرڶm֬Y؁tu]cƌѬYR_{H=zT&LФITZ5Fi6l,KR :(66V/ʂYf={նm[_˖-Ӯ]/=Nvt!]ޖ[cO?l6fΜ`s9rTƹk5`w}Wy0믗<_睊crHE\]]նm[I6l05h@=F@5j=ܣ1c($$n0ԣG=#߿.C Ќ3tAXB6mR^}@EDB]Ү]$_+Im۶fW\W]u5jgyF>:yf5kjnb=:p\]]Onnn%Iծ];IĉձcGĨUV1cEԫWO񊋋m۶M-Z(%_$:{Zlխ[Wk׮U.]TF lRΝ+qͧh(**J5l0y֧~h4j„ 3lܸQk׮U@@$I .?}jٲe:uT޽{q׬YSOUV^{X}rvbo__ Jƍȑ#t+>޾[6ڳg}۶m lW_}/B111Zd6nܨMӾz]:蠠| dyyyۛtH_sNuU}޽{={W^Ν;KԿhTPP>lo;u<ּysegg~t~?]:5~7*;;[aaae45l0jڵ:tve9fq^nս&L(Zt$C~ {YmذǖyiǎN:iر%3<<\-[ԠA4h A5kzKH (+[lQ.].P[yb*]իWnݺJIIt>7ߨ]v;vjԨgjϞ=6mZ~:uJՓ222$I͛7׉''PQQCݻw+;;[W]u=ycթSG999%Nl6޽$VZ馛m۶"ǫVZjٲ7 /ѷ!::ZWLL[5lPfY_|6mڤ~^ׯWOjԨa?Jw^=CO'hɒ%:{>SWy+ )H=Wf :w7N:zg(m߾]͚5SLL4i@fIc=&ww|}fܹ^ڶVZӧ~8BŢ}m۶ս+==Dl6 zo c3g̙3e뫟~I~m)-ZȾdOJw}猰V5B,$''9XNNm:_a1sPVkرjҤ~W=zTrːǂ ` p IDAT}v^k6/B~~~駟9l2224ahzW.///}7JMMW_}U/'www{_k( :B>1r¾ۅf!S+mJp%5kš\':ﯔ|7p~[?~R333o6WNN{YsMI/ߒr&;PPJY^ZZ5Գ_Sd*KKK0+7%J*g+VCD!xbg\XE%ʁh4j^ rl6YV?oR.@ycz)0LJJJ/Ib);\F_VUIII2LSE-.@ABL& ;wNVFyyySL1+4w R)(gRVʩ*]F}@BPUZBBCp \.!Œ=cg9;WJ8::yC 4>hC +p u@BP$p u@BP$p u@BP\3C;w.ҥKqrӣ>J'NԖ-[e\嫒 TI:u$Ţ͛7K-;SztrpdB?ԟ)Ij۶Ξ=9sHj֬{WuaEEEG_ZhSNiJKKS͚5կ_?ZJڵSa_ڵk[nΝ;cegg?=̮n6K&$$$ RK\zk9y#hO*BCPjZR(pԂ@([ 0!$Z=ɘېL~=~f^L&{>뻿K^x,X8u9hݺuO."I+%gЋŢ{9XB\s}|{$'$mڴI[n[L;|͛7KǾax{ }p΍]?~V֭_nm8眾//_3!#& (ˊX|^?R$I8rΩZJ>szK6Ytd0jg3w-J¦#2)1<"{~R2('@VSPq׃yބ~|>rLh19#RT:iRM.іD%a6Ϲ@\ P׫j+|yS`('2}<)|vyN<IҪV+qF[VW8p9(PZTcs:v7l֑B#( T*uTלB=0N]'-׏VY'=49,t Smɦ? k4_//w5(G`zMT{/p*`P?–.] jppP+VЎ;4aN=T]uU3~}z,{;!,0t=cLF~L/jod4D9u]g? .@ov|Gr|?1T|Р|>/Ukۉf_{RRJI)TlSX+vbb-9$yޡis'(ר{eYǘv^c)L0 ]|>ֶVb(第uY+2+眬cyg}6]0)O()L$ j#eQccr{cSiq$v򑚣4lӾHo_wiu+)k*Jdr'P)ӏWȳOYG0MPCcc<(I~[;Jnt]xF6b7|v0IT}}Wze+jhSXT׬.TPJXIxfs.+| 3u_YG0 PCGgf͚%G^y5Iaa9ƛZߡ/wDZo PvyTKK $Qjݦ0s N1=OU٠粎`P\>7jƍ{gGGtHֿ텦pXf-cmڣ[{崵cZ[[ޡ&nҪ7|I 28/ԪSo]\'80 s2xeL9GgOw{IÝlV^ݴYRQmب\.Y] #֋i8j:ʌGZu_ǯg('@PPRQ>T&sT**CQvXkdosI^ק|3EWiaQ1farR&lJ%c4224MLzX,X,VegRCI$udesi``PYG=c`+|@=Tꬣ('@VSjjj: &e:PX/5K>/g`3,N,x}0yyU*e1R:Fìc(mwY1Hi~1L1ˋbI_돽*`MK-YluN:)B`|'%c^^ɬCB(&P_k]u ӎ7팬c"(&P7'"r6#"(&H5ߥ˲שUsY0PLs.3je΅Y0p9di 䌟u :xjc U󳴣c(&@o9YG!?`Pgg!P8D Ǫ:Q5ߥ¬c(юeYGeuAp8Ǵ/BPOM'ed$I&&) uC0Rh>ܰanVZJ/}Iq؞~ezaLRAuww3FFFdѵ^/\>uEТEpB׿ֳ>+IjhhgŋW_}ݧIy]wqھ}~ӟj``@MMMjiiQkk:,͚5K9}߮s=W ,. gՊ+|>8ir> ,ЬYc%sNwdgv]q?:s|Egu Ѝ7ި}cjjj҇?axc˿K]wu3g.r}TCC6͛Va(%c0?Ap 3l{イN^UIc`yi%&9B}ݺujݖmo$7[6k֬ݮ g?Y[N_nu$I]]]|jkkW_ .v544?A#82ڎ)%f$5# !u]:su 7mo{>я3G[xN>dԢEOCR}sN?ժ.2-ZHW]uNg#GRܹsu)]uUZ~^zJC YG0I)_$*.2moSRу>oyz!}WggV\o}_~}MzH߶mnF]{DZnvZj)_~SկK.А$/K]x~p^ppr՞#`*[`sN˗/ԤA9Xoպ[T*4<<<Z[[c9կ~uGyDڪA%I"Izwcl~X?r$IdlݺUr֭[wĞ>[r oxnvqZtQGs 7pu,׬Yq٪_Wzo1LY-^luSЌ,+u '(?9U*U*)SoݺUT,w[ܬa -۸qϟ#khhHjU|^/< +]Ss.rIGS`zV '0)"\NryR,UTv[V.U*{xl߾]֪O- 'gDZ㎱`oj5kּnKtԶd㘗v㲎25 uegL:jUa,"U7_|Ї>+X_~6nܨݦٚN~zXQWK^9BX,g:$^[kUV>e*Tss P$xzjy:JuW([PL]sd=3!p*[/0Zd7c rGybj`q)IqO}2=z{ޣSN9E;i;OZM>zWtǫX,p҄`t`z'*i?:ʌ0h֫f41# uIcs1Ȉqe˗/WExnwxs=W>rwꓟ{dL(ԁa$GwYQ7xK1L#3P05o&MS}_m٪Ut`%=LKGoW-\cf( #ǮcL;Fdص ?-kH.iuK; ) uҿ8Nk 岎3%yiEW:m9JƬc.A2W9+_ޔu' ui _ֱkk33waS*+ul?2.::4b\폪urE}k)͗d2JT~Y;R{ϯԲ f:4e\j]!I& 4A-o@˩j<^lU kUS3 \>{sYGƅB`o{H]bTu\ra*9V( JS%IOF٪ QXS MʗUVTnG0Pjjw: Lz^ #W*!K9AzGGG`+YGԘqP`( uƁBqP`( uƁBqP`(Guttu 8GyDZ? /]{2H ,fLԤe˖_[l[^,/o/~ ͞=[˖-Ӛ5km۶m;򗿼۲ٳgs;NjÆ O~0I̸BX,s5g}#$={}ܹs|GIhڵu+<`/˗-[v$X3P׻ޥw]cq ~_.]EQZv&W\R?Oni޼y|#<^xA]twg]wE{#pd͸B^J}C:3tR]r%򗿬K.D7o> Iu⢋.߯z+a?^\.&m߾]#pؕej…YG.u֬[p8[Nmmm* YGfG}9IKHJ*K^ыHrۻ^._w^{-; FNjU===Ya̡8P0:@8P0:@8P0A&¶m۲S^T:6- Ƭ#g:Ɣ/:@8P0CupxEo9ݖU m{qx8퐪\-4RYr0uPjYrV 0Q0͙ch:y=5 =C*2V2/N륶g\M.5c%kj}_N|]VΗ d<#yrP-dLdm~?ZJ6V/5F i* 5WZTs*$,N2N Pq3WZS-Iٜ) #YI(PV?545Ir8=#-ɎBऒrz䈤DwR+YɅoHH~*y>2[gG >?/gl}j^}OBΫƮ/\b#]}DlZ陸^z7s^Sj%yt9߫rx-|#Wzٮ F:պ7Ii"Z}h9|ϓlፖ龑 B)+bٝ'yIEX)52JegrUza8TKJϙXЗxž7ٸ^A^ /xJM}J58+ФƨPT._}OW{s^ĥVPߗQnmnVcb)jG}O}r@[b5y׬RFcV"ߓMSP[僜$Z* ]4V FGcG>?"INrNr* #0`rNZ*c<4}^_'-ew.FGGQ$ Wo䌕3N./uq$V2"򣜒8JJY6vJOLH8*#\w]2Nl6 ԇjc|#)>Va}_T.I8U#PR}4^F9EA\jڴGKEr/HGwңU$IF~}gӽ~0:">Rj]1vNR+Z%I"[?lA'T^Z?eTQ3'\<ϫog Z}z"g0{'ٮ=d\Ψ$F04jp;'a߷/L80M` c g>5fZo_+S´d$!ܜʬ{̝'y{<劦iE8_NT@mNNښa0x9u]㜣ks<|psNON楗^bֶm98Xڦ =w,KRJllcsBp\r+[یISUĪI&M4iRdO4iҤI&G*\,+(VxH#ֆ{S%nԥ, MJdk!eXI prQ^{FJ ުYpݟ 76(܄b`1ULLH! &fEx[k{c+cA2 V_ GYMzo0cql4!+7MPA`aRB\GZ-Я*}|k0}1X.d,) BYI0D<լ[< H1zNK*U5mS@ DX_\ݡf6V,TmVUv(X0:ecH1ѭV,am P82UY={uCմj5|mpa?/UUmÒC1d No5s .EW=h5S, #u%ŐV IDATnU PД}r֒b"l9{1):rxu%cr10cLXgiobxZAYY<)"U{'w9j8Cfk>g{gN5˾ckkbXsqsB!"ܽ{ww#sw̚r" Pa~bq`{ghۖƁiy4iҤI&'2ԍ1|ƍ~ݻ w1721?0&kNL7SwҤINAFs1z%ÀI1jB{\35nW.QԈ P7-HJok\bV!$kRL="y &yA< cȔv׸_kwKeޠxMgYBpv> `M1\cxqn-0L)EſltDs) )E0aP4Q3]6w*s咳CέKF5. ^)bdgbJz={Z*Y%c))4FtcXhF_[y2isN),j!Y-cv%ptt^SLV݊v>3v0.UHÇ0kg*vwvnݝ?0k 9==m[αZ-.lmmu=8a,K8rqv^.xՊgggoϛI&M4=3$"|͛\~mݻszz;9gNNN4 cCI*];ϷF׻e[wҤIn90@J1&Wsefu drĔGL ,hzcN,Vv>d";\ۥ<_\0F|KcuzLuols=Y@Ɩ t63DN:LqkQNĘ09gbT]Yj.9)P edI)}!!s~ϳ?cI:2Ōsjϒ6c Cx9 >8pbuc&Pc1]qK#Bwϙ ewg8Ea>"DΙq*:h"9]9._ƒd1 {\>:b`Z\,8z$NϨŹ''ccՊNqα3{'M4iҤII\Gy]iNܻw )%ڶ}ˌD};[y^ުmwҤIvŤpc ؀I1>h XQ(k<ʫbeS.2PL5.Qojҗ(#I۠frJӵ9*uh c~DS޹5sD1Єrj+a| 4Y\iڿu@Sèk8bAKa= :8|b[b$AϏr*2= ƮcܞQv6הdq2?ey"66|] cjwJϺjKriofʀnȒ/>Yms_V mhC~خxCb¡\#LJMq@XM3R tk&i9{Ņ2ፐ#fsl BAS]G0jkO? Vi+ YnĨ>O"/PyMk+,=OX _ISdXG0,o 9F\ݠ}ǼCEmyWj֒S*e+eaͺU;$)ʐǙW |M*Xޕ5: 0 !#&}M[f|vwvy}ױ=b{ڦu]9Yb1Tsf6Ĕ~ HfMېSd6q=ڶe\rVvvvY.W|>U gzQ D LS-zמ4iҤI&&}eOEMI&Mޕm9eHjfF \Pj0^܏{^LIhW`ײDDʪ)?F,51dQux7Oc eE(k UP]41.Ugq%SnX:@(%1ޑ#i$ӏ ,G md -fw ]^ DS9<*=RON!GvFiNx_m -EMUqĜަ Xu Ƒr38F?|F}₶miۖoH)i>Fhuy&Gl $Q@P”.N hhYY8*^ !8 ^s%E6)FrN0nt,ȼj1QT1X=>v$[8÷--%]1XJ#[$er1 J_XŘHE $)kU9%1| AZfZ0qTz]) CbbzL\ׅR;OH$p%93z61tߊԡnD0N OFX\Tr]qs!i R|Wa#)e^N:Y9ڦQNʄ&45;;|igggs-"i`F#!NOOif-)'._B#ˋsU;94T.9??gk3̷fO*a`w{1FN^QM[&M4iһY C7YM~}kݛ4}~7>___Ǜޓo{f..?ߟ}ݹIrJh$),E ZiAFMꖌ+xZGeMA1 ],pd5_Q0[l17簒i\ rSвFYFQ;5Vb@bT5 W籠.ɒc4xJ| XÑrΫyn-&m ggDcjkwzwv .dWcI (' #^Wp;0U`k{#!X.ϷX =uA5A} IQXl|/ Rҕ)%VqX-55G`q҄g-måȕmz.nuc%EƎcdMMIY-}(jfQ9쉵my,Ɍ㒡c UB@(|u| 6Ho_S)"BWcߑD4i_D6eƱ/x5s.! UƭH~KJC㽅J>qr S:D2UX,Y)%BUa*O[WkHIyǭWn#";&9;dÃN̪,'ÊC? 6+ƐDH}iE*Œ4Tm9e!a,&x?>f٭ؙ5xG[;) c`k>'#}Xk8ǐr)gRNb@Y)Bbӕ)Ʊ g g59ǂX# )pcc"KSp/A95%c%Iƈ['G)/uS܉ESrރ\|9'Paa>q虷f̺d]5` xe #^ϕRJu\{쵮u]ip knܸA? XcdRJ};~ s"劔"| GΙ}3U{b3Yk׮1obbX}[na-ܻ{xKΨBm.N8>=*2ƩeҤI&5qu]??i~wRO<ܹsqy饗z*KJ/~߯^1O|\z|+?O~ܼyb-NOOmL{M/9R/BIQ3OsxxH۶R|G?ћlwҤI=iCI575&84Y1'"3ARCIP:D"eluD-<5b fyȶJbB KqMl +~Aک b ٚfwkݼ,e01a,qV F0m4urVDkrDܪyiP{ҪޓcٺuЭ:juH&[aX,4 լa"FaN9I *_qzqFJgsz.'~o1el n}?lZ. 46`.>EβJȼ[V2#4rZPUëzx_vÃCvw _P53[tn(+m=kLnՑsy%:G|yM=%sUjȒcXc)\|؍4 )'71#20fb:,iJ>mmbyZ02bdZ_j[Îw:$+[@(MJ1i9)zS|{}M8cXV]|)3Ĩ}`#{ʰ\, ?u9g+e6a #DlƖp㫪/oܼA6,X%Ѷ3Np֓҈daF޽|{a C7:\tժczٛ|w4iҤI&&k2|7n Rܷ3#p}nܸmwI?l=׮]>OsttĿ˿p%Oۿ׽',bakkg}ק]op||ng|#k-7oyꩧg>|9!]&M|p¨F{G,XacY1,;1IH,V0ZYshXu :55Q4-n*_02Ul Ŭ1U LIKS N׸ju UJSւӴgŵpMvF ,;`M;8Y3&蹴HjK"[GrYîͬF>1ҝ-e yx]G `v#}t`#0Àɂw<6e$cy1'wM̶)aSfeH̑Uu4UER)r~zFhp8kfsBk~H2G[/׮O>ŵ+/st*guG2r)贅 vx)sjI.leНI8 =Z}O۶sݖDrJX ;>w~S;͘])%lA.- :nqγC̙ٚw=X.Xp>7Ĕl\*;J?}Z=iᭅH1ruHy17 |0MB>mp7KZ팣˗8>yg1l΃"eafnj~`4pt*팶my嗩k ,RM4iҤI_ wLZ꺦iNNNx_[SJBի|>;w0F4 IDAT͸q/_m[D{_3f3}Y߿ϟo~8_Y,<|+W|mosϑRSW[Pq{{{?łO}STU7M}Y>O{n߾&}Ҥp\Xυ]x.)شsrRJjhzߌ B$ޑڵfWSD-Űh"O(,\70AYUSb2BӔoZ)cRpdX&7 H"[t(mYCD*)|1#YnJ^5:~\b0N0VIdAz\1qI *eUzD@Hcg:Ȑ!HsZ׸<Uk8O#vNGLU\̙kDBͶuyxSD :GpV1:Պ>GF np.Ӎ#8rfhkCg2O=>ngKWh{1 5Z-yp9'RL#X)X^y"BLnhTjZMl9K)#Dwc/Zq`ɢŤv3$gyU)ChxWiǯX!ūa}R8bow8&1 žz\)Mp{O/Ǒic1d/xK]W-\ʀP!E-~|VS ָ~ж 1  ׯ]֭;-wܽ{GG\,7"U;%jET8W\eZ1*I&M4i$d6ӟ}Yz)b|K_7$~?^)Njbx֭[ܸquo{#r1 Z'>я}ɹr ޳\.W駟S_Ww͛7y?S/qwBN4ȚM&Yξ0(b $!/Vk5K ZʿZ[S|Ik),ɀ )< pQ3WKPTk19ASEMvc5֩YV zrg0u9ՅnӤrƼʐQDH9Hfz,e&w$5Ť Hoe1H J9LyUa#T3RO Yvm^Z|v 6jn|<}79Ez9r:tidu,nx$ n#=A_p0u Zcw~9&j'viݐ:;F!פĸ#X[:XhekLmཚ)EBxǿ63A_ho_+qou&cXX,4U،X >s]K<1FƱ/x϶XgIIWTD$iB=t]?xFKGpxpȝIsn>/X,@;$ݽ=]u4720:>~H;/&M4iҤW5QG3}5ew+~vv=9_iۖoX,>7l :yz+"t] <ӤwrCo{5˴ImJi%弮˹y9'?#{{߼II&Awt|b jhɥl`ΥT6ՍR X-֑DMHIAH1ԝIR9XRfs^0ԾwZvFXX0-hؙwK ĶY@a!9BL .c@|Fѡ@NcA퀍z$&eS9C\QӃq @ ^q6Y5)VC$!"4FM;BM m#-(C9}ypvbְVu+ت[NWK@%`n٫g4ub !b6N2Ɓdλ>'\Bŧ|I^3gp;wr/s2W[?!진1X\%6 coIa !# y^DSڊ2 aRʈ(Zh,qd{}~*Ҙ;%7f+, H)4tv.s.!=L[<!8GN2\Vb8[L.q200k[,ʀ*)X)o5 kto8@y}OA?9.늙kvg~ժ wCxc,N{ /~ M;f;b1[ >gUe&M4iҤIduҥSOntxH>@Ιׯspp@J#ݻˤת*ވ~} c ?я>='7{I9|IѶ-g>j͖N4iR$z*RIIl0ks0絗Y8cuHINFedc "0jJrMb)դG-NzLQ`cDyzK?@K( %UcqTcyNu0 r& T@x)Oub_96<4t @NSո&=֒〩FeoϠiq}$.vA[c}`m ;E =egb2ujZSbL~#W8#rxt{5kq&sm,hb'\ ZIKkɦG--:!zbcdMbDŽuz9[iimk)CvS';k#}ƘX5I9@U(3k988[˽Ֆ&M4iҤ\.ȫ_OO܆?J^B_'ӟd_W?_|jœO>WNOOg? +J I&eB.Ƹ2BV^k\rޔ.R` q3jc18k4jX12IZv6%ժ6Y)Α}3C)!Ed-XBUk \2fДvN =;i:u`0Mil; 8"'gH3^){L0ԀwF :TW5f>W\ h7)c[ jB݊DVnU={`4γ'ĭřrSCx~+=Iϑp6cM`49?Y]1]n?|kyƿ7Ǝn!'xAȅBUV q)| qΊIy}>s&8XO~Z왓}߫m ¾װ֔RR5[AGLA*Y4w fM˼n-(u!xk7y5׉| Vf1^q7@ :K^De̕kW1ޒSaJ?J99[[[z_s|S bdGu eL1w>vvyprLw\? u.0#t]#vnY.Q #/JI&M4iҤPjgg?o'^7b1|3?D&|_sy~Z~_sίq'M^T W(ݘi-js\ax4 pJ`$EHf׺cAq|.85Ŕ3P5-فST52iu<#VH M}sw#h_$)= dp))+baTA#cF46+X̘Cț$ZHGlrd#D*ײɼ|nJ5g;x n\ #ɝ]$PUՌydg2{՜89;68Ip{ggeEJV Mkc;bpvvr~oc13v rgQ~Hi$eT-PI*jgg᭦{NySԴdLNʡOYrc̯)U:mjZSfS>Gb^=K*{RVt]T< eأ3h"[鶼g^RKtxf6tsNbSZX,1"vYPѯ*]abf@LPU{o$I]g~WU̷s}W0|@̌p$@`z5TUK5ʎHJdGYy{;~"oPT hV& D8;=ݿP|M1 ]SgϞ3Lil[紛rüu4hРA> կGGrh#&7??ۧ~Rkx!rK~^ߧ|g>߿Bw|_{C߆A}Uy3 pT@ iF텇"sL sGwXhX RD|0 >3\wp p/׻1r6FYY35Lۖwz2hxv@ȉ49:>fm9u~o$=M]ɜ)}/d7JTM1#ۭu5rJF |RL=9.w0-nmzζ9'Չ]0}U-e|9Y x;sۿۨ*Ϟ=w~?_v 4c*puRXjpQr}Z"}EP 23 Łf _opRCW"]2IV,-B.%;Vh\{)ͪ4W0 S1qp}oI6+TY_W AC@9BU>nИxdsF'g{;#*S^<9[ ;\5bW&Kܮxs|ͦI8OOY} I35b|vKل>&DX-yʑtz@S736W++61u[>>+>_ʗw''prT8)7H1kxRC}Ę)uM}aVr5{Oz3ҝs>.3}1RjqtЬq"F#fi)9CET省g\Vj8'IJB-L&x2}3t'g uUYձmh4"DURX!}?"ĔĂvN&{6q\]x7bL+_*ۮhzpNQs...xl5? D>T/64hРA> ~7~0e뺟H9gOO?LqQΙzz|[Ji;>hРD1Fs1v) QMf '-$2pOXxƹ}GۍVR&WfJRR-IqKW@hA̸>Ta\\WaS*f{o(u+-$P/H4zo`R\RC.9$%v4'n표 00Z7Hף}43X<SbU ݂HAnTR ,*9(e"Z,Cmu1ܫ䈶|0E^LH-$2,5K_89,bk bfrѺ><*^s:;vC]ל}GUר&';_>)9)פ&s^9:%uUq>?Ԙ>x& L<^99zIu]1mF& u-88nR$%a]@o.I9`X6DLk\y炱=cWg mR׈Œ Hw29f2 x|O{ܞ<އgrRCZP6Ѭň}j|=+ёݓʽ)z]Vl%7)_J=G~n5$($Q̈́P`&8'kO|kܹw 9u33dOU3LJ9szzHΉjt6pjfZuC)A 4Fx<_ 4OLwGgРAoYaIC f,#3[K":p*:Y V$YiIN2)!}1KDD\6SQ XRR(Ι׎]d.q\CY 9aقf"k*ZyK'KKS[ݘx_~+ ժF}|1ؼZDьGMeF#2VݿŒ/(edX}Em[$*ܿF IDAT̸Agc|8ŅIh&E@F-fŧOOY^5#~ h$g99RI`^t)w;V]g8xn;#x}zvͲ 햫b*q~e:p; ӫk._PSϹxx8BEjbP`UK^P_$3}5f\c`Wn]בRĉ?Əqeoh>ao["\K4"b+G#VK KF (׍9iU0PSd{iU;+%hmj1)qSUn}9)}mIjRTUKC!Х$+v~uޱ:xl6CUy%^{ F͘3m۲X,B Efn;6 ]qz60 4hРA7 ڶ{oٛ3hР_~  $E1xuXAh Iwe3xv @8GѼc OZLkñ䒴qX--ƩKxWj$gRIf+Xx_!1!%+ yrIRYE9`mݮ5=Dgn4haS8ꎬƛΔBҮE]e){ `3%eKٓI@Ukh댢59thМ}O+£eG>)'͈;^=?e?maZ{VO^е-_Uԣ=ٜ^|/Stǜye"i9 4p<$b O} ;:t:e6|zW?9>uUN׼Z.9q|zwɱ1p9{x9=a @ dFxJgb$ؽf+2)'p]Yp7 sVͩ'%-SFmEJ]W4zU`^잀 d`nJJsacEf'Mз.ub,wGَGҒ|PuW4Md2߿,nLy$}z.~T*M]]f%=w5׋1F& GG8XV뤮zq}}ͽ{0L.?(s6bA 4h ` i*77A 4裩}e`IJ N#r'PMbh23:8KR Z.4 N1[]2mo>1)6?lƾ\٧APi0zۢ[|Mn.7DXjS]reH =p;-;fû !aȆIْ ÛSs>8$[_ˊzozgK%3+.2J3f5)!5WY>eHWHC}U:\Gl{?ýɜ'<9's߬1]i:+q=`jIZ\ -i8ųM[Hʢ튳ь7x\92NrçY7|` hﶼp<&gu=y<շd6_e^ԛhy+sꦶ2WT }בrRRvbb4}Q%H, MHmߓsT8l+GU)ܤ̦4`iw z:'uE(ŝY-mVLC){ĘYlq,;n!W9߶lXu;O_Q}6=>fwۯ`O )=Bg\g-= }h4bݶ4'g\]\rxh9]숣ãx{A]Ʊwd2 ȗA 4hЍCtРA .)Ydbl'3}m^&xNޛC)upӐ%+pj&:Evm P=⃥-soĞĮ4[q+O,Fۖx9~zArBKC%9-%8hPKgl\ro)&3D{Hj/aǘ7{H=Jn;Kkvk۰j#+=]: i;r#)im,WmG+#c^^3Oț9Yzڏ+bm}zA&FU6&֩'n{&Uٜhdp\&[4GU Y\ȫ'L7 >gu!Ϲ{vJrq'Ѷ-l_}hGKb߉p}`23YKOC8W ~cLhFE5}!hF#>zOY,.u0+mt¦m91N[ FzРA 'P9]uu]7WF?mBR:ya|Џk_ j8-A;71!W"/za7邡1|Mca-en,1G:X ='fp!]ZXf=ZM./,39xW@hРϨ^mh9b 9G@p}4z&Vƍmٶj*FoN}(X3 ܘdUa+Tt#d{ΎkC͉Ʀhuʛ'\`OZJBX.9;;㍻wxS48Ɍ{ 8N8NupAc4xPt! )@"^<ӺtWlSO?ͣGS̃Ka~0o|?c֌8h$r#^9Ӌ D3NO躖c.}6+c<w?xxm;57/R!iĹwdYBl+=U2(җexs]nx֌&!^εal̀3M(eX0/5dU!UN e})ِ4L+8eח9%FMcCkGnߗhB)b`<ilۖvMT(o9⒣cV5;Owι|qt2:bLFcF1dB>trd<A 4hGWC}G䜹{~UB'E*eBOs麎~j8vC_YA E˒H:%NwIJ>>%qK  ΣG+h\ =Ÿݚ-STͨS89Cc)̖~$Kv;\RXv3jFbC$f}1UӒڧݢsAjxMה,qd,/;4E)!M 4wΈf1<>"um_+WYCQA20C ]| #躳F>*9+xeuxk hV2O?fӶL3"Pq[)w{zBۘlZnKYTغ@n-c\7Ԯ"D\,i Uͽc~ērؒ4n}{ߧkq5ݹv/9>=a4Uoobq͋K>xxtݻwiSkff~_֟gtifvĔH9R&%3w%R8 "EHì8άߥ-T+'НPpF.  ,â`C7V=dCݤ3!;boxëh7Ho)}m'B+ݖQ3az?c$Dh4{+ؕjyArf69_Ky._\00?ݴ6#vFx9|?҃ 4hР>Q;s᮪~ٛOUUcmہ7$"T,wcGG?;hРApC.Ldb/ԡQQ4&QҩpZƸd-@3EȻ*w7fU{\ YT$lض91-JTJ1ĝƳvb;+$ $K4&%F˘2$\+$ἇ-PɨKF!j[-um&w W{mnxcOGhm94xجdYga7**ˮdzs_$[gܙo~ QSG(&kT&de91ݖ˾׈O{Z!)mNdtrr͸  uk\)jbq_-k_*ϯ.w(8ۖ~#)93 prtD=Z,}UTMl6gYKB$;HwxqG͒ݔʕwJq1i)4DLʺǖ Lu M[l"sLn  !0jjbv}Rݮz["NZ3umI=$sͤ {ZW Ϣa7#<^H9{7֭†2,esެ.1j[o5o~ٷŗ>9ʫht}MXVL'SiF3L^,lF]׈8V5g?yРA 'Pxy%joq!4/j>ڕ(4/"#L4hЯ+3*AB;J".aAqe_jVXg`!- Eq{zAx:Ks{$51KJx*1\ xIP'BwC%d-E1BfDK1m7ALp7A%g1Apԕ2FO)p.J>q{1=KjƨWȨ1$G4C[*o ČChAZ+y2E;G+o*xFuzvw>?sX_Sfݒt/ǻ%Ok4hРA~1bLKas &dHWOjqq{ @\0 ff;4t(1uUIZi`&y+`X0;>m_Ȅb( aWZ02EDsU w%cw%υEKӓJRS)jՈ:t+XOr1@7 |KKHC\Ig{;{"bv`G̴RfBԍ=[ =@\8,8Yt-3M.zLP9aZ1OPU~ty9[s&sRL&MxU^%hʪǞ>y^=<3w9Ն&G3"W<[lWKwy gέrA9LLW+%T [%(3%Chΐ ؉*<1FV2dBJ Yr׎/vIo ~r!ɖ5Z` LI+uo;P3 wͅ,$qb5el` ق]K2\v:jfl@٧ݳZۈ. Yff5LJ fhK8fc$n='ó4r4{<)2"u@6[rBn Y)xo%SzࡍhJP;+)en[p;ݶvsI}QgI{Wװ\q H cwyu]n<4Zy\.<[TxyٜC޻ܗt#\_t~%;;tݖϽ&cr~?'8軎=s./a2NNN٬(Jv­c6%uxru"tJugeY^=J3=uާEՌrh$UX9,r;HߛQ.Ό웢OON-> !g;C7f8\Yat<2>=S]14L7,]gR>%n^S04P_(r۪hPW2L5=xD"}#4|/CjMi9MK~4jcjgK4hРA>D 4hРA Lt\X(;ֺտd睱³isHvNϥ`yKX;Av(Pu@c1>GP1Q!K/ eWe_㮻];+%e_RE-%ueton ŒfЈ~vmK=$pqݬ>GEZVC`(u}I;O$;Tw'HrAPrYO Y,alf n{.nZ]c2]?sGSw/̽ HGiSf.g|p\w[z245 YȤqk4{OlynY[78;3^,͏4+W$Uf¸ܻuP͘zzzk?xH4fSFu m(Լu$FtNuenF$@{Kh d9-]sڛwΙ fBW~1ӘKb|p%m%<)+v t-;>.-AG+LV%;C59;o~)IcBUo$3WW䜙%{#>LNA1_bd.F̏f^s]ns*/.X\_X,xX, O9sfZӶ[&1ɔl6J"ƞauA 44 4hРAQp Y "fhz.wp w}VBɞAC ɖ.#A2R,Oۥ۝6 ?'CI33Ktu7eKtCFNQQ9uG\SHX*<t6rJI덱Uގ^vb>xg}";g]wީ-H=J/}e蘲jA]^_Cpdq $ mA5ll< MUZm M$)̴HѨ!yj GaZYNNtvij%4U#& 9q=N/X'\oz7dvKv0 IDATw ~n}%iH}Q]:..:BU `6% nɅW{#=TRňvp;D4H~Rߙ96Q!AH s~q3c8l(9[iR5f-é &MҮt48F}`:1eุ`:lY;~PV}eq)FOn/x7ќBNKO88CEoic uUBţG؛^UUU鳿6jp8"P_>s RN)Z{]嚓}L73wLdٱwlb`;0h7es ČǛΊ3]>sT-)C|Y*_SBv"}^D X0l Tx!RψwfRk6;eԕ\3Vj۞wM )u`> ImsN&+NvsT~HLvc!vvge{LRWK2SAít9SU5{KɪtLm#BOt]OL'f3*ov8ٴ[֛*Ю7&fX0͘Nێ32 Ͻ=e/RcuРAP=x)H/}Mا} z/}'אP4hРA ʊ?o7s1g+%NM@ $Cq9K&('7,eKGOG}݌䒪@Lg1LaK1 I{oøԞ][^O Ċ 풌5GRf{L;oů!vu^kg^G.CJN5KbLޯJr0 ^t3\ݓP;n,D7|Vh5#)r W'.=cM9ڮc4~z+G,bŦ#3&Ulx:\ӑwr(ls톋ՒMR˳[+]rf*$)m3MG1u͋vk9_ATh/^GLSi[ysyur|Oܹu/}\mn[-hl6# ľg9}M/1nCRZUpt]g>r*,•Km{o8BN^pTK:ٶ R0)'|)5@ 9r+r>` B<1N'KWUenuc)[KȘuݠܿzr HI'xD͙xBRrq +m1۷\/L, NOpnZȚ.S͗L&Ҷ-шFFP[A 4P4hРA JeDwH6=,M[@rl)r %Ka-!NMU :+)UQ+ K}:DE]8Jl_4fڳ#$DS1!{3-e:mqJZΊCKMaOH4LHŊIգ$bR(bC [&#t>y-ٸ攕R7$՞Cph@FV| I?TuSa ӥ Y:޾ͣ*3uF.18ؓ4"3s$\Eq5©#t<{nw/_0zTy#\Lʸ|_d>Bn;xYPVH9sU1MXNONȗ mxApm Fj ċ5uchb`y{!c}w\s3mgwSsxzC NivqؙdCuSPg;Rh4 IJB;[JRS4 OL^Ǘ`N=1c$ۡ^BנyM_ k\-YWuh4ާlmT39FPRÓo5ꗿW/Hm9*x9s0#^hf0L)4^i7^p~l6߃ 4hРC}РA 4#*q%q3PYYKqzv83sF3ιf.Of$JV :[1]5[(),efJ1j-S)ƱX|gL>u=]ay rbn5FcWx*8.&4u, >Tޢ)9}XՐ0y‡@ٕ4K 󌙳ĈyKgK{ʐ3e`!YqtzeI;ϋ휒Ւ2:shD=^#\xpv|p`:058OLg\suzzˤX7|#F8sop.G>2iSg-8*V 5>8%n=шeܮxߵ9 6qbr] -AMLy;"hݪ 켶K%'`)!J'Tv\z ?]MRzjY U1U~ ɮ%%io{= "MCHJMUSUpSNUvs㉙2Zf9JZgْPUĔڗ_Ͽ/~<!?zvW^;f4 n ͆a\nKunZ?ܴ 4hРA A 4hGTZx;/HzW>1ٙ$j\)HUv{^:Eu!a3U'?BwkgwA>]%NMb娚Ji/9f8U%JDQ<+KVɶGW7i&]3Zx}h@qdP)၂8O&fJ"F7b/,H]ٱu]lܙ;w{^[Jid2If) RC@w?la%Q%PdmmD}RBܐR!=yn"bGD;X(AxŎ6d1#u i@/45Z2o{r_E/Γ!wm6 \.xݲKK9= m)9Z 0WOYĈ ߼㣧Ϙ/r{Bynvagꚿ~~|>'8v.i֋%=7{ mDgPUA4cҗ 9s4C0!-ՈCTOtF 1Mw%6 )gcέV9!Y^a@җP)4qv2m%Ƚzp@MEֵ{ %t 4MCJaԁ@|fF8Kc׉eft݁3M32\O)Uai9tT3\>m&7xS;2-ѳ\,$ x{| pq~nד&M4iҤMI&M4iWUN*3D(*Z5RAĹ>EQ1q5:RP8Ph'Ke%⳪1rk2ܐ&ôM@'dDn h*;u_Ǎ):9C6|6%y)rP/Ahņ v{ι+REAS6P8@;J93R*K÷rFiH7= K@&O5^*"c"FJ},[=ձog\__c1޼A.VfIfsn=x?z傣 -{_qa; D)݂݆'s.lgӀ:-GfSÖT />s{sgO\8[^T׿7;_G۴솎.@_||1grl"w=G1ļ1dX=*R2Fzhw1 }kMy=qNbMv> qwZ&48^1Dr婏Iy6YcjE7T"JEksDHXB=[A+JGwZq)Gٿ8Ȑ{>ztţٜB r߳-xέG \*/':#8{W߱;*.if-<=~0tl{g0k[bPݎ|N >7/?'B};9jnN?z-X`Gl]HU^w1h,1C!:*@!U$87߻Vx͎Ѷ )%B'.zeKmx4bRNu;늕1QJ6xՀ?0#z =PHηx _3=jv՛78Gm\\\_~wI ML-0iҤt}gHoKFS?/OP4iҤIdM?L?iU|Lw.(Sjia}ik f5׫7w&;\*r%,{\N.Y3JP-^WU3 Zw,nUjh_Pof3/ }7i7f|V17ax@PrT}Qhm" mc`'C   4q8+ ;12{5bDu|rs_ݖbl zR'Wt}og+^zmFW8wsnonq{,4^xwoIHcC40$Yˡ|8ÁWW\ѥ|1GUY/xY-9Bl8w޾ܕR‡@J2!;Ɲ34TB$@Mǵ8Ch];1ҩEKna|v!ĝRR O8/D(i _a pJ{o#ʮ+q4 'rb\0;1rjS{~[b O?qw gg\\\~s|Cǿc'?{ˤLMI}0'ˤI&M4iWT%e!a, K~ W9@5zWTufT bJo+,B {3eĹT[f\5R"Tvb6G㬏XqLE|CޘAoh%5%ƱE\%٠a #e04 xozL T .> Dζ7%%" d<Jِ!'|N{ފXK Aw- &DrC'}zsCDSX w}ر?=f sY-"1gf>d}Qw֣[oӧ||>778hN|orzw7_\psϞ1v˳繻'GAaѶw{.<S}儫RPJ9hf-}CQ+'4X c/r*bX#a8Z\;^r1s6B(Hc5P Cb 0&zFI@۴hb .;W t _$ƕb|Nf6QaKq֥xCHeVEVW$I }-U$"nYWv[#ÞzM]gvw3 mry7orww0_b(f2q'M4iҤI I&M4iҤѨR,YKSA=0.4[bHJƚ3 mj6w߫^8'܌b/1.u[ 5.N S2U(/bls՚o$㨗T|Mz$4V(xC20[dQRJ5?3D4ZoQB +eTM!1%#="R22_ >3Wz8b$9eG{ K 0~ɥ`&2E;b\qV;9 afDq|k>yrlx^iI\xp@>3!9ew,+n~5Z ?%ϮSxW#Gw8| ]ywwjNЯ_W^\\\pzaY %+Bc%G9%3 IDATt2 j%g pqN"KRFe" M9 d׉R1Fn9ahNX|➏s4- o ueڶE/bi}} "R^i;X~: l_}ߚ/5ͥ8r}neryy0 xGB݁RCwD^xsV'fʸo4mܪ'M4iҤIg I&M4iҤ"H3ddFTI Qg`pR*#@*_<b5jԺLhqhD𗌔ڌh0I״N_2ݱLjb[*0F` g iZ=%{\Q@j Ȇx/ R|w&BVTC‰٩%7V}s-ЀR zGGCN0@mpwXa Tر{Cxg\Iyo5s}3_.#Ar۷]"yty|Wxgs}O;pw_?8ňw<͎_~+~0, P_?Sv~k}b\W?2T7⽒#DJ6pqvʈG13[ ΓS>1S:I(8 8oFb)zh bD- ~yi]P j;JJxIi@6)>E8_ KcRBW1)KR؋׿AWM3p<̚g8'Jd=~L̺9o߾bŬY0_Zn6[V˳s>y74n~w`4iҤI&=h2'M4iҤIRhNj RDQeȥ0zRl5g#pd=bP\xGCPSkqjAR|Wa*%=5%+:ipC3Ė⽡*PH39Z7houKƞQd&y6 l ]OXfxh9T|M89j(y91%f=T({^M2V&0]:_u’zÑ>TgVؚ2:db̺ۖ k-9ZQ=CY6-Dw~TdZ#?d2 A6RH)q.p~vx$L#[x<жmG.n V_WO4iҤI~4&M4iҤI_Q RjeQTNv4`7rwK1DLŮf5u |cLuž=2N8XApvuГ1뛀R1~; W#bDTlUx"荵^K5#Αu4 ,ZD$:#Ŏ $ùM,</߽C^zM yH,3f ۶( w7?$T>5]PY RV2MtCYBʘin+Kj{\e;U8xB =09Sٙeש&\8캫o7jNdD9멌{m{Κ3ԁ]\5VAw5u%Tl@CgݛV:sj|w^Y;GQvCߓ+pq~n~x~c^pwC;3?F44iҤI&M I&M4iҤ sLR <O5"S}ccJT~Sy('zC hGIɒɘhԼzWp6Y(h2PQqޡ T{ĨZJeל})z3g j:WJYf Qv %sMļs@J5~5c5&Xj#m9ge}Wy4}C|Ŝn8K2T_; Ơg Z'|:A0_A%D\ɕ^?Z ERP\ Ŗ"4W휕&RSrz>yk|rsk8.&ɣ+^~x 磏>ٳg7_=!\ld~A0 f9Cվjih'u]M}`l*|ٵ\V0`Ş%Į5ner28_ Dq SP,=N*3[K9%9s}yu':hsHRJ*s; BzB Cwn-(iV6~ ", ^ )%cagO2 =y%g5缽}Luly|u~ &ˤI&M4A>iҤI&MS17 JRM<"834gG -U=r5 0z$؅6k5j?. f8UxHET $D\)fWFr2v&%W ;KzpCAcF)ȐhnvV(hl'HLmq07ּ+H !ݙ! flGA*8ףd13؎*Vwqc1 kAZLuހ6!8K I43<6С~D%QJ490o"Ŋe_z?fPm/^p92 c`s Iْ嗗|o^<іz>?$(RK F7~U%VŅ d®&M0ݎSbC)%%sq*Gt@ wH5Ͱ߲<$ċs1ȊaZ: fI#d8+VBq()^) aߗl)03K(>ՒQ3OHt҃^@QijdѺEGg8\@3jU+qԊqlǶ n,~vV))e8%ȪV蚲JEobWK;b_Wha0SY /|@PKգP1Il"h΄`(9g+< fxVmgo ćg+Ch#9>=}*z>;ٳ ͏xti<~Yp6 ~̉5 N<#}?X⻔X=bnem2 }q-~N5 nLl3]je{)y!ܻ@l3"a]][>tz]uuIWK!avB !Իݧ cao]:GHNחkbIґbͱhE}:?JKakmS^xĠ4iҤI&M5&M4iҤI_Qn"b|t,p. GpftIx*׹y5s!!a[RHVr0vrHZ 1b9a% -}j,j2PG \jXkh-_5US5b?+N,q4%3_D;D4x[v"wrpk}94Th*uha\ЂK(&*ŸԤl0P Z, rwt1 ǡLChжL Np,ĬƼ@X.ْ̒yKWmp@;GC8ʓ5Ħqπ7?قTߛO{o~!/_q}u/~wk=}B6?76H()}2UVKnş."1#'CqBϱRKxmbCP t\-5|JdwQC"WNΙ\ 53΅u^@93R b[NRtaD(nr9wy!{o)!b+P%_}uzbIyyOhZ^s3bp͙2WW:l[պ&r)};cO4iҤI~_4&M4iҤI_UiE٦RSR9*bXQAu0^À^G,,TKC+-+yd#b1|7-'Kǰ ͠B,Je4坊6Ëhqք 5kolaAkXLwđÐfƭ) ޾C6wPry'ɼb*$eJIq@9 j&95}ODŽs츉=NZ(fzWK>K4 '3Ǖ[Db |M0oͮĞWUTvHG./f`Fw<[ {~>XHCO,uh(CH@hg=m %K.g3} sqv~(^7.q_}G CYs]\2 owwl_}P1S;Rr2͝BٺXJ ! cʏzbEqN!X*J!օcN5I_;g܈:%ݩ\G_ 2jE<I)z:{l>noEJ4lSjKupVJ:zCdC*Y~j6sލJ&@-7_YWv,gHNд(SJC~޻3|t͌v80[~wI&M4iWX>iҤI&MUԲj kR[N:fa:3S7]U,5ƍqbEՒ5%~J:ԹW,1ufYڛdRwU|QU0ռƞjb 3FʨwrN+tc.fdUs_rsKh鬣+Pr2E%TEmbJ6~X.@|%>+jh;g姥C634":X,@OXB^*LcRpy(-:K00 TF=+,"y 37A{0ж W.s8sӊq0 0M':γw3O)ޣkڶd;Ǯc1_-;LQ=}C+>zC0f3SKB;#%KA\t3|S!ξi,멷E#us:s&WlwB*|`ȉRv%w.@}];]>dZS é҈:Vޓ1ђ!q^үIo^^*l6|uvn/><_.ַx|qI4 +u1<?_C+ 5޾V ^9+t1bqb[laȜ"&6d 9 8yь%rJzXشhEZ9RNrB_JߑS& -~HC5Nj ;!'_x@C@jAh< 'K"Q lV+\+8NXaWDY%)+*JN񖼷shCȆ5#R>~/t渫X#N,yq%ٖw- 1{YيxfG!xB7SۆKrne(4 n, yKwvr^=iҤI&MdO4iҤI&}Uq ( ' S*e ㌣l .S4UF:k FrmNIs_YZlt wQj()8ABMj-8-̓$t0l a8׾FDn޾~C𞛻;5/p}uI3(p.Y \=z-^<~HC;1\ˈ?K FF83S#Si)% j^9UX݋%:qoˋKÑzMȼm Nx/eنmpbt][j\m/b5.wKNdڦ%6X>r7xk.YĀ=E$ڦ֤I&M4iRdO4iҤI&}EU4Duj i>^=.1cLpS,u#ƮՑ%28&X'YbQTROJ [i58EBek>p7NJWqVa.VJQtX;qңZXl3EؾȘl\ > ҼIqTcAFK;[2Bz34F;pDr2$LpMC$CJ@*07Hu>(8*d/ v-K'?&qws޶̳eޑQZY,f\6׿,Hf/?j} #E> ] T S#w-mLujGlOGJ#9d3ŻZHj`\qi1>)gJQ>Q$"TpIuDy)MJ'&89U#DmnaAl+D3xC,gZފPs?9>Ngg/6gǎ"Ǯcs!<>4S?ߓ&M4iҤ&C}ҤI&M4+*)fpVX1Oެi:{2k3udDZd8lvV}+[a"e$D7s*3^kW}M79ߩ)y׻7`}v54Y*@4 p@p,?=JiqU fc2'b( 1XKIcOOE°Hȝ'uX2]QE>}?xxp~~ xw(ebZq}{"ٗ_#VC)s"8[?>՚4rutt₫+D6LSe\ެYf͚5klϚ5k֬Yf fhPKtSݬWa(*nr !)B3T-|P:w9߾XChq4C)&Ͱ SR񽶈[5LT%C_x34C} e*K/4 >|_$L&Ǿ|R1s4MU7'~Jvݬ&&DCH} mA tmQ n\aY=Oi`1 XVaz᝴nЎ{(Z}So cBHĺߓ(R:;+^Jc9reI䄋 7Ӟ*B"ONNx F>zɇs& ,7dŗxvaس r|[)s햷/O~Ն0r-n]ts'? +RKR AQKpcV/>3s{)0VtdXKe Z˱WK!HlxpACgg~{>h4e* ijߕqrc[O0s5#Wfzs2]&Q bd2"t/uU~ ggW1!15''H?mwlq]+R7_{֬Yf͚P5k֬YfzCes$"H䥥^E lfw3Zd#UOּwpLt#1/ t#A<!7 {#1ՍdpW[dh<рԖʏB>k7#:L6TmtBlDYܠ,1 1!z eۮ8Ͱ Xm$"U} K+z\}P!~: ="?o}rTTRKldBGt]zͧը#\=՚Ϯo?L7,^ѥ]*fPOnϯq?>g,,Ї[qxͳyK=bTĔ ?ձc7@D躎i}"("9`kbfb y8"IfF|`$8ܷ1_#@C t|)!e29gfӊW'F/1 {m!sFBdXw@ 4M->\.ZS Cz-3S -`Sc`f&# b/A'-"EFYHj Z*RG`]jl # #p:nbGs¤x<1b]!L bh3rq{(XixUZ@=9d5k~!9Vohe;Ԭ:F;6 ( [VZgrG:)HNq=]vǗ[.ϸXd{6buB-'g"..8?+vgct] ~iw*̪Ƒ(aG]S>{T\.e9Mm׌Þ{lKP -~7S`҉>_RET(ő.TdjUrJ:RJ8.fay܈N)S8HٙnwԤ}8nOD\xjU%&/QAa=)6#0?1=LDu'}ʕpT+NRȹaqHHMèV+1 5Zrb ?Oy}ӥz`ߒ'AVYcҾƊB[#3V x)o?yD qO~ Clճf͚5k֬,͆Yf͚5k֛*B-M./KDMiC?G;hk[P!1!U_"Vz X.N6MqjOD%qixO[w>i.Bo$q/V " 8q85伩x$qDR+toS-DZ ǂU9WCl&t R H3Wn՚A(>,8EES#q,6hz,o)}M~~REE;E_ Q 1b ؞B w9N,tH~$0IM ~ 1/\b(mN8?p^af =~9_+\>?[B[K<;"/O)0QN THRK3`!P\#EGTy qQSRW`РD{?RB"JשrSj-Ĝ:4/ Bib(G3JS"U%Z)-%] P:7+nGILcaX,WxbF#_J=~4|@"EI}> qfLQ/H)s}}rvvaGKů=k֬Yfz5f͚5k֬YoBG'ֆ9U(7h͇?&h5,6=n3*G1Dž @I I-ڊ0ؐ~Z3 )A0Ht#ZƙFܸjL'ދV vZP6`lS)ՋS3RjK~{N 2ЎB &= Cnc]JSۏh薩06.y}o"I`nxG"r&jfGˬ'|-{.QlBnT_tK:`"B~6r9|kY~ͳg՚ofnϢqb^䉱y%r16\PjqXjF'cjüaS n!i>Be!<Ĕj-cl?UpmV*G~z<>CRusJ3u/x}+b ~6s|MZ+j3c)RHcIvE X+}vۻ-_|͜_zøw{)xk;B>x;n.3M#Trŧ_;oz2GJ J愗-垽n 9SKj;&+ jUJZIW3TUj3M!a||\V5B)]zZ<DŽj+m&g _1af7;Ymo?j]{~ >R)@Q2/Z&oq-ǁ[-7,Wuv~_sS>venG3a㋫ by,,Z:9$ˏ?#D)S#P4CZZ 1%wm eP=j3N IDATn> lC#%OV&{04bnLwW0?CJ-%֭pH{ 1et1'7ըZWvj@B³GU#qL#/_$z׬VaYeBCw<;;eg?{Feq`]& nnoXlw;NN6}O5k֬Yf Yf͚5k֬7T|"R@Mzg7 4INi@, ŰEq=5e*/^ ֛ }KRNq LiZٜ^?Z=^QxdirS;BZt1"ыj?ZZUg 1f+": `;绮f)rP#e7c ^:¾I0px5iK>#)gB# 9(J^Q3#ʀ*vD?j!Ւ͊-"Hd?W+~7X, !8cJOv`&V"Rr&}pusMֳf͚5k֬(͆Yf͚5k*!!ipt I'i fhr6cq]P v:y$(^v鞚lEJ{}rl)<]-KAi NͰ1+ m[Ǖqn6~{p<4qecG%,Ԃ(p腚ldBǽc؄v~T*UscH%f`I)vua,zLtdlk2aӈ :؎\ fhj1?a#ҶE rHMWuԇYc7O-@7kBʰmEÄ #*Y  -fƸ grÓSV9z/̰T춞Ntzu-a7'?X=tUnO>a)~#> 'ky}3m*4ҥW?`gq GJ(Vգ}HH{3Ľ@jZZN)9f%6|_k%E/Edļ#1Z){0/2 !31#ELx$ B)c9w xaũ1U ^%S՚t]Zh{T%1wy(! ~DRJ+M}%a򓏹HbRCK9KcAdfOc UPSt bBQ)>8w]hHqb/R&~Te&s?>>vTF>{K._q_U})^242*LRs|> FnPUڐDFʱŇ*@JCQX Rq(% jˆT#&g@ }vG(ho9[{&bRJ3c`=?ZQjKýߵ XJKq[,HÂs~?} 6'쮮^~9vjbY{@Q\z~cڰ\,s؏#/x8Y5k֬Yf͚ Yf͚5k֬7VCKf{ WҰ,5<+IԆZ VԸwXAҐ!4v. ְ+t;Mz5EyZ h)XۏzAbmn3Qb i>ϣRoo1A r(Lɱ7WYP/z ''Ű[L+8b Ǻ )케USs0 w d뱕rAUG#l>nhcP! uRXʞlQ& 6L5 ɗ(IVFB >E&g5CZ펼Zq\0L#)aɏbAXp W[D3o*=>ln E}R[n˓˓wK}uͧ?1/?)5x)8CՔ0N#fnZigccFXp9JbhUR ffZAIh!D!g71 ١hĎ偹~XmU[]bZy";|χnm8aCV^~ř㎈TkAR&ƞ'olDcԑۛ~{rZPo[2_؎\F؜lxxa9_w|5k֬Yfj6g͚5k֬YPq ѱx~\o%Ǔ`E"L8کǬ񾽤[!lAV2xZ"]kTG_E3bAھ7~@H&O̗gА5^+6zi``X`U]ni?VY/<>GӤX.4!)]J!ъ =q8b>h d7"mJT<=r^о{YP ~$uU P/ZȂenLjTZY ZˈI"ỸE㰡$B4#%W/n8 ֩'ȫV1C;o 8'O_]SltWFg~f$B{~%̸'+5~wn A)jj%D) hŤ39%ص:38(V9R 6xB=JC4K @8% 5G䜏ivJhG~9 {#TNvXMygaRQn^ܱ>=c:9bR``ƫ+N=͆vn憇^1۫;$e,%GXe\:v'%$H`&nApww{pϚ5k֬Yx͆Yf͚5k*1E9üK? [Ѱ/΢^t|qF9pKusZ JA X+U3x)}jũԂXLTƂYunV$f/|S^E=_hF;q9un:()"g' uh^@ WlPGWlgvZ>6Dxۤ]ROS44AfJtDrBuDι,{?ުmu@_v$tp&bS jV W vsDJ̢SRJ-bnYRF > b)ɉ*}N^.c1=vG07[.Z|gO^s\przjw 즁ɆZ!l+\oV~E<>w?7ϞR,)r,*nbnLdm^ҫojP CqF=vg; uTEeZ(Se&ƫW,+a$障7>k֬YfͺlϚ5k֬Yf--쥜"ЍZ-~b8\c+6UmgmxpLjucZ*=pLn>lS3԰R!uB[$iɝzzYL5 ŇJRZCg0/m,s٬8Blx7#Zm0!0QOvAŒ=yX% Zp>mQ/ {C {h,aEA쥠`=Z`xyIp}h6sC H{S+X%t-YOR`Pfv,::q|*2<=|0`˞.N Y@JbThj%' vr)=Ϟ=/}NlW/q}uE+;Oy;\XsnCÈYeXDKv_)?~_Ui t߇0R⳰E~x u" PCRms(=KQJ 䮣3DO%WlΙv͙mX׬ks~CRNĔ'~O? Zxc5ʇ!J4y֬Yf͚uof͚5k֬Yoԍp0&r_r<\9$%f E͋DK=z"= @iv ]+!gdzXL}!q-*UHJ>ŋVU!cAbB03o(`m_iV(U#2 Х@nDv!y@>@4ʹozJ&(Ii{rjC`t fH)hVRY H''TRVYc 'Kl}Av^jkrBNI 4q1Z-aɐ u,>;G) 2fx] _o1@N^ O%;QU;d*bM3fR'U,2L 07xc=V[d,B_}H%O?%3Sr†"X'LANH!z#aͰ`uBY%4bI-TP.#}+;4Ǵx!0gO#2$)6LP+XOolbx1ۑ2s\ooY= [0co?Vb6j~/o8?ˁ UaY_99ve?ƑBk#oq+ggg~X.Yǯqr|墧;Van5O?{_ ?X lkNϨSe߳^5k֬Yf Yf͚5k֬7TJuYBM\ Fr,"N< Rē)dXvC ɣb!cfjliz9(bnYO6(}ŋ ݔQkF}5%XD j`rČƉ"ԛ[l}KRtsPb['}8@_c3sÉl6fT3чHK{ߦ zO[Aw{7{ XFLYHʏSռ$tRFRrz Y/A(FAa1"_/b~@B;Xv~hmŲ㈄HzX3|1!2R@+aOXѺwv}TVӊ99=!wl{GŒ~E q3CY.C)zn#)R}T!0eh"@hΫ`7pjqms ǢXjHmn'b7-Q^ z~/1})q/}/O8=Ebp"<Ԩˑy֋#̄ir3n~x7<jӪ?w?Uiwk{!}>6ГFFB͈H^V*xi7J# ,'7{ijn}(8.P^3?/n|#6[l}@&HlXcH lIVꈝhgi9Y͏&Sʌ,P :f|TCkCscFy'O7/5ˆ8Udj+[0|MΎ5n 1EZl[7dpZfMb1flc"3V Wi1Ӂ1E{B >7ugz'qR5^[" 3~K*M릤 RP$cgV{Q/):\~6yA 5_ʢsḠDo$j џqkя0Oc p:9QJcN2 Z+0b\UՆH?_|L4HR1oĘ%1TNZ ?)_6)ziZjժU.h5WZjժU>P ^ ^H=K#nviDǢ4HB@/TBh,nbyzAۼf 1RO3=.))-M=iݍs;4Ll7 ݘ>Tȕ! w ,36&qp㯗Z/y9'-a`T}x8=T@q Ԏ酧Y@Kb~6!:lGX7L45}{W/- =̞42NÈ9:xYM 3qYh^$D©SHH$8"Ȓ),Z9Yv6f*ef?n3Q# ژR0b ^ًdR 1Ƒix5 8;oןpw_rG>է2k?]v7D=fځTfr4/ w6B Ţzئ? mu<=xA7axo|M"bxGH)]S *!{?XL/fY>Ȳn[ R ٝ }?!$DR<4~~}Gs?ܯaV9\="_cdG7|9WWoH!k7/UVZjP_jժUVPՓ&n31\x$:Z$t,&^))ynS$v6{'/!zfn.C=v]bCzB$dOgS7BUռLO =^<>m0%||2N_f]qvd` V휼G< ])z؜{sԏft<ͮ4 Mv6 ) NhvMl %{=KkZa3?$:g}=[{ahDۙ,r뭣Y\εFkm6L0mnKJ DAMHh6K޾fOq_Ke᷿/^p٧p|iEk6<, C:#1ĠF)\<٭.@jm qgI_1~N^lnњ_ G)bdYK\Poul"Fm ^ &ё.1&$P H)J!K`>ҎrLRk/nMDg|bB ̸?/~4|;cYvw;>ͧ/1q4Mָx%VZjժVZjժU,%/4uF ړbrN[HSO~5HiՓ1S5 3Mc},m EhhG1)ҬPj};љ6"n EFimy<-liHYOqDS﯇!g^s?ڱ=t/Cd4 Q5vAES JrL#tnW0p{K6mi%´C(i;QJv sќվJ!0s=4y%z v~/$KA|AT5&lQb1TCYeī_QN ѷxz}E5G\ɖvK x,3ʑy>q7lwiGӖ_総Vg~+Owֹ#e|l{B|˟weOQ+-$)'NP+,p:' cGbh3!I7R1&fH1Ct{ۧsS7CO;]t BCd7Ҫc:~EH_E M*RN.zB @bG !c|LOs~BΉp8O?=Gx5) fNvl"4/^|A777|s*5G8zϘ-}%88FUR"|A\ H>cvI9bL~uyqJ)K?L]揃Hļs ϧP0Wsȅ~ƸhkZ V1m^YI!RJX朎Zm*=~p<cd)O )FOϞ=?n[WşUVZjժP_jժUV@ԋݠ/{)S5$F,{Xztv:Lu}Lnl;mHqʞrW{VŹ!DO#y|x"eA';2Rєr瓛. n[$3q*e <")ylOːS;;:AI Dj<䄕 MŰCwׄr,Pz0䌽= #2,fa<0-h@ ;ZGwl3(LӅy>1׌JGkTݎ;f˯B1 i&^٫VZjժ#Z UVZjժTGpw]o wT=m ՓyuԞrIcݔ77Iv|Lt.:,2c\lHUOqFh S!ncG4xxɷ{sHgʎnvS؋8Sͺ C|Mc:s|6 ^(ɖ^Yާkņ|P<O )RNCH2fKBR8@aiӲ3Z͎'2va.3ģ5ǯgČ-鷾ۇ;^䜝 a(4vL^RzNk1b?):(B<|g7*N;D.pgGׯ3N#_z/~ n7ǿKkd4r:xWפ?-jUVZjjZjժUV}rB7b`J'`SU!4'KIi܍ϞX-&np=aޓЋ;c e0E7B@4':we'/4AP0q1RFk#m@~jJ0# =nu}\;clAZlfҀN;0 XΎ) A;' DGa@A硪~q:D1D1p3lٹ@h8qZc)\mI)"CLVneP#vˡxzpk |k'_c>—}O0I[#;Y1ѴĸQ+4/fGuCus^: B3$tB5S FUݬ' U} !T{)nqbhj!$@zrSBf7^jժUV}Z UVZjժTz!&nJMfnv9֓gچx9) 9V{IG/Hh,=*ّ1 3;<8Xo3zܢ ۫5g+;j⸗Xs*cv;b%{AU1xc]$TDvCnk"OjSBO&uF~ &2 ٓ=ܨO̥_T#o8\ctL5֜?/!aU8$0 iuO#w586ap O'V!0~ + O7״業A0yT ;j6HΙe>a(?~j5O|@8y|9Dׯr,9܍t.*B==A>30`bJr15y?8)R0ȅΪW.+}t.hak.v]#|џC&|?yA=~_KE+y&%?<~x֑:F6ӆiڰl0U4%R8Nf|Rg?]~;t:2y8hj#x/셱VZjժUP_jժUV@ePQ,GϦxOKO7ETD4{ڠ\Hkݸq9ZG7pNmKOM RvYlsutvzx8"L&qغ_tu6K%ưềhPir|XҺfoՑ,ytnb,ξ]cGTLkZ1 )"9{&َQ_aO M~E ɍ'癶D"쮠4@&gǐ4jX5l3w$l6iЖ 8"fDdFwH8rv}Si|r6'rG>oO#Ʉ@0)ЖCk\OS!37B$@ )gLcӚы?o7[?%Fɞ@Y />~QDRyA qPUj<0kB7ELFN)R9%jSls#п !D⟑f~y^륫?+ ".x5%~Ґ/q1/3>6)p:B#\!aٲ]cR*U/>5?ͧ|;~#?~yL,mw4S1p8QjժUV^jժUVZꜜvC- {DH@za&3X"c*,.tjLx1Of"=ݷXy=.e{"EBѓz =%ЊČ*+Fi )M}b!^NVb~2_ ּLa腓cgXS|=+vFWRȌV !A3[CvvδS E/Bi^؊`ՍٰiKB `N hliDr7o99X2Cmb|zO@4~s8p.Q0Aq i0 VUُ2^ IDATSk 9hf>FDCj\<0kT1&nr&IJmƘDZTD} 9v* XCR }0gocNYoQ5NWFD)GNzl쇐B#[Z}EGK 1EsKo^z~sQ(Ki !a?8>%Fay(1PM )M80#O>s?#g2/OGTCeYa%;6)gl;_jժUV}xZ UVZjժT"wVS !%:6*h2'*1eu kA =qjjIs1gys!zj<G`XSZYzBA&>/nĕCSgD')B яfT+ci<jœE_sd}SO86ǿ-7΅cO;:VCin):_1#t{Ƽj4&y 䁫7m&6W+/32d^m΁ߙHcx^ڱZN|] *-7W4wbKanJ1eB+ƣiʹ%lǑT Kxj:6D`=ZxˌFJnF7uzoސcN|̯>67WnnҖCΎn)^(&,.7 f>)zo'DJn薲 JOtSo1)+&>].Bg F[#x1k+}0%r6qӾ5! &#)*{J_ Ї~Tݘos쮯iy]==wnT}RibZ yf^Ԕ~ON?O)?ߚAB)yGrHʙ4WZjժUVC}ժUVZCUU$8rS7zT.^&jR3Bp\ }1I (MIu~FC!8pw34*A^sU*hDc3o5g#5QO3G6 }&܄>P3B̎ Qkcn|,sd[kHNH絟4C,:kݜo ݀wFԞ_3b|-:CS4 " mv 'ETbDM-ffBΎfӑo=yWZ SR+xͧSLZ#,fӇVD35eib9=0hS+`PN3LHk S&䜩Ѐ02CXWlH1Rqj;͆3GU.gșݓ|g|vwϴ(<}J3)3ϧ[qKknNYj(NJE .(y)>xhJ4j}JC̨U ,Y2+*4ZO2 }!IkmJ,zR3_&6v7כ6P7Ow GԌqxӴèͫj!Dlv V^~CJ!8 {w_O~JCUy3b )>2w;UVZjP_jժUVP 8.RBl3ۼTM!d$4HDZ!tT@G{it*$!ҵ6prX/%cV:ݴu3߾6hRGgcCJa!v XPQh`^Rv<EFnNZSBJt3" ܇=/֖,$yD3gN7sMB ip$x?u8Gp3 =,S^f;︹LFwxwhcgS8(2U!ejYXZ#션s- ([{661P AM OW\ #Q5' WR 9&dH7ZV^ 6No}ƓG7Ի\]Yw,ҟښcf"EO)qffTB !Wo)e1bOO.G^JF^Z8cg[R_ bc41 xsA?uMZzgGјYߟcFh$R VJY|0ЙyH66-124MXYg6#@d@/q8c[;\TxgAJ7 LA zFPssIx]&%96#2 v;$!EbB0c1` ;KY5^1kbf'#!Rʑ'|-e qdF{mҖBj5o_]tb0 CfM01_!g*|}\LU]]**B36Rr 1lS!EvW?"Ex~RZRP7 w;'ԍ/'Am>ix9jm!1e8mm7O~.9c"᷿ՖZ7BhZIi Lqf "?B)uX晛[~or<}a"RЫVZjժZ UVZjժYfnVIMnL,G7xj_q @> CfsAh1ScQIHy^ |_?xfKC 樖Rk#1m6<{ ^JWCȄ ^L+avO)̸{`r}}6CMI1q_G>b2_}=޼{0<~ܯi"P_jժUVjZjժUV}n0q6zEʭW 륡@W&64u'H8 16tǫ zJ7št" h ZHKXU e޼ M珷<]\ԭ4ô fZmT8j/|sgHu;1F4:H5<|u!y9D70SEDO]UE݆aFڌJ\ 'uU.q=y_ j T\[oowiǿ_ؔx}wǒcokCm&JoE8>Q,ׯ!'jmlL4qq޽R x8r\ WlN8jT؏~駿͛\=y}]??>h%S[G@J XZC?.̨č | 1$JibFSחr) 0(3$GIca)s@/531 gLs8J}%Ż= zT{Ý4h/R !XG嗪[R,ef É/ʟR"ׯy{wNjW<%pt:1MÑ>zNCUVZj*X UVZjժV֪`=y~6g*[(lavh7P1GbrX!`: Bqd"*jus~NQ @t䢡ym"YV a~J!sٻbYUAs[k (8-:([/(]L^xnmU]+ !॔MflHf PLƣ<"j4- h$!fH2c` b/4< GGW7r=ON'6[8j-oc9N.GPgXs"Ԏ<1ihؤq@jQ9g׏OcFbݻwZS&5#=kGz}ِv=]QBP.tVV]q?_'q{wK7%)#qdݟӵ.0,CDg <4SwnFY:ܖ~dQ8#õtG0sB ]C͔)r2ӺV[1xg+HJ.8o)vTD10,SJ{PKf;o{8?ji=8=;#@J.fƶ@UnwMw(=.e>5N/{Gk/3}KđJ;gtC 4#_f͚5k֬Yo4f͚5k֬YoamC\Vâ`+T3kVMRr4CNlixjEb)Q2P Zor?-5q؎ CsCصT\-f!hCVZhPa7z1bhU] R QCCfGr&#PR!F$LjKch7\VXcFPR Y]AF0f=   lŁ k֬Yf͚J &%@!@nnf P&ZC(@fFo&p6X:WA/yp%㛗>WcYzɛ2b&>Βށ^Nَ;AMHVE1þŌ=A~)ٶZܵRQ[RPbhRZ`; H1fpS6?xTdpc5c; 3-YQ-wO@=>>0,W|rwfsǧ^+~A.vv;Hsr)__~㼒~O֊WIdE(e񃗟Cv,+(f¶P%1N阌fs^c- >zN Vl[ƒy✻4wXW׈8Dfj5DKΖZ~oc+$U)S7.6˔1V+$m]`%'yql+I1n\u/-~0UkCm\Ԃ.z lUz]%[6S }3;;'Ί]E?y1bI8\_έ8 HO^WOx{KHh)k>x;|'b)%Tj-ΆݞCYf͚5k̆Yf͚5k۫C*G,mTB#6P)^x3 ā~(  j 5E[;rU$UTKjO `ZKzT/c3n|lm}Hmū2"-ݝcffvSwVj" ^±xArVjhC$8]+6(H_[yk 8:oXoZZi5za0!t˞3'^Tձc+Ffk v}ɟ|C~?T&J_]o<|qH-?斗k^^rz q~Wmn ӫ/蜧Ҍk/P c7T yJ-=~7$LcC@GyVN[ 8Jv7!h[ }+4Lw% B5KJ?x)dîKy$]Lg5g"3۱yf9>{5#mv;: =yÇ5O9Y קa_~=_|cy_gzb(c޳߰^98* IDATv'o#Ș'V9ۊ3www<~Rqg͚5k֬Y`6g͚5k֬Y^UECKۊB+l) @)tC4#a⼕zATM@T+A=c@Z--jI׃a@̈BmHSbqv&j-H eof=:JEA E,AHd(uRpΆd؈DjN6#+G;5v}ARk)~OHhM8T )!egx8ez˼ux{:Lub&65q'VT<#^PZ)m7|##tI_`ϲ|7\!WK:h%U)9 ֱ'Ⴈ6#tyd2cI1#/ByR"]AH3CU3ȸ߲_-Dx}w iy\#`y~ë9idK%.ZkxO!#qec` :jrNǸ7H}KjTA%Եj̐Z(8ᄜ{ mbl糭iIy|XIrOx1">4_)f=[[鑃~X1 TQsFĵٜ1E*>JJk[!0 wy_!.G'+NOΩW?`{Y=v?v{TU>|??f9_7X=RkRₜ׬Yf͚5klϚ5k֬YfûPʛ?K"ft. <juqUͣ^!:=Σqݛe~Nk Q&[!w,OBmlе@m(JIhNfnr)Ւ=Кm} =>yjpJl@mX L'ppƆߑcZq ԫ%vÙl:4%d]D1RC:GNoi =by.q`>N췈*+٥n$bU݄< &>3~SPypYGAlF!Llx=T2!I#yϔv!F 5x3x˴L9Jd#Ne6J0 =E]I?&noo)wGrw4e^Tx%<~LzDVjFrM- R"8CghaDʉ^".UHhiumť QAxd _<ׯH93\nnY Vy t]Ϙ3ӔQo88krGSvE4-秧+)[˕Co_߱pi膞XĶʈB:|-ͰF5sr[1!RJʹ$8p4#"\wVح]"+U+7f:[ԩ'6:Oy3ivgg'fX;t4Q՜ii%YT"E(S\=u;nŀ,8smH`iyihXn"b``^uFdm!d]smxcK[Al784%&8=<9)!<|T Hekgo~sX K;{ո>_OcVR-KVJzD|K.QUbb~)hW"#6% M v\j.v%CǙZ2|ziCϴuچZ%}3}Z6Nr&xo95V9qJO=@m(nn6\\j#m;>}>~b'皏؞-}!· \\/gDaZSf=*|ſ//&V+8qӞбn~سf͚5k֬4 Yf͚5k֬Tz`clt}4 $Ws b[RiCJhǙf=nrHJE)KgKj)BWjH;mrgF9RՆmB+]iq녥}[@59PKRR$$wrà4t 0cV` z(3'”!iVT`b=(\o ̵Of{(7Oӏe i"xxp=<}~8|~O.Bz{Uxj|#*xiDD 1r) ɰMH`_ 9Y-d5DJ.J7{;Ò]=/Y/y~{~ܱJZXw=\<"o^(GT}tsI#nc3ƶTY'm1{9rv-KXSK璫]Ljl1#%gJ*KUOP82EOl(Ւ1ڂg)R "b{g&|I5Sz!yo#>fC!*횱{v~? NON9;?W3_SR)1D`&4 ~#wk?dc+B8'-]c5k֬YflϚ5k֬Yfj^~93aYJ/3JH2 nH"@ls5xOƎ.;Km\sjF[b1bP(8äHK|cM`tʖmx~ǹ@]F=2T-f;ѩ&:Ɩ:cWZ H;ƚ/Z\NK%ӗ%S$sVXctm}4rr'/xwyΰtѩ#ƀSmα#><k֬Yf͚J0NwcS+R-h耣zgu=$#Rfk)z:fCԜD\4s2ER<1,!b %Վ8A=f)m{*(B="J-}&F';o0h 6po5zlBlF .D[A! f3UA(f\s'mqwhL;2p:߳@'0N 蝇e%D.Kjq>)ݞ1gR Dr`YSL=!n@1K&>}l}Ws|ɳK,K64q{{2l;NNNO{nv[aprB[SaUKRk[-RK3c'9C`Ii't,t=8OKPD14ĊdslZHٺ DTq~Hw1ڕ "ڕZQ00U-)Eũ༙"B6D;PR)p (ZlՆ,@ 1D;ceh)躎҆Œ8{>M#7Wޓww;._$F[2"i{{lϚ5k֬Y~͆Yf͚5k[*gͤ @[qT5Jp-육pR:6ڟ76zKҬy3Cf웽}D#٘VFP(5m2Nf5ZN0b#9CBf{gCID sAηcmƿ{9T+Nӛ﫭NQUbm%}t8[MKV 㝃>{\.$b+R.ؐ؀#5{L) =~/vC:~- %gaA=k֬Yfz5f͚5k֬Yo45.XVnZ>b\T[RZAKñ,d 1 L>q>%Vî4V;A)-(`8/6SZi&:|`bki[W‹w͌7}wd+Jdz]oJTXP\2sChۆ: Ն4cZB㼗j Z=SANVHZGz]oTq9j}nL9#\iE{zK/ww&eƒyv?~ʓ`'px3\Q~+_'N1K;f֖.k3Ñ}~zVK}'xrFb ƈi2rSav tX:R8eb̉EgӉ>z)H@|_^^r2p#-eJ\XD\m;ч ܿ|va&#n.v1 ^r!V6HΣ\pNZ\?]+=ڶK΀KK`on7;ގZҵa%mU VŎC낙޷d{{B YɪTlX,JZIv'cjX~bXodۿzDJ59dVRx :RSchNsDcл *  *J+ "ZVN!Fqຎ +R;Svqo)#*ECG A5@ CB物T;zUR>g 7e$0-+WǮsL\6-VHY)blrrsy*Xkc"@" Sgwlȣsq@Ʌ.u{o^mw4kb|x~w}ќ9]xcnn)" 0,p"bp=!T`䶒`:fwQãD[J^4,{oZqǖY3JB۾tzUڰ`W=jVɱT%V+N1j Lpb жm[%#<}$BΉt]%`o<Vnnx!JTV ̚5k֬Yf5͆Yf͚5k۪!0,?J0.Vi|qȕjDxW1[Z2DY5-姌7i[ ]Ld=pтh\x:?1M.XBlÊU8f[R ZU4x{61j%UXk*A*%ZulB` u:Z+5qΌj+D;vb03Aٰ@=x)gI`ZUlS"8fֽg!iq\"%02{HŊ\l)8;C`3%T Ei$X-Eǔ剩!KsXq/!rO9Ex繻E+<99g*r{g !r}s{-%|gi|}Mlmڳɉ/.__{>3)N~6W+BҌdevTw+O,99ዿ,<@jA R6,2syOQ10c{om q[2Z KV/~԰Hg :YkUCRacCbnfE䘶? 17Ł.5VۺnO 咓XZ*ACxyS*m ]J,-m.6lp~~Fў|ѿS~~w=_\&̥f͚5k֬7 Yf͚5k֬Tՙ漃NΒڹ[h:b[ĸT3ˏ:j*h }3$63V6+'\rH{7Y3v}t|57jW VΈ}P#TK=(\lP{(Zq۵1;MQ%յ9]!Y){Cz=.0Fz!,N+.zq"vjf砤 /E q6$+ũv/^qs{OZ-_*Kf?ۏ Ͼ=._<7q{89U~s\/_hy:aZ+7{NBw ݂.\zݡ|E3^)QK4dݛ'!\jÝ(ǂRr_+9100V9 ej-d&uB3i JVφCZ1Z1.z􈩩R{ -_qv}g=cl)}@ mt@VƼƫ!*5`u=!HgC}֬Yf͚F>k֬Yf͚JjÖ4T L0MHxG&r`W+~P3ݛ'op f롼gT T3QA:C@ñLuz`K }keKalęNPmi v\ezȴIJ%쪘ݒڒ %4 JiGZqY`Z)-X,-av.:jL7wÒR2WM8=Sɜ4uI)T'V'M#w5 _ܼ/m_OK9g })WW௾OM{_nz{OFw\g{$xy}K~)O<\bkҘ*tT1DB܏#?zEʕT ^uWw񈇫|vybEVxŋ'"HJT+-'vn_jԨQFmX$@9)-9zL)D$5AN0ŏɂ I13#'pj&11bT5hZ7dDCHoB1э1j81' AR8ԊUQdv9.DIH Ȳ$6!& wkZOI3^#Q\F5o4Kў!, t#ZZydA"c'Fz޺5Wwm۰k,;WǁY9vd׷lږsX?Th˂!)jg״}Zz~LJahpndJ>z;-<ʌBm[nC50ub>bɓ654xOH !ҷJT/b{O~OR2gs9_1(XĨn%E!)Mm!@YqX2"{1sA~t7Q\8ďה8(=JdH> W$s7\X!٤TqH"bS16 y b˧3Vw/Ϲ|pJ5jԨQFh5jԨQF}{ɨ!ZGz~H&vԒ$AJ1EN+X V $!'F}!3f7:ӯ'z| 8ҝp1 vZ*&U{hJ@iGn>'H1*^B o\*>!!!>%j9iME+&-<KQ*kHàca }G{U35$\2- Eq$! /{&*W%pSwF}?pven0jf7 ̭e%-tK~lN f ڬ~bz n+fWkKvH!t&Ujw|aVB!ETQ|~}xGWϾw..imw`QX[&ઊvn _zAuC d9]I`uw C{rڶNb1ulV .1f\JY&FcYBgf !;c`\5R6'XZcqΝΙ?v"]T}"%i}t}Cn, 8̘D5 yJX M2qv}*u(;c(Kڮ/@6;./)FQF5 QF5jԨo@ C*l([bȦRP-4^@hB((q x*8c[ôx9Opsu ໆ|klQjbRߠ0tv 㓡#v}J4>R햐f, z2e߶1/JcƲfϛ9HuT`RϖaQV,b]C9,FwPDc]#@7yV"Dcs0Lgl|tbɩO[.KFX@!)t`ɻ>7470PϹl#c4InHA֓Z1ưI)) ]@c#m;d2bm۱c,+:C׶ϖ=/_w> U1F5jԨ7 QF5jԨos 2ҵ/Ӝ I"$'xF 1GI NCƖ5!\%cOHE 2"IgWGpB2`ʂ87{gioAK?)n洳)!ț2PV87ƨQ-jiIK~P8 3$ ,Xr\DpDy℅%$bMqbXcsDxQ V ^F0O1.RVق"]ײ^޳\1ϙN%phXT50qN9ޏȗQF5jQF5jԷUǔ8 BX-)i\!zRgP&&SBO5M=}ۑO*Kb'߁< / & ZL?]/ZR؈!j0&͉'%ʲg'cUsIky>ׄy$XC(O7q3ac Ɯ6Xy׼ ֐zO]DXCOtL$ !D}]!e/~ g4͞}0x%) C|)=$ױ5jԨQ QF5jԨoB.<j;q"ؑ)VKS&}GK2-K3LI63#k\Ii=i[Wa@zHa? L礢$OaaH E0&uEr%gg4͎5LsN|bY]xy}fl6_à 䗟r<^.pΰ;n=Fpc0,W?ǜ/xc~zŤDIbnC.zݚ,點"Þ@Kw'KJWm,K'-.-jz}ϐ"Ujͼw=zOPMLJf7-ID("E-',!g36^1kqbàI c/I쉳ns ab)FZ{ J=7s2 c!@$BY}SI-ޔڌFQy eD հ \/&G\^]u-HsXo/f) T((m:RHuQha*u`q2 E-5 -2:M'41P.7Bޮ)g&`[0s pn-KgLS~w6ff ]-67ܴt=ήx|~ 4Rw>׫{.}|~ƒh}-Kn7L ?aVT\߾vw@mKֻ7t~%+p[ΊG%y.՚?|}ryv.$^7YgϿƣ ~ϢMɼv-]â(( ˼* )g >E|3c@,}籦gI6v ~`Y3f?'=o{RpNKLQ̫fvL>O b Xm)V'DaY;+bT nGѡ峈GS_( z\cTTCKMմWv'FM̋+oJC^$\Ec91q9mi{vbxhVw+b=ϿzlI &ㇴmjuGQߡg˳{ԨQFh5jԨQF}[5A ldPOS szHqP2= jd)eH) Zԙ"rt;>&S?QDJ3S^076H)$LteA1$!& gD#MJDցW#P1&$y88%uxDoc-LJ I}"Q2;~ԠQNt#b0WK-2$[)w}Oxw6磫GÅ r%;Ӫ+ {1l)=|Ļ-T\fRTtzʣ 膞Ŵ#"_2'n!iz00)+և͚,&5a}G۴|͉$/bd^O([е|%8OZŚ]?#ج Ӭc-h0'6M<<8Œ a=ڣ5 IDATY,ψ!4 ]0pz}QHbX*#wY,/< D,~sK ~]7F5jԨQ>jԨQFmU!ꒉּ1Mm ! E &rN ǒS!I'܄5Ӯ)%E”1Լ"gdMcKPm1$bN%HV 嚧DrVQ1}Pƹ{Ra0)GlЃ-*( &cYRBA+d"֒ C꽚֞xR 0L5HY)g{؀"LksEbzJقy|+⃳ ²nwg"V\,*yw?dBbb ~t5/n)Sv mu5:bg}qtRs2w>kfWڞf%Ʉp, ^zūׯKwʂ(:l^,L~cv&o])$ŨOl)2ƞDK:dj^3H"pe@"(A-B58s5c2ESF $C;r)oȌ=Ju7 Wx}9u]/蛎zë+=|eW/6-$f97{ֻ{){^>GOh)DB1"^ۊ+w/oy۬[Jp>p^ڬZ֣Gh uU=7ׯhbks'vC g3J"Xkl6x'*Kv]!#] Ѥ':+(.㵟mo+3SL kR>J zѡCT\ X$C׶eMG (z`N;ʲ"(Sy8?L3ڮeVQF5j?ٿ}ɿ_ag> tꭷz7xF5 5wTFh:Un~>Q=59 .]XS"CP $2;S3ܤ3Dc1֩a űD0΁d̑& bbb C*,R:$I}8NtK9&WNl=2xˆi?Cңٝ3ROHLZyR3:p+Q'Xmc. (P`;vʥo[p!5)E ~bRc's!`.?}'%)xnCJ0dĆC߳m;6af`0p\L'5߽z-uQ2D"KΪ%94HL4݁1@ﮑyxv/u-~~#ڦ%4-{Ҋ:pr UM?cbS،$1(p!"Xk)+j\9[9";~d$}ň9;1zk(*u&VoཧpVWl/ !U,͆zŤ*1@J94UM7 e]s^c f{O~O51?O Puj^]G?~ G]5gzw1>jԨQF-UMG P|ЫIQf:r/h=41$jk7hf{e1|3"8s2cNJP0@46#*`zv'AH)3HMGuo UM$geF,鄟o^,&3|7>>p^Usf2/+ʢ|2=CHn8:لCh⌺,/8[#w=o#Og[^[~3b<^^5}Ԯ`믾"0d_~IJh,ׇpՊmjĊNMs) q$zUfw!<[v#&ah[C`pO>K&unesu~i̦MY7-A.ɄCoZxׯy5H07hk. 9uڶbR:E$qL; =Z5Í";:ƠyA p,mc:p &B+FQ^0xb Ӵ ?ǿ#ʢ`=OzO;0OpEAw<~/ cv͚{..YΦEA?QF5j(F5*kLǥ1C_OŔ$R?g#AbMfgn\)&ՂHs,A;dY}<&79!r%wBR^ ɤfϷw),F/!  xBH)KD"dc&M>;HO)@xH$4IA1VV_c1H~}:5Bw 4 ^ƔH#> CQ"Gz/v@t'aSWz[o!lUCdoyִE0釁(9/˚.Okf g\ow!M?nӆf)&54vu:1Ԍ0R%!D6A]8Z|s8iۖz:*+*W|p8OY웖W^1'VwH͆js/TvpvICQk֝bZ.S.tUYa#ƐQI\wƜ޿FDwC`Ŝq+FMi~.|k#Xt}Ig<<\&ES"@"bqA_eUYR򒪪t j7M~lud»O0`cݱX,C=`c:GZQaoԘP5VcB}ԨQF5jߟN2$KQI t0le#4uMK>IXq&*!Ѵu$'ION$z#? ZP ER9M[35p'/wPUĈl[4)<&=b(^*8nD"}ҽy͜ᆱS1">\XGLiIUE{RXHH6E OzFGWkE{LauńU2|>)'£rU=7իl;>fR|zsÃdVF$Eay\O1GBJ,,IܬUE 0sK 9[?ଥΨs^]fl1 M7cQM!cb?`G4[U+p1b΢ HkaK5\}cpslWk<MbPb(%eY1z‡|6g 痘ٜmڑb|tʊ6:W-{VLe5',M!tC6:S!xlX#ovuĠ$1XYyƔ(3%%H+O]g5ou*0=GRZxQOZtIHEAfy >&RV/b!#f2|AʽE.;҃ZK]` ,iÁX!1{, vN!e3jvp:c$Ud 8qޮ(j#rT5jgTKLXcVCD!VNq5+{(IqVo IWtobвND AO*5THTw4,t^M簳1$A(/_>ڬx940x}wái|3fw/)J׻C!Dýy%⮹0e5(K;3/7TwHLxk^S$#lg,>%M'+3;>1p+zR"ϼm3OH B`a˒Cq]"# L Mj9!5 (EhX?znC=q6;a DsfeMެ胧DASX1쇁qzJQ%F;rܚWWBKSa]&bPMcd|4hƕ$k"DsԷ7d RQ(&SPc}r)WI#FbP{MSED ƽQR9}NC}:M H isi:R'NH&cvO-K)!?gf2ɿ7}cjwW~s a>E¼p3Y%]<E=.*b׻-{ʖ!:baLDnZ UQ!qe\p;lQpy~j2")cj|Գ)eUl7q`" q^E1<;c:l lk!.!0`Nc6CT4/G6D"1֒'Ą1=\fGZzJLĤk~gkޤ@r:1|@J}мlO~4)7Gk-+ %& V,i_:>jԨQFi4G5jԨQ)b"cnRPSVHM N Q9MPv0INLS!IR-1\{R,C= Z@F4ŎsHX !F1/F1ʴ61cm}ƹ$3(NIj`s KBCHɔ렴?ت$5-L*LY+H U%XX4P:RBhRP}[|}GG%w|ׯie6gs} Pf]O*(( %-a`^}xʃ#SݎY]_nMM컎@a;ژh|VrpB?XQc|qnuz2('-FX1, uTW O,?f}wlR[wM,䈋H)9BKeY0| dA p !0 rdK$ER Ep83]]ۻY9U| 4p.`zރu5-MUc8 q12Nn؏v9Dax XPWP9nʢǞˋK|pXCSbPK%1'8]5D{{dl&@ή^9$<8yW6cJ=>>OI_sp*׉<LQ<<|C./wٔ|< B wͻ xBL#J!yY1W:W=N+*wdQmCew}}5Ut/,,,,,,,[ll?H$p"&&?VP~#FEK /ҒA4O<=Vxp繕NQHFy*C[S~ L̏KBFifhqnS`8.I'[)Nȣ+xr C >!ƔV)”ש1}@Bg| c.O4 b]I|8Z4* IDAT^$nA[ւRضeJUA= |FZȚ2$۵- ƀ4mV>uRgTwC|ۮFpgWW\^<Ň~LE[{I΍5)fh8`hцa!PW' `)%|tq]Ѥ ƲkuC#7Ī9k4܄m`3%8`*#9f4˘臁]K+Ƒf9mUsmRw#MF55h#:-j ꘰ƢpswMLmF3<|7W(TB#v) 5tgdʹT~fS*+y8Lkʗ7L&DŽneBQYגRi\ZZ*f/sp^/_HӋ B @v=9!ȡ?r/?/q.obkad^qzqʊp/,,,,,,,Rvit(a!'Eh3;T)az~8"1Z DEK JtQ"| mTyp=ȥB * {) 0쪸EMm(2Pb Tj if00Q#L@A6-^ =/ي#(mɫU9XF#ZWD]n Pj eT>?tC]]pb*>" L<~ԘM=.Lt+18NC /4FDпf5g'g|lmTii ϩÁ~@ 2Ǿ KJXE'UiLUոik;ƲFfV I~8rΙaO=]G9G ?leu2z&ꪢ,>FC h׷7 C0mA_|})~'G47HTu1[G7ٞl6/_~x%xuuE8T L]W+ڶ}!}? FAHv-w&g1V[YcyP/w|yгFip|#hX)3:Rzzk!Xhq\tM)43[FbHDonom0ll)8=nnxsw叾Fg7Mal4 / K[ßs*=SJK<eʬH( Iz`nG6">z*Ṋ 1|~2*YcFE IJ]rHe]9X- ) Te7+ZhZ3ңj#W-I%m@k. *Ȧ+D.=ji1ud5!@:XȾ'5vv'lӕ2i_ۢc91iأƑR5!B>xij]S Oӎt1%Ҭaw`d?:=A|#ViPXm-ѡlM?S25Þ~1QY8)94RiMݬXiw{00UEJ3up65`q 6׼{}.YYMjNۖ}`QiB[If)cU$h4y1?q$ejO5릥5.xLm٧'<}-jMg <~ww[FCS4>Y/>&n\nUV#UC p>AG>T*u[J)b,^RJm)AvJ]^:2zNj!PYDbMMNUFz&@Ly xH!❣]/.G_BM͉<9&VmXmwѻrZ{ZqaDQnpSۿ/,,,,,,5,JNu f˘h .*E?6ґPC]D)t,E|,ARd (]>^8 dmPk?xA OW1r5N'-2Zj;ekL6\PCDѭ6e85'3v͖=.m Xۊ?1{orߗ~tMͫ+DF@}aaaaaaaE;WzͼI RB"u"AdJ](àhUB<(ht hZA2Qì!#$Ucwr<9gSo^1yG Z*OJ(,x2l:jk9ݜs^qCOL(Qhˡ09<hNzaJBAxQ3ZiE= bh1M~)>*d򬀉1>앵ݲZl ~ӟo}Q)\Hdhpi,/m?xs}O~1[~\A&W򅅅%P_XXXXXXXxKBi?OgVu-.uɣ 5el,Y!yLUcU"F!B$Y!@m `8bsr^ӟF-͆"|u]ٞ1:OTp \_a^4-mSÔk[V]RFYYRUNH.0Tn@4cmQ%0)"eEq ]NA(9d u2 3B{R,FkMPJCGksOo(˷;>j>rhs} ᓏ?||_Um͏W|W 3 =pӧvk]V[a 5!"􅅅%P_XXXXXXXxkqMXT%s#H1!ZJDu^f0Xڀ %$Q.WS.(E (]ڠr *JI $%s I9J"WoU)%%-_s&ri`d Pd3WS$]+EFC0$Rے\(J[UTZ'OpqTiL.)$SW5Ji@88P Y xm j"w]DOlm8_3)s&HWo󥩯EyG9Y%P"!;a }쇑GSywºi8L#jbV&NִMCcjh^`LU0TMiG9q=?Cpm'Ę'֫VL ; 'FO&3\uC MM?+Ks#;CڶQW>M-WW(uʲnW\aE#1xhlEۿvGe,VzۓSRM~Wg(leYZ40즉oZo|#s4m˾?m'鏸%W57֒RBDa;8*|w;X]hT|5z%HI1B>cAkM.Zk51k9b2/;X12 x 1>oxLaڎjBv-1&^|]FML~D9ٞEU5,m^XXXXXX Vr5$%?. s,tr y,\/H!guTڦ8EV"X57g苨QB qv3݅"YJ}BD6yX,HN ]+rp`ɴ%4gC(1=hv>|JȢH#Leaw$PMEZW'nс0`|٬QYbn'b0MXQ  6ޡz>QuC?YXm8]m>r>ۆ<9Ȃj&f!D̑Qm;jeXiæ9 V A (PQHGGc {azPUm鯮-1lw1{>{n#nجVhIƁJ9?g5wuK%&|?q8"mW{|!?';ޠS&O'S\hk蚖7G\C`ޠYVkna ?*gD4D8ﰵAkaZK 9'BHdkLe1G*CJ.꣔A*&rKd㺔aӔ38 B.)ͷΤ2b,*ZO0ZcE\DPZ|aq!壯|f'O=#]bG9=7)b$Dܜٖ1:ҴnK~y4!lO躖Q(i丿i*QmKTi1Ѷn?!{dbLhk87TU`E;/zI}9؛qRU>u1*j?4s=՟J.YƐRbz{~wM)8mksggri‡)%Đ40 x IDAT#n4 mv˟g/_rկ0#͖kkȂR6%P_XXXXXXXx[3{ƋQH Ʋe|WI$ \^[RΨ%xOŕ,(](Ъ|`/f9R ?wb*v(ay*qSG DF!ʐbί 9D6n&*L5TQE|G)-#)+S9~ƒ+Vۆnk5^z{~d<e5gTeP<8mQk)xț !3YԺ&bUyڶ m 1S@[R$xUmUQ #ŵ}{{KR}l{”2Tk-^ /qt:bLCO=}yJl[T5fjZ4"Vvlr&z"&`pm =>PkfK ~{&nﮩt{B-Ն_ڲjZZey_D[U ;.ΰ(&:Bl館A$RiHr#w{(?}'|p}s#Á~1Z{4|=- W|F:iD3Gg+DarP^K"wh%䔨Zle]#JSc%(c=FLTYP|9FZy4" ewa[臁uA+EJ%7&eڦKy{P1Og?f{b7#WWo ?pzzp|OӵL㎧O!֮ oKu$AުՄ/)FTDj S YA@BF LJJRi{8SB<[zv%E+!bn+hCvR(-})Ybȳ&> uEދBV1LsVa.NwW^ L7$$ZV]=vM"1p uČr!tVDP!BN;Faz8 I[M"zO@(yDÀ24k51&D+1&My?jj(HTiF%LQ Eo* 7ԧ҂ΰmj w8]bk5| svI4]ҝpvش\rG.o?N짞)λ _kC~9/^V׿]VUKm,mr)O w;'݊O~2&Ñݎa5.xA r~G4xQ"Lȫ{b||GlWkruO~}>l@Z+ov;0/wDTB @4œ5J\+5+^4vѼǑל3ƨ^R.%]qSJ;^H)rڰ٬&|׋]Ѻ(JS0#׻{F$42\7MOYwkUo8ږarprrJ􁪲.۾/,,,,,,E,[JssB(*$[{d)j#YJ+;'$Q;0QE!(A4enR00luFs893U.^TkL[4 jMY)fٞ;1uwH)T)jݞ6 ~ruiIwQƐQhc*N,8 G pzEL=Qknw;7'| |q1׷|͆hcCsSD+ paEDSdլ0|䔩%N/xH)q{ơ/?;b!dn=mmu]0m"GRς|)%RNES\ZuSmy~ A@(A3 @Ωh^fUS /x[U%lWQ2KMƉjUw ©)> R&v(܀%$$Lch0MTp:=a$1:Dz uYz] ֐2S+v=9m1"ś?b%OrS9LH PY-cyHzn?ZRUef_~`RMi &bֆ*ex9-[A MEc 6΍ONY}kGz؜j*kM<>gn(O0I8;0cj٬xslUѵC30%^wXmXw+HZt+ڦiڶ8 prvj@<{5(6/?p<<9?ZKuUc$ù? H]aXh(-Bε"Ai2\<\=x6r%tWǼPiCJ<4\^^Y"y>u2JiQ'@m,9W> Cۛ>noXVlNxuBkѤ釞?:ۓuQfY҃jaaaaaaa%P_XXXXXXXxkqT(O &<7JȭdJ gH"\6$8EvFԪC}(L:@de!MmjVM!V!E+_eu(&ħ{CFjC'u§|ď?4ܼxA_a$x[]iϳgϨ fCڐR&7_hѢEZ E-ZhѢ7T%8"MqХ .a3LuT# `iH7<GQ*R bbCǝ(3\f5q_˛ْWs@`Y8pB'Xy^оGԁQ7paʖ:j B0* $z{E2}:´ǭZ*A.G4e$8mJ( P8?N-O?+;Dl@ǔe&\ݒ8$S&V+Jg)0sx2]4qu6 %f̵];ӈʮ\(c­ !Y8]S&xϙVME4NCG'BRmj=!&2Mtޱܧ˗D|*r:cyc$~3+CEiɩuznFؽ2cӧkN$֛5!hg׮خ/lj201zٮY֜g<|wnxc*͆_|_r}EP iK? ~6!#idr*[튦RsLr{ZUbk˽Pff=~+'[C1r[Og_=?)PE2u; G|ɻLD~_;n/rHS"_gN'/.i7kvӼ(.8p-ֻ 3u=hѢE-Z4k1-ZhѢEP(4QJ6Ī|ͷA+[IQ7xaϐ'֗tbxn(Yc/yvɓڪfݒ??9rh@5~*UǑxpq9BFKqu 8G5&9ÇitD3gnQCxf4=;?0#1o\d[ !"䔬@!'O<p*_#fRJo'B#R=5c7?+fW_ͯW[ģG8;r:9OV-Cf_.KAQVmK.˛WE-Zb/ZhѢE*%\ՌΡy#OTt.,U kqW%1<1"fޓ1̈kv1ٌy?4`hU 50 d R2Ł4Vԛ!^Qe8!>nmy@QHUS挫j4ʜZE{oȘ8cnVl޴fbO!B<$rlʜH?dmB]3<{r0rzЎ^guu@L>Oj 4[(a ^x[ݿSn} @H#y8s Oҟi"~CS7\_] lČo#IaY3剦O*j\tuhU[JsIsJfl TH$kyOwb?sbUO>|o^򒢙U[~pqqtwAKuRx/7=U[]=۰$-ZhѢEj1-ZhѢETE% KG-L.udq)mA.k1SչPTT)u~%{1 "5yKavQ2DoPi Sq4fXa*9H9'\J)xJ)h\aENР >@V3c] +!Q07y1T{eZ O iBiqDz}i=)u]stG5 |YcL;(yZ<)jÔ2LƽN#z)BƿN:atٿ^!@#2Su-ϫ7Y}GÄυ#VNhRL^A ݹRŎcb]v7pγ?왦ϼ11qѣ Wخ74m[8Zmpkjƾg'D,==\l<JI< (o?~v')|3>;\l5'~OE sk F8V59gBsb2=8kA]$8rc6inX%:xH9b3W]Ķc]Ql)EƑ|X?ށEA4s>95ͬGIW~.r/z_3|؝W 0늻[n_LHΙ~Ou[>c#虫+[~m^hѢE}'E-ZhѢ7T*i[31ŸޔtHKAb 0c5P̂3q}Jad-"NX3D^{H*uu_S'3u.qx yZ]gtEP#CqƱD+P r-/ϊ \@bfjUJ2)VYBD.*88XwmK)Vؙ*O*^)ǁ鸇n_#  z8Wy@s"l7T!Ϙ=C7@)hI8Onբ=aV+nFdC7_+uti[2A!C5] 8Mj;8i W®jX5-.Vf"Ci1M8OT!K{8OA]\ C3`80d VʊsfkXO̹~rGL>i5|M)q;tĜH9L)SNFz+3442L8CxsAdw91|4" IpMcveNbdyזXRь[JtUqs+d< ݈NR*O T c׃XqsBWMEq<[XVtْ8\X6܉ƿjiintgnwT![oy 75+_ϿwޣB?{3 fk;*ҏ<@NvB<(1|/ް.% !BM](N"*AKB|c`]۵u:#c g*9x˜mBqU`{|VUKUWU+CŤ0L#cl0]PMK2c /n9=WKlu'\ٶ-u@8ӉW@#l`ݎfAU#p{G? |96lɅuSsYѻ׷7ϸ};"ӄ#XQr2:4i9%V vwJIK\0ď!” נX{*Rzmr(F|[ʼ9ONuo+a O^"dyL\@u:RRl!~7_ 0a@Tf9t;)%sw:#2i~H]Uxoq"T~yѢE-Z -ZhѢETYj0eHs[!W Q@TE 5gLQf 9= Tl3`I.X6֭)h(d<{>wwV31gC;F+¤`UF[)!rFp4⽽^JV:'筼*17G-!d M*sާHa#h MH?C-L[%Qq6Lb"v>"yFe:Ɏ -Rs!^ E~8y8m#J r\p|ތR DU\lފMc0PA9<ʪi.su}tr|"CtG|8V{>RN8Ujt㫗/Γsrϓkc|$ՁW*T5axV mܟy[h&+#|_V+fmk#u|ƞ&dD*CO)'*Ry['̔?Cʉs:Ϫ pJKa_)L)fct>1p)S!為Du!2N#;;fRJryyϳo__B5㑪@ol%0ZhѢE-zc-ZhѢEo$\R+'1d.9n,YmeBsfƪa.QDS<q2cKB5%ęnpRLFɠُwx T2AK2j< ׬C:%R<b.jyۚ*MfU h呪E]oiq@r#ZWH7ŗp}>^lxMk蜬1Qif8حX#E) hsT`7%&\}mr>Ye,Cw睭pޯ7^Rٵ$C(@?V R :f\h"%Cnq9GvK#Z c<џ;*"6q;覉fMpfC\b6+"Q8ug8Ul9Þi]bS7ܝtÀLT ۦ|>q{{C۶ A8xǟ_֣K>x={w"M2a #L#d]iښ+D41!xD >\TD)q4M1ĉ:{{8O.tXu]yuXB)!Dʌ)Y_'UR)|B2"xyջD軎-ŌZ|jœ)q>/x%.(Ն#!x꺡m./.x'\]_1}߳躎is<-z:n6Hf}/ZhѢE,-E-Zhћ*'V,jx/1xޙA;8̓.:'xa2n%[}@#;[b>h)fʩQԨ.EĘ41CO/'s n2SB"WՔ2}L PBO2c=TiZxeFm9ŻOx/ 1!T*| T1WChn QE0v.HU=:gtkNxUR?@6Xxqټա6Œ;GUubȟ_ +G\\Z 9)BSCBĀw=3.M;w̬  C;%W/_rssCZ㼧;uC.J < z#z%8OQ1>F$'ੜΓwi8\_^ѸW_>e6%U]O<FS;޹رl@:{G#tH&q@cSi](!8GN 08t.g;5ʼm8bf=}E>>??Z`wqaF|\^]1ལ(t瑹-y&*!FTXHY_~ۗWv[֫5կȥz 'L

ٳg{-2iѢE-Zhb/ZhѢE*Z SKśn61՛yEQ-]067wnfͦ!b"jƪ2f3X{5bB(1 `vͬ˶,y-Ιܜ`wHZijCtg(PW0N8Ut9GjAHjIpPb$=ea0n{4Fƛ%hF[d|ꑺcجж"a`zKB3ZE$'3 @EuO*v'`iآēJ*̆_.Iنqf$cke H ?+d heZ't{CL4Ɓs)\m]; PyoƩ&Pd^w)1B+S9q9;jqE-ZhP_hѢE-zCu;v>{os(4ZR@h̉j@32&">ZPi.E5/h!`0SC'ԙ;2 Rb BLY( L#:f0l`wwsׁ@'!(}0;?ٟëkN/_цf%7HD]\>xvacچ|/SJaԌކM9<~(Rb4%|y{ A5Ck4y&(,,23Ν%(ER"(ՊR }-O>?CVk;޸ÞW^hV-O~B.v͊>$uU <}J?$q _~ {.\=5zaD l6 S///~E-ZhћP_hѢE-zSu8@P1N6KŸUԴb.f^(F ~.`g!k16Egz5p %>Psfd\?bx64Zb t{$ٰ7VZoq6PyKUKRn-2NO5lh ]`%A:&d"u gcB ጤQE4q)9)K! M= vC}4\FCXR'n:&*y?zCbmc**fL:vK0zp<^p©c4 !PDhꚜ/M# JZ#֑ckRCkʹb~xr=82 yug9-0QŚ ism]㉮9zDZ aps˦ii/*=:VlWi@.IcV "bl]KE.3ΛamsfGqQ}s2|N;W!O)YgB VσD{D#%d~ӟ~"N2nOO>^g_=%M^x:7xQ~G?3~!0u>K.[6-?;ݿ;|{=&pg߳nWrəˋ N]8LHGF)mX=X2%Be #a!DN{>kyXp(ǣvʌ"Jp,gЛRk^bpp%me8MJʸh✡^N >5R~W

uM qJx?fFR3_>{1ΐ7=n^bz~6N}?W%mX Ͼ/W<~.)<+.VkJ\]\o#\PQ ʞLHԌ]G۬~E-ZhћP_hѢE-zS5e3T+s Z9C4%%(EiqͲh *+4 RԸሱӝ-&P+~iwb*PfsVԌu7*%oY(.D onא-~/K;E\3޼{xt&;h坂PdLz4"8Gtr q63YZpx͸ Gi9;! V ~.ORf:( Aކ(݀ΜkD :D"Ι!ъMMq如C`RCSme@7AmCQJ?ʨw_}v=nH΄R\^n7xՁܝhu7{iO*DMfͪU͘^fCNHaƶiS{'zG4eR*v̗}٩]Jj u6 q|o¯!ŎOvr2MCf$:wζU4f)V3` RGC?'3,yK igfnG}\+9 3\ud܋sf^45ȼRc.saDqZ9sIɊBN 0LQRJ |@U #n/x;\=|z]XnULEa1?OCr)o6r^1|nv7}%;~Y2z}Y!v IY EZ–o `;ldʤ) 0 ܭZ2,?{ "\#q=4]t)9Vq*옴 7arsy5= saܼ@rBk%=pu|L~sBp<NGOxۜswB;bnýq2՚42Ήte{N9w|{޻ǃy)-Q˗|jQCk@kefT+^BPj|}صkkƹ-h#}wbhJ-9cht9g}B@աj*_{ޣ'>xH{{PZ3}Zo g,~K(qxƆ(.!PaF y+,ER[&mb$h0; TU%A9ݺlе%\ƞ3;|)!/{M\ñ8GG07&C!vc9G7VҞ<8ÌDp8TNc0S}6^;"lv{jjX9Au ц>˶ RBTE zOv|0Rwi ^ J:R)̋/Xu=~KZ2dBxq(q9^mxc39H|s|/>Oxȋ/O!FD_Z]:.^2ӧJəCW|! /fͥZ P7c\ ӘPL)/_oRZgǜ+(QusُW3T+|>] n臞zE0M#N<%ϼz} !ϸ_89;~zMNEP<%:ea:"r}uPjhѢE-bj1-ZhѢEҔ̖֊B[JA7$ n銤dl䗻??P3}שX1#7-vݭɛ̬6!]װ1 f Y\c|@È* ^jDDp2윽G26gj7C:)jS,s6H3ʹy*Lvx^4JeePqVRAljFXI aԉͭ?Xltvxd =nnO)T jȹ$;DvER[9աmAR*1D{_:_RID#g5<@_ѿh_6O>yq}ujM}דKa'?@K!ly+e?H 9~{r8u\\}8ﬔwѢE-Zi1-ZhѢEȪA\K,cFRM fwWNJP%[)Tpܖ*/ɳgľʟy_] )g6՚9#n iƇ@u๹"f>-ZhѢE_-E-ZhU>yqR-줙X2Y " BNIFrU9!`|3Ыs`ne~Voaۤg1 3yKu0sAB@KF44ldtU\3Elp0iD:*fitK;bہThom)zUõSF˄ƮF5_+ ShjZ^'FKV)*h;9#3ÿ6^'ff4y4X*Z-᮪PFpьu'c v' ^Oߤ"5ޑsq|a!Dy !O?119%<#xt EsHRP'5J-պZzZk5$J Ϋa|ܕ*ڒ䵙blj?jjTbJ-}VC]i/yƛ|Hi;OG-jE_\o[D#'gO~Lw=<~JjE)o|LĪ_~#n'YA|DQ6G[\3<]ߣjnAhѢE-i1-ZhѢECsr3o/oϥAH[k AoicC3ĭ IA1yC{hb{-89AJFd@8nPK13U+`\g͹% ?WUf{;ƍ&PŹvNޛ6UZV`:=lǩ"R@M>úG!!D8oFt Doy1Z5WKGsVpp7D s2vnؐ[ƽ"PV4*Gg>þLɰC݈ +sj#:'4!Ss^]\b@W?'Ǭz;ѽS s^f{uAYqǞ{o32JgT%D3$vGMtV=''G;4O~jo~ NxZ ` EK%vG8OʨoWx~vh=ݿǧ?)td |Gj%FE{K{޷`16(U ȼ--Z%sss-5/;^xWG;5zMBto[9R>}?gO??O!C`>J6zuY3Wzy0 K&x -ZhѢELhѢE-ZEa45BҖN 3X78OMs!PQHŌiTvC%-N,ܾ_PkjZ43RUn |{ əJp!p`Υ +KkBTÔVYNBmu'j g?+΁4 /%)~eIlUYB\khlmrVɐs s5܇U|31۹Z!pfDKd(.ZAiQd5*.v6zpT-<Ԓ a 7Z'+i"uz`uq$a`N]9PRbo)BshLٗ0lք՚iɮKFJIݎ` j*?}g#(ݕч'Opzzʸ;4} 8P-9<ҝ(c$gg6kMVazydZ (E5!F\ZQ5 KJn6"θHYJip㟋!hTJ %pΆQ9'3+sⳗQǏ=WIx~3̋gOP5_Z݇wSNN?xǸ?7 \\~}>g4Ox'ާ߬wz GcG(7psͽU9::JΙIhѢE-%jf???zɣy,Zh"D;ܻw,z9n}(pߖ;Y%~"E% R8絡=(&f`Ƽ4\&ք2NP jjpU貕rk bSqb%zcQ;g3jb! '}{>{]"Iyv!87Q3ƒ6{+Ou+smK;+ޘ!#. mwrTBU*t %Cפ~ԆQ[5i-η81Ni!@Qj[Kb.0R_ .Bc$mwtP LS"zz&9.^SDAR‡HVQc=;؜%p'JTɒ۵dn]9ncDBKn1rssC<}߳b$t8%T\~Mʉi!0 v;^|f᷿}sUE]ߠi&j&z5^x): \)uaՆeM@Rj3=AZs.~7B!V!|g\]_oܻG{_:.NYVxq#T%xa5Ϯo{x=|yp;~qYVؽ;-!D|) NObЯV[@X?__EdZc}(w_W/ XkHo\hѢEPM_S[ܶuf0["@EC}@ [ sYD7[iKī!qi)Y^IoGr fH3S3|n|jR2Jf_ヌvJ>ВR*]2[审4J@[_dir'҈v,!XQhjlQ+̭,+y*v}{ y(b{2D;aєp yup oŶ.DcƓg~ERm!b{jk*IF+35ݞykoef1 B@:㈊JqbNySL t}x;6v8A1f9"x!Z!PVP,x- _!jmsμ}j;+癏?g_p9zÛoI{;[s.n_5J D5L)Z1wcVfʛoa{ysss}ow8>9`^۫HSV5Z!%8*pQs&_݇b-,b/Z7 hѢE-ZƨR[ZQ4#ޛ\bpf JMV'8eKT+18KBKd([98㘗Fx&36IEYcF@vVREBD]yj-.1v( )6Vv{8M30[2W='OOH+8g eDmc4$heF޸(^J%3owOLӄ%o :D]K!cĞ۔:TURɥpz~5SB<%ӎ}1׻.8_^q3YE]fa-HweKN'+o8oÏ!f&x3ӻ5՚l6%g!R*kT+13>-ZhѢE_x-E-ZhTjqsK6"R LgKUq͝PTR5z:s;1|EifviQHEi>NmoƔ@c@jũ4DsR;:cMhEr{0G4%tJ |wvEyGQhW pƔcѪm$fxiH|> Ss|cbF3LeؠY騔ܸ־:` j FLEaQٵ%@NPq[yzahGa[hkiC WZeekKF4!:2Z)aE=5΋؟f*.xرPUO)]vT ᮋ 7D]ߣ0O|ͰaZY}v9W'rb^1i\?m׾ƴ? &Px%'13Á3xm8;G Vwwr΀W\ۃ"r9Z.q( ]QKi)t! DjRbqJ.؝qwv5͐rqĮ3j+*-(J;VwGC9Ѻ稏tvt}o*J.8 >s&@Ag=[oqy}qj0="f̃q> rΜml6 Z(DvC?Kz9QKmE-Zh"b/ZhѢE}Q4#۵("QQcr{G- [湂PR2CL/%^%x@-[ wF_3ABfFiEB3T-rE2$6HFKEwz;p-MbopהÈVzZjeΐNٍO-V<f33,VJ q |JQ3p>zt!{6ݕ:3m+$j)TmWje57C>Yb V7Gv=y$'d-^ oAlip7iB:ck0&@M]mkA;C iP ^tNKb`{}8O^QSAP&J*/B1é)J't]sNNOv\+-q{Ew|B:4 8s|A<Ǜ WW|< Z+ ?gT}ss z>e#2:V)eZqh#,i.T4=x_zYP.v-:sPS\-uwfz %L綯@ }z+Gu&+Fy Jy@8=ݖ'o%qd8^oXZ.Lwx9 :~̰Z1ƢE-Zhi1-ZhѢE~f9oom1 `rWޕORF:zy:IqޙY{jKƵ0V+RWQ/6;MV3#"ތY'fH{+*%L)[2څUD`E1[ښ(Xͧ FX1UZj3zI 5QVy2C;H0/@3ZzvCg_ѝh(,(煕j҆VsVꂭ}-RG<1(|>xѪQE#!xVY{t? v6P7܈wΰV:l*>R`;$ga`:J/<t#=iRج}ϸߓi9t}1c: ÀP#^p8YFc/^b{6͖"Ϝ햡 L3E-9qk1`・ENj\0!O CĸV[ZπYY"ݷφzg;1|ŎP `[^hk^*{Rە"CND,!.<}sqụGxs|=g`lqq]ssss#!eqНgw{~\]^ӭVw%KQE-Zs-E-ZhTZYX0&UT@hiTqΌwWͤCôO--r[HtmBGlHRlDΙv˫þX*1FcհbNW^ӄƒ>zīW/ !.+O<`)e֛ٽsvB)53>zjE"ׯΟO?+:_GE-Z P_hѢE-j,i9݊>p S jNPRD.E?|.-iԵZT*"4Kk)cu.x۵".x;0G\=nZkXCQif(D̤&3"B2A='5vmgQ[\ H ck_/OD\ۮ)7^sKkwhK)^S`i҆%ܖ*03K4iCA8Ե{ #xA\ B}@ƺN颭bB!TV* zs 98ui6DJ: 7: 2N\.Gc5qyq4bO;kz<;v2O C V8rqSÞvGS ;L8;]? xϟ?'@g}{]F9JC9cY@|K 0m8 R T[<| 2'*^섮~;&'r@Ʊ=wƻp Lu=1F...͆ cTg})'G5o>yȽb7hѢE-bh1-ZhѢE,rԪ:BChct{(h-42 @ Cc7\IJRՒlXj5ycS13^T1f!AQ$xjHT6`zo%~3]6{j1Cs|^TmW!{8Hm$ "تV8BWkNG )'K;O)<>Dzg'ڊ|jGc@ ef {wH`UuUϾF42li`c}>=H0| `̦Yz4ՒI2"|Ul6gVfefD`trGNgΦoOgu7G?̗2?paNJiJ+5%hm&&i]i\hbYYŲ,e,P1&*&C2&ibCUĖ֔âLYf)j2 dq(M[#2J}32P>O)&4i!X*nzI4~e<,mq1Id,R^* ɪz岌w^WV4òYM$M?'Ţ\t8_dvI*l mr|S?)?㳗If2MWBI[EEq( &C׮*Wmr6?χ.|q>}Ǐ'$II<""r~'ͦvL']ftti{Yӥy$wr|t7e4y2wg,9Ne9ٳ̦]?N0e_&V|ou |$ͤfW~UldסT1K>v'MɽLӮq\AIez!C2%odQ&?L;IK;?ORzyYO:dMK ޴iҖMiA}v9{Ov*nidPL/ ݪڶY,2NSZR˲^y${]>ʹƲOӤ Q9EƾͤM2X-3ϨY,2Β+Ay7Y~,:fHIKѳ2yA9T˷=7]Vem_-rd=g[&-} gi&(iʅ-lJ[ebLU=d$tZ.h,ͪb}YҸl !u>m۔s$lV&ش.|\~5y},NL']&e,C]GIiիWj_Ӈy|xtj"%>eed>c&k LCadMӔ\j2iqUj[50$ݤkt2f2CI}2Y]2cJf˓6)W&Чk 뿽fL$2ϟ=/}-8<,9>9٫ 㘧'OryvN3ii~Ӽ:=/4M;::J;)^n{xTXZqT+W$einq:]F/c2fhdM_*۔zl4I\#3ˡTH7m8V}Sjr!9;/=&MVECYఴ9;Kv]P霟&gCƔ5} <oڥ[Ŕ<% Nf:ySޔ+&i2$/_9>Js|X. CtvP*}e_.4m6%HU΢L4圎MRXY /6i Jy1Ϙ>. MyDGI?fha:)`ÐC+!ic.Jזs1ϷY.z6ZKfXfX.Kӌɪ}Ev2)4CJŚ2`8e2llyӌmyߧ,}I{0K;'''ytrb_dtmfYɳO?l'y4;/U$]%Ç/v~٧f6o2tyq~ߕI=zAU|L\69{u}nAdq~?-vtc}?dś6IvҦL2t2giӭ K>rY*'2gh2f,aSsLʤP>˾ʿI?I1]bݴ1t=tڥɘ/u&|>b1gofM3Cq i_<ˋ/r|rrD;gWIDATq3Y]̚.$uk9/ȓRޔaU*ZK:(2)vfL Æ,mS&LL''-=iIƮRV͘_3x`ZN3{M;46,Cg\_O9Y$ê/|&C[^gL 4Cqyq^cJ˰˹ɐ.W&pGiNL}LҬ+'m&44y(cY>NӮڞ4MxӔ6ؖ@4YMOJ?YMde4Wr4an?>xvL&ei2&j~,4eCʸ1+=c/L:mۖ//&Un5lqL/}~UNQ?icIs29H|wi.//Q?f42_eX,3k';:H}?:liۦ_9m7A9{ui>{'ɓL&M^<WrtxɤzΚW?Y>?,49::`vL~gbO>(r0 Iӗ/O2?'MѣÐgӥ`V%fӌ.""<4cezt4RJ0u]&.mۖ_4mom۾"_1/N8٬<ޕ6-Yu:j$mtuf9=}?<}$ӧ_MQƖ$ϟ=I>F~yQYǏѣ{9/rrif>/_dIod3c36IێYY,7 |ͯ.OdƱL A'd/wQn/V~y}nޜ>Y6e"b혛ա^yly~kMd2+U租g-zf4o> >^| ^["{i1FrC];] i/@:T@:T@:T@:T@:T@:T@:T@:T@:T@:T@:T@:T@:T@:Tzj/ܶ4M綏?Ԯ}|w @8?)ͳG)Pw p|p +N撽; e [P u q=zTU[.qLw= z_-@|]z*/?讇<i[ZWn:T@-_+oox1_[L_rO:kf_ݭr-wuw= Kw p|pPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAPAP]k{C @}Յ+⺹d*m׽ <_^7 j|_+_]2#/s/O^g%Pqk ݇y'T] {yC 7O>_QyS_|p'$_xkw>poݧ@}Ն}ڗʂ]}o|I^,Ɉ݇ 7ν:^;ς&P_P&޷^rE^gW-_}k2]zC˗}L2d ~vY O}=7w7nf2ބn:PM^}%Buc+eyǯ]T_d~%ۡ|w;}we71f~o퓶]>_1d9oR׾έhn͎eu>>XvI6K_uv7ccU|Ȯ#0?''9_2o~9{IN*P\'@K g)t^N^o&߼ a;pW.j+n=q뷶/7}<_W.Ϯgr޷Jw'1ua~-^ڼ|蝔y|}8n͎EMu\$_VY>Xm}m?|k㭺@}ۮ+#Az/N_懰Yk^f_떨P rm_Y=+H 7|˾v.vU*CDaMV۷[l|juEx(.R_Te_uk͊]a`}kߨԷ+̛+7'$]XoMJm`p w-,vE`o }Us:*d=/'kB}救u;Io^PW'Uokfavom/Vo޶wo㻪7Ov6o*7;ɛi&h_ߖbvӅCSeZnZl?]Z=[ǭ@^Wgs6v^C!oǜYnV'3U ֓wJ}WX/wl/XZԯ^=V'˾**6|}{R߬D6/uྻJۗ/ÞہeC}_H~'-bf|>/ 7y"nc[/ ҅Cs^ ׷ͪ]Eav=;ZlUm{f9)vx_T^}F^wUo@߷OeW I~T%w-Ut1S]J}/ wUoM~Q{^]|J}sMȾ}?y 7͎`IHC#e-`vP=;׾[wہU׶{oVoڜl4;7_{_wR:\t׶w/aEAݨ ԯR}E-`/c+ۭ'"^^vR>_onmW7o}x.{H.[l 6mV_oIyV殺߷/](L_Z}]ˋwk;uEǺ{W}vcnٳo<^3mtྺ(i3lݯ /k8ꗍ{ۍ7DZ|3om?ov{6]]6.]A^ݶ|eo$=7'%m6_o|lmX5A0n}-̾*»PR-VU/. U _e}=w:Zn# jŁe5OxԗWEL}碱>ve:PxMo}fUc۶o> /Vhvk. o*LyJn+~P}~M\:=хWe5AE}_; ӓ sP}ٷ>WeeUzt^ϕfp|SzU-_jb*j{ر*دx~@6ȯR^{봢h;žJsR~s-"(P}sUk vlrЫn59u}w`uv節`jN^zWZUp|׹N}/ܜ{~coLn6T~c]9wu&}ǯﵽ@=Pzj/{uy.B۬.#h(n",LO6<~Vp?\7~0kw0|77^$LOO|/ &; c.t?}.;7@> sZ?qp=2DP:n{o_=|=D.LiIENDB`Akira-0.0.16/data/screenshots/screenshot-3.png000066400000000000000000004071141410625726100211340ustar00rootroot00000000000000PNG  IHDRJk8sBIT|d IDATxy|T=Y=(J^Q񶂷ŋ\EEO(ުWTKV۪((V*Z"$,BXBB2d@H2a_L9ɜoEÈtt43h DyОD]x B4OՐ>W!9kBS{粦!L`r. յmph(h,9'’s!HhNux4u]cۅ"45$1X9N KspptIc@BƂkjaASCk\и"M]XBƂ+=7MsZ1" 4AS \&hXCA{ڏ}#  E=jj <ﱾDT{jQrV'!\_`bC6MڭD$9bSPҐB-Yyt04RyH IjBەMIIJ*$^HWR J*QwMpu5IC㕴V%EEC]c G H,III?JKKpڵk 4߹s4g%}A-NN^jn 6՞Xϐ"ɒ^zd g@:ut5b,vV7n̩xV GjSRP$ zFjڠ'$V?JJ޽[NCT\EE#] ଙ@ P(ڭ[`nnn?I+%j5҈x6~GCJZܘ6A|IQlp}"%ܒf]U?4M$ BzJBU6CMR;8iWHm1`b54>MRzU 4MSRk^GL7EEISfcͣULlbZ4LӌW=zzT޾V% =osEI}j7өiSs#p3MSgCg˒vz>BЌ7Iv~Mg UݫnP÷ V{#ִ(ݳ׾N"}}{ Jjkhک-Jh?jZ N{ JХAEpiAR;(Y~^.3Jz@Q%%6KPR.`:k|OjZн}t. FZV$۵s%h֤S8%ISݴ9(i2+[A].tKhjBsR$+ޜ8{k O}#㜾w?ׂ'">jPJT#(FPPA @5j%lG~_iF*Y3 Cv].+Uڍ`0**4zt:էOHW 8k~_999xW_޽{+..NNSVҸqp1~7ސرcyf?ŋUPP.777W+VP $믗кu}8ÇoR뤍7jڵmP#DeX4{l)&&FwuO]vfi…JLL$=1b5p@KX,ɓ5uT۷O:x𠊋}9~}*tj…w"`08)%htIjl2\fu\я~jڵk.b͝;WR>|X999NnVY,\.~Oаaô}vWs̑$l6=쳒M.L/#ЕW^1cƜvꪫ"]Um%m䥗^ (o]~_>y-^XT%$$W_Ֆ-[$I7nV^+RW_}>#-^XÇWvv\.fϞnMQRRGjǎjܹζ޽{7Xի5f̘SZŜRx2MS]â[P:ZTxitjlCMNUW͛7+33 'j͚5ӣG};OSB!^ZGnݻuq}ھ}=SO='N{eL}7 BP(˗Ǡի\.WTՒ[noW_}U;v|ן1q駟VOٞ3f4I%m.K]v=Co$p(%%%.]vvSNuHOOϺYɃ&$$ȑ# B ^(o~- 9P($ҤA4xzLK`y5u6MS`0??_> }=щ1J"{ї_~_w_xI=zijZ}ںu:uH2224d} K.vG?jE`P!_ oKW0lћ۷W^۷$gϞӟD|>_eUW]%ͦoYKl߾]={TJJJuSNnWzzOJ[. q:HAAm=B6oxHO<jԨQ7nʴl2Z`%K())I˖- 1c =S*//WRR͛C)55c/]T=.Bht[Ce;N͙3GӧOW_}b% )kO?]r***GQrrp+Vh̙0`~__C={G- tr=䓚;w*++/PEE~?H c~_yy>|P&Lo#GDJ"h'6j=,Z%))z`Q5mHjjy]s5JLLw&NrV_YaEMۭ޽{D=+W6M홋 $@;DPw]WuIhm y<-^8hIm]o&Llѩ}H D'ZM @A ZM͍a2MKDӼA:ͦG*##CV5Z0Çe D9y^۷q ÐjtU0:"AHb,z/цf, Z1> ]JjHҪрp^%hS`3:TE ]o hD/ #OP`v\.WU)+ө>}nGJYɑ餅 EJ~z-/g0 uMvtu sEnCD @"(Aц4zVSF4Mn,UN~3N hQP]o&zhN(Fvg鬳Ν;ۼ.||z9snKJJJyf}'u/^X;vՌ3#eee馛nR=t1ڶm[]Jڙ+B3gԉ'rss#R3f/|pe5K.c=%'';PNp={g?<$jjȐ!2/R=z׵tReffG /UVuN%Ν;zŢ믿^WNN}|>jZnƎŋ몫믿^999ZtFk˖-Zr$)99Y#GT^{n{ B5j﯄\.߿+gH^+Hҁ4e͟?SO=J{ny^g?wnjQu饗v7jڵmP#A9GULL># 6LcƌѤIɓ'kСP`ҤI߿+M8Q7xvء=#***ohڵ?[oUiiizuA+77W… u}>kzZuֽzG5lذpR .P\\)W^5kW^yGPgJڡ^zI@@t g?S޽7w`P}/^Ç+;;[.KgVAARSSy橰P@@wyyIR~4h m޼Y'OѣG%I4i^~eܹSGՎ;eIҘ1cmRRR$IIII8q֬YSgO<_Wڹsg###CG aÆ/UQQ*ƹiڵgzڰVvh֬Yn(`PR@6m ,IׯWVVvïRJt𶢢"9IRff&M.Hz رc-w'1cJJJi&ۧp#IJJJ t:5`Iu];w2=zս{Siƌ*--@DAI;TPPpJ ۭN:Yq<|Øsqyil0WIz= o~5*СCСv\Sbbz=z78EQQz!͟?_zAcCxO inݪN:[JdddhȐ!/θN:)''G_~<n:۽^tyȑ;㵄`0'xB?~-Z3g*##Cx@}QV8@mǏoS7sDyyf̘zJ/kyСCg\ڵkxl2-\0ҥKuM7ir:3g.袳=W_}κ~[+Ws=~[o;_|1BĹz駟3 NmzYmՋKSRL/i#ކRSSUTTP("奥iN^,KY5vwmֲCrt@Zڻw$UMStŦMI2IՋWGRz J2k=,x6%Ӎ\ ")|X6@[>Zվ}Q0 YV9HW@ #(AX,r8$*ab"mJЪjr х$J GEP6 &==@5j%JTcDaw >\G{8p hQ{t'/C'|R˗/W~~mۦCiڴiZh$bh;vt={( *66V&LPyyoш#t7+66VWTTKTnn***ۼ^&M{\cƌM7ݤΝ;kAO;v &{|>=z˥#GjM:b~]vf… MӝԩSua]xzg$INS .wf__/0ԧO~y<pכP(@ ^ߧO!LԵkWջD޽uWꫯV0G}ŋkVll͛Byᐡ_~$!!Al"jqiҥr\={ Cj̘1 ZrVX^zĉŋURRkתB:tw}rrr|Nw?j*\R111Ԙ1c߬kk*++5`yӶF BzΝ;efJ$ ꓕM6) ׭_^YYYVii %UMy{~EEEr8$ϧ:e 2DvUPP I۷\.W$(33So%K믿֒%K矫9phTRR"ۭXUVVرcM~RSS 1`Pa(55Uk@k#(Dٳ΀={Ԕ)S4c nuTw(t}&iX,g4SjiQv0 9NUVVQ&wZfZ`$%^҂_ԒKJJRiii7***jjjy]s5JLL Oۘdun+>>^EEEMZq&GqqΨKbѷ~fhm`PСC^WPPpJ7O'NTBB~ߞvx|>|>ISO=3gn &Lݻ~: ĉ@ǎ+6W­[C_ⳮCRR 64i[kԡ)N "á͛7v{ڵkm&z8P:u7|<9O۶mTu?0tPegg.T=СC Nȁڴi6IT&zJtfǚE;epDfzz7Q JJJHU4zÐ֟qBjn0dLdaiWK0Ulllnkĉ[=1bD/\V5x,]p2e.r͛7O6lЋ/ѨQdX  efLTAs=-Y:~xp Mu8hʔ) 'Y~*&&=z2M0A;vTLL>z:v`0(ө+h7m\"]6eTYY)ө@ YV?~\>nHX,SLLL@]vH#G wi-ܢ 6n믿AJHH_IRZZn?0܊bSe˖G1b233g-]TPjرԗ_~Yy8Nr-7kieRVVK4l0}͕$effСCoR=kf|$UMET RLn֭['Iȑ#?- y<-^8hSCJLLlrS(R=阦@ Va83F+VЉ'riҤIg(77Wվ}e<_~YSLѾ}_J111uWhѺekiڵڲen}}'xj*]wu⋵iӦ:ѵkWgZ7jذams!Zяc/ƍ\zua]uU*))\e˖R߮ 6hǎ7n|y 8IۚRDr-Z|hܸqzuz:pZ;v* KUsuׅԳs׭ުΝ;kZre~uQzvÞ-[4< (AZr:QffƻX,YV۷O%<2:K/ٳx4w\u-W3˥s窠@RUWʣGjΝںuk˗>TR;… 5|p1B`PO?gyOS?}5rHB!\޿ ֌EUۉ'1󟕗'˥;S˫wu ڵku饗uKRuHmɚ0a^x:ݻW_n6O>uZ~[>/{)e]^xAEEE4tP}7ڒ4jԨp`Bk(As:2MSa1Kj>4k߿uFǏ__t7*//OGow~y;Y7nTffyf+++KRU~Xo>{ܞ={j˖-9 W:eHUK#]0Tvvt[NYYY ޽z W^Qnnn|> Q'8wҥv.B\. 0ۚZ󢢢!TϞ=~T~)F(o[}:v>:^wu裏?7n[{vfGR ,Xb]s5u^wqӟ_|Qcǎ\EPVW3ݲaڽ{?@ &!ͦ@ ?obbb42fرCݺuSnݴsN3كRwYn[nYv|G=VZK3gl첲:KRFF)>|X]vmٲEȐf 7uݻv$inI.zE ڱc)5qDmٲE۷oW\nA%SJcLNNTcǎr8~7?~\RUǣKjРAի)u_6lmbtf,}t}W7d۶mJOOW߾}ߪO>V)kӦM8q^yuIcǎՔ)S@())сK^m6YzI袋4k,y<y^>^O>d'OVFF^x-^X#G/h޽o}gzu7+&&F6mү~+~ :T?UTT(11Q ,Њ+p8`eddTvҠAtm)%%^y啚5kTVVn"^{vjy)==]v]=\}|ddXNŮV57VL 6L-ivB:Hhn= èӵbn3@~ٴi6IT&zJH T/AIfǚEO~fJ.Sg- AIts:u4MUTToJJJu]miii*))ip:,uĉz->>^M} pn A ]oh!'E}O8Q [# ՙy1eeeM.pn!(( 5@A @5k_IJ%}5 LВG^%8qr0b]CNCvڬ|>_p8?S>S>S>7|ժϦi;i4MP>S>S>[ufZ8[%J͗'DݎF7Is= :?_.'w+A "4MB!B B| u1ZVv(..NU Jl B h)% bLӔ?RL gb3#{|lq)z&VgJ ػA%)CR!قnYR+jWPvU:{@yw)RrrV+@ J@wDSbktwɑECCE9Y!Jrw`Wn**PJMlzwISбBٶ^II.mKzFP6zǩǿ=es˨zĔI!\}/TC*)P B 2^wp(_nWwRRRޠMy^uoա0c$gƬWCmGTM ^jJ}_):qDx ~mqqKwá z1F ڄU*ǥ-[)BARyX pw.ӑ}JMMe LTG>|>_|ʧ|ʧ|ʧom7~T%hui Uwpds׀BE7*;Te(TQ( ϔ>ePrUWin5k۸F-(&c\)]e-ˬZPHeG(5%_Aa˕_X=(_ r @䝗AIvvvx&iӦiӦMZf$|nݪ駟>m$Gյ^l 2Do$I6mZx~iܸq***… ~4 ə-0F( I _-mYiLӔBp9/[ٳí<&OGJ &M_~Y+//OVʕ+#өpKkתBJHHЫ-[H2335n8hX땙Cj̘1 ZrVX^zzeddhРA馛 oжmdoF]w-[V5M׫1c(??4MI2[<(LS2C> KE2Kj0W@"($RU1i$]tE o+))Q^^^Vll ohɒ%믵d}璪~z 2Ǫ]}r[HU-I233e˖էOeggoCyp_uuoըQ<رcgt=-B%Rl*zڝ )Fʯ8eX'DPr?~XO?2335wƺz+Zh.{ر֬Y#áp.]vXi9sfJHHh^n[:th_+h͚5ܷ Ð)=dXZ0`0kCVWPTQ*o PȰb@cԩrrr_ol:wٳgBk׮Ն ԷoѣGKt/hֱnݪ^zcǎAZz!FuVO $[$:r䈦Oe˖yȑ#פfvf+aHrƧ(LjkN(9knӲeTRR]v5uV л+IzR%K())I˖- 4i4{l͟?_բET^^.5sL͛7OJKKORcL+2\b߉  hOQgpc(lb>+BPo Z >1t'FScϤ8Zz#,K6Gk=/x ^0ƥ0b#SXb]-}wQL|&;Q'ʑᇵי假O|LMMW@"""r]\ԗሜ G5;RP",K,ݬI?D{L]t.|v/q1FB<9!0霕a@~vb]Uj&&'DλꫩjeZv̳9{{Bm8GxRm._"Vkshreb LҲI|NSP"Bfc]DDZz#ͩ1Ɖ$S:i>S""2c\DD(iD6$U *J6v(CA╯|%`00'Su{xg7x#3c}}<mW͚rqM7>׽u9rdS:+(]wGq}"??;}_%tDDDDDd(( z+> ozӛ_ '=f|˷|9mR^2g~W׾y睏߳,>;w仿ٿ?_Wx{{JSǸ{yGUUEQ~,7On?ӟw~~ݻwF_{__z,#s7/ſ8s~B`o&^{-wuh9M=*n&gv iO{vw:W]u>qeec(F}G7ݽ{7/zыXZZ[nx?c?yZXX___1ꑜsu#2~~mtVȲg?t:m+++tg~o9w8ߍ:W_ey0g߾}euu3'woFK^ַr-ۿ\r%m""Ǻ4L^Q(xы^;y{KQٳ}~^~;33??"6<໿zq?~O|]w/}K>1K.{ɟdffnoo;;w~9.buq-077M7ī^*.~~RCߟ|&ozӛvٳi`k/| o;x;?sǏ[s""G4fB:t3oy[ رロ#r-z뭬{neG>^WE/{KKo&kkkt]UZox9>oxyy=vȑ# o~x{CYɟ x׻hiϒY|W oeuuuUz(:JW\ _Bn/|# ÿ-:mD?ED1ܜwh-|Lo~MYkٽ{7>sss,,,6*V)]v}}m9)k-Ƙeg[wquI]%VEɄ !<3ǎ;G=sĉ~t榏I2!J=JDDDDDFDD JDDDDDT/"" -M3I/'i3Iמf"""O9o1YdҝzN[&SYj:I. :Iu b5 a14EEw #>6w~GlӝO 29ye={ds؞ Vkbvz3o=> Y"g=꬇w=|s ^\D] d]k\DaB0>ZU/?Dk!Z(Gp YW~'/]Q 80q%†){Sِy1)6j{*":l_D՚cоYzJ.9@>ڌuqcBM]AQQ`cdPP"睵(&*$1ưwމ[Rcdqqq2ƌ*aD Šױ:s+3ױ޻5,9?w/߽c1bcMݕL|ėKkLGD&AٹYF֦%ڭ+K>},=Bwṉ;G=EyosL걞yS]ΉK]A՚kvڢ+XyW4m_*;v<7dqOODDD6HA/f8eĻy=r^C4eb<;{_ j*""2)X|o+~7L6yiD㨋,~.+EK|&㞞<%"""Yׯq|'q#e,X\;c=;y"KDD64ekŹof;lZr|w0-qxK-FDD.XeY?E7b7kxxΧUusrg o\L6ڌS5{zkBDDD6\W{/f ;nӱ JDDDdCYm,ylc9|:qd㞀lFDDD6lsԶ,6aBT'눈HCለȆ=O_3i\p"cq=I%""PP""""gjs^` u>ñK_B]̎{6ۏNii((v|0^2i\YTDDD-%"""rV|>ͱ};i\|߮^%皖ވHCAŋjq6gmZ֦T-ybr]w3c.gy9s.DDD JDDD -|m6.+I{鸧}(syB+s߄ϧ= 9Š{9+= mGo ( g},78N>8]U1sHAQ[{*hP,sFA<= 9W= m%DDDƥ( g}"EQl[uq:N?^F/ S\Qlg_Ęj$;wk3wmh,y\8ՃX{*r^v?NI e""PP""""OhzzmӐSWqOCDDdQP""""Ohĝ䃣jEP]9@gqOEDDdQP""""OC#/3yrqSvC6#9qd{Q3Wi(([* w{<ט^Z=E\EDDDDDΊ 5?qOW a/RE4Yq/TQ""" %"""!ί?S3R寰_y2ۘr?id㞀ȸe_ņ߈I??~;]cqebcp{ĕÜYg+oLSJ$;wk3wmh,0W_1sSZs>10g#""rAPP""""OJk~կ{*WL >W]͠DDDDjf| W{:R>8ʞ{MkqOEDD䂡DDDD4Ww㡿IZ1eNf|Ͼ<5 JDDD)'ag0qOg %sK{F"""%"""{Fo+<y\tO'= 9'{~=e>{o+= 9gv{.|ϸ2qLq\w2{:"""leяqܷUF b.>zqڸg%QP""""Wd}S>ˡkob};-F Uy'S']=""PP""""#vfuzv|k31h!dk\+}6G4I`bD1`hKl(~>׫WN]tHgkX?9߱~qOCDDLA\ʲ{/6xa\DotEE՞,XvR3M& KjuZabpbp<!sGfBwWusw6c|܆9 JDDDd[a@{CE_DDD'%""""r}tܾj3?o,PP""""",O{$-=?l-v*4444444qO@DDd\{/ro_k|76snCc U44444444444qO@DDd\ʲ{/bo_k|76snCc U44444444444qO@DDd\{/ro_k|76snCc U44FDDDuVb0@p0ւ!.qPV1wb ug1> ip>X刺j bl|q ! !}!LI'`,DlhcS8#Z`ӱ euĐg-bԭ1b#ZSh"ha #F5PX 10>X 0S<pa!+Bd. ,#H<הLd9YQjX,1x,g,y @t:^Qi\1w[dkuz'>ev`e`yVvcit\c1Xg1@ϐn1h!=b+2d.4^]81Cy0g3{e@$М4?B7Ͻ.&P,8"eUCL% Z.YaU5EgX񘫪"x<ڈg-YamNB$/296#eΩ4sY>}M]Xk!P5Ƙkćc(˒v͑9T48˸h"|y 9ߜ> Օfff%9ꪦ*"V^;>`"2 JDDDd Xk4֦ۼi0M1`m\[ 7 '"6ƘBᅝBO!BL E9 ? [|3K7wi\d),:loR/.ku4@&xiN9.551}9DG*Y^ǞY0M>0NY!I1bB$)#R3{yArJ_Ý9y^,x2.f"uM,UPtz킩N7 ƆȠ? 6yt53l%v1ft9GNPVtgg]EUT#Ccיii5ZE-& bYZ&x5&@ku]|,B0fXs0FȺ]1<ˈ!PUu=<,ր12Cu0PU(cD6O㌾N L$4xUsa,Zs3l3veDk06%jЄBJTФ(FU-M%:aSP%jMdjXV$= J}zEAhn ʒUV [CEĪ-ڽTgtzy+yN鸜=eU :.ZCa;Eh Q u3yX\]db) kX)+KruTeE 912Ƒ5q֤֒ K$H^TuEМj\fZB=Sp8_9"(F9}SᜣcC),i4nh ch2邟5,, 'wf&ۄ4!Rq6U8a*cXc&N!25aOTФJt:]ʪ:%t 09c$3"YK=^,RXP%1x=LQ|O?(ICGt:Vj"/۽ _W(ťE4U]5dY e]PP""""[J2@SGb0L>hK"1 %X0!%;%VaJgP#-yUolZTD|h`lbvc4dPc YlM8L~M)I &@7*c"1T ,E HbsI봔X[34fb64ALlV7&A AU,KV5UԵ' ^t{]=r(#Kv^0Ke{gY%G2gz=Mple~vu)t42!_[#t2-p6={fxP)p6#F{ΥjTIvx暪#֕|4D5f 'UjM16a@-M|!KLdђ6l^ ]!bsC)2!pV,sefR?k,tYJR 1M=EۡS:]6,HUymFݦj7;RȰ^I6j/r< -R.=ל6֦ ) sQ(4J1R)T ,OVW>P5[^$,v~03(KT`P0&b 9fUI}Z:d,e,'/ZU2^*uL%"""ec0ΤBmD0þ%'OV83  H$RS&,0!\jit֣*0jRe;hOTh ~!Ð$=@FVomhi)bPc?CZRA,K"U Fk%KMK/jB .vƺ8Tcp3G -E2.-EF2!Ut8aLH"#wVN.SykV҅~7/93TM\ &IK7105˃>sSS\{vk?3OosTO~?{S49alequS b%s >Ԁ1OEdhwѷig5;u5u"2ѼS?z5Uh*5> m1Ia'+O+r&Ѐ҇M5KhS\Tc|H6KTB e 'Wu'0 `Ҳ\ZM7haOă,NːbH1D9&OR'SjLuqXSJhǧM^@y5Y"3l'<+&d"6TlK:i9YŎYZ>UY[6OlX,ǙTJt^թ"`fzKw_:,t]֐r uښ6ڴL0:SV|5K[Zk%*8Y:MӴ4ƴM.`r0RHɎ†ᒝSO shJqTiMt3u,[C(ͩۼ/ 9-\5UM SWu/jn|(Zi䲜„pMW dIaOV /! <8=yHMwiJ ah2p)H̔Mi*^Lj@ tANSňs߉/O^bRK ?IkHԐd-1XI MH Q%O5z*ˈ.54uEJ g3btvڱCVv3ئqlf-m%3YFa {)4qlf"ݢ4 6KBC2(CnNѢ XrL4}z6DX\]%kEAgMZB)m};<'ÒᶶÆ֥jiL)Dk3SyZ:u]UPRk1izhQ1,H쨓XU#~kTl`c!iy WagKRJ$gQI4fͰs9,9NE:y^:K˴Z&ٹsgz^jOY7ycSIZ*ifz驩Ԍ}K:^ٖy1BmשJP<>;4y1 RS*GD>%""r*fg( bN6lp))e @S\ 1ҕq9Qf%zrPQ".h.yyk.;nޮYw $xkk*OOwm/HY4>t-u&q IDAT) Ypٚ">T29 k)"oy_;41##qx`l[Nq"4C  戠JHjpD܃1OT2JYśwĦlm7;JN<=>ih8gf(:\%R)ĩV:qċ:c) uZs Se5' '!!-0eM,;bK h!l7[ږv(Ù%󧒘NjƯf8q8/x(%b"Zh[B.^{W9W<>3 o߾zE҆V+V|X+VXbŧ4OC.~/z _u6jU9CJ4xIEɋ9&iɏ#SCř`=ԩT9W)+QVZŻ$a*@,DOTˎ耭TN,9Yed!jĄ+2 %ajJFX5KWO#y<]kI *(d\ײ{F# nݖ+)L93L#1FaCʤAJWQZC̸4)8:8L#SIm5q xǮqta<?{%ÈfopxdGl]KZ_]qE#s<6GבZx(!jkI)XU7ջOu J9T,{OIOr!eP5;5!8HPwrW6%!74TX<͔1#sZwjjJ01v^mWQt]kǔ(1HU߿} q9eӠ$GߐpA]q.{Ŋ6VdŊ+VXZD AIk Y&=Rc?:nGdsgg DH pАI%NSWc9!B^Wc^4tsV£m5%{QPdHѲQf(G[ e9VS]Dh-T:,FSfm)NJ ! zI>ꙂX0cݞoLRI6ִz{hÜsZM"s_1[Ubu~S\Zn)l;欯!ؿSF !S 5pŎiJpfRE@ڂ\bO哶詜OG߽v^=\5 LD!kiN91LA| ay'BoوDDt7xGSl֓cbv8)<'+_ C7W~OɅb|xt`8>0Bk'x!DvNσIU]{Ι\HH9g䋐=msf<_=v#k128O֦3#qԆ!-Ϲswf *M HZU**(UcH%gy24#NSڅ4 g&stmw&fl8LVhXJ䘘牘g%h0L6IJԺ~WeyElx)%8TRsL̶R,;-9`` )`;^& 1Bˏ(sp59D Lu0wA%%D2Rb V]r&L}4k]j#C2ly sN34eJx⻧Ruq4"lڎPZGi ˜f83Ķ y~<ᛖc;F?mz tw\7Z6W2eL/bf1SdSK(QRf*b[4,9!%6OJqaGLkhQԘZ{l%vj~bĈ ]eWHHKI34.,j@XTgT쾭+ C]"P`uJJJ4 n[H*'/7\XmI)-(Om>;mivG&4i麎qt{oz}S9+>}DɊ+VX*#Սcm# {r[TX.+b1År %cmAP닸sM SJL!!Y+O#QLj gj2Xӟ[%u=>~d唸 ς N;fSclZxU#ʊ m$<¶U8Uu6M#s\]zes8=2ʼnyT  M{T Q@PeS̑yLh$Z=w%K%j3TYE!>QF9x ڎm)qR~S-3QJ !Y$@\3t, 5M8Wn;QVLLy'KvIU=9p) 4]i|_N'@躞H)iUpj ]aGiR)WVMɊ?DɊ+VXB]T9ٞR\_%-J))xaSQ@Jb5XXwP1⤪H֕J T-2`ABPT;%K#3 lQQRTƚ:J.JdHj%+HF& M@GFXqT!CfRJN:0#mK6: q‡#K<6'4|{82G-@^޲oz433)GdrgW{ڶE tz6I[rɼOt)%DU*Dh r1d%p88Mx??C-q:)fY1OJA)顯 >,Ks$ks֒y&D?|D8TflRRk#Rni\J,R imʙRN91fU{ե]XqBJxKG4LDəf[Zs!"KOhUx1N uan$+|o繺e< 4m@'h"}-Ch2_b'(YbŊ+V|:lЫA"j@p8>ZrQkLhh1H# f|oH6!#Z3VyQfwsϩ @,US4kmi6SY"t*YƁ2۴~XAb ĥĨυ5|Sd:'bY(%C6-%T,*JEOGU\m)Wo?]h |7G'v>Љv߼|A,?'e^rg#_<8.Sd~S-Nkn#ex{|"DXd)|#/ ;nv[948O'l6=P2OO8]vɑϘ#<#4 BJ^$Gp \"yadRJl4^b81l$J"_%GG"rIa66X5)jVIl j ΨRQ3EMO.ڀHiQDMfeU6M.ehޓ)jNqp8y&|EnW|mѵMa(w\|thT@R&BcŊ?DɊ+VXBj Zd2 2[)\dضGz ( O!S|Vhv4-(F_IƄ|lJC,V"4$ꌜtS$}JHPn)RT4j) eHf)܄=ެ %% n=ĪeƝ512BApL'xoV%M{nq'%~Iچ?|-R /_"6X3U:N93#6]4 < Gy"'w{vVCG dL)4 )k˫۶C~0 tm˗t!9|vA<+>!Έ|HEeN)&\a@ҕ)nOr"{y\CJUnA%%l$Յyt#Dr{-2>xBo6j[1Jh#9W%LzSdzqAvlm{"zE*b$UXuo8GHy!)"_qywԲվۆ_b黎j@#MSݾ_I?`%JVXbŊrц:ŪpgjqH5d,E,,fIV* SϸfT[O%S>qtQgRsFRWLJI yqXOiՒd)JRrLPbz1b M)QRR3uI!^ZmС6Hۑ 8xxgv 1f24r4!N mpwyq/qǑP |϶;Ƙyٰ -sF0H!O) Ua獨|#DvIv#yq1c ;U!X(YbŊ+V|:A6\*"J$F0c PNӬ4R!F#ϳ] T́XU"Bq&m+$N`3!W1\dUh j/MAl垘ZƉZ%*V@ J.Ǔ4aNこSzׄi|E29%kIysNjypO3;=4GRo6W;o)3V4cc&H8kwJ輿3x5}3|t: CWlM:/Xk> P"F䲴8QTFr\s+VdL va$8 }UR9mR H&!$S e-kߎ*b-֜RiKPȩ(|}Ț\4|j#<9&R(RɞBK͖3mn5iDɊ+VXӁ)fI G*ѱ(T Ŭ,6Ldr5n\ D!Qt[]dBmlplG\ gw^+6l.dU πT .@)qⲾ>kV`n!HJdYmeQS,ʟdS1R(eJLHם:]I}LƉX'xt89%\_NmWyo雖ن{͆Ç > V`AنGf3a;&)hb nbV%R0EFi #cL1P"RFrJ4_Es k Ӭ&:2ϦxL ڈm#7y Y<1G IDAT#ؔpa;tuU(TJKsLΑ57#NC'ƲKyrr֠X8!r6SR8$i%rgFYZk+Wr JZPS/Djb%hBhSbGwxP8[ bɜpL@Z~?=MRR&HQ3a3{N#4i<)kqŊ%+VXbŊO "^l/KJjP37b?f*1U"AC v۞q2%)Zԥ>uﭟ-~{T\[<rwi)gKSRJ1StHNYm!>aGU !SI+E $iPnҘ%I-3'}{J =W ,]1O3__|x:W_Q~GD6?Ox;nn^p͆W)oqS%`:[&)gRʤ97X`WHz!Ժ K^FjANhD-.pam19FD\Q%|r[D+3ȣ6AIK4ѶBTT Q1UWmcR덜 U%T2Aq<>4G?u9!4Rȥp:TI'By-bŊX+VXb'A,E vtV\hoɨZ8g_yH?Ԗ6N,2\{p 1UJ%N7ɦ>$S8 {JBUS}X6I !l5(i5"RrVn$֖`*sj-*"#EfS4`6bA2:U /_og~%z݆{BѐY232C4xGbk;dĔb >\ʌM L!-<"_rw?}g߽#ioo)7 >̧;y/~+^akdڬDk1*\[Ju\I,R4`OJ #|`dL0軖TCX|+a,\&ܒkz vNЕTͦd]%] s ^}XIz_J)K)P%gbLm[᷿e[?{9-3Ziia;620`+V|X+VXbŧڶ-Q5\9,JΒCD U"RF(P(QPUR#:^J? %- 8x{m@plUmQ#v CGEU7R)vkXE) t"jG"y;8#bk 93@N&!耞fqX$.h;NLJԤ 119o kb$Ϧ蚀+Z H380' mۖ4\vG8q8fo>7).q#>qmhɉW7d8N#vg\)&/\0|]496 si;a$BZ^Ϳ8 Drt8i͸H)ONX4)[FYX$-uյ-D5ԂbD5%%wD[/T-wqjĩV;6yYsN,F_I9cΉ&ڶl-? 9e=q.)RҔy>p:ǁwW/xtd*94 0 ˆq !0)%'UMb +QbŊ+VtPT%R9sU"SzQ%UDYAmЁn |+N'}-M8WW{@ag6}ǜf)@ad2bm6P})P_$Õb~Tb;őK&*b"K#RmjԵN[D-/[T"#Ig*,-UBj@+ٿJmDs4R/3J*$EɂrS E3!&/:Z1KI/$^>}!qJь la1uWVKm?vۓ&3.CHi -fk wHm jY(WZ%/:4^=y%eL2K%e}<]Gg3qdLgOu=s;D ݫ/8 3Bp¶k)^HÀwaNuDmx,Yӑy7l}B׻OӉaxvsC#3eSdm(8 ÀMh$4c#̔ZR7 ~5V)猗W\ڔYjr;䉽9ȂSn'y$U}em`!TJ%GE˓)\QU"ƜaܺΪ XfDԲc4:ZvUUg VsdSR \xOq4Pr'V+}аggFUB9yb.iPUЊ+~X+VXbŧ$\fěWFT6Ĭ;RI-L,F^Xn(ײXfŋms[L}_Ğנjͩu~L)?92P_dC, |x&ih+5TLfHN&9CIF`ٵp h8L4WC|Y?"A( _ݰ9<qGjcʉWW_߾W7P24MӲ9y'NS)L17pgctd״ERmgW6|Pp‰lv4M{x<J4,8<=kۖ7 m"Ở~s㟿:m5B!RR+ڼP.lRSRL ^V#J4Mc sM9s߸ERKȲx5Ttj O–R9O۞GďMm,jݧ#hXl*DcZ-<{<Ѷ tmkQ>Uh$<7@alJ$uݪ(Y(YbŊb?m}.=P`|ɖ=l(x;J!~`ƶB./ ̀gi)&G4, "5d94p!J3je3% dKS02fU %T"kqHxYhsmUR.kTI$72=XkG{=^є %k Aqy"6 )&#ӉI2~ö plW<ӄݞ)&ƒn8q?>3v4pFM<ϴ>\@v+~rMLLhK\ml0Gx`'޼{ϞD M=!G#ǿ/,k⣌٥^Ty,(Bl/zb֜KՆu^5,K&O^,,9ZWsL%sL[Z);.$~N>z{:v1μy-햛EMeWPmd89X0 Mh{[J23>eaimۘBG y~ ?_*Vυ(YbŊ+V|:p @HUn!Nj%>H@W7M1 /3t,U_U Nm;MX{%WW UZ *aD.P F_DJVm\q")Ql9*fi1(TՌK%G2)TS`*L!MPB'%=~{mi[=R}tV#Aw ܿ{O>%fk[N1`{J3I=qd&tDh:nE81ã6!Wo -7ϯyLĜ!f80& Srfmд|~{@y}8Pm%>#8BdѰꖜqbr!'ɵpi|޹PS%h{RM'ެX9"EU9fSQy!YwKv ".e'X~!c:r9}{daDK*M˳[83M#mۡgeB:]!%\WRo~?=m}1hmJiSd6&v oŊ*VdŊ+VX>NbCPܙ@prU: yS*jЂTK3ֈz#Y!@W#! HhfL;BLˆ27Vު cջ#^qfCeʥVfȳZrraEچO@v4y/9¥h()$xQ15K*Jx`38N\z͛Á_|+T Ay7NܟF{:4/B냦Hpxi82C4!\xcN g }-gSꠤL4v[yޱeB:=ueJmWr1;K0j/잔4ʅ+HƙHD!ЄoY8%2YgbUb@W%VU >%U{65/HđR\HY>Δ01ynZy^CN1)#8{ܐs!Tٲs0%Rʤ9FY'7om'?1dK;W4fzF[~RFQb+QbŊ+VtP$AtW"uZ,FJ(0262}*Yꯪ#].Tu9+(#ٙuERPU5C{}H>\(>n"ZoƔY痺ScCf3 5붽A}@ LrM3$Y %a㪲%0qF$6fBP5JvihcvLJ?ܰ oA4xn;spLf~яR@{H.}(6g]Gd 4ps_y&x _޴G$;{{l4) "g3#cq7GHDAq232wO.iva:@jn%OdU޻{'cg܂ p,Dɂ ,Xˁx0C 1?ԇ?ǖˉ-xT} AsNG$)-ܴ\~c>T+R)wZmLprQ̦ ـq4Nh߿yi*L͕ )^" |<~$?rnpׯ$rݖ2M$fJc>4K+}͆q9 TyIMxgy:+3jn-MB:X^$*DmZi]P6𫇪*]gpuRSJ%# gTHnA>Ӯ'K`1$ʬs+Vb2[͚Z.vQVF܉Pr:)Z0T#%St)g:6 wH|zx|:w5޽y~sC\ ~8<&WՆj"yb~F,XB,X` 4Q.[RK;; |US+P+,fҢ/]Gz$Z h=MQ `*^,8\pL$"jU۱`T.\a-WArQjY!@j W z(os:)A. .$r>[3Ngo ΑN)}emNEͰ"ʔGb-TIQ UY>RK)jcO3?xϦK{"0ir&2q8<tViM% ~(TVOGbS<t}OT[RO'~nn(jA4HzTo~?x@V'mMCywuT# e<$3g`DඓLUt& Bs0N.&fsȅlׯ?TJ!`6mAL4[O)FWey\_@No 'euAVBq>H{,6PG4=b@'>lA %ٵM",q3E # L3yJxgڶmH1gTtɃ]30?'@8L#Kf;YJ!S)VH`wϜΥ*F:RϤwv̵f8:}Y]Z':o&o+R(h.^Aȥ'qC gN%DKWϞ?8&b(e"I*spwlSvyCq@mI7R٭z٬WH{͖8RbDJS)OZ[ĽWj%Tqk Fdyn _rT"fOw#&ZebӮR2%+gzـ˶Rjcnv DD"#MRsv$29Ico nej)X3OpхHʩV>ճܖʻD-_}-}A"__sssKR Vd% !Ӭ)/bկ!¬2wZO\E[m4]'nmo#<v<ϡW*Vsei?`]H 6ZD=)xiqCjE"jU"-xطFWhTU*)u 5iznE:4@ZqBfM4eV ) 'r<֝zÛw?ܮ4fd_ d ,XLkuF$4ڬ9F\/xex綜 Fx#l6ƞW'',scwhЦ`lth!lͧ)HYl:eS'e$XM#:4* m>XK[iUBl 0QGهnor3ؓ+PR ~@bIًJvˎ7}GLJ4F 퓩mje(?|@B$ݭ>N5U ݉q:-w7fͫ{lCO Of4e`o߾w|z nxK! =T޾{dzo~DJ!!HPkAr.bL$ Xi# TTTM:Rqn{jUYuv-DUΗaI 9 }15~gUCees5\&/'ue/Qr?jup!>̺U,3J !A]BOmҠps 5=:HY2{d.%Z\CIJBT6|QH1}Q'PnVIfKHJ fy*B=+G <H}"#81t?ʚ$+Hg~| -C(f5 4]Ll<],'UZ )YU̶b*"D(Xz @e] ŔM^_*T4vFLdQuϬPeh(fkY1"M2V:4&M3'_M4K v`IīyLh91SDsA&`Hs$,}G,^{9kTI@RHmדK?pmnxzzbϟ?z4e'_^}}-V26Xu}J&k ͆fWɹij ~m8~OteTU h9'ZNsb }'2wՂU/m YR‚V: -Ujvhk9ȯfM4x;wF(EA"*42ӧO~.XB,X` xbzN-cuxQlX 1KOanQELFB[peʒuQ/ 6ZsRC=Z/%v__p+QpT H͞ 9 RggX(*^9!dGrJ( +4F"D FxhE\^ˆ"((՟7jA纉bP*ěM*sw p"ZK#LV<xȡRn=5gn[bǟ;^|ŻÁK?r|FRbٌL:^B̈ު4+EdfH_w A є F8MM2t~;l т[<Q/mʀ(Hl| Mb;RK!4E;nnѪN0.D7k>_~=H囯W8;+Mv7 PP q{HVdhVv~@I1F:]%qR `$|ܫ$BAg;+'l jpPnb'AB6! !}UУ!M< bl֛ٞ2N1Fә2=ՆS`k >}D~09=:4B퓜-k^J{1xK\@c l!ux} mLU82svx s^ch'PZވJ z ȩ32vM`͊ۻ;*¡dV]L$QBdq8&`aT\AsJ9#ߋRLuz&DVj`/s:8<RdH:-Bw*|z6끩35 2% ,X`/LXjqTeHTJ$[kpQ p5L-Z v^Ϟy ̪SW uΛyp",TU[(P bC77hm@Mr Ą&AsEfrQI ]g$f *V_AcD $^ t 2v[yFW)hYJAGyD0LtƠJo n֐S5KŮ븗a Ȕ <%rXfǺȧ#iBb xfXoOĘ8#wxG~?fǘ')qXm@H ʔ?S[Dx H!EBDE EH-^z@lGɎv=W-H^''U1:ybuȪZix9o0B=B-3 Pٛs$X y"Ğlj2R3]߃*<<|d1jȪ_SO t!1#S( ]`(Y` |9's=#@[Q\ԆĖaPoX1C RbiwbB2Ն`vl jSX{Z8 ZLSrm#0B`Eͅ# JaV*iEgISh ai$*(O2KE Z| Budh{!dI'_:i 1Yyzf`? ݚÚ oOgdZy;_|e&s{s_~[oOgbLӄTlYV=y̳"JwϞ?K qLk+WxZ)eBD1%%j5;y/BJ%J@DCA$# 1RvIɳ]-2%:-SU.܎Skf1#ݾda(c[ U*гJkN|51J|mg2w=}ߓz!Hd<_ Jά;=q4@FR-!zHR(x g ƪ|ԕ+GҪSst&yb3{=z}YZQ'dJSj6UHY]Hh˶>b֤dCO 1CsvÚx!ZX6E2uljo_|6DV !jaUR2Z*_ɀ`2L jΙb F h%Y! 53s*jB.\A$:۾.$ 2jHX0n$}xu6|!U-5CUYqeFq%KfLnZ$613 /4RU@jV1fL IDATrs4B?KS(8<~p$2 +DҜ-t>/ ,r% ,X`/FX\gT H- `>nqWb$CxlEiյ=h aݤYg|vBSVRuU~oO*_ Fŕ*2ΙTs:jveyh!%Øcfz3XMG<Q**iy2:zn'>Y2[*҆ӉEX |Gw"bC{任{cy*6;^>Gse<)5t<lrmws_}zi*lj0c$G>9϶mJPoLJB\4CaET!ȮJ9(]!u~Ϲg+vxs(Wi9kj65r/u!͖/Ƒfr:!~^ef3,ku2ŵ9WbFMk @"ϟ uF|$˗}3{ݎ4K 7_ |iX ,X`UEb Lw?ZONKv#mvr E: qA:l''p0!a#|4?,l'y>ɈvUM(QP0KOX'uo VS5zy[!.!,M:Ĥk֗'ENh-fN;6^la2+P(nC͖]ZIe_޿ ]I3%OXuHlB7^;z5@4iOueY!T?Sn2]]U$Ri6(Bl͙jO 9$.4-(hiWRU膞wb]ɱ _ULțZyL/V"zðɹ2JNR)SΤ)93 =8 .%#Xd_ d 'q)?aM{, YO p&EL- A.H{3̃\rED/ve m@OşK{=U>kkijEWbyij_+R,7kgXͰxp,^T6Ǭ hLhgrf{"F Ji"vZm%E}Y")cLFZ iȏ͞6,k)\1bVJR'w=#O\ gXOhʞ?CD JQ㇏tc=՚9H("f³^=xH9Y0Vf#"R5jUJ.8R]u1_6vHԃ[$ 1mF+Vkx~nz |A,չz1DJ)hG]mV!BΙ]b* sF1eK)L]?VKmF=G&9ݤC@ vM-Tnq?v*0 Vq7>ˏ1[+d ,X@Thh{DS\T$Z`A |((蒫{54811.OR+L.dƀhSLvb4+\l9fusHF'^AĉWC `ՙC|[փgqN&&$gMAP;hKrSr!ZYֈfN(E)I$Dԥ": R⊙`-0QLe%P24'=)W |$D"I#)bB^"͆*ӧOn7[2|͖.>]Qś?Ԙb@\Rբ*7*3m$d;*$ABA#/Ն9#%\3f#;R؎*ATMbj[S\D-6lBJhK:%7-p8p>Oy'կ[RwPTI[vw iog]*snO,,`ax B%TVW0I#3j Jfl?A -~{Bc:/*:e Ԣg|2АLQ2 e<<Y#Ts2ڃB L9j)Z~?l]Gə0ZyM$ b% ,X`/m Ikr)?ŸxLTlHoą~RGPVPj l.!55DSSJVKq+hj[jWvT%rɜ(DگE0e ɐ\Gx:9T8E:54EF1#!тgSؠEQ<lDhL8H`OTUhVb)G=@Vް" bSF+B-Rvo>7lOOZYwÁ?4hWhJQOEƄ(ĨJVhGJ ^ MUv( 'j1r"NjԾr-Z-(URPU{a&B@Sk21Mj Z}|9j4ajieu%b0Z A:V G3㙒M 9aZjeW3Ӊ7o]+# u:"sٻ<D$q(ℌmH)SŇ42"V+AXb0x^"CBΦHIіbN0E6kܣz8Y=2RALϚm)E`!lR$Fo]\EsA֦09]IĉH-(t }7@fg Y:bסA+M H-HбrN'y=c} J㇏{㙿Do˗ @STRHl7[W]ב'quBEUfUH9̆RjZ5Z[{UcLyB:hŸ=BW\lP^. ޾{"G^kAbtN#3*nUM%RB<#'3S|v{pjH Áw߱ݬnԢ\)b8*}<6kn6+tfD> b$:9o_Tw]?_͎ <1N?}b2v-XKr.X` ,\>-ÕCeX_K6[!.BӲ,欏jU֛si49\ۆ0Zμ/)\ڍ)!iC^łlC36:- }[rԚ;8p<[jfy,Z6zYNFTA٬+!Jd28qJ+]12RʾR '{-)mtrH% ӄYNxlO)Zl.A*IH#R`7C!`/ Q` ,rWg/?o1GdZޚc>ޚZP''WĞV Ap3a19zvҼjp`˴pL#]*\0Dk `汁Lk6dʖ{BTs3KH=t0p>[Iq4&Zsz+<2 _&4!CD1S@REUUowUM M:"TbŃZ1Cnu*)Ft]a]+;GuLaFj#?7F"[JgpC-lVwCɕkFa6$̦?cGNOlPnT~NmųvjuBD"ngk9!c$ֲ4+>9չJt(䫆)=`Jv_cP.śr,?XLy٬8U[T%T@j0[ǵ"ji3=%8XyawRw`/ Q` ,b`!`j.3v9@9P;ZM]¥QF-n}VvH۔9Ud"m3y^m[#=)d~"߫{3c8^nn2!e.2Zy'~vQoO|?<>b7W!q!p{wW_ݛפ4SdDJAB"J +3fTOXv6%,ImV bv*<V^8FSߝh`!{mE$@쾒5(vJԩ+dU4FB4rjۗ+QVgYF.qBk!g$Fg(/^p\ Md\!>Cd#eH),3!DJuVlذFlذaÆ >AŸtw{L[oSU-4+uo[uȲcQ#TLM~ժ 'ksL$E(h棠jm*F,JxCB7 ~֔0f[/l4G$%uBE]dsZIurx*%H+pX- GH6Y lOL' W(0=HAkމuR-WQ$gH!z7 !BB8/3ύq!xwy=Vb_~߾iHE̅3I"Tjkq A21R"F뗜޿|oy+j)@fFLk Ttz>HF*H^z"~_9QIuUW4W4m'1ii7Su_Nc4itArf1ՋB!\.LxLJD%-̼hĜK!d!&BH,KYqÆ >6dÆ 6Oa|_<}m\l Z퉳H5lVF k[xVnCU)FXm83Ҫ|dĂD<Hht !y> = DU+=7Dyxqw GSZ8yg&H7u fo \ NIEfLA6d>C)r6.H$~ZY)RѮtbE#v;i@Ul)Zv;GL #fR=+hF Ϣ0,@IGv1r8جFPnL8#cʴ֨LYL RgntfZΧ'uݷ$Gv7˩*~9~ IDATaOH~V!ُIo/'4:YT+Js_N'PVU( kб]ܾYZDL%$:cR=lL壨_T`*,9 ~hJ,Jc૯g,PbI1c|ω?3~--U;ܿ`-/C@JVvO'rgME}~T=OgÆ؈ 6lذaç<jitQxv]eYt6RUD@ jb{mvTwҸWU-4ȓ6Ǩ4 XDu0xY Z=KuY-$S8WZf8MA10 d!$2=|2bUb58l?<@Y:CJC0G*:O0$Պ4HH3.3L}"0DtQdn[h~ȹg?qMmA.')RBr?9Y(J͑8==!"|oX*ë$-\N, ~9/_@kZq\9Liɟo/<~-"BF .t,dUdq2SZA*yRVm NXDʮqU( ͮ<$5jmW]Q:q*H̐ÕU4(6jYZ)S.w/>xGRʂjc:FrHko߾S^g^_ͯW7G\v,RJa~eÆ <6dÆ 6l AWJ ~̀ó֧jJ3#2qU\ՆH${PAT:<1 SVҚ*\ ˲ Hy?)scbVK!]_n H$6 S\.2~˛;id a>$~p%, iY?{q|R+ӻDr+nZ heHy?2=5+qBӮ Q'-5Ɵ5jm,'c&ƈm*z+1v h]_=lj˘$ nJJ P[8< 78r{se:?O9N a·oq'OO 93 zr 6lc#J6lذaÆ Fӟ6P!DRB;t7Z&b%b-@S1j)<[sMk~o0^,!"ZLFF#X /ϬHc٧&ǜ 1Dy@iy<=1yY, cRFb\ z:/"̥[TaO'Qb+ "bp{xs\4@HF=} o-f7,W|hՕS"C0*!Ȫj[-/;7Ț#=e!au1E'H.kRVrGYB]{%4J) 1;VV5mD_ @)0M²vJk3)' {^q84ϜWYmذ(ٰaÆ 6|:PAWMϔ)в*;x{ q[[ܚQå{cl0Zm{ OOy|ywn^$Hvܓۯo y)F@. 1О5|WBlX ޯ_Ik`+ nR5T6YI+ҿg$&~SJaQ%:IBt%: c5L5JV}s"G"ny/phZceLlEeooX۰axlDɆ 6lذ:,uUHpe\-3:cø#=UɉugJ5`O{प т 18'ܞ")GFhP}PPU$gDG;xtEFS` vo}ulT+Sy;VScr\(!9)ѲZG 6#G^ܓi)Qj1SF` %!8tKCSԳJJ}leBŲI]mT yzA<`R1FD.uݹҨS6 @>gb fљSF))I&c3R8d4#_=K{->!7/9O/x/8]i%H,8~ݚXHxVQ

ilDɆ 6lذAjW_AK0բxZMZE(>j'-3CV؂Yn{tڐ!"R=$zۓ5KE4ZNxuDǣ4h!$2!Pi"V{,t` ?ja\MR"^+Bh%ڢ0/Y\hrw7f3W| 1LFDhWi0Fo].FJUiYL$뱙 (LɭOH=/h|h 9TxT2KnO^"Fpܥr)iATÁ0r^&^<{}s$i#y>|\T~˛;^| !/K4q!gSAtP/anqZ S^C`S+T۩,$rĐ06&$ 4M\bj{k fSvlbNj[(K%5ZY<9[8lZ `A:7׿- _˿%?яyq{ø#߿p82MS ݿ .ܰaPlDɆ 6lذӁ`9>PcY=Ĭ&&A'U\u" Zaɲ=Q<}0gHWRl[`VRI&]bNHH@CpC[ FL̋m@8=/X3 _zÏ'|=ϨB\)b!Fh쁲 F%XK64Whʏag+0+d?<}j_bZ,-h H>;ͦ0Im꘦f홋ehh[6dYY2fZ k!P[)%NY!b*َ}eYWxx8OT%x} Kd,0O,P[WGq݋WÎo/,LM>*S[D'4Z5Li%'_5\SJPbQU>7 IPBY' MnSݕj]tۘ])hDZ-HPRZז2$DHꑉ*e^1Q=S~3O?$ot>ٛ7~M[޽kyAϬJ6l%6lذaÆOA-!6;m7^sjW*{&1Eo35 j]m!>Ua-(^5dUn%0TY}*nPD= 1 Z#BEΦHJ!DBpsFТNᶝYUS4e%F șڛy*]%q"6,ՎA{3{HFjw7ppYiz3pK gV;d hZmRbYEGԔ'b,N*f@"GoCr=є TjPenL;XAH4J-|8UV)R.CL=9)΃Dm)_}aM@ {_8Ogbl4Q mb 1U6UDob7##<o2)gXlzPZ+_Vo+!PqKݛ5 B Ψ]ieW5ࠄ(ә(;k!Fn͛?UӉ%F8ЪJXEZy`^j-wr);RoIq4 Fnhs,"+홢@fgy&N( wFl?1Aj--68_})zs#Pz|ղEwhKu"FPTWޛ%OנŔZZ`* $+] Y!8uZ-əap̯y1YAe٧HÐ@P&!@rF& ǝ Rx01S,:K0Hy?juj֪m7Zڈ&8IɈV[s*@o*'PJ/Zo vHoN~yM0CiQkmkh38gV׻, yZI1!1F!@;Me(041,co7ߐua\\S<81%6|_%6lذZV]`>ضڄHzk[e Ra(ے4}9-At[ZK(X@%QR8&Toh \ΰnomV,+c@)(' CT'kUY !41J>`HHʐG[B^t2KJ؍vqj$I)1ҫYe)RWxͳγ =t E)1!y@kFŭXaQI5v1q3 |v8pLm!^H!ٔn"4egޝL@MH)G~5o~d2oi]U[b,4XE/|)[x"ޭ[ni҈1IsrYk}N?fQ3نe҈u%NB` ,_]IVA[R VRS$SݴFe e&~jmB޼O|/nV 91QQnY}~T?6dÆ 6lie%PTjʛNʏ|H .D:<өW( ,U}@,8HHWF =FZDU{ߟدUDYpUJrmQWٴ jY R}B@+RrD+[^֖ɲL ɔ#1-72/)5*X=5Y+j5^+[3b[P#QHqC6E$Dpd#VR y#djښXkfg쇁=sւ!]fw8}{>GΧf_#%JpnYIB:F-bZ2~Ϭ7{׺a~kZ zmiJ4Zpvj[~Ӫ*.H!Z-1 R_7hS~?'aә_}_$k2p:i1d%#<= @6l%6lذaÆOfqXlpΛ\#e ] b}Ն ;AF\i@geSDuLq Mbʓj7%F.xHZ'.$E['m=hvF-6Cz0l"2WUND'/mNZZڥZ#4hU !MPla7M j A5+n0Ly^y\fb*T$ rp3$*1U}V%+Bv*Đ2u($FFaxubaˌ 1aMc$`a5LIpU*A!z]!BLp{8r3Ja^TKRr>o9:6"a9%n1V[$ ]8>dSl ԯ}g[ۙRm;&J0% bZJN6vR'CJMnbb. yUS}jUe%}Xx=[BYBVNi"GS( B`M/]f1rJop Q$ׯqˡ2J)EHbjgԷ4 !kD2M @ y2OZ yĘ8LnGJeY޽ D ȸss{z 6|؈ 6lذaçKDl@tYHku2tD ņnk+Hu]AU*DE^]?BJWrV fOө>x.3N<1r8bC=NyeK3R?֮Y5l *R#Y*1%ZdY2kUJ,"ޖO=U9FJ6jߑ^oÑU^zH8LBFS(E3j !Qm.Hr&g`jUǥp)H9ޑb&B&ia$yc@i~K+^P意Ws vu*h4+Ҟ)mBP,D[Mq(QIi"~gwԺi0Me2LHkiIBkY|b0ݝ[\-|9[ ؈ 6lذaçLjgc#@eCLjûDB+&m:`QNUUo* n 0/W3;ĕ(f5OPk6"1ң4xcD0"1OM-bڼPD0rjꡗ)zXitBv!`*&XD*-Cvζ}q[+hJC2ãY+nnl!)Dv1QSmR N¤@ThP ZArRO|?RkCUJ U,m!F/P 0q!̥0M܎;RA,dnʷ珼D^anOSo"%TR^=VxZ*>ၖ!'R(˅/USz +I\UqV"ˢ-CCe5%ap՚@I>{=ISaUЭ?Q"v,SH~5#Ă/H d#7eOɌ}bA , Ð)c۷r{wǛׯa^f Ax3an{jԪҶ G؈ 6lذa'kP0Am5AWY6\߮6.UoW!I !nN4kP^->mviaun!SN*qb؍p-@̲#U p_'܎;w4;K5,$1Ҕ3YŖˉFsT1F"fuI1P5ZW=/^q|/8?=1#Me镼R{Ku@Q!$!ZqW^)1@ 7=b->ⶖ^%h#ad`~=?{t]ʖn gW+#F'!!FJY8==UbOPRH\[#LO3~Ow;~ 6ݸCĔ>+v6lFlذaÆ >)]"\3DttmX5"^b6+) 1W|bvoisT:)+n>*l/zL[Atkn܆3oyQߧUHHLh)HJpOצn{͐w+]] s[jpDшzbv9]..3@&46ZIe!pV*04B\j9r(3Y<  B(=%^ ;t_|{x1 s*3?{q8].=_}N'i5)Ǒ}Lt\eZɬ82ZH$o`.e& in}[‚gLAr&)S+=L8(WrJ4FQFF`=HhZ` "Y{ªfT5-=heIdPJM5Db2U0d=Ѻg7 { ?3efrrJQaQaÆ 6lЕ*ז]ψƪx$uHp"Y]Eʐ7gZ5,mZ`(<rv3"GyMn %K?Q̨-?(nes-(EhH Vվ~U6v=kOᛷ5* n 2ddMCʶnFBvp)@3l` C-SY)BRܥh|?W8f<&}}}zbR2qFRx4_o>/keVw<-I B#DHHQx)lsrȋiR"Ht>'^|=~n_6B<c P0ٔ`ZRT:GJN j4v M: c35GoVŸ&jDX&J WVc%ŪmsvDJ-_5Emn骲}!o*)?&AҜؿl* Rtsfw8fY^B{zaկ 6|z؈ 6lذa'mVa N6jAVmaB`W0WC Y+g#]NKJk!s CB C |||?.0/߾x0[Vqq;Le ,etbY 㑢]̌)Lh 1J)|v{wwey|HLB5ZH h1Ҥ5[ssOUSX(qij J {r'0[9U=px+Ye3ڞAD U5ͲBHh3L-֋$ " G^XSYVhj(*B#<3]&޾KJoi7zS NRjBٰaQaÆ 6l41ÓZ)\&F-4PtNL]k"5lʒ֒N\ ns#ȳ<L58ٳUWv99зך9[j+j X J$7)\3HP#V׫;{퐍BD!)C'F˙YbER 9 S15ҔACZTE4a=r2sQy*5v)v8_NД.bm'˙HsdnT ZQZ%@Y S-<>hc΀$RUKj6%0FrJ18xLJA8Z`밪=@ժR]@U)5JSuH)*jj׍U' 4)f`@ŠOŚDdU|Ժ⣶kO 㳯w1S ?^я\GU3И N=%W5Hɐ yMIQ#)FVͅ)'9 ճ|6tϻ;2g+Mm\LH{B\ xZ`fQfq<;rU4x^d{hh2T)H&{oDU;b?geƬ|Cik*^RO(KDP@Ub$55︅EM5ݞ N}g7׌ 펏}˿~~_?,8WߢPZq>*Allg hF.XwuGcmg)ev$Z&Iu4+9-nU:6΃S:EKdq'iZo9")#Á]Q޾oW_qw4r7<ܾ@̙V=K9v!xq3\u)MhQb2 Ja)FTi, -2i!pS"ŁT6in4r;U5#ӴU,98VZUpHΣ0+DMdnYeĠ#RUJn9O!RUWjsd9}m2Efa&l*Fe.a39)83B'{;nni7{?~-mx՗lohBNjWk]gA?'xx~`ĕsKM|-XJXbŊ+>-,b&4$P{"%Kl%SgRU({kR:p bj~6-1u"ol1^bm;c2b-~k+). B9rQT7rxظZ'˅YU@\[T<;BCsr<8 g/Ț%5-":Ѵ-d4[J4G2fϪBDsC{8_}g*#s@7=gVUBd>gUܮ6TТ˶9OZpHU4DYNۻ[~`?p~_Ѵ-mhhj[Qy,壴m_|8| yf|[bIڦ*VXJXbŊ+>!\Rz>)~!7qb*y,qłB fwʼЬ9"@.<}MUkTۊH]3b6.zFV&XfSUW-5lq?5pU6+p%*QBDԬERsאr=DL0ZM0MU&4֔ #:LM71\ؐDdJNYCG³nMh8󙷧X૶'=_c5y/5[+v^])1ĉ&Dl.ȔQ("vG;<ЏC9OaFR5ae ꊫ<1g0 ϯZ4' 9dvL1'ΓR`-3U4mŁGqbIve-$]?'m3ׂ7LU}wu6e꽋֩5ӅKNv]+1;Μ"O"O9fSD޾ ٠W瞘 *ƉR >"2Cٟ'³GUSǏtE !8bǗ4EҟO{5EDVUC|?5:k%[?m7l7-L&>px\o:~k6Nm 0oZȘ )J-=(öu4uEN0Cpۣ8l7\widU:R(\-w'=?ql6Q1E\ϟPd-ba/Ѯ󘣑⪊U g{9/* .eJXvQ/'OMK;xQv9+K(2Ax bG5&di  n$󵫁XQ:jKUE=P.c&AdDV'נ*VȘ&898%q g45<86>Zc݁ #-loLq'׼8{>81H*&1ΓJduA)&Rxueȑs mH5lRȪ^ǶxHmypZ.x(]Ǿص-E)gǑ!N~xā 1VkF<Αc&T$wP+y疥:C9!f&XMl=S(CJ6U{{OBwKFH%D]%mJ!? bďsvdd͙.f{0o?+xسZ#RB2x e{~oÿ?iH^7g\bŊO+QbŊ+V nd$.B* aOKm0""b4e!e\ ,3~"rQH*^L,*c@YmlZ,hw7YdJ f5Z|C̢T7j Y;J8_tql-sc虜G%Af3ky/O~³n^rAT #Z5 V_7ܴn6p[oGZ?Mpl}ý-rO$SS h CϦ8w 'PHEk&&E"3L)J#]p8=WlBC{Rxshxys~?zE\/+ۆZJzZ1kɚi@s8gYg=j_F]ZgD1R!ɹ˽>+y:#JZ=#ä- n!@d|~@״v滑f\\+V8%+VXbŊO)BLpYv"bWeWV1Յ$3.S?x$fR@v~H,&l>QHSƳEjU\uZJl",f7t5rFġ TT;ȂKMَέ=Z`Uo-'y$W`D6HF;/aQQxNqdr| %Ti}T 9]=vϫ햻ݘwBaߔbow)-r'fNj,R2d&5Ô*db(Ekץ%sJӴw|L)rvFԔBYRr@[Qr ژ1FB_pzܟkPBBϥԬ|bŏ+QbŊ+Vt P h5Rdij]%U%[+CLkA !ۂR-dP/I^lj#RJy'۬zuEԶ;_@%45Sk6n&jmPov2oŨ*D]eWlͲX|$'Va 4*Qr=ŗ9&>FetPMhB #c>!"cEjٮ(1 ~bdvt]w0Z LN.8g ) d)77[{*|6 n )R2E <q)JOESr&F/hXHxnnͶ5SD6A6Ysr #S4cbŊ VdŊ+VX@s2ˇ< ,Cd~B=+?ef!]oOs+y ՚1gPpiY0K* u&WϺۤZHdzy]:V c-Z-48Sh1*iPe뉽( SYΕٴRG8rssc u+Vd%+VX-iZms5̏f jqqb*Q,#FP'lm-sP85RJ3+PGs4=Δ'5g sꬼXx4*4ٶUQj /EM_mӶ{t:Ӣ@ʪA4gW ϟ~U+QbŊ+VtP 1"nT!33kD5^R:y˪)\dB3 ?iX͜2C{\d,+GPI|kq5rj-'eeuBq.BI2Drr3HJFS zs sCB<^QۓZݞ~kE1")s!xApP{Hηě=w}OJp82t'+#) =\\(Ē(E >ph..s?xmhq2~#̮qx6MØ#9kS5qF>N=N) Bÿ|mDM0380q]q<8lxߒ!II#ƾf˔+L/ΫZnV.-RQ}ZwT6LnZ%zqKuh#KfS!˜d2'JlC`]P`9².)Wi/H'1A;7Ws7 .\qWXc%JVXbŊ f Zx8z!-E i=C _*QfnӑK&˸ \OcDE-.`(b || )ŢNȵJxVu!hU=OS6ۏumMJE#%:5i# g![Dƚ39$Bh-)&i}>tMGx )"3>%rJЄ]x4xsF"mԊr.i=yR#͞R,Ң#'5(β`\Uui) >xiΙə :g#Y=UqWe\2i"sm'SI5+r Ù,֠&4y=q̷ފ+>EDɊ+VXⓁ\O&g m);+jũKI'P\7?F]b9xjC=e$bU*YiBCgH%ur9uqZ.L.p: t;#`\j΋eH.SI@Kf 3N Mr'7HR<A}#k4d0;هQ۰ )&Jܞ9 %F{=<Дȇl7oC̅|?Knb)|0fSeLnG1&nO4RVRhЄ>ES$ҧ|ȶpr|wDDi/ooGv]ÁؓR"Kd)RRx[/^-#y\)fRClƇ@&r%K|mC*!j\d3P< NT*5';k}8g$sUqbu3TآZ _$iD+Lz.RU[>\..TEk3V8I15ÞL瑜ҸsJr:=2=W bŊVdŊ+VXA-O"R[_6.JNԼ x_a ˶Rйڲ#ˢ0.3;3Ykn?/U\~SWu`DŇFznnNSZZ+I*9=犑&f6֊$*H$S RFccj#O)Dmh)&Ɯo=k>\5D1x5ߥiZ6݆SNo<>PP9|Ց|%=yo߿aٳvP`v8qܟStbg3mL4캎8̛L9Q3q11=$ny<@<*cq]N R 9}M9gGa$t#z~$N<ߑGR?MpBEUI).w,WsݯEGʨ'ָpu a IdbE5"5sEK2^lg'}H)B.UaC)5GĘ(ek;xJ]&yJ< 0еTw8Bm(%cyOJvÍޠ(CߓcdlXbŏ+QbŊ+V`$URj3bL?Xiq$tЧ>=\rC1)[,{<3<wQQ{R_oLuά"fd D7uiy&j8srp<ڵ`(nV؉mʲ 60_=䔨KK UwY.u˓%v]۱xu8:\yJ~;v_Gƒ9MӸ5 L^Si jBa`2W29&hƩL> * =&3%G:ɸ$ks uB")%(P ݁h1Dv@SvNp/76e*;f"~^MM25V"$YX7ޔ">7jOPYhCj, ˾bD%Zxx%xݦZ)VʼnXqS@ˉ9^S:\mp{w߬ȘJ 0j+YV\403Pf2*uO cY9]fY4YwHdQyAFOuu)8t\KcЦA@`9hv%UrC.! `ֶO7BF/m8S\*UY-EktV:ę(qh+~k|h8Ǒ|Ϟ?u-DG~yL%"\˗/^7o(~v6Mے%qa3H߃xψ- mh'.qLN=E,x"⸏IG"ʔ"'~A'S~i#Z!pΉwG~:Mtx<= M@ϦH-IO ww49Cr,5[@ |-]whY,.5֕3G(jV\˶Us19g$*\ EpUq)b{GawlKVeT bݒ?>ru#/(Eik4 3_19ϺvՖf7߽W/ 0|EDhB yc$x8a8Oxq<0qa8ږg#eq;Ɣ>iF=ELQB +Su0P6JɤiOs-wf; e۱?sN)Jr"Dpz|0*`EҘ- L.9 Y|Qhi/H%&24ʒFX56UA 8 a Szb=1%č! b*c%rsHrN45ĈjP(FH%Bx}1. m9()%|.䣓EQUs?L/g֩Fk|RFHYN37 YC7U5q@#?} ͱëןlz00N5.}3-ZLf'oxݪ*YG(YbŊ+V|2JLldS#>r[a-6 7~a2 n^ȕ dѺh4k@ݧP<,2gz3*ƚA)1H-bma 6#Z,eqtXHd˵&2)%e4n!G6^yӡn5N Ѭlw3c|}Gn;~8tBrFPrF4 ص5իLȾkysc|hM@߾{K,qXplwjg4rl& &vgyLJJ#\SR`m~WWr8#E2!|Bf )q%[)ؽ++2CŖ5 YE)X/NuF_.`̬8%0VM/9b9*6'a9tʔ)iPUB0O΅>Ͼȟl fO{Bv 5Mt|R)4]~bŊO+QbŊ+VtPt i[.ߴlێ8l8ώWo,5M,,@(1Nx>0 =q<G\nî۰6N8Y8ͻ c q',yD= CJ&i&iH힮[pRp>Um MCʙqR)ݳ;-;JhN\LA\mvyry E\eՂV`5%lBHUVUf*x52F1eVI 3c*JњR$3T Qξ[JPuF8oo_n_ڦũs~t]x 7o"ݖMYaVXc%JVXbŊBmu"D/RUi95[`fHէb[N-.3R4aYd ,Jyd]*mU.HU,UٲhdYl=⽅V,y# 1?QX [O)vT)TUR-7"Oij]:762m(0=' vx8xgWW7[nv[bLq1&J%RQR.Sa- |kX&W;z ) 9>MBs# |*CPvi?WOZ(h9%M4؟x"C\ C%D@hGq8lP ޑW17޲74ޱ^l39%|"(mҶiLUmoxt~6U*1J䅔sY#UiTYZ #7(9Ěvw5('Sf]s/ޟQ+Qj5W9DJmȻkx}4f<>5̙<%%Χ؟є.itknoq;qJI0+AT78'!{҄B oBvݙ'7>$-N7J~g%3R6M[=Fj0,/6ڟmؒ,M7${a-w%[-`P.VeddDf$'njJ^> 5Ym8"-}m[BӐJ&Ɖk-=i\]]ZVI*#͖W_P=hچ?ǺؾVψ(YbŊ+V|4"RY[i(G5SVUKj-CT"C=HmpTەz'`>̹ _D lq1BX}kzcs{ ֺ ջKCjo0hjsgk bW%&LʵrZD 8^!R`1]x{Krzϛ=SQÔ#cL\5-9Fr)i?Hل,aJ AWB+vƳ}-rgr[̃w?>ef@N햇qfG6-dna Jp )ihi[ʕ2rlwbp92#cry 1"^[LMFU"T  [c5Dk-K\5VUZ%Zu1˚45WZ5\d-{Vr{5D*OAq|Xc(9xko)r'hޢV LmùMR3S d'E%W [j8R`$<_,5]ÒQT-%ܒs+t)`E0yQj ҁzNEE20$maTD3O.. Gp=WEIM8fUxsoOG9βq#)N^iO)#s<71iqΰk[Lh S`E!bbigt"HvK!X 7=i",q %y&J&4 9P!/;ks)Xc VIg 02\K0P_6EJݧ9Y¹mG답:{^V:~C.[8 ^)8Bt:K8vw;p}uEuZ+>jDɊ+VXA)gKTR#dx,%-` ~=ƚWVUٱ4ȒȰYāhp*@%|z j.(|U m0m6<xxwwc(i0ꚋVmlvL%ihP32G\<38M,c=yZI2'h}Ü2Q1MCBf(H{4T`=HLUmxRJagL[]G`c-9FoO勗}q8"`yv=7t}zKӴLXÐ"7x3<qHO0P8];|`S2^1F@pwq5ODak:[C^|m)Jd1;Ԁ#4GS(63 +BhQI:4_<~_8B;v;N#mc:oVXc%JVXbŊlYcZE-ah+pUvx[kruY'%DŦkaR,ZDY.X0zSDJPj`<*S+5k%"qYYmo,F-C9}9CpVj޹v"(S2sDf +Qlc)ӈN%nL0;RA60WH[h.߾᷶x{8K6˜GcfڟQ%e5Lst>p{z$Xe q"0V5LɅY qdd="Zn˔2C8MGyLO8oYԶ ɏǑ9g\=%R י8Ov-1 () }2Aii9u #8n9F./hڀwpBDH֯mصX1rssc-y&Xa8f'֒򠤜.o } 3& *R:S*5SxiQ). aT4O%urU d@)j9*bz [yP"w1פmct><+V|X+VXbGUxԿ ^W35`5#,řhNb!05(<,i4눵c6H֬8:ĩ}ڪSډY[!"w4$4F-79s㵡V8`b\ljs nMc`Hdg0ew?W`zg'|8=OՋ1G{7Ii{1!NH\GvxbgD) ibfRdYg*#)Ncd0PRTGDQB[MG }4Ol-ӀAygR)H@;6drj7hH3 "ֱbk$j鄳g,}h }1&!W)XfĄB5C\޼$Ib{&m7X-n/+|ש L28 $sg.v3C,ڀSKL"1Vj~ȥhrn֪L%YX~Zsˋ3iSR"3hXUyǫW8 n^ )Ұ& c~jYbG(YbŊ+V|T0v05)QUK&I|8[VH8,w+!ڤسD_~NA#O g*6H IHjcqM*1ӊ؞.jz)8LUnƪ"8ѪT`8}U̳Kh (AN'mL]qww+gGǑhth֒N#ia7f t. #f`q!&sʯhܑ3YcٌĈs1'90Es#)%ʜT*J%q"eUx$d#x~&4<Gl.*sLu."XƉgri]`3q2 j Y @"l-!xqK isb3Α.z\sSNyg>9Eol%;MCi; R\sI!9_wT&*9 "YlYP>$:Dje<:31$nS!Q(Im [:}=Qkh֊&%}JcU"۴$\l חsJ33B#.xRG,W+iKyHO0(U IDATxzvW\vv]CrT SɤZ3|'&`#E ת0#=M3Nwo~Û"TLmrQE}j1a1* 瀂Z[U C %@V_UkHU`悈ն=+LVBL+wJ@y4-wUbIJNض!JڼE]2Ϙi|%jO|XhZkq c*Sj]Lu=Y%m}sN΍wqF=14ljKKrq% یHy@~%8-׶&29:]g}O))'А=)fKo>Prk.6;|h؏u-?H ΓRRb/gn5_s^/0ř}hbdO߽~nҶz9gHpyŮydGnn1>{ͳg-ÜIΐbbo޾c6BSa6zmn#y?2?q8 5RHJ`a#kzϢvh)I%"U #5fA^3i&?z% Oy&}mZrLooxw|_w߱ -W>@J\:vX}ºbWXbo1ϳz?i`X),3*9JV@.Z_k|n)u%TUmT; V)~> \4I9bB5Ί k F+1{_"/k=0uڤ%gZJJ|׼{8~K~?yvswydW1}cݿsi~DɊ+VX⣁A0IUT.Rij#5V3|;EUeQb4fu@Ʋd|j\dz d9)Aa84Gw |  sU2gU8mysFb7apTPrK%J! b9"èi x#S"D(LSV-ps9ןk9|o9.0#I+{4cMxqgiq3$#!!RCm0V%>j겞刱VU'V5=78,Qe`jwUYk)R "L{rU~?sv ;B5Q2fiYtd5Mw7b3fs~]fe&2i s]{(YbŊ+V|4X+曳8 TOmA#Kx>dU} ]$d6Ĥ|hX+)#F0PY *WE0v)%HU)S3hVXS]8R-6j|6)œ(4qcIAVbPbd,N炙*= j0M0D,0خX pt"0%cS ^6eYAP'v͖ )~O۷ q~FhGu==Apmlj-$!~T,zDɊ+VX ;S!揘\cZBDXs& ڠBAV#wURT.YF>z!YίY_q&JvT$e(Zyc*?T.KrzF+RIT Ri1AypPJmj-0l" Lg%]U2l# m^w@`G(9k 4 K8$<0Ob-!xRNr{8C Zj 3) [ !F| NZjcDsd] IR|C\]m;R\l/qMn7xvMj+xc8kqf}_׿ yZO|6y9ӀHƙ 3LSp/68k)*a\TPU EEDXJxVCE*J.5`UI;KKs9ΤTp֝+5HP^ΙmY*R[Bwwo?`pӨmBnn*tu`TiŅŸbŊX+VXbGma*`˨ʓJ6,Aǝr~T#KdjYϚlJbPPJ)grI97,v"kb1*RrJ,Kr-"jPNN|Sf83H`y9(#0-cvZ Lpwj1DfJy%ZyR=aB SM$JŤPc R4Zf 96%[aH#4semNbGs}&gKގdc7"iFg'aBrf}KbRŏnx@#Z|45TjiK?'MJ)5ٜﺍ4X/Xe,>S2MkBNIB\%/Wio ɉǻ;qd陧!KauHќ?s޿{sTU..]W>a%JVXbŊ 4,յJ,D =Y%SpAWݓE9K}n7O,{UjќT-TP=BМH s$mI&0 `mUT"蜹MJ(!am9apt &`0)1tmh渜&tjv=(8Mq:WIg%0 Y"e<ٶ1I|La!Ƴ%!EY0]i4oj\!! 83؄CNAp֒K4A-?9%l]3Áޛؒ]g~8C7\UH!Rj~i Ȣ%JH*֝s:C֎ 4l~E$XyNd=1D Blb'WOR[j-[r6dQ =z/]J)\x]_Xc٣K:t=U*S*L}|=W ݞwt!w=ϟ=%9%w_U飧L THMj p0B;ТV1dvԪ|πJ5bj=V|oǑ{ī+kEj]--=%'j{?}xy'p7}CWnfѕ5딌Km\Y5P2,2|2#SeUͳҢ,b џ rRi;ABj. hU7_JH{m)m}mn\0':>@*Wkzq(@oX4Zl&M [844a'F:ۗ/OnvR1`l"t 65wL*t ]jT2x0%l7&4O=GnmU"8 @iH R~;`8c&$cN+Hc7&DqkuiN}Yci)#8h& Z醁KW jmoPα" q$RS9ug<{n8&.yqq-wT)D7ՇadGx'UbhpLR5x #sxruC%9XvjS 4ү<1x46~-210:hN"'F*x4PΑ b1iװ41qLk\b..oB̟p8A&PsRj5Mk)Rs%Ǝw|ŏS<~tE͙9[8?;Ç&Lp&.Qyk8.ћe",2,t4MKf>0&CĢ%sK6ǀB A\-pb;'qg"4P:W71Dv(BzhV :qdQN19p5I<(И }&ςK.aB7=A/J zBkGJ;-4ݣg[UBpbGqb5>ZTۯQ16G>@Y.'[w#hA}hh-Tj)d`eRDSւ#G}@ct A<]okJU憀Wb \#5θWEqhh bubZ׀unޗlD:תjqyQrv{z'Gep?UIX+Ipa}lpg[ݡ zj)c"PUX~ -#mU5W6IN2OX@8\M\dQ\tR)s I)#qB)pCp>B;R-P'#\W LK&#LP\X7\=3!F~b_!'Owx9sw8pᚧsr1 &D%g\7f'KƕbC Ӆl@jɧ4aʺńNd'M q'8,ZT`qˍ@j)V7iUj7_7PKc$%)"x90Qả?o?^n}q|p<4M~q9>Ҕ I[fe>YeYfeYәL!)D11D-fsQ&WcMB]>g1m -U QbkE~oP613Xb֚.*o8U!ҷEb߳Qj8Lٚ`BD6gs3Ylʘ [j5KuC bDboqh1 7:4%_ >*xl98">FaD)ŒM)Պ`9n d̔}載DSعHNHMZƶC ]0tul1E6<'Nayl5۾c=S1D Ω9۔] OarSɸg}q:~"<:=~LyZ[nkq4qCk%8G) -b1Pś\6cÉ+R*%-L9814Hm, Y`N :;[~ 8$+EV3]y9WOsqvF"/?~x`ct]Op.tmq1 4rL#q/xuVkK#$de=%,2,'40HgcgU *xyHhM@sA>٘(AcXênݩɉ b6RuĀ' jbGng4Aastф5aFD\+ |'0o:mgiDS^D&۾ UJ&ߛk Xr.m"cyCzWZ u2mM:aN1)2l lZ8r{)8ǑG-6ǃTfwsv 8d?8߼yͳ͆ _{cxQ$90ལi:R~:H#)Mh-o,#cZN-ijS~ǁjo!U칹^&281\ >jlTf&8A_~kG?"v3y/>_iJԪWk~8Nyss]fo,B2,2,L\ PO``UQcL8(!sm5^q2CERu b̄@cqGoKi|!f0 {sT <ȘcX[Gg9J5>vg^)%PC6`"ڶ** wbOYT8YGAxHN1~q/h)9pIi-es*&b 6FB'T*Bb6FJ UpюEJzM=Ck=yJȥ8)qsHfMtUZHV@#Y E+3b^~z 5Ot>㡌#0Rrfo8T#x8P^\K^_߰^y ;V4q=bi2Ln"វ2&ʊZZRDP Ο;\ ']"Mlc*;1QḽIbi\k={2 oݩ9ij5fb\$k4[y5]DoBsBfU+!va8ON8XybױXJY3P2,2|:#3r5r )?g'ˍ]@HԻX&<0> 2>ھ8sqTi\ΙZ3;G#:fEy=f܈,&7.6[$FjN0[ޢ>Ū%xv 꼵{81f6` z8bќ/!XO&Yə:UwMͥӸ+} aclZ[qc˥AZrCt`Ɯ1@ Mb{4`J1BPpI#R ^/pZB  L$nnn]8x3wy|w7ycHNibZ;͖@*jM'oXo6V+V9%j8n8WbY.rǣk9:6 #3 #'Z[,+i\S$MAXt%h)rBmѵX%ET؞YV7׷zD澪j2zᰧnW߱ ny/>o{l)?i:aYٞsswja=JY[3P2,2|2(#0'[ )mq7d]\ M$iV~*vpjn [u‰ªaux!V_bCpv`QRij9EcXۏΟ_yx[V5 T&c = ơP@Sƅ}@ۇl0DX CؓLQ &b\m)-O).6wM%mՉYa Ԡt>ĻSBc 9Chw;. ;sGjcdPV ] ]$zxi{YZ{T~Z9_8ec4ѭ~ u߳gx8TrAk%Yu?߾=%MDÁi9l/xݻ~+;b\,TAUnїvZN6n_sTlv ժݶ1%gw*w%K\'-&?统}[X8w;v{ar8ng jpqq~N J\Wa釞ŋkBge",2,2Hp-lj8if>PaڊmG3f Ebۚ9'-O8U6 `Im7U7#Dl6V= & 84@h_jnmOc9},D-%#ZNGaCHʧ莦b9s&`xJMR ,+W5w8 +\̂W[\7 [P[Lhm@!$Y+Nj!8%'T6+HZ{GB7': @#Hi9JUo'B %2w-ݞ3qZQ0fXS"4MVpwwGa5EDp!J%#%4%~/p}t8́g59;cްl|=ȒQEbBCU93MwPb|ӽ'L*Ug2MhPCmcnT釁dvׇ=}?#-ՊJx80MV_q&?Oyz~ƣ *ݞ319W^憕8;jwsf%y2ߢYeYfeYәM秱M6k(3դ '&h?f1B0xCkiN@hNrv?` 葰؛[6GUY5-9q"՟$ZksVft1QF7PM,ʭ.wJ PsVDm?Jj@bDr|Q I`i RP-bDR1T|b p 0K#Ajc$ՓD96P廙s{_s$iJv޺a=Cw;HɎ(8N|z7L ];s ǘ*{'*.q-19wL1r8Nx8C:PU1q.F:8Z*E27 Q1'~qG9/Λ%(׾W3uK!'dž%vUib8A i Ws3W1I'VP}vΝ#Jʅp;o^?C=GWKZqF&.۷_Kٮ;.Vk(qg;/<={F-zzE0aziGQf2,E(YfeYfe>CڂJs%U- ڜUꃹB>k,9 -QhEjXdvCEm9>*bbiO?/Z}ՙަg3P[Lͭ=5v%88XG7ǣ=zJH.hZ j610p5FLDZhlT[r]s[{1i$v HCN9nRH.1REMHsΘ.w z@ z9tb_.\EH=%sT t= }QJ!Hv, DpB¸?{.Ή.PSfZr9pO& )w;l%vAC IDAT0V&i%䬵&v\ 84vtqx-ٚbJArmBiL_4aq`[nmљ_4ID39$d*3G]kUr8g&UHS&BV+Z7^c+>{=y/=՚)|5cN/~W3] ^DcݚXcW5Á q>ɴ},-2,B2,2,Lm_mѭ "3~Ҟ~b?ZgGI6 VZOwl)Ѧ $7[$EAgCG+Pע2JYUԀ ؂~v`E!-cIFEe5!jM5#/ՀMҪbm1Uiu]Gki[)3M)ل-O&j"In6Dt'\939]4F6]o!RQ@GUn#G*OqPs\l(Sbs8v{@q [v{]t\]=aޠv77L^Q=%gؗ w! <.Zlvm&0ZMEP|?K)8!ȦjZ[irjSJx%_~Ώc)JUR9ѯTU!*??'T'|9U:n%d5ˆZUу(Mh.֬3N&Q!guESja\%NxaDTHm0Ns_HlY'RNZ PH hIpǑ{Ú$fk{y ??ClC8 eCžd7?4X зș @sB(0;LDvO89:ˈ {J)h<}f68s~4rg\=yx80NW9p8n7W_z3ZmK;ap/՚iJx(Z[no޽>-1vTLJ@&(:I_mn{_2E(YfeYfe> X U\Dpq0@eh8w x RDun錗A)&l9sbR͍'D 1>R:gNȇ=Zܨݞ8Ǧā=;t<"#q9 wXzjBDȹ^mpq>n#L!vs~>cϹÑxǴG$KVO)fAE_UUqIS[]ԏYhr-^UU)UKGN{]A_gumLzcњgwl6\\^/o޼{~ s&Ns4%nnny1CwG&TK(ǎeYӟE(YfeYfe>i/3;@\s>Hsb7#Fzޙk7lj- kTS{f kn6Z&Gd1 &:8ci̍9:^r1Y!X G5HQ(x+Զmb‰r vN}5֙BQqh&Tl+F`֌(<);Kvv SctWSt Ksʌ'&DtJJ?ܫq3{:ʼnO/'t1Rja?0fޗʶ9R8wvsfX ~ŽiBĞkv;򔸓;VǬbGJ^◿ >zvW5_66*-]ߡ2N;zGz?ܾy5^9TM|J)Q]̜s8o"[vVrTDOd.DN9b+5k9+NŞ,Ra׼}i暧Tp@⹻az֫Uk1|{FV}w{+G֫;?B7ag12ek0*TU4n#2,",2,2rh[[ $maƷ(0j !UN|kqfw%27i \_VEV+^ql"˔8Q}AbIp'TX-&&$x;`w0CX:h&(BuYo-s8֌l6ЙK"U5Lp&h쳔D ]g܆T~ ʩ9H7éXVf E-ƑpSгĢÇ< 9RpQ*BpC\̔isBЊ#G0\V"#^=FJa<xt4gRXuoHDxA΢=WOS:N?|C煻=Hϟ=cwR_}Û >Mxq܃En aEuMC-v"3WR-dLN/&9I6L8NX sz<7\]]#nns[bxasveHi"BZ2w\\\PJ>D {j-t}8D+38OI8&!JľÅ@,̷cdeYfet$f(ʼp&lZFi #18#97!>͜Dh[iƴ]qړeG>fs>W"pHN)GgoBP1UCXfk#ÝX9yUԋ;h$MXжMɾ|u9r&0YRqehlExfK & Q '6L#a&ZL} ]+1慠Mrѣ1W4%)R2ɣ9G$e@;4gnnlad lܗ\  !r0t5Wn7[o>f۷iD'Ps~cÕl ϟs-aǘ82t|=gz7%g]81eJ1R&W]knV; =Hd*vYfvcw%5탽N*{!֬D{V~o&#L Sj&zϻoޘ<>\|#VζgvEH)!8iȣOq.VLD"*¨b7`ԧ?<,̷bdeYfetFhBY&8Bۣ5 ! à[̭*3ABӀY6*ࡧhJأ8$͋@kyќU;&@B)b=Q5 3(FODW̱Zlrc*ҚgjV&x81Km d'#J[b$ZRB1k[5Td> ]vbpZ'-C@|@Ҋ5M~ @7 J%WeZň"V+B>\o9ȕ<&fDXWV+t[|VG#N͖qsw}/%;>3%[(ps;c4gΆvz:8)!ZU^PJv c׀`HM;@RZ~MA,)XMi9BUkZ & %e/+J|? qRr¦?Jv{޿{j(p<y ~WϟkG +*RnXo_\r<jMB JR҄^^fe%,2,̧3I)mfvZsܐ270W#}HkiKZGcxhӷ^qQ="i~}29%7AAxr=9d@}2NV xB`F[Ÿ!c#ȝTL#sn jPc`GTL6 Yc9t6D?4=mX*n懨9䢊̢Ek</]#E'<$xigZjfa:L0BwH 6ͱ"U3&.JM۷Z!5"X̂ckBV8E TRGSPmUΚ ^mQ]}A_.DXw~5;Сb )قnnbK0WDŽYŢH*x1'`'T07;C`b+VdMTR UVUl6֎/ͅф~1 -*B'5{*jxgjHNL:MUAFg\mSn\ ;G|hkq@1?0z;AXڹsjn HqTsyLuXRJ>"Α&*3b<(x#)g4D&No#]p.2'D )Ê>F)jL4JVeʅ{.r{s-ars8>wkTi9%YvOP| ;b+ v[rX8mVf 29׎ޜ3޼xlI% B|ʟ'?UGgt1te6}{^߼5Kz9;{8lBaz#1ďZE CA|C;>yYDeV",2{YYZ}׺ih@[ʀpr9BȌ`x`uQGb4x Bq 'pegPpTN㨈- }Kr|/kc7w֮]UP;wΝf]_>ϳ, W/RB^$z҉p?, *t9D06R}3F:3}:Z̗UPqi?LPZCiF<ɟإ6UDR*y܊&UvT)EuB>̛K!uy[|sUK?֛.Đŧy"1/"TE`HhRb9)Siu}zdI4֙)M~^TǮԢNURi jmŪPh;I-е &SŭxK!U6cjfdETN᯵f*S>Yu]6rVijQlHHsjԵb*4!ht#jf[6p\_Wvz)i2ֶTW邼RQ8>#1H]ۥVgRO7)H5y笼yOLaIZQu7i9tDjV:r^q䰪Ap ckkҧW:ٳ6"Xk)tMG9wVO=HR~!uC'62):e]j8RQ֦%u]^<6,dU[7e (K%x\oQA&rbrsKhLژkE}ɿ39|_SDq8?RsyFvR9piPO+K*„MꜢ1iJaⴹU']jehC i\P[ B* &Ua"G6Hh;_̐L~Ze\ @BU)y>dT)U |>I?$hm<2nIPbt2mzc5X#3o2y+*kMijjs/VIF8NF:|L&TSv1jvƧR,\UIUmeUQi!\$U?e5sVUUÑ|רcU55fD =M:~&jFMÄ1Z[]p0PUU*R >c5>7 IDATs-uQ*ՠt) F(.U8km4ZWnE4$Z׷ۤSB K7&1&CW u1ٴuU*qWy{Μ?K^2Guc喻 ZVâh#2:syaUesZYYI6E)WV Ghe%ŪdRQ9-047&_]ˎpêJ>+~%_ /fBS珤Nc'[ffQ) ;RbRxџ@E]P|&kߢcÓ<j$E;J(evhX1 B-\०A||3i)]/<(uˬHTj1S$>d䖞$qn-jYB qeZB5p\I )@rme909HN?'>ʴBљp겺uVUUʀZ/;Р2J'} yvfg,ľ"DVIB>KMb2NץN("劔{JƤ?bJ!WD+aҭn4_X1*6-mRdNQH MsGdRcb~kl B|'@*Vz_a,a1Ut!R!,dC!Eil a!}/R0!y^S Qnw2M)f,~wmX2)Xz!m([ Wh\]1Ƥ¦4xύM9r$ ~m5M \ZTe\Pu:ZZ+CVWV6ﴵ-YcLf8`uUmYhTXXXѷjκ+~! 6\ee>UL;ũUkTn>c(-99q)41fggTHeQj;/kɹ*HLZ1'ɸ%5yd[si}cC9f3cUTI+YEq{R嬂oUSmom TVW?8J1],J6vh( U' HU#J·Jѿr{:+E;_̫4j.6CQ1 >|r.c\9T}4$(.tto2&iy~W|~B.J~;LƤUvAb?!/ !U"U/҉+QM=Hs7[Iv*KRhT~Է$E.T,vZb2ԭԶD"Cmnv2i]2FpL_#Ůj"UfgnK)26B)T)U^K>*T b(v(簭n0\ck6?yBS%V2@1zyB)X3ZTXz2Q]גRH5XʊmS@`܏d2?y(cT!LmH]9EBVmND]hn9]PKuH{ Rwq6e ٵ5n;sgͶC)B+krUj?QSO5>{& 1tgJrƦ3u2Q)~9RUݳ&/-C-]JsMbI&`׵:N|TMP2&-;JB1RJ0)By#[۪ Wm)uZ|ݥwj¤.֬ck=A X"fcηΉiL0?;xrOiޚy;N_P SKb:5Ʀqs bHOһmդ9M'~>6Ƙ+$f䥁LڦQR%BtQvD|js)}s'6cZ$GIvR(r>kR[dy*h y:[ _߸jƾZp!Q<7k+A'a*Ӫ=K]8i>,+VLr*rȼ(׹BHVPk}uMmuM++i*DMe4MsH$UumBשkZ9cU jgSu+F] g4SIٳ :!k[9~Zh2jiYUX,T8n=V'gFU5hcS>D5uZбCZ<'N=0ڝ #UpX8cBH:QyEWl)ȺO濳HmLÑc Z]YF@T jt]}bӜ~Q !^q G>@{m+k>h4*ƠSөJkAUw>W7rLoU䜦Ӛ!(#KSD}ÊY'XˆĠ,m~[i ( ~>G% G1)p i( \f2CTwڀҡe!ִ>޷a1q.=|.HYGBƙ)1JFgJ42eZM-y{D}{rc}bbUiaF:qQZ$ m9YseR`Z;<1yHg !UDŽNo)B*m^'\Ŕ*jL*(A]7CGrxkVFicڶQAdu kWQZ 5ڨ-5M'g6dbTh;-yUÑNyBu]k4i{267'F 2wM&Mcڡ5x<9r2:穙L4=>Ղ6d4LTAGn=juEۏ3!*)M&ve&(ڴBr}1ܾRCc0V]$2UAʹshS(6u 6 JH=1Z V7N|TPPuС~6RVʚ&}2xZ5Z]YiJF4\UO>3[6Fˣ)Q[(9#}uC^#mkTܒ14S*RJT*C,̌zXwi>SE6>)(߇ypH3JK"=sV>.;vL1FMp4Pd`Pkuyh-Jm9QeS GE p`W!)ӿOjCס:TKJ3~D_|P@ΥJjbj/qvg%6x dۼK(>HAj)iJ%S0}'M0W47pi5EE:*7o)1m4* SrIb: F; eد@JXX6UiR"-U jDm~qmj=QеZX׹sgtѴ1r. gmVPy,zzVkhyumBiuc=}EvV+Z#oӓL]3K֔E!WrZ#c]I r+NqV‘3F4o*?_)J 1U:9g]jVEiZ匂o\Z-g2H7憂ǚN&z?_eY(vR]OURQQqmo5L5Z奍|<J)6-Lac}uä֓ΫBzN[w|euΥ6GMs:(6l9HU't޺%5erDA|՛<_ʑ4Kiu2*DQa>n;5K!F2M fsG2HSIՏ~y嘖SZQ6-k \!RJYUe*BTѵrLn֨[UzUj}mMUYjVLU3J&m7$S?&T d{[HEQh|ڮ9ukUΟoҲy ,NOj9JChFRp{,?ku# N{|(vrVpQ뽊PYV*2Lr,Ә7+Vr?lsgicc]kk(8泺qҭ\xWM7S"6O!nm'眜s:=UNEYبག,笎$^4{\ku?gjO؊gӟĄpeQTw ۯۿ;j[ #(J2fn8c4%^l}>ۿ;_ eSN)b,> 1Z;NXkp0,ሤ Id׊p[ H !\P_b@" E&Zn(b07,ݭ5oxZ!(*vZ GC l?A cDPa\dw`$xn(q-nH{&`! ӁpC,,O}A @FPd%A @FPd%A @FPd%A @FPd%A @FPd%A @FPd%A @FPd%A @FPd%A @FPd%A @FPd~p1.\ƘA>=VA Ofڶ=Ё"cʲp8cpϰ`0 ^e߻tMm_Lࢪ-:7iOvl؞ "(A۶;նݹ&1/|A`۴m_M@qZ?{x3бAo_XL%>NrnWrL1Fy3[Otk a`\'WrLq_/BTϠœuw^.1,+`\%WRAP,>.q:}>3̾˱cw[+g>-Q~o?iy̽!hV_+r(|@'?i z[}:.P߬.{<\5z?G<{K]~#/[v?TKZ=ܣ__$}}LmjssS|+=O=Hu]kssS=ߣ~ovmll{?,I2u{^ԩS?drys=jgE>Eׇ?>o?yOVF~/JpN~SOΏU/KϹf=~>FHoߤ?/ǿn=vXo>ՑL;EE N8nM{ww}~X1FF#o^ܹsn$mll{{GǏ+_Jʊ$]u] ox~~MEQ̿MDo~o)Vtyi}7~Zwߡ|Z[;_-f u1'_Ϻ$;N|?r~ߩ6$Im) C(Љ'cɓ'/::uj//SuL&z~P'uq}z _iP CIDATWZ??OwCֱcWJ??{L~P/{_c\NO꼟_on=yv'#* 3l$һ߮7/пxq}pko~%I_3/=[^G;{>/{?%:}1Z__׹sMu:v讻ښF?/IzG4VVVg=KX I> Iz+^~~q,()}G_ݗOmoz~_pϿ^7kk{Iv^úM^Hqr<ө^׿U}g~gH??}-u] 1bZ]]$iuuULX{/sI㱎=}5\/=Iz3C.HϻV=yv+;zxC|bd:t@A5_ȡucܧ $%Z;w]zߨ'N赯}~'R<ө;x??S4zӛtE۾{5E9uG>9rD_r:uJkkkz{ޣ/th}Eo/a%ImLJNow~}KT}&__Rcޡn>:YRnVF8,*J}Tڶ;N:tHM~7S1F}S[}C>O_ݽٳz{߫;5Mz$I}{S?Sz׻ޥt}C:un+(>x#zK^~[>~Z|zs~_y~Z[/ ^~z*?td}ğNzwW_>V~.ea,\"_F&/}K_ 35ONyΟ?ɹ1FGՙ3gx[>x.ޡCtܹ sҗI#!\^W3T4\_SUjڋIrXO<[nn 4gZOHڒ4͗ZLR/^ء;IE p\jkQO3_NS}d/+Y3GrZ{tIoقI}Nyx<>!OsK'K,[P%;c=?*`l %8 &(?_gD%V~tCŊ!$]fk?2_ |9"5.>\]2SJ6%Mep%i'D<ՒϘev%Š*%}XR) d(ip]V ^`,v*E:v3NHJkP\g AÏ_ _$>(i>Q{R*Y$*fv}o,tqbua ^UUh',,7ȥe>Fqt>$j}v@WU^aI ^s_-CPr)av}XUb^ݕ$ W? vGX%}G޽vjj3H=e JvW}:WZMBp]*\UbX7{,e J GV$*Jdj7{Nta;MIKk M%( y2][ƻ8o郒KUp顫j6nx\LAɥJv*K.|NXbt sI} WVfȢbSzA 8D{|{ űCC>/{=RXd/}xD G@nq~%\^bt .U(e /sb>j_ݡy{#{Ke+ K-~~Ho{[;4?_nnÂK{fcvr{۽w".R.ͥrB KoװVZn6v{#, \}fXϥ^nhR$$\n Gx]Ɋ6"$np5M ƥi.wzczq‘Ekp@"{X֮PWAm@~IENDB`Akira-0.0.16/data/screenshots/screenshot-4.png000066400000000000000000007240201410625726100211330ustar00rootroot00000000000000PNG  IHDR|Q.(DsBIT|d IDATxw|c6뜣.{=Wf)6첻ټfˆ$@HBBXH)/! y zaދuEtι?didY%YGžؖnҨ\ QJ=(W((GDDDDDDDDDTnfl>v{*݌ +9fWZ(]i%"""""""""*&\㬔!"""""""""*Re{h\$"""""""""t 6X/נy*EDDDDDDDDD4[L7/`܂|SVž\SXL9N"""""""""(;,Br sTOv˜t.KCx &"""""""""dH%(/i^`PAQ ݉h2y>X/Uh\JRDDDDDDDDDDeTxnd/i)@=6:=Q!zNu*EoK`'l2,ٞ붹nS0 '6> ܉M7N8>>m p>W ҥ6"ii_ O>:SOq~A{.O[iKU>8fLAuJߓt=vn,)F\0=w)Nv\ ։h&HOu=t|Y ߥ  L"t= t +:P/t*=_,LW01`OW՞8sنM'HOtmw=ate4M'V ?lBDDDDDDDDD4eF 3]$oxO\[i!TU2U K?Mkk&%Q^ªt !Dc{jğ~Ow|ĪtO}S}iCד%"""""""""be,CQ/}K_23zr?=YEӭNOhbwvvm۶UUm@DDDDDDDDD4+I}Yg}w`b"gLz=//ԛ*]uz29iXhyꩧ>it"""""""""2"i> L7V0 L^73lsd;PƦROX^e""""""""":Z[[Ѐhg`NQRVg%zl u,˝aV8ؘ`CL&V5UE+ʖ?Fσ-ܮ(h, cl̋`0m"˰mrvA%2ڰhѢ$L'=ӵ)Y^@=bNK SY!tMwoPW_&Y`v(" ޑ0v#Ɋe츋cE3زS9ZPUuw˯wUl܎RJD eZADDd]A(jP @PUn,`qm=uaD"*`Zu@==0Mh,xB{nXviCOo8c~/ `K 8r  x10p6 3sQ><'NNPO$,?K,,fH$χH^\uUBIUUObѢEB`tt. &S971Tl7]Qu 5\/=˳YT k68zFFFӞ_U2| tQXZ;dGH%Xt.Υ 8{X*X3XLXLv,x!2jkkn!t  DUem0 Yp7bf$ߎr/B!^ t`!""҅4X֊Q=euv+8]86<ӽ0d Bmm ?ŪR%InÒ%p TxtzbL_ !oˉZ?u c0kٰtH&̯lBcc=u}}rsI?iχߣ 4Ɏ;޾e", +2zؽ{7N't]GGGP>`! ( <֬YeIgl7ibez;UoT PH6&=++"(?襣( /_> ]D,P׊Rc䷎#-]KU__};QODT1kѐA}_ST :=4#XRPs4ƿ=(%dcc4MK2#C874XЋH=òF8u %XVtvCӴ;'Nt~ˍBSo(4czzp`Yx>mxzk.lܸضmz{{i&h?@i6mڄ6l@ww7m6+CuDOEU@=JL^i2%=rDI,O:b@wzU.Ck{T;ۿd~_ն{p]wMgXT Fo@ l?CVM. Gsb7`^=zB]][K1 7gtO歂/QG=QG8w]!/B^muWpPM'}#B(m>0hokBw؇-|hklށͯDzeKߎ68p0{DO=e1')he6 9 )`׮]ذaZ[[ ~zGb˖-vʕ+qEAQAbÆ ؾ};6m4ڿL{gjRb[S DEIg'su^itE{~?F2'լ]FNksah[0dzg}ָPNxp#Nw^# 4p+lzڽ/fo0SfH(ݤm³EHWA-3A. x_OjM|B8ݗ?:aFv~'azCB!XRffZdRez*A]Ũʁ^\E=:ASS#4M˩i`m,x{iŨA( tpXK6 Bd=cc4y~U>O˪fQk`0x4M2*>vňO8;wk׮Ͱ~?sN]mmmuطo^/jkO<}IoٲeHTxѪ׍W<zr?Y}2 9KQC{vaaɢVx5ji~ -8q4/C1,r`4 =~m|+_Accc/"\.jl޼ye3F{{;p@4|g>44ǛJ8kqګCM~I0pV;q5;LaSlh-Vri咭\Ұv,:+ !$Tϙc Bk]ixm.N\8i@¶uӫkӖ&Kգ~ߏK/tB{=z_܇ג9/~۰yIwww?9ZX1 c&?N8{'rU*jadVxL fEo0DKssV$h݆SnZ|zlvş@ 99ϯ>|~[5<~ 7| NFvF7~ʍλ&[o8t6lc-Z6۷,c޼yx뭷&쫜]wulx ;sX =&7톆}LINuiO}݇ASS`ppwnF47Wx vjB7l7D2lpa'9%K?nVx^  {O೟,?яaÆ/#<Ʋ y7`Ψ_Ƅ`D} دM}>2FPJRy9UU@ȇp"Ҹvc7{+[L/7lW+G}ؾ};>{b{.ޝ]o}[Pw}7`޼yjժAl߾^ziݷo"y{q B o4v]Ж/F$ B$#Gj*X֔-lXr%:v`ܹ~0 s~x4M&ϥRp'K'(ȣ?!ك뮻*```<oj {_|`!$.Y^U%;}8 A]ޘvGN3PP]]]˰~ e@?8/.6l0@t16`ddK/'ſ92L2<ؘg‡ G34O3T &WQdJYR߶+ao#YzXư7,zFy,^Xl00w0zԗ'q n݊ؽ{7z{{q9`ʕxg188Y_]wFGG144!O]ѣhjj>l6gA ^IS|W_m|q +H~i;Dag3!1|hx σ91߿moo%͘@m}x̺/v}O `#P@ۇ`iG$#o-t\> p8t b~x<{]~;vsk}د:|0! 000|5vx'Q# l6g}ݒ$!@QJ8}ݡI۫jxOCk +7-/i 90)t^ D]/ 2qՅ}C04 C}}=t](3p߾}¼yi144+V`h"C[?044f|{_g?yǷOirj*Ջ^V@ɡʵ\.~[oѣG=^fգ!w7t5^&|쒠jbG%X^c( X^(&T_{OsNl۶ wu>l:u _|uuu8r>+@WW>O/( _`/qmQP  b1H](N;4%l}/#I>?l6sN70.!! f\x1%yhK=T$Ib is]]A\7w|DS*"@0lb*e7Fk̘01L*mY3M6˗/[o @UU(YgNgK`pף \st~6ۍ^vSnzEHSUTϋ哰U0}u](I@DEtu P5iڕ3Qbv%r\uP(o <1ضm8Ǎ7ވatMS(ꫯN*,hwWAU@o1eR$>:"hhxco(񖳫>?{OV^3lWex}ϻK> IDAT 9 '$I[] } v=#E_GD5XHLG-F:}y.7ͧGw\u=n=]o+VE[[hĵO6?qbUVuuu.ގ`0n&iv"f6e]b < W<(|__~ࢋ.~\xc؄9*ߍHiyLg%y= VD{Ey… :?~7^EB-P]@jPPS.7 \C%0{a˰U"*vH㬳8pY}wOcٲexߍx,uʃHUM˪ƁQ as9Pmh uTqkRbLdS-cMpywX2 o]?޾-l.ãX}V۪!d$١߆W2أ\B$L8gޱBVUUExpI`XolmmpyM`X&|$%R͹P$ +UpY 'RebF8ҵxule$I(?jhz'U+2LvN˄E Wwd p-zWX3׏mV$|!@t]סګѲr)Y뭸|VLU^.3k/niۣk`߾}oV۷!2N', %no~EQp_*`ZqEM̐g7&Kg0 ԋqTEgg'[nAww7~բUY6UM&sZHU:4)|$A4kq_ѧhlly睇|w}7e|>_)MMM劕KUD[kE 8:CQ89,XhAK5wvi:كukW{u4lX芏w}u'{fnED#I8ÆHt\4I؇(Ђd;Վ w>RTAS ?cXǿQdEQR.:M(-ۀѷ"a6[=FBVknj͛? ՘?>x >|>l6N8}aŊK_~=V+y\wu8~8~_իa2SO/^1aYA . "ɰ2LC3aٜ&Ct-_`yCB81ꃵMm4]e$a`4ی 2̯`A +W$ B$ VY ̅E۽_{O =T+C8FG[a2vﺮ# " _$Pm~?'ܪøJ$ sgk׮Ess30 ,XG7߄mmmX`"'Ob׮]yV_[lCKK >q5Y>=Jӧ=_җzk}Ľދ{移+pȃ6sXC]8a1 Їy-dm򗿌/˸ˡ( \}Y /`xx8^ze[n~;\qE=̴D6p2ERnST ꚦK/aUVJh먩 E`UB6/˯dgJ񭘁(9P#@,T#?UZr!-܂o M`puk[ pWw܁G}4pw?nFȲK/֭,˸n%\QY @DSXnubYpP4{PEQ 884  :dIC ϶oU6EI/V4lU1Á0VZ]X0& dh(mtbN`ATWUbpn(FFܰlhkki$E D)@oppM8vnZSKXx1/^!:tmmmZD"PU@ ,ҥKD X@f$I8z(:I,>. wQUUe7s]p^A`3t>Mejz^jjjp@t1ʂ(tnlzC 651Tv'ξP[}JfUx u':ً0lܕ}/})_P$I"*;K, ǃ>1llϿ q^t)~_󡹹ٸJArOLە*^.W]]FQFmm Q֞Oy/zf6+/.:9e~c$Iմx:4 JQ_N, nv~C]]"HҥK#@e<񊵍7C8F8FMM̈́:~ Y/b\r%D"P:"'c<[MEpЍFٌyV;ZPp't~\U#:Zp쀱*B UUU|.cX_o ]]]/ˢ:׋'x rBN7,/gl۸$POMf:M847@W'/4#$$>렌?![/)B F]Y>NG1c0us=Pe>|OrrT[.Jz"sj+/8~IMU's6{ꩧO^0)b?xɄߦkַOgG/xM|q*r^Fv~і*BMUd,ˆ>fհUmy^:u{zgſ3!DÝdMUU %DDPu=EA(0籅Os6U&}<ͥB@"$,CQ=_㟙3˲Uv;.;ޅΎ7pX +&c+t1* 8lt$o%(X,XiFcW EQ 5տ|z=f ߏuȲz0Vp:A0$IXb^}Un֖gqO<!DBD =,X ߨZ'~$:̨M~X_TR]*tFu58v+IP__6jjpъo9X,)mǷ,S'xbCkH,>xD=_/rtBWDRVr eBCuٌ77߄hnnƞ={066s碵5~EA__P]]+VGMʪ]hj|lS){,t*TB@$hLS yѥ G Muhc[_&%Zh \&nMC@>אrEm?fvU09y_Fw[%Kl5R.V.g~ox$Y:,e)."DJ$$tTz.FZU2$UUS/^>ўt=ukG}ʍi4M$IX|9y:t,;v@SSӄqرK.^z%D"[$!ǿ2KLugjAҙeA4h;l,SE4afTsڂzXf-'E !G5t3jPB˪P(ZQ9 39Tuw^~u;R/;bm=ިj2`Ҵ0CpY_\J_ɂQ56K&cccZx=`ncyi]lA%WXc,Ml. vDA|Ox @@@ @O- 'D3L\t ]]] ԩ%~P`Gg3]g:[bݞ/DDDDDDDT9dYܹscz@ ]~&鴜K˗LMu^hvHt:p8t8lQ9Qm"""""""eZEKr pfP='VR=?Ş ӉT|[:ь9֮+~""""""""*J Գm C438eH;}C""""""")Ut[ܕ'hTY1LDDDDDDDDDDTd[n-_0)B.HDDDDDDDDDT۔9o +B=Y """"""""")U\[n- t]/8(YCJ4_x000yz(DDDDDDEq 477jz(D3$IPVZ.%U*ԉbʕ QQx^,^.C!$I,0LLVJ ԓ jbau:48l68R(l6?,%'&a:4fL&R(b9X/Bgn\%I""ʃ,ˉGfg ~"*r_a^:Q!ׇD"R"fףe@3P'""""""""Jߏ@ % Q"ߏR:P ӊ/yoSiQ˖.6l :tK,1zw 2חb=Q9+wYDDDDDDT\Xx1a2(kd2 gHjDZڠ4m AS5^"6w3Ap\O^@>uΦ+||"1M3&|}HmqB4^5=wP4"N'tL&8&iV>#j χdʼn}RTVw VFfXH5d>. buZ`$I% R,D_=pZ 7"zdUtCODDDDD4[DFnfeO*ac.?1]'ӊH`!T׺O4 yP[0@ΰut:в*}{ XzҌqK@膏B0F}p9Np:|p&yr:avaSq!z4 J IPkVHz eA ٪:f!_FCd{DnqA4f']X fG`a9ߟ|Y'@0G ,kG1BM!Ą$udRdk0`%i2߻ &w!4\^!/g:<8aBs# Q a֭ؽ{7P]]5k J=<"2Ȭ ԁhH&)L i04{|7pA3̏>Ҳ N8ߴc:|΍(1[mNbcyPSgs -?99d !&FL _݈1E'""""" ݋zЀA7OX"ZyDTfg.bؙ&"!<idk6qۘ\yِ(i2:Icu얒U@]I·gVA2ɱ=@Cww?ĒHu`rD`xw-.z/{wW5!ⷵXUDDDDDDt z!\|Ÿ+' O׾*?X,8묳pE/K|Sr?q\"@=^juat auENlLM!XԐV)   χ}C )g}'mfe U9)Mzm. kW'83+g>L~P +ԍBK4$! A-8:’V5C؁]׋ZODDDDDD޽VKw]x駳g8ƁpM7[644mx7p ΃<oߎ> .$IBx|r꫸KQ[[OSS;- e\zp:hiiAKKK|GybÆ سgv܉nHsV^ŋ^(.rB!<8p֭[łGyP7nĎ;c|P(-[`ػw/>yYߎLcZO<_|]vYۖjD6+u`7u؋z3FavL (‚$teUvkނ]{3U5NxFWUU&P3Bfb)HeyBFUfgji R&pmP__~/`֭WN=!Ip}ݐe6lm݆> _B<8vBP 8xӃ?ʲ /|9s^t:92MACDDDDDD?A|ēO>j_B'ѣGYchh0LXv-~\s l6ϟO~.gZqq???kE__y䑔c31 r9{֬YZ455ԩSio[6D6+XX\6~bRX_ 2aq̹GhK # uaqEU#þia9$@(t$Ii{6qd3+cc(FouZ$NUU٨sAe>*JwqQ_ rѼcf^Riֺm2WfnZv٬bs3k5+M77%)A bVt~>ʻ]wہcOxwk*Fuるy, hZ}+"~C3va!/˵\=*\s,>N`H|ii]qb+P}>*i~.p"pC7FK.<B, qqqq,\4̙Szxx8wq ^^^ӦMƌT,=z4o>>>2x`|}}oep___>~m)((o?epam<զA6mZߟ%Kp饗جVks7WUjjǣ5zU}Wzvۗ'}3j.:փ 𡬸fIj_`]Tٷoޏ|)+6*8WFf u>HKOO'!!EDDDDDAlذ ޻vO>ֹB^~e9BTT'O<||}}qBO%??Z  Vw3eٴi{?4-EEElݺ={b 6 TvF匶:NUOw{3m^Ż]wpQ|5txzECʈLt3 bҤI̙34x {챳~gm&u]388NEMY| v⡇j3=\ bɴm۶^F75V~a"###rzH} 7:F)FYc"""""""""""H-.""""""""roooV+FGi2***(++(Fs$<|8e#EDDD ""b>1c`Ϻ}8rHrlx nv/_nt$iB{$@ZZ'NdFG3ED9iժ[l9~i*̞=X>C^~eK6nht,i{9s&FG9'^FcZlȑ#Y|9]v￟iӦos֭[INNfu]~^{B, &Ls`1n8عs'/  ĨQj0gyHIILJ#Gxlb[na͚5 0>_Vi{$@-?-[ؽ{w}""""FuipW믧gϞ̟?#GЪU+o> :to߾ٺu+gϏ͛7SO`|}}yiӦ >?xgfԩDGGDŽ 8p ;v1ôi֭3f̠sxl+Zom۶>pѫ'""Ys~ ʑ""""M|qz^Dݯ_?<<<6lsӱcG<<<8m[Ç~FBB999}ݘL&L&wuIIIEtt4tЁ3;v_~?Oxxx-RcR|}}m񡤤/)"""\|M .BZ<==Ϲݔ׿K/"k|^D?!???O@5ĨQuֵj+$$cBNNAAA|ˋp=Jtt46mbڵXVdϋW_}ł X,< }]w&S N7/77lñX,`ZlТE ~^}U^xbbb}deedl6[DZcXd iii]ŋ[Ν;W+ 2?OS\\ ((( ..-ZУG-ZnpdڷoOLL T.r[lIYl,_}#""eҥvrssYj :k#""#ED}L0AW";*6ߎG k} n=螓.a3338q"Æ .c|g3w\xg2dI&ѯ_?WOG>}>}:Æ c;r""VXXHBB4:HذaqqqiӦ8ݔ/kʔ)\} >ܹp_H۶m1$''m6nv ajՊ+#G:*++gҥlzN:qwX}xxx`*~o=n9q/=Չ[Pg̙_"&&S ~GDDʅ^HϞ=Yp!/ sgE]@NYNDDDDDDDD̙3Y~=ݻwg޽L:vgev;f͢UV\prСCjm>|pg1*dҴrQ*ӟ2d>>>΅%2999DEEa((( 00}Q>LBB9{aܹuL}TZ`t uV~ǁСӧOg֬Yz뭴oߞz7$?? Lf3=ƍP,:un޽ݻϟ3Lg+""""""""{<3dggӱcGyx7.oo߾CZZ)텆r饗xbƎKff&VbH֋FHH}"___j5yէxuCDDDDDDDD69s&_;5jݺu# D֬YßgڵkÙ3gYr%&M:Ϳolܸnx74*Zvt94Eav )..jbٰl@➞x{{PHS4M6l ..6mڸ׸ry_'ͭ6Bm8ɊoԿ4xxx`*~o=n9ǧ=Չ[N"""""""" GANNeeex{{c61LvrV+>>>X,hٲ%5Dt=gaAk"ԛ"RSSIII???l6׺Áfdك':tm۶QTRA]DDDDDDD\.##{RPP@@@kfZ#GDpp0ݺu#22EDDjLZZ{jL֭4s]CXXlٲ.bOqo*y+..fJDDDA`` uVիҼ"""""""r^Yf 6CP^^Κ5kHJJ2,4?."""""""ji& "Ãٷo\vex{{MDD8P:/VFSL?l&2227:4qtrss)//7:lbUo4:w:wEDDۍ TZZJff&~r, EEE|7 8-ZKDD(] ##ڵk(?o 233l4mAFFF_^ѹ+""""deeѲeKSkxzza/9QArrrԩxy%=.+J-͆Y:Ϗ]q'%%%deeqϏ-Ze yf#H bd3E@@[LyqsWDDDDjѣlٲIӫΆ 4h!!!FGFW^FG&B*n~gNW ##&5ƺuZF&Du9,u:QA]DDDDDDDN+??NXXQ\.44|"""M&Mn@k׮eժUն=SbYt);v_4(;@V7nmڴ9eSTTԩS H)"""""d#&&YN-ADD{uIDD9Ok.[ D=Xx1w}W;wcǎ\s5mdgg#ʶmΫx fpoٵkz+Z`ݺul߾#FЮ]jhт{M6|rfsm۶ӺuKN9""""xeggR͍l&88۷sWGDD9MrnݺG}je۶mtٓ8l&++{wӧ(oΝ;yw?I~~>v/^_֚5kXf1\Gcڷo޽{Yd QQQTTTϦM⋍V8ڵk׿EJJKs5"""""gwqFGi0瓙IddqDDRA-Z v}QAʷ~ 7>JEEPY\rL&EEEFs[ >_fF>{9=z4~)SdjsWDDDD 5:F 槟~RA]jѣmۖ~a۝kqUW1bĈ{SbXxNy.33{}СC2dHgiTP?Izz:k׮%66T,Y9v;Cm111wFذaf[rEp8Xx1\s5\r%ƞW?Æ s'U5wΜ9.i10`˖-K.7x ̙s$&&tR.]JQQL8W^yť]3+//ܭFW K9rUVeFuA&L ==6mt랝-[}Ǐ3aիlذR~TqQA%K=֭͛[ӧy<?̰agܹ.J߰zÇ⋹III!88[o6mpa~.JJݙL&<<<\6UQ_l߾_9 TNo;h"~*:wEDDDDά@;dJ׮]#ؗ_~ @\\ |СC^~dd2fczۼy3[nk׮ <ع5k֐DDDC%""zj222n $$GIaa!˗/nsןvENNwu&LСCdڵ*ロ3өS'/^@OqF1b!Cyf>uv^s{xx2sL͛fܹ ᄇ?888q9vmFĪ59]79991|pɓ's 7鉿m]3+,,t)O8p rF_~%^^^֭\yQRR`ws?2>C|A.'Ndk׎4-Z;Cxx8G&//X>3/_·~XcÇgر:tSlQP9b ,,_QizyւzϞ=(M㡂 9sիV"//`L&S- kEIWObXغukҥ Ki箈LJ M"u8@~h߾=qqqٳmYb-Zd2g8vP9 }ʕ3rH/^]wźuؾ};]wO>$֭Gw塇btԉ8y֭[GRRR7:t+ٳgaLrcc̙1fM4֬YS bҤI x*/[oAbp>QFGTRR1 GfffuD]ooo>q8];ӹߕW^Y=.RiѢ$&&Ͼ}ׯ}d2o>, 6 /8+--C{֩b=ĉ`ن.1L̘1_]+Yf2`HJKK5:Ἵ0:4RU[^z͛7W^keffVo2'88,rDn'88+VK/ /-rJ'Xl6i3:tǓK/D߾}ku,L&fΜIˬY40q4B]DDDDDDDʂI___!Pbb"W^wΑ5jd|;v?$++\.f3 W_eʕn9BxРA=zΝ;SRRr)/RL&V"22~9rǓG~صkv׷|qfg}iӦs=ѱ """""""ᠢltyyyQVVn7:42Uӽ\s5L&נASGoחyU[n믿棏>}L6 VZ1k,˙>}:֭n[ook׮+<3猹;t?Lqq1s%669jdtN!yf,X jBI+œ9sz zlǣ5z¾Uz xv tY䒣8G{K.+--FVEEyyy$&&6utPmqfW EP!AIDlj۟=nNs7hyܾ}{$wfZ9z([6:JƕW^Y6 q 6GtttgٰZܙ0ɩu]< ], 6 Tv{l'rcoOw{3mMᤦҦM\?~FVYY$Sc梼s>LqqKyyyL [,ץt"I.Mzz:XV4Ykiۛp%~:ϟ]iv m'0LCDD]nIddQܡ yrsWDDDD\p᪙a>EDZTDDDDDDDL*fADDSԂ """""""dԁ'"""r2EDDDDDD1 Ál6:42*& c4v]u9]f>>FG1Dqq1۷7:4R*(8+;Pb[ ȭT~^pI4\^@߹+004, FiPbڶmktiTPi@vHu]9*!*|\W`dp"""nl6c6)..&008 `M"""H=*>KFΗ9핣G\vSq]DD݅q1+зo_cH6~:[oS/*ԓxSD?c%/:LDDDhb|}}4:4q-׵." """.u N{Cb9%&xe3x!LW3:4Q~.uA^^FK0eV+ݛÇc2%EEEx{{튘(((瞫v.]ʎ;x%H].""xn=4:|DW-]+_ߟ 5:Nbetڲe O?4aaapB>L@@f8jtZ袋hٲ%̘1YPw8|$&&Ҷm[nFϵnݚo___֬YCbb"2rHrssꫯHIISNtML&?'|•W^_|l[o%$$,Zj%**ʙʙrV{k׮1_VZqƊXt)3g䩧O? ƌ N)""Yb6\^/haؓsN#"""ˋ0p8\vgp88vqqqG䜔|7c uΝ;>y摜|J3ҥK.rV"#< Ɗ+HIIaʔ)pwktTiw0{F1ΊD< _ f^DDy \,q\*77`_o` OۀA[n7 ˤIHIIa̙=<e3iAAAL6@yƎ{DZcN722'x'xݻ_عs'&Mbʔ)<ӤaÆ>$Gip?aƷ*5\dFDDD\ۛ-[rQdMQYYǎ/w.(T]vek׎%Kн{wOvv~(//G$%%?pnfV+>>>IveյӣG]={ߙr4vn9B ..gyuVپ};/rڵe˖1zh:uXp!?OvDD0b)@6 }ށChӈ+ѢE 222hٲeMZRRBvv6#""8".x#F̙3_?~O3m48v<*L>y-[ƈ#梋.U___^}UΝ8p  :e3iܲĦM:t(ڵ]vxzzl2'q'`޼yߟC:W3SHO03(9\P97m݌N#"<4Qظq#aaaMEEE1p@ZhatiƏ_w҅oO>|gZmz>}j*;Fhh(wΪU(++ۛ;Gf~kVpP^}U~SL9OfXN9neALJ/3|pJKKo#22_չoYY/Tn#55e˖q}ѽ{wODD\`Ʒ0;p ;^{`FWjѢW_}5=V0#9rss)++ꫯ4/Rz-#8>_+9v;&M{tޝ]v~.s)eAm۶L0%KK/Ô)SрE /s… ࡇbL2W_Mn'"Ҕu ̓x;(‹FDDD\)$$Ci&233 61ldggW_47&7x׳w^YhAAAFGq,\uU\uUUN:tRwݛZpPPP@~~>ݺusΆq' 6aÆE^mA. uI;""b 0YzU5_Eusδnݚ۷FhhasbaСCDD'/LR01:?W\q޽| " o߾DEEk""TPNxa)?Å0IDDD>DEEEFF{iR(..`KddK9 ""V.N""""^TTDjj*)))TTT燷7uZ$p`(--jRRR۷m۶M1#""Euq[ZatcKa8hltOt֍nݺQTTѣG ++ Պ7fOOO<<}0a_o⋼l Ǐwi̝;Mw^Ν˯z^mggg3vXmƖ-[=sN:vȸq_y97}67UEYiQ3i*l6ϧwތ?X|||!66 &ЫW/ϟf;>MƤI}%$$PXX?x #GlgM61F$%%qvʮ]HJJe˖tڕ~saWV&MD`` ;w>СCtؑ]vkѡC:w̧~Jrr2ݻwO>aҥlْXvn~>}m6)))aժU\q\x|ᇴlْCl֬Ya N:$%%Q\\VPP@RRyﳲ{ڵ+#F\zz:7tqqqն7]yBկXX, 2 :6lUW̭[SO֦M˝W̟xUVFJJ O?4#''89ogNo DDDDDjo˖- < <[s?^x!ݺus~v_FBB%%%|:t^{E7;; o{nvA||z%h:BX,#33qFrrrHNN&44VZ??wߍl`ĉ}|Gv̙ǎ#T};# 8k wy'3f`ʕtMĜw?':thFVɓϩ3y봿 7n$)) I}ٳ'ǎcرQFl2tE{bMF'Z $k۶-iii sRRR¢Eعs'C_ߟcr7ұcGyNJϞ=5k 4M6aÆj\tE΁v"͕ ֭6m"!!///n&m޽{IIIw.#,,ѣG;{Cٻ*ʻd_ D E6" ⊈[֥բjq)h֭-U)u! 7eQP$; Y6i|<ș93׼g$Ϲu_τ HMM%11x< `JL]^^4MJJJA۲e {8ީ y8p ,X~G݆]UýyЩqDmqs=izj[RR-B׮](((` :2 Frr2}!>>|V\ɴip8 0k vرcx9;;իWM7~3:wu]G>}ͥ;3OEE*KA۷tk.." Tdq8Ꮽ߬\oU~ѥsN~G=\8eӧdgg3ydvɌ38qi9ݺuc˖-t҅n<>|8YYYlٲuܹsO>g]bo+ٹs' ._}G݆ N y.<')DDDDDNW^|'r딏NƧ۶m v뭷2bV^ĉٻw/;2nܸ*TU!QAڴiCNNNwoΝyiݺ5}_J\\C (?iRTTĐ!C9r$cǎe̘1L6 Ͻw=?׿/1"&ǜv30 ~iƍ/L ]v'En`ٰ|kSH, 6ϸDWyyƥ㪨v|W|mѷo3>snfJKKY`w۷ogҤIo߾X3`}YK֭)**^ࡇ5D$+,{<^{vٛ/2.2ORRRq<&MxLӌH&޽{# . . "C>^pau=z`ƌ?Ot˩QAz_SHB>h$""sx<ю Ҡ9Nn&NH^^\r -Z ??STTw]s~p8<755{rM7QXXׯ:fԨQ@s=Gbb"==񔕕1|pN9H]z-ӨQc>w7#jChG8!ݻ ǪN f "Ұy<JEDTƌÒ%K9s&[>>ۼyszE߾}O>c>7k, h~GQQ9z!~?Uٳ'SNΑv܌"u "6|q9Ct1Ej 4|^!N//8Q)%%].1;Յt"5McDe]VcWp84hH$Z59}qю!RH]s5\s5ю!Ҡm9i@DDDDov :M=#vN8̇`׋v~iH*v=eN """"""x((( ++DR}eeeԚ^/ b'ݿGn[zggd~DDDDDDDN дiSoNNN>/q͛7ךn7MbYVRNOڧiezMEDDDDDPA=,"##hGkIݿSCw<i^J%""""""PzǧkS7IDDDDDDPA]DD# $b:TPz'Nz'FoH-;q.(F;DR+ DDkر#1hܸ1guVDj(^$M.)"գ;M`GISH$""ѵw^ v***"Vn^o*H8> $>NNĶm&Oŋ;E5zL3Muj MSJEDDDYp!iiiG+ꪫظq#/f'}˗?𺬬,+V833{Ƌ'N~`̘1u]$''EEDNN """"R}˖-cذa'K/?>:@hҤIu;~޽{SVVԩS0`}III :tv|׏;<5k999hтCr2uT{=4iB۶mYz5| 7t)HmdF;HM-4Kv 9Ug'kt[v3xZlUTT{矧}~_RTTWsO?4V`ܸq,^]{n˖-x<*={sRQu&Oȩ8h<۶Okᄏ׿oqq1v[y~~>ӦM믧#FL~'//+V0sL\r W_}57nuvKF+--={ֹ6*EEED;Ht{w<4CH]ҴiS h׮qϧy|LJi~xn7:u /ՋUV7̰aڵ+7p}eTTT{_Hiiic K ,૯:s_~9g$Ƿ~oݻyG֭9HCuN"'궐yDDDDݻ7;aA}޼y|#P.Ǿ}o۶Dn6FŪUxWٳgtܙWiIN5kƖ-[zO?yJ9Ej9z||<ٴiSx9669s&`z;""Y_r"""""' /d߾}̚5̚5"U5{l ԃ|ۗm۶SOG~ٳ'֭k׮lذ={GXxULMM%;;ɓ'sNf̘!Cɉ԰C ׿5wߥwެY,)--oaƍ4i҄޽{3g_|1?۷oW^t͎pB***ԩ]tp0w\6oތdʕdeep8Xx1x<.bǨe˖̙3 /RH0dѢEض͕W^~QD! .iD֡KDDDDq:s=lܸK/-[Ǽy(**bU@?YF4OgϞ755={0b 2dHr6l111%11qOii)F"!!ሶǎ˘1c6m~{wV{_dAxYt)e1tP < C,ZKO_z5i}v>3yRRRxGHMMm۶K\uU1"<{eY޽˲xg֭K.O>g=jOΪUp\l2l&&& 6a~h_RZAACnJDDDDJMMGaL>[мys?|Z y@x"bccó<~JJJL0ګW/>cOjj*aI&QRRB|||H}1{u]@h뮻VZ;g}FqqqoVrssyXf ڵ#GrsUWz6l| w}|wYo.;vp駟ҫW#2УGFԩS:ujx,?g򒉈juࣜh'㹱#l"""""t2` (thù\*ʎp1A3Mt '=9s@xCc}t֍I&q=0w\>ZAA]tଳ"===L:^ƍl҇|p""ן.;RH-4CԌx~D;H1TW_}kFVVcǎeȑܾ~a#!Czj&Lm9q@ U;iDDz:6iZ>"""""Wll,Çv :Mj8T>C|oժU{лwo233ٿ?ey睇O?e۶m̘1EDD"O@huj O v пϟ?Nbb"z2˱tܙm+o[ۦqv6l{.""/ 'AP3 #ϣH1D֎qGnߞfC;~9.}ގYmrCTTTP^^~Y++**"))I3!U\\ڵkׯ_XDKBOv=TY~SߘWY(%3z͛IKK;C*,,I&NWC"u %KйsgEA0 [<8X->;u;oIQŶ èvAp4jԨ."RÞeD;h O v QVDDX'̼ G;IÕGi;TPdhU=xd&G;H."" ZCy 3)DDDDDDDN3DDDW`^xfq4 _"""""|Purh{DDj;P& /v>h95*+*ט_.v SH%/^#TL@uüp<~RXtTP9» Nwx7 $"""""""1nh'{NEDDDDDDD$rTP9즰N$uGaůGh',EDDNi",%vD;Mvт[!#!iDDDDDDD"O#ÊTӄ?^W[>5;v~s=tn$"""""3zo[ %zضٿ?~?q$\.iiiuY8"R@vr;EDDDDD]$?⻈*G;(//e˖\hǩvIFFFicvAӦh9ÆoG:4-#ࣜh';/6iN"""""p<|>RSSfp)))vv#|^޿m-c& 1cX8yvKb۶)egn ֕@fl۳9Ѥς/o rri߾=7 !!z*\Pm?Zh!C#*T~.33!C˼yXnTTTpRXXsk4M q:x㍤N| OFFF8!y?dʔ)4nܘ6mڰf>3FYӗYT]5*/?O۶MUoc$mV(-c}WITwa:p?D;)/,R IDAT ^\ 3ׁeG;1 .n4"""""r8_ 8Kd򗿄+++cРA?a…dffBff&Zrӷo_vG}޽{(//￧_~,X+V0qD}Qbcc0`seڵzGԏ[x웝kr "R-DMMeaU`&MضMB\"~(lpMe!9.4#&Ήf ?.,WWZ }m,wh:9b}uh,X@rr2?o ??+W2m4 k%//o>44hӧOӡC2228sڵ+ZxHxz-n6 4Kf͸ )//g˖-|̚5 48p W]uUVKjjj}5jݻ#QEIu8۶ջ)+/]7_& *JzE|F64UwD1q{-l.`U 6qOJj#R۔(zS]YN9+ውs`oy': :9DDDDD|wűrJ.nrss; o[QQAAA@;'/5M믿fڵW4%%f͚'%%Q^^N~~>ݺurݻrV.'&&RVVVeR}D"M3ȶm&Oŋ;Ek;`Y7t=zv$ ֓#OZcnc M$%gS;ԿA~=[});AE xc-)/.QX*7H.l<(9{y8.j*_ *z{/7fٲe<~Đ@ǎ7n\Yr%V?#?z)>?~|cuLIIaӦCĖrVִiSn݊%&&ӼyjHMП͕//K/1yd#ĉY|9cƌW^u]EV .]KNN7ndȑ~bbbضmv"++޽{ˬYk׮2g˙?>/getޝ)SsN>|J$bCb֭[GN믿cx̨Sz:u*M4m۶^O>n)Bg]`GYYYeΜ9\yQNRaY'%n8,ʊħOl,,^v+}'FR*R'.4eV B_.^(AyeH ݡ &-49iGDDDDDѣGs2tPRSSyx衇Çq;v,۷x+!Cx'y駙:u*Æ #99W+Kll,/"/2:}aGlxܜ=#ѣiٲ)_/ӥQ\|tܙիW?vA}˖-x<4i^׳gO.]zqko_7\R=s 1ո#&%> 1 /y) ^.MV#H`*|7OϨ`""""" ѣkWYСs /ٓSRXXHJJJLϞ=Ó}:s|x^n7 {!%%%\tHKK;z唔^|x9+x<디]$ZTP? Kaa!֭B?k޽4jԨʺ4sm;wghg&?W\W\qJm]xjHrs1(.9@\2;rRRϢdoF |]SlLNyqK=MIDDDDDD"o[#պU~RǴ,1cХK:w̷~ˆ :1iurVxRYDj Gow֍s=LLL4ˑ~zDDDDDDDDnPA keĉ̛7;v,cƌaڴi~^Zjr4^m۶dn7q+ԏ`A[j줢 wӨi\N#jr[nP"9TP{k.]TY>]I&iVZ@[-[[^Wyȗ#'%"(+ &m?՟:@fMiڬ)&=1`@0H0  *=>N}/ڧ """"""""H(D RA \|3))XV^QjǦջ?<6l\Kٴn՚JJ8PRDEE9mu3XDDDDDDDD"Iu9¦Myp:TxǛ_ ZXApLEo~vvi׶=ڶ s=SJҹ3-[QFeeWyYDDDDDDDD"Hu9ºZjru'״m0樲E,+ҹ+]:wO1ОL$PV^DDDDDDDD&Ev/PIILvvdc&ptJLL{tփ>w~ lيf͚SHCzn|>`q xpMp'%7Y5nh({]@ٶ}+sױfjr7nH܍7x0 7ˤyLl\?Wz"RGM6eڼysivxhڴ)eE(UoYzV-[ӪehGӠzXEFFю"bbF;H]H5hZnLADDDDDDPujQA]DDDDDDDDDDTP."""ROe# L0]vѢE n_XXeYa^}U.b{1cƐƣ>zsL43x`.3ORA]DDDDDDDD$lݺ3f|r~_ r]w}vp.]J-j<,_M~}e֭[w/\M6q2sLcԓjI]/8g0QH5v:u*ض}D. Lln77m۶8p"֯_@޽իi~z/W]u-B6mo߾8B4Mx*rE1~Q;cSthEϳlٲ*nr;wb&$''{n݋eY$''Gxxhk߾}j哆4MƍG>}?|Əb[Q"""""""""ՐÖ-[ѣJxNNNN'xw|7L2ݻw~wo߾+L>Lϟصkڵ 7wvv6i2c 222ꫯN2Hrxyq8L0XQ"""""""""phXAafk+5jU&ztݷo9 kү_;FJJJ-""IEEEgx'72''͛7vI]UXXH&MҥKDk^ٙ!d:wLӦM>#+//'..۷#(--%!!ݻXv| ؇}Ҳ}pX|u'ECNcM)8;HhjPA]DDDDDDDDDDTPEDDDDDDDDDDAujPA]DDDDDDDDDDTP?ü^o#)pF;@4mڴٳgyf<}ϯ1vX|A))) 11Ǝ)""""""""7D; j*yС۶m^`СtM5rf͚mb&O>dODDDDDDDDNwю "uD,|M:,ƏO\\mo0sLOBBs̡_~i&С|7lܸ&M0`,%KGF0`IIIpXj{0 }]Ί+شi#F0 ˙>}::t[nѼd"""""""""" ^C}˖-ٳap7b6k֬aL>_~ _Oj* < >|<3{9sNfΜɣ>Jiiim۶QTT{nlGa֬Yi6ȗIDDDDDDDDDVi=w@FFFΝ;9shժGsw3c :tu]GVHKKw>VZŭʕW^ɖ-[x)((v5tPVXiw} _M6mIMMsgʈȱ4Ȃzjj*U֗bCGii)?ٸq#EEEx^Cdff2vXrss+..lV\YjTuZAVj>l\._~eK,s ۳gOݻ端^#++c2r6 ڵ `0O?Daaaߟ͛7pBJKK O$EDDDDDDDDD$dA=!!뮻˗/d>z-=\wv…O,Xvʾ}B_xqx;'|B~~>SL'+aΝu֍DLBff&-Z """"""""""'Ap 7̙3/_~r-Uի/2{SNxXyILLW^믿#}0w\3v=DDDDDDDDDDlA0 !C(..&110خm۶|͔^"RRR0 7zwHHH ]6m{ٳ'={^p80Mĩ)hʒNMb: '/=jP11cưg:<O:P)*o&++Ӳ,zhӦ;DFu'[|AchԨC 9LHH`РAg""""""""RwJϞ=2diV%%%nnw$bL0 &~>wyKȑ#ׯ_dI3f 6;3K/iӦ_|GXbIsϱqFxzq֭[W EG=EDDDDDDDD:ФIy'o m̚5ZhСCq\G<СCeΜ9P\\LEE_=/ //6mpb&eeeL:.Yfr>|xx.@ 3ˣO>|>:pCs嗓Lǎ={6k׮]v5yEIu8v4 `Lò N0  ۉpa`*0lm8  6a`#i`ma`cvx;01Na6 lF o`f94109pp;r0p;e a&¶ml;(F:6ˁ1n @#h#Ďqbf0Å4n871 ƌ.abA #6s^LN$XQ$&p`XAN4 ˲p9]]1\.`mQZ2 >|AvئGL 1nM04l Z8MI 6$v&,ZyHm8hDJ\<wm%=&}(*b_Q!~t; ڐ  1$%$^=xVa8;0XM 0,l4M,v ZAN'. Nmx1=aؘpqp[@ a@0ha bY`i:y-q8#0fcML0 M\l  6&Åt0ML _Ϡ?,B?6#t-NoEq1I0t|t`[bcy8.*`[- i?m`^+_E.`00 L  m[aIIؽ۷Q qqnw YYYW4M**q,eNYE9mSQ^N0 !>a=_""" ')))lRSS9iݺ5^[nӭ[7Nʞ={;`ҤI],[7xzX.~vmGԏaÆZѣGĥEDDcT`,hYa:BL0T6 lۇ4Era`l l0ؾ ŶBE7P 8X>XLt8x'vA bV i8L L009&V` 2 `a,a˅46m|;wa8Cbr!0c9xM-˴CW*ca;0m.0pl둚e1|A 6B>wA4 ,#T&Ϗ#68W q.7,668].~?ap:( b.p|7QlI\BXV`[˦ ˅öwIML$; ^bnHps;!􆆙K,>eQRXĆkطu31 1M޻Je8CZzo |~݊foEcL$CQ4&F Qb)1%1&F&ĐVf4`7׻us1UmҀӽVժsVZ뽟{\w5F3)a~EuBE@51 w~.LΖubsjbI"U 1b{0 Y,j|,9.#A8vqmbpK !skGJ\n3FtS9Gׯ0KKf]:lF )W- 2c [ YՊpBj$e<}"X^HU~Xy=%ٌ膁a.]<->}םL]͹]r>\x1\q鴥mZvg3c:N!r|r![u|΍5jԨQ>f3k~Gy|'9;cx[ߊmo{}s=p%>7sEڶɟI@y~ov{rɣ>OΙ, ~W~g?_:jgP5jԨQ49.Pul2H(6C \k4 \ >Ԡ1Y)aU9E 9ilH̚Mē1}hQX5RŦbWqV}Rsy5 =xC{MsK6濵z >@:1C?1D=` L1md!YXɤeŪax$wG@r&c.j{߀,a@XHU׳/O[XٛhS}O4oIFSCH] [LfxIdch&M,u٥(|u{;;l-PQ;VS_Q/=wl2; GM,9%s*i| @R )ERq_㽣{R8c!c&ͫPSc! ,&۱4|4v]MU|>GD2!hB=&>ai*R%})- 񪪈Qfc )e=t(dDpb2bI'bV 4&''La$B褆8 8kt@e 4b3=IDDJ\XVu&̤mqaZu6ѵKN!hkz9"TV0O=<{sT%B;ǁt| ˗޲8spk歛4utt1/]䄾X2QF5j|m>^lR?0ՊW.K>c7;#GG<,˧pmm{{r#<<77??:+CZ7唍Eh5jԨQOSX/qc-3,[&%+>k< 6f5H`C,dŕ51^X[ jVYm & x7mS$3z1!10֮4y\)X5em  bE)܌ň1M j<%r(2Y[z>'Hr>}6bI9aY5 1,nT$C2(&u$=Q",wmsTu: 9X0ncI6X*稍bvΚۚ{XIWoN9;ݦwX2.yֹs }Oo nE>SP0/b-QJp~얜bt+R$#xpʫ xy@>[VUJZY9A넹Q]zs9(KiNN'/l.,,c@II#YF:K t蕇DUUXcgp!#!r)hF3ΗSk-:,h& b2r-xnܧksuu[n1YNNO8:_M{ll3LY,؞mcBpXr+[ ISUĪQF5qUko~~)_ǟ?C/k^y^mn_'>|o>?~nOVJO|WQF$FDhwNjܮ9) GQ)*%Ra[LI[[9I .AȒ p%C lغYm-b, vzlA3HSa I1O)ߠ?zCrT,y|t[A+b ҕk-XHzNRDL* 8ta5w#jdT-)U;zk-uSĭSqłh,i{ "醌[fsg0m3b٫Zng'[RKx-bʚ>rҭX:P!Lvr:>>dJN9.- c: I1ﳔ e'%'!grq|:"Bhx x}*:XXVt]OUU.SZD RnpBĐ}^D"cGw8?b~V&u&uL"qdu V 9+SNX. DI䨟Zr$g@ZGskY<9Ǵ1qu槧 )[89=!lJ !Mz|>s NOON 3gH)Bv2;- |$srz0ijI:dLr g{6cwmKN:LQF5jy9{/Gy$~|Cc??@_vu?k׸;y _H4g|λ.~yvO'ë^*wX,G˨gTcB}ԨQQ"•+W888x/Q_^ !p.])>ĠE%Fku$7 TcÚ wrF 1kTL*Fhym-IQc;fj0{Ho `^2,02%q׸_5ݻM%,s`Yre;XkZ-àʔp`"d4/ ҠN#\uHeNdYO10xMV,^cc&1 q𬺕U 4uU/WZ¤Zb5ja83]l5-^`uP6xO=픝D"Xc$k՝S*8n;˳<~:N;d6yorzz0 ސS5} Y!g8g7ؖKiRASR` }hc=RUUkm*s咳"f0[kh]Y@)%RrlbJz={Z*Y%c))4FPZ1zNu4MSn'6D2?ʢv8H9E2:@9<#%bR3}ZN pz|loPU4 ޺&DUlA%>X-1ֲ3pKw H&)NNN sttD۶={SΞ=*lmmZu CONpytbN3_Y,f,:!7jԨQFٟY~g~׽g20!)_Eڶe׾˿|7~7˿K^3گj-M7Moz/zыokkӮs-k-_z7X,o6^~gmԨ_>jԨϨW\.;7IQk׮mJZk^իW|e]L)Xsc]-Jr{`c*B6qcTsZPXeR)Fq2qPI!YdL{"kl,Ň{eK$ҽڌ"\Ț5ٞSLA{'ky#R)Q Rq*p#Bx1^6fLA3jW, iPZ5TTȵ a%;u K)D!CMQM֜tW@5m})Dp֐Z)); TY &'MKp`-aQKP )v29gb#&Sm`-; 1'|^h[GZ bCZb9MgLw1g jۀ$IayƁ ` {;1# h0 `Xn1:8==iZvf;t- )%ME }dQ8繼k9Džٿu@ L&w,s9/]ĹuIc*pz&!)evfb;ac\3۳yԨQFjOO}I=߿/xo988`ww)a`݂S{シ~Moz&Ad/̙3~.ox6_կf6=>:?oir5h53֭[}ݜ;wnJ)} /c|d4ԿŤpc/LY pW6cE(O<WVTV(O=b*t׻Y|&}I1 mP39%]tmXwnMhhB9Ƃ*84YXjڿu@SW~rQt80`^Ka= :8|!Fr)(;9eX'ԡL5- }bY,d _פ<) [[Xt9s9pt|Ĺ]VMl{E;VCOyEzl#jhCEjwt}v?O|U?`7͘7-TBq1PW&sN920xik!^'_Z\.IYsP:,=" k }o #kbXwlBM1VXO3tDXf9*.kɩu|mns0XHƠL5Z&2p8wAJӴJ4Mbb1g{{PF(6m˗)4 )FV%{L&89=/\`XR-Ed& 7o\C2;wM璼bG#mS1tKr$9=X@V3g98w5jԨN3>mgϞ)Nuܹ9sμ5{{(MyɚfZFRitF5 t4ӿ߰pG} .,7*-JkLq㝢W b HKA0-ZplYRZ")ʻibo0!hiZ Bl@Y8W`+炘q cL.6F0dcC8C"70V!yi\]9|fXb@J2` GhZtxz1nj#&Sl B,^Sɫ=]߃ T[-0&'-;M'1 :d@-V4eE0_t<:fu&IJ >dxk1$`cZy ,D&xoy.ݭ)곚>O4-]ţI^F-bi: ) Թ`p bG  8kHʙ!=V 4E Lb+H_0+Q=cZy뀕K|ж-N Zkɩ )c ^7Tv.#쐤v' |M3WkFGlt:%s=mqٙOZ=ݢ:ڦvww[^׈d&MP9O̙ISK9::B0ihچ"7nж-ł*0X,7oU gzQ D LSXul|E5jԨQF}Zz˗/''lo)z4cF}(̭[8::bZmRmMӰÙ3g KKe@Nـri9̥W3w&S1ƕ:jQ?KgF;k <:qwc2MӘi)kQ2Ik j&ƥ ,$vsJn nФ7Pʝ`r"ԜHqY΃/S%ɛY9r!!"P\bz,Dɛn蚦F"]d1ޑ#i% ,~.mڊI*ε[L,WCmq̨fxkY2}̚FiNx_ ]$T]G̉mPeZ ~/8C[jgauҶ-m2t )%MHc$}>8MZ{"d BĤe(J%@eVH]בЇaPBp^}IK&&AJ9k17ؘ# d(c6'ĕkymo>-_j6a黎6: qbd\t>7wHےWP擟| o>I.M]3=/]"e-8!9fPc jưM,ysΜ9;{~ ~rm[zh'3=(gϜa{{P)a=jԨQF/{x^L/eԨ/FC}Ԩ/scq]wq@? 5CqREa9ƨkPGJ SHSLlS bb*Ť,be8xWXŴ N W`Lj|X,hմ_~AjbY(k$*ǠGD IDAT~)i1"bt00 %I/RL-Bڀ)" ě_bFiHi*|0@SՍN)'2FD˕`uksYR" [UzeK=$:--9{!'rHlFk:*8W,j1QT1X=>IlyO];o[[, V݊!Rrt8 )cD!_PݽST$e71T>` 9G$e/!hrXdZk21V+rԜN@'iUX0Y-R;OH$p%9+ޯMsbzbk,u+ş"S“Qv:V;$bb\Wz;w4D)f҅` CŁ2nu(VhFQ8)lfziLS-"i`#!h&-)'.\HUkW94T.999ak>[NY#TC߳=cÃV]QF5jԨQ4F}ڵk"<!peΟ?σ>H\p\Q_)ئcV jQ4[T:i-5bX/bIC&Z,bӮ?LNXb‡5? 0"70ީQo`t-t_sض&K" Rւ)a_`j3l G8湵1QMs?!\@VH#%n7 HJEQ=IqN_w3?8TgwܼvSg raŲXDخTn.NB,1&S3R`H)+Z7۾RSQsT,MqR9O6;>r8۶\plg<ł"f [lac!w $Ŗ>BT5oќSF ZK6<daA_x_*PP)| 6Ho_S)"ª nEѤ})Eؔ:$lϹ`0Ti."]^8sf-$=fGP+0kAP$|`zf[drJUm&WJm@{bA8tƓJ>a(YMNǡ VlH;Cà/ؘȒyKDsN skI1b떾Q[ݔ$w"Fєz𤜹K.B D*1L'S"V_,Y FLa빲ֲ=#D]ʵN^P0Yz]c!I)u ]דs9OJbIJtt%*T\v Œ,b˗NH1/x| W\ZqU~;;*$ڦ蘃c;i,C>F5jԨQF}i4G2TΙGyE5ý??r}}ə_,y[¿ۿۛ{.^OOh 3Zx^~||{^^򒗨 3꿵XQ $T wi笘ř\u$B("c2O @EZJa3fd[VcR<@qo&AD9Š_? HCtp1lMa&1R((VYŃ_XI,Y1&!sM}I[dHzO.efoMj;9F1z_W duX[mAPM1 S2mX4GǤ_<]8ǵ#np *k6SƦ`솻uK@cV[ѥY)c49ն" ,$#Tc%:꣏S3gIܸ~ӓc|AHFoѹM,&6Ķm \ϟǺ`\sy':G|yO=%s]jȒCXc)w};u!&a]ƬY^eP5MIקͱ},_K/,KZ`bءNdc˰@1}eI)&-7Woc8^%ݪc:قc>0 =UeX煉XVޮhdl \8a2L&1hzwwdzچk$v1zR, 7no_,W+;wrEwLyԨQF5jԨg^>jԗ뮻>gc{]w>ϟ7o׾]=7MDrJX ;> '&/QeCXpΖ BU8fĜ^`QOݪ9w< , A] 8o hebJZQ6`.zE?>`4 X[uxk!cec"0bk=ocak:  '''vO܍.I P"p9om/xٌ[)nEB?4MCt]ϴi8>NtӮK"Q̜pԯrrAG9S`5'cvph ȕ)?D wOi<>ǹy8r?su-nW4HjBp'x݊)Sֿ)BYjEwV8V݊JRUiIu]kbAjEUU88:8dgҲU4U믔 k9 )Ų&RbXs-ư:kekLmཚ)EBxǿ63A߃ho_+a6[v X4U،X >suΞ=[Rȏ12 ]+|5:KJst "I9ggZ={Q1=sk7ISV{{;{|N]$nժ\Fh'#eԨQF5jW[k3=L/eԨR"B۶ZKeo}n޼ioltYqα#<‡?a^;;/8w/o{K_K_~M2ڵkzl,tgKg./vv\Aє:R>ZR< %"J6`|ZG5!%Ɇ!ŠSw$I1 bJ ~ya>}$t=c-bb[ҪbgR֟Z,ɪ NjP #R81dՃψq :i(QρĤlx`"gk9p:0. Ӏs7xd֤X jФH)Ԕ`0Nj}eH_=9o mj[u3ru"S Ǟ(zBc9M{"zLas/D*C11Hdb< *Po,͔ ׮]k89=C~_bUs呇y?>Amp")Y2m0IjBxH)Ó*єm mFo(H2"Ji+DaXD_멪4$NI uŲF)e%c] a b1gCFp֑n[LvgːExbàLL2ె h9Vi[ Z%F-0!P"]BOĤ bZ-͐7,˾=}:uNWBC3("8bA1DHbLL5hcL_TkBG_ËE_@ӂttwu9gk^T;` ݲ]Y{ZU_ p=Z<:꣟˪ȋcSE9R%+׮! F><+ln>ޫW^=j۾,W^L_z^v)XVF{x]clX_{&o׿ms=PU[zN*./=l3C,c'cԂЭuf$9iRV UDLt Ӽ.ULŢte14#)>1h"9_ R7T0 b{Ғ*dɸBQ0| 2 9"1'df׊av,2Q2'f g@UX7T^`nךT^6|vvs13(hVnxJ޽~B>t[s Mrmi`zUް53rTY*ԍ,b:d̹;;˵kW~2E̦G6:㛄ڬRiD)Ms7hZhFΣkF龬VRښJUCdYc\ݟuWJ%JL~hE 1!3HQ:,&NwOciE@ _sIPJS+9o?tKӭkUV95riZI-1Y2M+wUUJG)7C|3*DܼqrsE/WOg(!0@kvvvZsMuU}^zիW^4Կ꫾xg}a/Mi9]. Kxꩧ뚢(xG8wg|蛾雸!peyի^{7Q5{_>׽uu/o1ӻdk۽}IYg$$c\A +AL?!KE D09TۊI&FQFF#QQIR6Z˶J)o'V4b A 17(A+BR1Ii 1ރѨ2Tc(!J!)(TY%J`"]K<]-&2ď4 huTb1yH%ӝdfy$ڕø$hI1t$V+&dÎ!,£f>aE[Q+ׯ5[ˬZPlecajP5TU`glIQ-yQ[%(yY"@i,aQ๴ g{9ŝyEfuPǼnsYI[&[[ 1TE 7|gϞ_ |j+5ZxY ;uc45V>6-ȇeRu]ľk8"~gkR)JuqQ J$͝TrU ǻBRZbw| 5Q z$_eP2M #6?{e5 *3㱤;Vh A-sBL*hM:h0Fy+Lƛ8:+Nm0=:"E1`csHmZvvw[H\.9N)^,d%A^zիW^}Ioy[ /%j//>'C9/9rwg}Bo6o| [`"%_k d+0 Q;"Z1xe{Ij IDATH\fSZ4pւJKLjPJ̮A-q|7N1bGrFAIub;TI9 0pyA %6rk%,$OΡ$UD1Bre"E4c*,A3DhZTI\[bF9QiTM-Ե堔^8>D\+m-2)ޥTL.n-hV)Yצwv=M匆C ȴ+*na4:%uzf1=K!~1e1Fb}@)RX,Q1J~IgY.+LZpޓyz(U(1zlf!2 Ngu#Jqjw'O>u|ŋ^B{U2!MӒقoa8Q5t=U|>cg|իW^zE_1}ZBWg93se/~'=ym򖷼?}W(888cZqpp8ϋz^2#9 O h2m,.xרklO<`.B6spGe9;,ޡ c\(LWJBG]MԚNf^+Tf[RUbJIz j>#NS `fZkgޙ:-Aw( ufE.X0ϰ6;X>(咬xc+e+ ߴ1G3P5¬oÜs=Xe)hh4f>Ѭ's0. a>_b3ѫW^zիsG_:Oz*s?}=#&z~|N/vvvۿۧ.|>g8>m^{&|7s]]Zk~P_ Ub[)U@pNT]"H ! _*]"6 gVJ0;V sX3#9s4`a"!(|Di#8[t*<#F-q#BPk>Um, 3}P]4Z [IwF"]~2 ¯OwYIWLJI=853Ck)s].!~ 'Fh,C lAyJ6Gy="rǹ;YXE-bn1m-2W~r:>>/TVɸmkXix)FAJ+\?Jfr)c,ycF%P(u>ysmb*L3iHZZ6]"3M¾(si@-8tWZCXV,G%EZQ“!'=Z+\ZBLŸz2.~tt)҃e4yIձ1TUEY82 Kz|=Jg0e4 %4O)22c4bse/nvvO1(lL6Y.WYS׮]VhdcCxcnܸRzb^zիW瞾d ^RJq9}QlI.}k-Ν{Ηުx9dmo{~>'Fs2vI "ZPȞdb+< 8'L<㐌V| d#h/XґYFyO31u** PE001/PMKl@2eI^ 0nATnA="2&@fa9(aUUlonm;;\|94dF+Bi1Z02N  5>`]@/.Z וZX.y߼%98!Ƅ '˸~:Mb르MKMB,3F1c%łKI{իW^z=z=KU%wu/^}{/x 8s eYK.#pEz%%) (r^Y^I*tTZRJy)0Mi| 6QжɔN*%`!@LtE1c#'_pRJⵣ'.q!RZR! Jb RؽI{I"TZ0&Rhr'( E1E'cAcZ ֤2ָU3>#Pe!&XU(h-,^)x6Ghޞ0|POrX-j|QSKV2?\2.J<蘶ɬePZKu[;M2ed96EruFc.+N&cô^2o0y]seLLAf4jOsV ڥ9v|=ɋeԵkCqf2dt ZwhNz!PT2*(,X,l㽜cߚkӾij|*7ͳYfP e556ep 11F.\@"pu'e1Xd6Yw2S Պhi=3{իW^z=z=5ۙL&\~{l,L&GJшp'<>s%S,sv&[lZG+(ҥ 9,ea HOZH vc5<*pZkqM!\o)@NƭP/=׆$%| ʤ"yQX)1&̋<Ж2ȲR@X֢T1}ЗTΥĻƻ ǔ|7X4 GGEp8\?$.Ly$uC=#7FZA+\yNTЄ(+]\^9![[hY,~ejNx8j k*d2apޥ}իW^z빥PY,) ^/}Zc Q^ZWtJi:I~$b3jIR+$n3DH ta؄F*Y0Y1w  ZNǔph-QȊa]WJʼæf "^RZIj_'S=F 51ā<賧圹3b Ct.!:8!FI+#ǩC$ޟhyƋiH.vwV1{5eu$e8GT-K2дmdr0px`~2!xՂidyFg<9;sZ[=r&pEfY+CkYu1wmmq%,c= Mf`\qmwpy6FK<9BZ4-w9Dž8}c C_^x?}y<{ɄȥLty^6 >)%A(!!x\by<#hۖ±X-'t9CI ]l*,uto!BOyaSqg6bK1^:S>ƸF(ddVKMiȕ- _[g6 V=bMn1lusA6XF: ba@L_%˪M1h {ZQ,ȳ\8.p@/z~G~I^P ^RJ1@իV]S(&kL[rvW \kzb"1;8Q 7Y0H<j) dZ'̽ʵx )ǩ<1yZɾQFQ%9D)[M=hUQ^xݩ[S(r+Π(!rC4D9 jyղ ‹G1-{0|P5؏ZaQaJ)= ܢ U5E j >ϸ\;2 Kz 2\.e#+{kS!eS;ҷe'R8BfjCd& 0_ΙǹvF[+!F)\h&8{j"ٔ W/]*%-ܼNY }YFY΅WU3}r'?!XFBN1p(]b@;!22r>y1]Cө( Q j?-`Fnĉ*֥ZRk1u bI/᩟hTBt&rEP,=K|Rz1Dy^pˀO5%ľVh@gdk-M= Ku69tآDEAj]|uڥK\rlƩS< v)P3)Nγgx5d1y&o;7qzc̒k͸(0!@c- ci((/8230.Ø;vv,G<:; GGLLdcwhȓ73.J6^Wtvxӻ;4M6G'>AP`#-f._ lO_<,q=bn+RA sh)LA8+ #~Lx ? /B]{ZVxb z!a`lZ66ڴbE .5m6d nHG|u"A4t%xO(d yi4&7RRnMx9Bf32mXuUaeY-Ɋ(#,Knbd|f?0e4n1iUM4Mϕ^TP#QEI@ZCSRhIsRV\BPy.[)T:t&EpT :zFւ !^obZ]Нd2Dy\WXUG`gfpęmPM5OvΜy] ESg_l#._bPnpY*pc:e<*^/wĹZ {RbȌyދ ޕlT)v) Jp(.E.t]i.u؄3*<-h1R{ !$dZa ^]PLq Nɯ XWUEf v ,ϨQa|=0t`.B,KڶEu{PhD\{\ݢPgZ2iɄף! U`0dU-qQu*oUe7nˣ>|^zKY<ow[Vwe`/{zOuY.]?:5]Ξ= ^ЙJ*$#C$ QE3"%}2cb-k[7RN"tP!d+>6(xV1>Iī? 58ȃNP)Z[p'@fK:])KI aj'xqQ. ~@ts D  ,b Js{ 'RlATV5AxATfϥ+M|-d9s{([rzg^yח1dXf許d͵&&qKe-mt)| $}7' IDAT-h>b cwA)Qb( '6 YyOS6JkXg,MƝ{\=r}>cY0:01h9eٶ(>f3*s\SS[ŀ&_h]wrc9~_7=&Ʉr⪖qDf}R KuC$ޕlcdusxbC\IZt4p]lKF|»XIJd  r ) \w) U\dؕV;}붯Ŧ:FMkcLPx.ᔺ2Vm.^VS `6 CZ9rElO\9_fg6_}m10 S 12, Rܸyp4d\1d>bkkzիCmrwٟYڶ5y {~W~er䵯}-7;wMΝ;wM]|+yK_s jŻ.>_x??AYկ}{Gc줵~ֿ?::G7{իW%i)B ̊ƕ^lQ+AA.,&nV0cYJJibVLOX: `U@Ln+cF&CY) !f0 ɤә%4$]ъh,BLLBs?bIrPdRSQktD- c:;6肐QDI1XI׫PU-jqxI2Dx XbHk1C/ePi;C\\vf{d²ZrRcvfMEư X P-WdZZ,Ɠb<~tH}xo 6|p N01rqz"/-Eu-z޳g9wjbEa[c{ޗqMNonR/O<D,ի:'%{[("!G`(h1bdwe %>ˀR Dksm A@i[Ld.*tB &8צrNo;~O ~c FYKy& -Ĉ*vHxxd`a^޷X[sd{eOu$SNG麼鮑sevS⽮k@цp8䎃?/ a{wn !2=iJ-8G6ed>_ mW^zdt:OOx ?΃>{1կo|#x衇xߍ֚׾)m}^җZ!|;~@xoy[888ovVO==֚׼57w9OO=UޫW^z+ik׉dI -E! @J+w qmŐNqbHfNw+$}L΂ML2cJґBGexB3jӬ!J[.5sڊ!FPQs"yJB^{g)sʶ{Gp-jU MR*#ǟͬёĶ | ;\饵?!D{N<$n!ƀc횩4',.ϋftd*^u~b).sޮ K SzɶzYb4EZj C()gJ7R0BP, oFѡLo@U\ &~H\-QKXUx a5: bt)fo'<-PbnЮ!F-]+TPf"FGEEP0t!-1/*̎on/Ѹ6YOΘ͗܉%WhZUL+FE,G%Z0V3mjZ☽s? 9SlPc.'chˊEUwɩ ]|Ʃɶ! >FbȠx)N`3ˠ\.YΖd2<ƅdExin ,lng3a0І bIU Yds-uݐgӫW^z=>?EQ0}p8d:>~x[Vq~gvjkss'|iX,}ۿ\|__߻W./իW^6ŔqCK:GaIxkL7;,wgUrJAx9T۠V+k\Z $OO}C_xn!(:޺Zv{w>tz h13' [=xTPbd;b?ψ@XybjĺET s Zc2+lfMINm$jo[|LXK=dBD/7 ETnrTf%baO蕫\-xU\%ZIJ񠲒{=p8bsI~P#32hCfaY8-JΑm_3#1%ͽz!I^~$wg@w:9 BJ8!DŤn[&CYiUJLӭFc3ˠ[m@}A-)tݡXzIg\RzEFCǴX,3oUF:91p޽ xPU+ pMrHٌ;og~,Kӳ{ǎsC03clF$q9p\!X j4 gHl>]]Ǭ̌̈̈ǵ{Τøqf=R)2#wukz=4!X.9:>a"m1GLS!Q ׂCKol A D @I 3-ZG=,Y=PyTz++|pAJ +SNe13#dH]k5C, b奆zCIa52 R }(GB09@Ѯv]wH %G5$R%ԱT+-d )!1گ+TSlIQ4CД 1 HQJg{|-uxK|MY:'_]K/* ROoxpI;䄤B |-+|D8:> KC49< ad`u0739LQ(V+dBllXs~tR((CG.<76)C iB(ESMλ*bМ9QPc@;/5/tݖ9'[}!5q("X+R{֛uF8d2e2d[B+g3J.xqϙ!py`ܲ7 }& ۮK ۾ϼyT5jԨQ~:/%{wa6Z?w.Ʉ ;/ſo}[_W_/| }L&O_?|idPG3*0>.w>XW@K|VZ Btv5ݤ0a0JИ?cLqcE#Z*[~WKIUAǩC'I[C1ܵeafT_!g48z !٘R,/Dû ך`<Łx5p@C?+1s@I9\-Ax8:& GG;y[Yl9?.=4<ڮy\%~Û6͊>%o[ q4r36rpuܐ6 DDތ͚vGsz|̃>d]N{S\\]r2gཧL8' ]G|_~MΉ E:Y=@J-uuYwfVXs~nt|+_ݻw?gSҳg8<[Qg8n0sI}&QT,PCr/P\5K'nc)uWa\P02Mn&!%+&U7h#dKWSM>1MP\.6lp- sHӢ`kCphJ#8ک̟T wv@ ۷yl/ nIEԓ5!O)W "A:qSGtƦ}|˧삉w4+@t>ʴI|s_v%,nrۖh>od|rn۱?cmy֭!% æWm5mC8?p͡hv6qJp/RSJ2ٵUJ N򰢤Mcؙφe2Y\O®!),JRs2 OʆZ,+75&D\]!/*os«b`Z4 tnd6OZ()цHJ=OVo4ʗK>u[J;@)n ^tit6#Dj`zS{ԨQFq aut]I f:7~mRo[o|o|;?F$j4G5jԨOHscTbgETubIh'P3C;cwk19 \J1Ƹ7czb<,o_s6LoynXv$Rc`LcB#"`Ԍy-zKG]o?+)AhlvGģ;$"Ŭl/\hUsN1$}]Ӿ9S(}yVUKj<%wv{h:bC Mنsqq^f;+)Ƿ +f ՚Mëk&] Tz+ ޱJ=lW[fmdZ3y9׸}rDW}5.ur (n˺dcdyujGme"Mk>:{& f|L. Ś>*E(%1jaeD0p1bWL9g;6}C$ԄW w j驪%DKt!rʀ}@K?Jz dImwȚ!ɝs;Gb oKU9n0&LÎq)KN ^P0n@ IDAT}߳^o)@ o}G~޸C۶dnK}Gl& pm^\Y ! t]Ǎ7ج7_|:QF5jOsʯ o͝;w_Q4F5j'/JTWMտ>URPkBUK劽]CP:EuVznG((tt.j}2ki.ED̬^_ ,@,,I켣l$䥠1y6F@BKΠ(" Ɍev4S pj,H+bǡ)#CrcdbHh,u-q1F)'M==iђyrz w?&r]>eb]>bmYf\,,Ӗ=t3y\Prb>rav,Foܹt6e]sm؛"O/X,,Y-W~%n&o~g̫sZ1NI6-7ig{\V<]]Uhۆn؀H RO䜪yP RT#Q%S 89Q_3nˬFI =9!Y^оGj{8~9_|)"^*g>;tX(Q˚|WU!LN0i@Pf:1#]9Yg횜3M3!P/v xpZf%jk/}9qB4MDE7ɳ ^}ǮL'3|BݓcRv[ \<}\,QF5jO9_׿ޕQP4F5j'jbF"VCM0*K@c+PP՘"R^qʮRC-fwY%⳪Хꮲk2ܐ&X)>Eco  `6X):1"g:!lJF0Rdӣ^(]g. f>tj&v5_* *} v|EE`E&vl{t> dlՁ&C足;;1RBdm`QKk'\?dM>z9'2Ly֭|cNflTZ.xZk}O튩qKO=\^?+w^߮>5r7<]/H𭏾vgOrgs؟Tkɒ{heel Φ, 6Mrb+Qs91m&fEsjdzs}pKy=pNb%Mv=`u'Ό|iB)E!y| 8B10^6uQ+1PSbiJ YQ8X! nܹE[y{R="10 S "f%KywhH6,W+|x888d:s.RVk(3%W [7YٛM٬|~ Omx&Ml Nh5jԨQFh5jԨQT h5٥% TUERO QiHBDkɏ8"e1_"|,-$Yw?jP^TdRyՔ#.b8!%_j=WSS차E k#Q ՘Ԅʠ Cq ^<b=Z<.(AupRT{S=5#Zp6]o|!ňL#5No3ϥ/Ű1]5 m V,.Y]_՟|wyu|)zo~\.hg8q>z|F >6'ϱ^-^Zmx=xձnI-#֗TO gWR-2^4`uf<0ҥt|7b9 @rн7,{9JJH!n`BP1+ms1/-m+?ǾfS5޻F"J𕣞ry3nR(YwQ>ڎ7_:v. IkcT7oT|?֗yãg|/!!D6-g1vnǏθq1>jԨQF5O$ {F5^:#DOJ)w6[&|䂛{1K xs&n{Txm m<8;7r9)ϸZ?gX!"Q)p);lYW[7YC”_o3 Y$Gnh~=s|MVo?y>._}->`٠9a8x!GG<}vwb{\^]RǍ0k[VG)rU)(%t4련qϕd(1 Xwb\uˎP,M^ }BD(i`gH\-5|_gXfnJuQ+mu.?7 Q3 tIpLu-B w.qxx8g<- fsyz>Mll6tz IݖU)mr|r'\^>EQblMb(}x5jԨQF#h5jԨQTSY0VEViMrN \"ג(Mm.}5CUctK-3bw %W7c9T% I#ȗ"6Wu#! Y5G੥ XR;4P*OffH ` cU㴓J5?%S=.Avz { 3CMg%]ȵU|/w~)ΐ>3W^b$9eG: K 7v;\GAhLdҭĦ9: 6cY8_lXk^71iZKqłc{v!@m)ޮy饗)EYo7(Çgx|2cofn6q}i5jԨQF5ǢP5jԨQ>i&,Ql?xh]3C\qKI;4Zgp{5 jjh7x%W3%#53Nض`/kD|R{!F$[Kd+j x\R->aX E12߳GAYQc 'jԨQF}R^rNWӬT毀F9!K5:Z8"H !f25;KK-)U-HbQ7|}Q5pC3Ė⽡*PHَ3)7rIKƞPLm@ЩZTqΓ)_es3Q\!)hWGe"PPHKTXL)u:r6Xm:_u’:.Tx+lM3}Kb[W5(%wk-)ZQ=6!mZ 2V52A<9wdZv6x~쵁׎o2XVUnݸI88dA%e.A L4{"{{d-{8pxxb>ލS18gfv4l6]zH,tC¤ZRkn<"ҧ =Tvv_jz^|?1˽3}>՝:3siT@!@)u0(Rp/s!v)O)5yܮTd3} [JZE\y.w4 ]ʹH8O){v! RJK9 lH9c$]ױ٬i۞md]CK/գF5jԧAQ~ QF5R@,1+<Т"hƊ0 R S+f&kMBR5eWNTWޣ)`g0J-!5k}H;[Wݮ3f}.Y >4o'A&YvѮ"ÂJ [l6h.HZǥ:߆qYa-_"ڭ${ %}`__v;.a;rDfJ *ۉ&zmx bjYψp5Hs!4>@~VS*>:=qV6ѣe8J~z##e>4H.bt[?{@pB8bʛo|YhH{sbpȩ盿mNONg?ϣ'x|rۛP.#A5z6e)?- 3UMj2T 9nD7P-,61Vx 6wq8 zk+SMp>}W߈ jo#DXN%#]V4'#j(nw?9k Td2CCg2哧sPgNM`Z1N{1i(reu9Ϟrtxzg^}r|SɄ{r]RIߨQF5jԨQ?= QF52 炙ΥxK< 3Ne)QMMjW]j WU%%K'cSW.9_S]MjXgIZ*WKF}Dynu&FR*K% q?}\WԹʏW~k&`ΠumHx7tHƶۯzd\m;F9笌VtGiۿ>Un}bߥK2T;{ Ơ Z'|:0_A %D\ɕ^?Z ERP\ Ŗ"4픹&RQr:޻8Ա8ho8~mZ7Nx7oxݶ7ݻ|<|<\^_1gٰN}.j2 N{3CޡjW4wLz̮E06}wH}yK{+bϒqqbi--jhM[Yh+{H)Q\C1xLl!nVoRvI+rΜ \-Ժ)Ά!<| <}*ݳ\,ibK'J꣕ixoKgWBcrJ1r䳟 woߡ;~g~Gg8ght-+nZ 1 8jԨQF5O>jԨQF}BN(ސ.(EJ50bF6JBӜ--\jfWQs_H7|P ꑬbjJ˃wS;8$60T͆"R߻m1 !J12ڭX5-ZYփ 3JAlFsPDASf=AfjC])-ȤEb\dH )!. IDAT Q0c8RHϮ5eL& 4gvT6P5_ *dbZm۴,=6$L ZD=d᜷7JB4q2e/4Ld6g/ p9^zA_zۆ>_zC'z++Rdo~sYtia8-|{HH-)|Ņjy.Ԓgp"+ ڱb{pSeZFv}q)*n)ŒռRZzAQ=.ùT6WPUrmUH=?Y\_] '+v5_W \} |wYYk3BU X⠵.vWJ.~rœiiI׉pα3Q<?G5jԨQF1k4G5jԨߣJ @Պ&wn.mj!Czv8%RMq3Mwbb2b6 _1]}_'Le A Q($6{4gB0~RrOx@ LۖOsՃ9!?wE =xzqܽ{=zy(MOs&MjE4l66%'zd(qC:bt]oRjb zsmKwso9$3Xvna_Dsؽ%N;GaW<,θb\P 8o+:,v)aU.sN !}^WaD]OvHzapZbnۡBdؐӖ}bIӆ>햦Df)޻gt2mZݹÇ\bXF5jԨQFi4G5jԨOȌp3XUket9Y>s6KSΥȫqVZh!'Łd%3jk'g#^V* ҧb&5i_(yᾝȥfU_S8+;UY)q)gʼn%c4ndGHq!"2zK]εTNx} V;jMŐ0-, Zp)%%Є[ AEUA֝ΡRm&@ @A5æ=SVWm3Sà|{jbVc^ %%'Ӗ Y v'G͊{ϼ ɌT׋%nߺg^}Ղ8=9G|_x?4byf=9H5Tj\*']E "* <Z눥bIrqhE`Uc%oD4殮DxAT1Y) 1S]cx8Кp>&umfVΌtGwym= no=9 {hF QrnS@|B;bQNCC@SO*B<iT8qsdW(>c{y .]qtpj(gϸx86Z8=:1DֹcNqtB,Jg^җKg*fjR*[vsV([KPTӧa5Vx]QCTд( !+UE)5ֺ0p̩}5>ylAەkA&8_W")RYgv>&ZԪwl\g]ɩwު0tKN6!]]39^@%c<+ _Es;޳Z. M$LhZ)c\rtpX]>:fBu,Kx>{d6ޣF5jԨQFk4G5jԨOJjh55)^̀-;C30]BAeਜ਼HV8!>bEՒ5%K:ԹW,1ufYڛdRwU|QU0ռ~0""fxQvV8 ]".* )#5%;#]F::%'\T2xIXT&*dGEN ,yuYTK9+?-lqf3!Sإ\hE%Qo*m'x_,Y<ӗ+p7@l+RӶ '.s8SG``Z9)nw K2 ޻ve޿w1\׽ܒ IL$-bV*D-?-l-.KnhhK? R !B \}_e1D"I|N}^spMӐrh8G?uO:Y:.?~ tG.<՗ wa0 {"ftKbnEc}Ug.iUi%ckF* 眕uDL:_U 1'2J.E*W˰ÕD.s"*&T'"5>fA֋G1cTU@9NAX!%)Iz-xê8_wB*C8FbgqTuC9s4łg1i5M gCRל9{dـ gb4d8c89gc2y&ݫW^zիד~ynb2sf{{|7 /໿իW^O*MnyT QC-ѭˤӂNjFV"jfo AR8ˆ6ֵmRDWVX1b FC^tqb *(Ɍ禲.H 1ǻŘ8K*c`U*bW>@#O7dm1 .!ɓ3LN`<e-"XW,Y iqIyn]ƺZ7L8IH :Ҍ_r4MpAp9!"TX rIZ@  %XpRMdsRP>.'؞# nSO] *0񞔍_W]6$ΩIi'|~*㪝u g9r(8;?Yt!x΀=D#G%rիW^zSPﺎ{ĉsm7''yy>ޅ +'a{իדB Ʀ(TXp4"ьj+H4`d3{JTv.%.+ΛWf[[GUކ)?Wd)ۋ$ьa,iO҈|՞g&v1s׭e Ц[vvf/3E`8$Eju~tmEjl֥8 aD*!krC5~'/,Us@Ty EVg,xg\\ " S *{mdx5,MrSوD zt6{0p~hy.[vCبkiU1 %0 I]v͈6&6ŜIӐ6fwoxLl)d39G>qa8`<s0!u`QX➘"{' cBn]gbWlÎb{Bx\DUl(8D [{"H cm^)|ı҄ m%BJRNI!TPQno{;ff>A )svwkĚ%O1Sĺ8]}W*Ꚙ{A.Ӎ ł@8u4͠Ԧ!e 񄃃}]}ƣрa.98#p8սzիע~'~1 ox%zz1?Or=p-׿__㮻CΝ#W|3Ӽmoĉ|yͧ>)=K^?KիW^_ e%ntyrB8([GKdfƥKrufj(,hc1 b C.iTR>JaJ+YPZ NRFSgf=+: [f;&:kI܊;3Ef3fE2\M\<8f^S9\Vp\9yZ̕MU=_U RS24M(8V-h1m,!a^<& R_dAM-ڵƥ.yK鬱uڡьUd@-a M-䡶 q[hHɑ3 x' mUEs73(mײ1?|ޱ ^ yW;k;; 3mmQ\fXD*\I#Df*gvaGgD`.O$K*Ƴ6mYW%C]U{RL5(H&2lEKNU9/(Q/x<̯"z)${^6O|w|۷}yk?;*.}.R{|Mog~gPWU~go+￟-ofccիWFɘa.Ef ɊK%p.#9IZ ɥ_EslŢ"SoF!:5zʔcΥTmg& RQJ\$hil"  4t)79l`I}* er5b2Dė2ȕv/~K;CUk>5kԊbG \ek񔠩yBl5@U`JQ-@HMFm|F-v Ύ0]qbW%OPC̤d w7#.xpшerf@c|I8j!EGc.nѵKF;r ml0_.(;||Ή/+Ν9ͅ=ptt4 lM`p.A>|yy\ib.iõGeI- Zn]Ck[rNkWńΖpmeI1(/|?{|gJ^zǏggs~:&8cǹ%d G vd;IKGlEVER9%1 7)dT!ϲ,zΖs6sH9q8q!W _\W(eZʊl+#9=8R)Ν[,hqeWLrYWL~R9CB͠iږ]6Ct<5=O&=rK.}njr|Sw>Ʉ;<| ;lBbO~Ǹ?mY^MO:+_J^|oѣGuÇg>nb3 =ɓ'׷?CwӁ{zի*@_1CB%_̮Z!Z3Y <+; Vv3Wke.BA:19lb;3*YQgx- RR*㢊.Z3ⳮ!E-ٍ(ݸPfAb*JyM 9 y)dt(b+jK%i.5#QјrbR jJH,jEmX!f2[XjzҸ*ĕnV( sׁVb[R,Z[Y`iCHrYKח;{_UllΠ{A '|C;,s l\Ͻ ]`upt^R{>{q`lq8ze1666b4ÇTPUabR*-`ŧ_⃷sWq{uc:%bL`C`lטsM7c%m˙3gGL'ajw$Rk3ue1RDjD={vw= x0@׵\~\pロ٘8t.\@dB%\zիW^M_˚L&/2?S?تw]u]\q/GiO… IDAT{/}K )wu/|~/Ν9y$\s =߃sl6wx+_&`sIgӶ-ǏsSN?|=/{˞ګW/W_, wO~KlƋ^GfJ۾mdļ^zʩj(ZA qEq(J&ܪ f:W UuWZP(c[ӜK2^hAUzzUVҪo b؋]+VPU-(HX*,Qad%ށ QS0-]yk?dS13xZC2"3K.TT Mu{b)T]]dg[t߻23U*b)ASBbD PIkmqghU$#_ Ƅ^'YDP671Vw˲EP,<2oSmN$Q96rtl܅\5٢SGgg8ʉ<#Gq=Sα\.X/|!}{y{p嗳_W_rys76N>ͫ^*{ws\}75a0?wq裼/+p ={܅z=&=e K.; >B\{F#ڶ-oy x+?:~6ۿ>>OxœR{իW)U]y Y\1y)p3JlibMU5`&^̄Mٌ\ts~]{uD7Nn o;1b4C~e*uubs) wHɌd07rIW y*$;$T\ =!u]P8f:{ Ξ)XfݝFƶVt@4Ftit ̠^D4:dcݷ9+=əU bΞ;uxQ'm^$1!)PVti`;t-[ ,Cw }qv^.-puxgZnƕs{lܷG|ٕt{ B;c&u8;|5'D믺? >ô%]{Nb4T R<>uwIvpxI9C(+$:lɢ7R;P5]וD ~O_Vޭ)ECܫvFR\UbA [K[K7y=T#"Kh cR4 [ham6DTU8p0[℮Jbe8nKWp8]Qvٖˏ :b G# p<1[!^7&S%?N3#_zիW./'Orm''x[5Ecoqm[n? 7M7F;p8ƫ^*x?s?ǥ^ʷ|}G?Q /x Nꫯ~2va^h=e n__ oxo~i?׽on`:g=R9Ce +KR $8+ uTπx3G5HPdՒ656NH`̴'P7D rԈl8SՄ͆lqg]\39x(Рg{LB͡є=6'xmshk31o;nۿas<˯`\hS7 $+u!>݂KaZMfs=Y8R{Ҳ#ir;OKdRAI9Z W8.Tt9!^U^[ k#މ[$Ά\RLtQG hD ڶ{grٰsD YJ)Fqo%];nSKIӗcDm#DU]QTq۰]tĜNt]f&e>lgƖOV`Lr9-m)xuPdD{fʙ{իW^Y~/X:n?#?|>ӟ41F9}'O{{|g>AY&^zt|>ɓ}뭷r뭷rYF~9z *xINk69?F"YѩsܚK S402Ka/Tjb fK.ln'Uɢ6!Үnr1<.+9Y0R7V%12w1[,K$v;iۂ~VRp426[]Cδ{OP%Mpep`z`RK輸X7ɒ–q)⁕\ԞHF5iB}0\M9&`(f$Ue%>ǑqdsΟcEq|ſx733>{!傽ۓ)ל8d,hHNIuUsq%p$uEV%k, GԌ*Rh2f(1gsR4M]8fw]/)g|,ƕ{!  S.;vk.? OCM>џ1c501_,h*9vGz~ŒI{)PjyRۺ. N P9G%sӶ-]LPŐ=dTjXTY\7u02)+"m _p-umFD 9qȊh \GD>Pys$/BE%rٌͭM8r( ,VĻ»B |`Em#.?]}GTC4MԖb25<^zիWg=Y\y啼-oo{3]qM7O}{/9mkXixxᇹ+yֳ`0|W=7tf6gg|vTB__.o{oz.9,rKt%em^g tLc]'h/cWR*9 A;$k)\aCV۩5Aģ=yaU^g]]g@)4;Qc*(R)dũ+^JN$ENo#ES5;нTe5@4KtXXAC!8 l ۶MGn#*j3#ݼ}AV8#gR<Ԗ&';6T /DИ FPA~ \k~rFg {x4Lںb4rtjx**)rRvG+Cr\q̡[1q! AX&>uj4f%hN 7Պ[]ګW^zGg~g)^k_Z~h??x<W~W_!gΜ5y򒗼__;?򲗽 h[ ~w<9_2:Lv!R#_/LۗCぺ|]7mUիSX> wqysX%馂ƤG_b\r356A,U.D\1C@EH,L^xxKtd nEv)&!gR / ❥d@ .%lLhLs1  KR{K|gJ 0J)U$df3u)Ql+dX+Fg% \ƐW<:lyd ;fD` e]Oy2s]1Le?ъ7ֺ1}m D%Gct[<[HP*h`!m;Ab9r = Xr*6 +78h'cDc;Ǩi ēsKs&WC;\mf>u-=;.;~pDLh)S'1F|A* M`3uKV@)Ե-)%B )uz9mŰ/۹a` Rz8***b*x|U+NkꕂBsR6A"R  =rb4gƣ1ێGy ))?]w}E=zooz\p=^ɾnz||7~#'Nx\'~'7<.t9d@̙3lmmϖ%M;_Μ9?s?_r=D䇁rC._o>9_/}1իW^_J@14%e$Α-]))j8\*@) g+48ۭ%;R%9^WEgk)2QQ20#R7Ya`D,}0^uf4[3^ubsbR`j蔌Vf5FsEhV"Hs]N,M7WUU 3mbM~cOVthhE$)DTl4)5HW՚mAo@ sXڟɀ\\ F<fznF86Y2vhCc'ekяr=g<z}-7{իW/jI6CJ)28Usx3 aN%H] B}), n6!{fԌ̶rLg{~-9YM49zQ5܏FĮٳ8F;{Rf666R)VA8}M]ѶK%^Cc<3ϙN'4WtիW^zswy'\r ozӛNԛ֫PիW^H2@VPY03/vޓWl-HM1Y!͎\jdg۷TwnA͸-HJ%)nip㹯+ʚǎ\dz#8Tf B3& sR9MbŤCR13Z;t2Z" 0LHDgs8R3$g+sFQ%ǬV2v IFdc(_ hc\; .9tOwv>n*6vopȍ7HgΜ3<'n*%Wx躖mN/̇i}GNLm;R8KS,I;W $2Uik|]6Ab\*3ýwvAӆi.VlږPU8k>;NuF WUIk"c\#HkSLHY 'FCbBh@Y,[ƣ͙|`0,V;Vc䂭9v-麎p`!9KU嫻\իW^5Lx_̋_M QoիW^_$M !Vip֑tq~ 58[( fm";KS]f)[b L/),]-KA)r ck̊X^k1uWϭA W HjKG_&iJhqU+PNlu 5CHGnV( ƕ' !K)biQZfR*-Yj.ȠA  qHЮEk0 ЌT ,1zy.-PUj:eC}"O OƸP*+:tb]*[)|9e)Fup*0+` IgN?C>̽0oyWsh{q@]3\E/i=Sy&GNqo/}sdqݳC`l!Did*ZSΈ!s! < e1w”R["}5ؓ U=&(Vʘa(%|4kϲ"Y9ǖ׸ g}w} =94erʶD'@ǑƇ᪉og,)8t!4|lѱ\;;{x ''VF\.YW ϼY?X/,Sy[ȣ3<|?LfnѣGe.WU޷͚5k֬_͆Yf͚w5mŃTeٳ͵Y\aKVԊfK1ٵ(+CoTd5nǥA+v:{ڤ/J 8h, ])XGXAbnU4@55Eu "6$*hL@}f] <RbZѣ8@F)mY\DKG4'$h!\Z.+`--jla@Q|M)kӢKEo͆G86ߣB }O!Z=Cah"\W3U:3Hx1\OXAӈ>E<-݉pX1^ pK4&>s,]pquA?>:⬿DJEG|krzb}cjՐW% t]ݖ~w~79_赗S&xO>*SJsf%]dc0M7^Ԟ5)jX!aߥbRy칦aHtT[ġĨ}~_j k;@My#jgugRw8q]CΉ95FRy9Xi+ w i;@AfobO5TUg1&D4 Z )H !]pP{dhFh6PƋW%+;gB{]q@BCьYQ lkޣ Y gtH>)C5BILG eBfrǭi] Uqv#. 6cZ<Fpgo~\|ν[t׳Y1ј"^Py{صgl7x땿gwqs 33Rw@-&M!س$٘`ƱZR"qrHa%ԽTKźx~m?SR)1C䂫FwGCN)%׶߹aMyc;aBh .^X0Q0PGzne_\p-VJ  5 8G?8im:roYf͚5k֬YB0;YfOO|]#BjrN++JžK8S1v\1v(禧ltQH IXNGgeJIhC-Nu8$'3ʘPM/J0.TT,m_F;㲻+d1n:Q8\PbgS%Z\thHѡb;}_ޘ \&SMK~TVI3MX2"ѡLw!fg\r]R6@v5w"&4bSqjZ RRB /;K+G *z[SQS3r2;W]g>KqtS7(mcX ^=BMBI ZȪLG5Q?;LN=lG Պ/&n{vhM nK|߈ٜrg?s.޺OPCV2[1cZ&oޒa $aY/SR,{{ܯq2C,P<ƾ?X z{νbtQ]뺖rH[Q3Q!b;g>_[xF4A MGQyzڲϰ9Zc?.>Ǜçs~7}94MgY, È͊>k֬Yf͚5{O}0k֬Y󺸸N/FKMlRNF4s5RnJ?t1 X_|-6-UlƺT㐂WHlSTEєyq IBdvz lgTb%AВl$ ٗz:b2)Ί#pXSR_by.]beDK׵8=ٿR_'P/ QZ뺡 e{iCeY -]GcD ȲC7zJz8?3͘+O߸A 2H {3h5Pj6RRq2C]qxPo1Xʻ)S[wT qD:%8$FHJr#:G@8Y,9=ٰp%m[o?΍7c`E?|3ٝ][y't%m\vU0Yt bNyr렙qp"5n8䒱Y++UL6ssQٛ)%JBPMr(s(ΑJvMѧd4j&RJ{./ZlsF`|MסϾv:OGl6o'ܹK_h}4{N~%feZZl;obOO^}5WP޹j"g%DX.6pv+2k֬Yf͚5_Κ5k֬Yj1ot "{6\K!g bbRԊDS>Z" @vuם3.FóhLu!q-EP|:;Â"7 P Wskmk :G8"M toF4j/KX+HE c[OEx)YB9:Mb@ u]0xAI⥖T&d;eJhH..^)!G haJDAe:]v XDtR$C rQRE,.7 +\B ]vvA +/\2 POmú[j&剬u6,BDpg}0 <:"4<>{œ3}g{墣D3>g)oڵXwWyŲ+"9 {-?~QG۬ lubPJP-=oiRJ,qBӶtŜc{3s4M*imw{V"=G}_h\jʼ5/~xcESM iJR8Glwɂhłض/{iU޼sАJ{LJ\ {i$#o&?ΘjII3NONX/DΙbAQ|֬Yf&5Mwz flϚ5k֬Y9*Z`RRS Xr ܚNW;&!]Skε<ƚb޼!iWL b]wrL+-żNd1a11F0e4z[ <.H8ߢjibe+xzJBKP-Nޯ2 Ey]]OqW\-:JQ Hd`dZ)1d t4z - G mUGዢZ(C%jB2+'}2SBM4ikQdې -ZRNd)?=zD|ׂL:P7ڎw$w;1Qrs~9rݲ^DNvAyIli[N5 |p8Q]pqq咢%w/qjI)j7`}tnK?LȽٞ?^m<.}%4ߧA%C9'v;ޖ΄p4qѽT۫ȵ\VQ~zI\Zf0bw" +Xt$#GGvO3ӝwSeyB.h8׆b]hsld[2RT F7#s%8k...kln[kʫSq޽Kʙv|Ϛ5k֬Yf͚mlϚ5k֬YT`fWkQT3 K/{gv&lʵ\2pSo2g3닫{L=V滭I'3ب%{Eaņ{IKH0ex(մT)}2ӷmmO.B0^px՚34|(j}hŰ(0FQ$e3W̨?pc-ȃMä(1Q-hi̘.uXz3NIqapn'+Y'k񱡈c<; jv0"L "6i;"=hmG4>: a =m脠po!i8^ d.R⋯ƪh}7q脡y1ݻy-u.Wgg~]lچGEIMlAM6~))M'X_}hϚ5k֬Yf͚/P5k֬Y!Uc A.+&ԋ<Ī]an"c)ԉCVY Tη\di&67~+4ד5#hI\*~%3%KZWcv={3SM\5fx*TJ㐋m8K\KۘWKQ PQmO/uxQ9T }S OʛDe5 3ƶ8oжEn2`N,iD YdÈ\99}sт`H"#TO! g R冥L6]k0MB#xSyk[-4m9c^ګs9Cviǫ|CI<‹Opxn߽Ǣ[$wuh530 qUK[\-K`kQjh3މuT3ik{oHƳ!u%Bζ"O_q z-6d'Dc@vc{{"iT|)ƟG!F!k&;3׽xn 7|=]"gOp]#6' c6GYf͚5k֬Y4f͚5k;U*f=c*;%ohW$XjWG W⮡ǖ`>o;Eʞ i_$H)4%Q%A<cž"5ݞr&gC(TSq zsX˯akDQRpbm }@ sLR΢JY 1xr.t]ØR-n x)MlgXwTn/ѵ-Ͼ1,ca(10wR'kbo1#$5tZ,K0QPv;q|1 =Gqi9|8eDr]MG&si[nI-yם,7s?ƗGd)jl8!@f cC-罱O[) @NqWN2Nᙜ`]cwTPSE#?C!Rdd(g7HUJѷz SID8[K&剢qXv .YkHJ"P@.6|4٦k}^z'@?v ;Ξ<&7Oy饗8ZoqzA=k֬Yf͚5kwH>k֬YfS%"IKɸz%T(mHBjTR=\T# /%!օ`2 qEKNO#*3j]뮈%B2ilM_:$T#+F;EDʥ7!Q"\t_&@v}RAR#$~3qֱD@[Hl(E]PٟSƭFȻ ۅK8@J&;]^^"˅S\(H.Yj.&"1Rlc} ` 3X$v?( h~"\n_G+$' Rxpi]ǃK^S5ix']0yoIzfsDql%s||k/k/PMl b'cR4|ef1,rm7 I*^ϼzez.RQ="Zʼn="B*PQC=ƥLJℜ'Na\TXF3۶-.zD4U/uNo=6k6%K?!7>m=A2EI.WQCdvu\)pbZ4{SttxKGハltz)/ޟP-<Ժ?ڽwT?Hj:ݰ1/>xFTT#RKFkMj|x9''7\\J'B ^ KsUކm 8Hu04DdJάV+.//Eۂޢ7G4MC? ߊYf͚5R)%>_z~a?k֬=OYf͚it4!;]Eq-Œ ,ɋswPGD,A$63&`h5TSm mogIv`Lt_"`loǁ bm#GSLR.fJ}EdX9KEh5 )lEҩ@vEMن !4e3XD3ka V$;ղd[u?%fRb7o#M4.Ed\qDEq2('X/a,>%6lɆ3,q,]w.FKg'e\p8)`fTq4'f``PdѡAfu blTO"rM 4Σbc{A:;&)U9n;֋%9g4@)c}ꊱ9^.٦[7n2]\C WWWŎq7/e~~b%?~oy)P%ޥﯘRhxs5k֬YJ)я~C7_|_|O|IIaoޯ?+o'X,/IU?g?Y޽˯گ f}h6g͚5k֬wH\-TE ^i 8Gk{oWC[+'D Q0NsR q-KLh55G|w<4W/r]Ӷjl{NAu2Kd潤lX}=;+ǜhVOE)Eib%+Eˈ\R4?|uHPM+nSa7`)lq%WFlcA*t6dhB5%kқ֙QKC?;Cdad4;lyq5M.M 5 hr5̱4r[nX4vH!Zi i" hq,V }ϐ9:ٴ-wktyb\pkqDVDX5%i8BNJ)m?;bCRx=H#eui?xZ MӠZp"+`6+zp'x` U_ z]aJV1ZhrHQ,P梇.qȎyq6$^Puf55rϧRiJܻ^bkR{dt݂bB q=9+>$0N|?9?‹w -!x[rJ䔉!Z;k֬Yf}3 v}_泟,?s?M?y~7n30M_O?4m7/~|#K_'> =kֿfC_lo^ƬYf}IKq )#^ C:R7kXj<+uĚVHKQ[rUp=?X PTPZXT&@BUAԢUEHfҋJ4d,J$xyMȪnYiBq0QuY4 9Op^3M,cv )q>c$xS{Ɯ4m즱`Є\[4꓇rB6{=\]paD'PELe-d%r@R,"0#!͞Tn=!DPq-RBPCj{hՂ$9z3mBZY\DȹZp*&S2RE yR"8jR=_u7\^yNEp^ua/_~ƍhE "~ꇸw&0?ܺq-cWW t[,v̚5k֬Y?>//ԧ>O2~~۷o=zٔ7?Av'ٟY>Oqtt//p-)q>`ӟ4_җxg_Eb:0O~ܾ}^x˿OO_yΚݨǏ>vm[>۷_q޹rɋ/ȇ>C]/|ɟgs֬Y 9WV*&#gݰG:*>-57HZXJ3K% R*G=xCV\:ClүXU+m1Doư᫁P,.]g TSFZr<'Cָ W[dqpJl+%Rl `M U1<ow#PW*;0*+lsEiBBG X¾b @4TNqM &cMy{κs>IW:e<.a,@ͯ Gxx|:Yld IDATaSs4MG6E5'O3 VpHZ x ?s^s!66?8`Xk$m h8"Jb%zի׉.^!Njl6]z??l6|'yի^Źsxӛoo2yk^wz麎oo{{\pg/}KG>rzEPoۖ￟믿'xo-[?|A&ɗm]wOG0'uI~~뮻=^z"9M2ϩR1FD0< TUc]AjgAxM(Kv޾ Q҄HXnb']HeW"9o 9O !bݲ4dy>LSUo;$jH2NH2>t,bH7UȌ!(ʷ$fČmʙu<.a.BDXbє~Rq9C;ڀ,A[~@JZ&Ք gioӄ+ڶ{Xvv jĉC +x^z~g7~ ~o|gw׼5LS^ײ_r!>(G?;xGkՍ .]%g^_4z_Νw ???Y,ć>!}Q677y+_x1>OsQ%k>q.]W9sz׻[曹t|>禛n[nYrF{Q;-O@J3N!bSR~C,c4,pR,Kx(  4Q4 (Yl:M[hص9emuoZ5⺠ (͑3 ڂd-SWHqXęI`&(ҕs(r59YljrO!uJ.$]Qr, 3(3 U)r_+bҕt1|}%WB#-XCZj:j(2d&[`E{.~l\| D+̛)bxO?8`4i'꺦tưmIX]]tt](?NXk)GNd2auuK9^j m/tΞ=K^wr뭷rwloow{w//p9n>|V:yof>9׼1F?'loo~{/"gk=ylnn.??s 1FwSOo;\wu/;y^e8zU0Vd] DeQ bFj gդM I^q6)sE6l,kybj[0Ǡ\rbԑo:Fec0A zA! f)qZFEEh/>!EUAEqiؗ՜N D4N"A.eJKo<)XCaҴN<Is դNWX4E*0,gWTD9-/hߠ Ib mc2#)a3䎂EPHIMS洫SN/hf3UYN]Acgr^00b!{OUOwǎ9Sf}e^{իWDvm>~wsm}9|g1ԿPm?8u{w+E/矵pO8 Cqԩ/iz}P;;N;dMozŋ)~~obw7wGo|#wy'Ν{68o{xK^SO=[Μ9m}.w}L&Ν;>1nFיf|?^{-77y{>ԧq}x"Ʉ׿|w}wy'M|իW)%0(.B,E B FhG5[`lDbRabͨ#2{O 18OFY jґeKO!bs5KGTb6i(uTs4.pqu1B6 $eJ=2BmEBٜE*1ChdFNMk€&lx$l@d+]L6*3{`kk_*hZBY3a%E0 a0OZ:Ilƫ#Y[Y#[W{ۜ`R1ʮ$Q q`|:kicb 4#%êt9zUS1r"Vh4tFTd< w8<3.+1+<WuM: 1#Ĉ_t1^MeWF >lwNi[5MOBZ LQ,J+X[P$Z0W:ꍔ ʪBϥ& yuW^sW~snyoYWC@Jai#4-Ζh}D?e䍅ό?sE(麎]@f'`49wW.P5"4sٌtʡM;$vww Z5\K H8ui@ha߫W^z}=x}^W=c/r~7&Ʉ;oy[x'뮻pGG}Q.~?Ο?4\:w;;;;w'O?' Χ?ivwwmU|Bu 7p뭷r]wz||^zZdf3675yl]17)A &\ XMd{at&-)$$QsBDY2Šf>]KJՉSlFFdh>s!@$fL"zڄ<%N'#r%w6Shds13Aa|91".OL%e|ޒjq !ECY`N` F#!΁w8$--(J/IyYήkcˤ 4)"α6ZKG,kH;ږ`*GCLmGaJM'Vٞϩ(Wp{͜O^z,(rh#IN\E<}pƱ BBK6HEA]v-s!1Zs|u&?I׵ #>!| H6ɥj 9!F& +^Ie/6'`Rɓ%JFyw%Vc0V֘Q׭c̤N{c D1(2(%JN'`b xg5_j!bqDې.2XB< VCb8W +"eNX* ` 9mӰ7 n'Nx {{;_|~'O__я~L-\mmm=go9<<y{'>//3z^"jV[I+WLc٘:©y%?D6ί_lfCƗǤu1 :dj:[L_Y-YdP$lgsds"a6Ar;rMB RX ~bswBfQ9dsZ7'ڌIjDŽ5ʅgyDE&ɽ#y! I&3"u5t&Wغ&Afun*?SXzʒ+a6;L+l%[͜–4! eAacC Lg%>EB3篜9'/mqe&iTʲ&J9{O `4|K^u v4'0l⻮ˤfm6vlsq=u(ӭ'Y2",b-N~hٚӴsWVY mh0 mגB$`e= q‘l?Ee/F.z(  FՀ1`Nzxŗ ?3:/ '|Rixh5/_Q8BjXe5ybHDq.ɕ1ss:Ge'%2]S^a+@Ei$*%jBI]²tk 1&-5C4}A`p8dee$ <~GRۗ/qUWKYUZ9ϩ` uޫW^>[VO\pSNqmqs? C{R𶷽L&*o찶9=M~WH^_O6{1_look-'Ok,K~~u^ڶ}NՍ7ވs=r>@Me׽u={Mozg>^~g~g|2p%} 3uQ,K>.e/{w'I)Ťz *g\LJe\rzU\ trDF9ams١ "A19 $ϏK!xSB Ara2 _.fs5'jY$ub2/8MUfz ;{0dx̩ZS]Pf ME$A$@ LPx¢qT2 o=bF#9R6iez-'5NńB0mka;FαB1Pbh$c HtV`٬kVlMvVC<',A+bqcN_͡z4ԞFU^zo=~mNjFWG5c6p$C C @aӗY)Jl !2 S5Ӧeo NH&;Vɩ Z^$$j5󏲳x0W99>{8ƨR|<X]L(?fJUxImKB knQcS>zz.U1Db}`Y~ZWdt]@d,j[th"}7tEq'i{U,B+igk&IH=h:a+ bJx']adYKI;,^MhLsGe{{}t|>kG3XmګW^>畯|%|+9HEQ?S ohCs ~'r")~W韦,K^򲗽~Y8z(o~ ?Gq>}zÇ󖷼__g~grwpM7#|Qկ~5?G|A^Wpws?scn%ZYY=;.~o뮻nɻZ]]{3W^_ג$b@ )saĀY&OҀ_F0[ȤlG2;7 `w ?Z,aYX = jf3Ք/$!o :fmx29Km-cgF8h;vw"JU+.W5Y;ox73 yr˸9=`w:Cݵu&s>uIh1ŧ)XCFb,)2>kU u_SɄ#+5_P,{{{t> MX]YaXW`CV8O=ȡ'(晫!E+,\"XMǠyDi"H\^]S e dy/7]˂+=cvQ1Pҥs-9,,&!r9D"q/teɄ#10IZ#I\hq>0W}2^tw~Y9]c$e2 IDAT/V"\nkts|>g6?zK^_XR2d &椪`]f%ɏ7&,O+qcxm6m6ލrӝN@M$Ϙeb;)V&ޢhPNjS3,Ƒ܈l[vyBT;mBFL)K,L BGB4*VE$_^ u1LcfXrĉ1ntN3᭧pX$&ËxNb0T `>N޳^h$b-1$(c}޵t$Lkض[9Ή ٌkuʼnUG#ƾwWߟd04RXϠUPʜx b\%tR%)Eer(qwzj:\e(h-}G{osO>8qxW6AMA]cm;(뚶 |OU+>1ޫW^{曟իWNeYcТb3?b/J /D_/tY#c̟/d\ Y_^z}M(~[Qb=xMtKp^#B.ĀM,&%eKMÛ Ztj4%*ӷQQ/6ڄ)ɖM9}KlMBD,JLĄMQh?dDU1'M9 r5 <1QgLPC_ 5 9d<5EN$1G:>IPxe7񂍆d=8MHeu s={ėH+ b$qjPQY !Ymr2TeE7Ze[ Oٌtê1  9;zxH +C$ 62MuxxG3 {=n8|ٜ"!%wLj7q]1 UR%b|Q8NHӶm!0(k 1ڶ1QV9}d.Zir+g mƻҩ!\z7jz2iMAY!"t˫HIV•I'I8g ]\EG!k2']t{a隖B1/DMnA-+7"yEň@# j"&=)*H,3,)2`W%[g ]VWVu"@UmG O>yr o⦛o -/TCJofevvI!pp1 e^"" !Xʪ"+jޫW^zիח]ޫW^z}LRU@⅚XRF()!W*h0!iZ<A © `4uHXQZdī-(J…LtPZM[s4Uf )'ﻐj.xb0!AZ2A D5Wsd)"unLt2pAHȢU45o $&%J`2|fR{l9n$5]&fF}fh D1T%eŪ\Uל?PG|j2>ږ$ՀMa`6%\z#2waе(gX!蹐+vsgcޏpN8h0į;v.oX0-my%ߥcqIƃ!ta=)ΥΟ{ǏqS3EE]p4$DJ_l6gܫW^zիגzCW^zL%F4.&}bIM[l:ŨEeKzhhll||1kfaUDOorA䨋Q܈MҤw6 m-!)đ\Ld^G:ו2oHgAarBcHErgk.6̐҃eʻ"#hZ$c0kzˢF$(L\BD"vEA' ̀Q5JNL*'jE#-+1ęjUf\ԾdoSåd%MḨ-FSOGz_"cA3';\yI<4MjІ %Ha6)gPTz HJTt-MhtF Ng4n%tQ,m[(=)%FafS06Qt)'׏rywK)c-UY;}knx!}qJ(k/"PXKJ^WX"g1Be)&3ɽGHKyJ \N#6Zb zs7( oŴ8rb*v+Kb:$E]ME| Iy%1y؜!|Y dh{`0` Gh>'$'ϝceP3rioy"co}9uYQc&̙LǬml:S]_4e48!ϑ#G1}^b^zիW^_ ^z3 m7hfNF/Z&N )-F2ҳf2Pg0b @IZi(<2<%M~Iׅa-io2]lN; c+tr 8(v"&RU ͂$o琖\* ieT&L]S 1bN^,Bb bN9HP1)t`M.HU !aBϥScXR$!6ͼńk=EB'4cKVoa lVˊdP9Gimjz1I{emJ2U]blA > eJ|*\SOp#zH"OZ: پDi $AC HT3vTT!  '+u&4L@;B0bCtI1/mb-efԧ!P'^[c44)рw@61qh| L)b0d[CsxcM+A:EiN'$鵚1!RֹHDLP$zSC>I$ƘqyVSXK(̫ArRZCX$A888=eQ`2\Dl=rEXc C%16͙+~ƽ:ueC]z\x?~O`wb8WQX]Y'%C (T"z?9gN'/qӶ ^pZ;|RTeMAZ W^zիWz^z23 )jv\ FK@(k$ѧXOir&l2_D%s iyZel!- )= |-K՜ԂM;$tfΌr&黤`@R\T Hu X!M&jfL*¥m2~,K*qĮ5M KpcIA\Q|Xì(CV1%_W**qm8RԅcaV#0O1"cvg FSTf-a'Sg8s85:&.7L& u Dius3N$$Nmfh-s]|2@]x1Q6:=Y iZ,EUbPE'.v-$a=W>+Uͬm#v#'178z laԥK>rbI$t'j$.sJXG5ppW#)Q* 1@ 9ѭŦYB( -|y5Եr-A\6D{|.-X˘%bK"r~o{*}QlL.d76-MwDd5;ۆpѐ! 1p}WUg| W:xu%)&B1g! _h4k;=8锺 ;F|H:YP+BޫW^zիWFޫW^z}ŝj"`!6F 15xeZ32%"6k58Q 8#@-4[LYhZ=LeN1,Y yݢt k4$L$ABhQ<9A+;+URxP &ƣr\N;+WF5 L.A%0BZk'4alrR(ʭ. bb u*'a G?ϟ3HO=-nɕ0D,#[p^8^YltTΗB Ă"]i- _pt`X/k."^hF+ i>\+pwֲV;D&6t2چJFꒋK&&F8)ᬃ(\q[OӅ@3ryǰ0 #$,+hc}7xUޛO`k'SWW#9`pm9}7ß``A9+bf6 &EYR$5BH[9u]62 ,mWcnRTCo+c$\fStXQ6|^aNF-'\67Y[`<Ӆŋc ޹̽OeA3c`4g~?ǙL G'S$i{l69- zիW^z}7{իWϐƷMD 𤦴X+jK/8i;'^Հψk5Ŧө)Hqoݧ™uaJːA]3Zʺ&bX=|nr{ì#"E!j(jǘv汶eec̹vwSJ: QTP&"$&&Qn\(HQQH:Uuݯn9;Y%'͚^s}&e:'dD MW yʫ9ʢ4[BcݯGL虜PKФƳC#`ƙ\R=Ƅ1I+e1JG< P`:2N\bR>NespI=%}Qgu^ǰ?z泉I>yk fs*fSN:uԩSfuzN:uYJK9FGhfLÒM-&H4B4&YtKI2/}Yb$c4L6d ?rH[bB$?$FR8s6-D8'2\(ƚQĤ6!4h^4B[LiMCMXg [Ъz±76þ+mل+ eNR > aCi\:c<z9n>ygD0i=usȢi(4iChM.c2 Jb0""4M)1^_g6bW|CWQٔ+p83͉12\2HOtpk0>;uԩSN:uQgwԩSN-<,9ݙMNHDvh&21pIټAIFz AQ1kH佚Ȁ ƕ$ \&Lɩu!D-$#Oa0!(NIi5Ѳ4K%QlE"Z qHLE116pUd Rt ިdrE6Yv!"P| $Ny@k0 _)Ըtc<70aW|YԄd0tń8Jiig Ѥ4_N8dX3;~n}^*0{j>Ц@.D3,`? 䐵ј5f$B D`[|#h}K#bs(B@,z(h:GklT}ؽ5Ǐ3Q+\ߡ:n-LIpp0aP.k,O5GmY̑4IjQ\d|QT ]ǠF!aDˈ5ccT{&#z6hc\1Η)(j"b;#-10)n IDATcҤA& ƪy-9Q/"ĨC.!%"!F &b !bjuՆ,  W0yeR,KBruMZ1N9MS坜=yz>gwg['EQZOr4vx۝:uԩSN:w3;u*TJ .KvˡU[[[>}zUr/ngդQ @sqĤ(gHI($S(!)Bb"qB3='ŗiVcy q`W{ zR:RZ+s](3 %2n&ԍpKdMA\fXXOa] D,QrƠv9m)8}5@ r+z-1_KafsY M5%aHHՄ{HtA@iIE,2DLŔ֕]IzF]`P$ o *g0t%!CZONRGϥހ|ccck7\8:a}02+qEZc2rX/6s6#!)%uH("$H4iM^YEb;C#T-MCcuH^81:T;Iۂ{\hN#Hz6hr|M{OK>r[khF*)ir:hckyIrަy(|=Ƴ!%ڶg6ߏ)ih"s^s-+Q}Y2qC z?ƨ(WeDyLIKbcY`01F$'Sr%%EE cp ؎ym]~lf.p)VWʔe->'Ϝ~w+ Ν(>&\QAɄ,GxN:uԩSN:CSB]x| 7q>K.]ԩS_5jۖ/rEΜ9Wɥ>"fIzHD1BB^ GpGmRF-hz6 Z w%dG՞BQKʦ2Ad:DH"r5kIwkA d{. 듆]<$!q%'"KKeh5}NZj'-HL)ibI%Rhj4‘ RqnCLNǜ.d ),Z!E,jzr?OoinϤȅs4-uƨdf9`]O~c]sA`2ɤ`^+b>bg-&bdX x)A;lh|2jr;WU:&OK70 ʒasp>^Eݴ\޾xaUQas8@bŽW..W9ZCB HJR5֏޾Hp}~LH<[(F(%_WIj#MwS1nX[#EM} :m } m/"(,@̩\Z5_cR o:p$ lLz5+vvWcv87#4-EQ"Gg{;?jcɕSꦡS]F,bc UUmKW6Hƒ$1Ibe٭n;xhj<8 V9µ v=z~9ݾLՔ񈅞StWLU(z?/IokmNgZ{UshɪDt`+i[5ۍ\6cj,sA{>vwwf<9 ?NӟW_ԩSN:uԩӣISשWڶe8vf@9aH.W@tZl]Nm=VΜ"Qg4^&c"ITӽ7FE<$EXcV"cjX%Md4(ݨ)+lxYVyCpj.I%*pw0SKM5|K2B&B $NK# %ń)^\NA Ā)K:h5m<̥~.Tm=RU/#(%ĕ]:Zgh,$ bN/%[{bCøاDv}`$y6F\04ΧH1p}DW&L}b^Xy14/z_͑-8Yg*J$c_(%&X[ٜ{;lhEl}D1ik :yHAKU1"8cIAZ\lZqL<>$Y1ٍ3ļCD(13`4ĹM[)F&.yenV>XU"5cB&KyLR@a-!1*9z!EAJz8# dD7X[CmY[[,KvvvSX,.]DZnx:h4UЕ:uԩSN:=Թu_C1>BRUlmmS=~V_Zb ҬbPr &()X4/nS9SdJSgyNFM4QJ9vbx8] FbM$]&n̿+D*?S:X&ufلHpqDkpF% p)Df;{4mat^Ӧĩc[l[bSv. 5+xZ1Xkpsh)c`YjR!KL%*feg܌#3<VșqK6GcW,(u.2e9JJV8IW$5ZxwS%ct@lZu|6ɓ4m0H6e 9o>Vy_9DZcuĜo]!S6РSN:uԩSG:CkD{{{x㍹XAm۲͝wɹsJnN>O׾< חVhᥴ"L/.2Ȁ_"RbR7N*-2VLlK\1#5Wx14En4rq͟T}r}D4jBɌc4ټHJZ2^)F `M MPhݔ8Gj 2ԓ&ߓ1H$^q#]`GOP0'+EHNg4z`O&Zݗ}>t춍niq=ehMŐ~Y|q5UZ g?ćĥ33J1mZBJ65--8?`/iږ8k&#KZȸקp ~z^Ck;5CLŒMh ]ߤr{]$@Z-5-]0-lc7ʒnpChG|bΉW&UC:61bc]x16ᛀH،L `lo%xx4L9 +aоV"Y2З$&ORJJm B5Ηu5."rX&F(\qt\,,,? nlB(HhUZ*AQ5|rT*yqu2g=CqsEɔu\Q1%.<'} T̍JI;uԩSN:=_tɄ<)8V EQpN8G?Qɓ_Cԩgi>r7p]wO}je}ݜ9s~9ίE&BZw&k4EMT|ea9 ujIfZ. 3oVPO8iYeG&-Vk3 S["m3S]Ĥ\HҏcmX!:YZ%.mV7 :x)嶧xd(fv8UM2HYhR=ҰBֆOĺ֓XJG]Xܠbrߣ 145M J_l}zEzbEZG(&%FLpֲ&ChW1]45Uew|ǷOϜ."ZBðgXدg91Zg61OIKFB8ܟPA0k4>0*vAYb``R9"s L&T"DY]RSs^WpwSNq~cҥK)Ox_T%1cK2J&FhGXD(s`OZ棒P5ݳ'GF8Kjey"K2 OTdKI&-)rf A1j%#dے y3b[# $k!h~ls8&9+)=Hjih3O)bP>&cDVׯ?Є3X4Cه`!xv)SW1\l43lKAЦ@EѣmjcK!:hxp ۗNYEOۚK; {C }<{|$绾of9۳ a=gc-8K,lOݗ.81^hceQpioTUЕD!+p`Rܳ{G8IYq 99\̸gńAaOpyzK" kVQ5Eo@#ٌQգ( f9v4:IisL[#`0"⨪mh(4 ,s⊿ft{uV"ĠfxISԻk,&c(`ŨGwf.:lA12ش2W%.}Q4r '(~%|Ly 6Tek,V >\Q(D 1b/Up^~h40zXע?1NX__'D=]by:uԩSE}&jwC(V{=i_4YDoFw'=cWvZ׽uq\s5؏]wR|+|ANbo?X}|w~F# HrSX[ru6/ RIj@:c`Dicf,KNzL^"cbŨjYѴn3'Ɉ#B1yFV5SFȘ҆v)*Ū(~B2Yyۊ$dY EKRB=0j*6z5H Dq}khڗ3=B, t#ZZ)@ H\!7bI>@Tm äHϔMh'HІD!uJ81zSFGZY,t^*vtgp bu{ ^{/Oo 1wZۻܨbd1"\s$2,TnF(4  . ^-6)jg2_0mj^pKٝNINoж- 0\YrBkTA9N(s(3~ bvH9QU1 )i"2^7|3ef"b2ՋSdsx:ۖԁ\n  W$s7\X!٤TrH"bC1Xg\rh& bd1e8[WIN:uԩӗitO~3L(2<:885y ykץxr)~Gs_KN_ uXx9U9Ǎ76'NxӣM|+9q{^~~7fJV8;( RƪU=Hڀ@O@Gnk41!F#5cT @R#߈DU|BBB| JԴ2s"iME+&HuTtMI6V ! 5E($ֳ>>+%͹kZՔFMr)2܈߫Wed-Ӌin3k;bp0< GT`}8]<0`%cdss{ C86Z9lB ~MjNm+؝`˗9XV%|G"Gz!QzV%pr ﻛk67 0Aw8a2ji/]k6 `3ݝl_]g6b3kbav1R"κ51Cj]"44^Xy9 sqAԜkXtH%jۜ_bcIڳk9:fr~ى<ȫ2ɩDJ^&p/)&.eQ0I1A4XS0/ F8*u(ascy=#DQ,[<3;>^2G(;u4ԛwwЇ>d2JΗt^:/~p u*Ǐsu}+ i-!3?3F#w}|͟ao6/zы迸oo9|[۾[o??ɓ<}D¬w#k?wzի馛ʯ <|oGNF I IDAT6cb6-1d[r) /D I4DzV8H\. KI&a?4j.]n?*!%&8cH}nMdEဦMNG#d$|J3r ,hϟ0kZ` :K8Z"eL6SD"yI#9S 8ؗ2IS%Z݌Y.=azhoc,O1kٌK;9sqbQ`g^/5<?b qϽr}pcn:A:OFfM˽{4md6VU s=/=- .ү*[(-"DgZ mɰh"MJ}5I =|pZgw:.1*Jp>Zo5->2uMLJ^l~`A:FMXL 6cj,(:m;Q0(tՈ2ME aJVhl. 2y _VC,Yt.N[.KFX@!)t`ɫ>4kb!~@x6D1$7FHDI-mcFѡs8D ȢR75EYI1rqbeAP/HO?c'>V676ۥWtzN:uq{߆шW+C=6>s@W}Ν; ^x9<}s-s?3Nַŏe?ץ׾~:uӧOŋlC|cc-nև:}Am˥Kj(c{{{qu}ַ7M_?Og>=u]󲗽o|yӞ{^~~a;G>Op]w:^Wt^*~'~ozӛ1r7w#$ŜbC6A2t4+dBH&;ɉ%ŀCD҂Ӑ%$k@&WAb"ra%=!z! &ogVo䴷e[9E G3rT*Y53EsY 2i) rAqF%w]KNΕ(O0XS|,1{ddgQZZFp4SzUI5DŽ{{xY[[g41 >pe{P|ǹϱc>O~y{H]N. SGRJ?~>}X*SNqC1W{677m>iO~6;;;}[W/| oo*Mzs%;ٟ3>>{s9{,<ϟ77X:=D˔8 BX-GҤC>'P#Πf<sgO3Y)h\" *K1Fޟ0!|a3g^{.ĉ56qГ:}LY`{%'zEMJ0h給 !o14-W1ϙϧCYԤ֓ʒppgw .~>m[ H/#xk푙_]CaL*SR9ߛ|F,2*^9|5aIF0(ʣBՂ5q3ajc ƬlcF}y)1c b )j٩~u"x8iyMGBj &,|\  hH|t>-Rm8m|)Ѵ $ach\N:uK;N888//Xky3w}wqw|7cxs__4 9}4yғ^:N:(xK_ (o9{,w~w29<G13.a٩g5y g|~{{//m>[ri|>_#ь^zd=ߨK0W?m)r9xYC,SUQ$J2Ml5mQ8꾗d}Q~mi9XD$jAe9j6\*b>e1b%b[#1j;zh NޏVKS&}MK2-K3LI63#h\IY`@Q1i L( 2<6yW=+)Z_g>0xĉ/\?^U .^>>/z9?Nqΰlϧ30+xg]sݩS|jǭ%q~*vƱwgO)79G`>2 {{2٣,Ka[M;%\ҕq9yE͂x^2蹲w@"=Fed:YXL݃~D("״Te=q['0){fbSS#c-N mu;h ݷ0_Į29|K Me1F # m` -]݃VJyYK1!@/ 2*I,W">}N>$ŷ H:* $y@0ˈMݨa/n;<`kc qGOuu j8y$up8~ RLx(KC'>N:uPG|Yz/zы'?ޛږcvkwUEQ՘ȅMiHBb 1KƘ<\*@9TNٍ1Zu PU^{k5^;󭪊_ݶ,Ky<_(xk_o>?ePd2Y& ,yyK^xK_RPF'w>?!߫[ߔ|˷|$W\{X,0ƬZ{}D,gyJz{Í7x;>~~+N|C"I>pwvv^\rk׮q/H_|yPx"}k뮻&c*Е TLvQh]4^:1,?-IMH41U,Ei0㕇PGmǥtFSh$Iba2.1&F>ӦkAZm#Q 6B:K3/xA $,7Kb?1}Ə"&8Qm.O,I SH:u Z ~c!{)@L;"HMP)ϢF(&gβ5kF3)`L-F"b3ں>xϟcTEcZqݰ=bgk=)%9/6<|r&Piͧv8jJt| /pZAIMg',:h6Yέ]jb$a$hg=uyY9bf (ɫװo;qVU(P'u8IH(KhbdP`s7o`c-Z%sl5m9<>b4R cÃ0WV KTbn+f~>|phm!:OT4m:>br8)5*Y$KS.*xQB* Ҁ54n>&EK]wnŅuc\4~^.a/J;D!ti{OGLb>2ٺcwC"ӧI%v(,hmǮ6Y#1 &9EU9\,2Y5#fΣ#G,_Lfᘲ @J(voq籽Im[5\ݒ64a6;GYu6łmYfLN=[)4$E|6m u%DnuC9.XE਽C;Gڿ+-1WBIJӘ_q̻C}F^'G4K (犦ITdXn vA:FQ ]I" 0F6/x鋙ؿ~7~4M@Z#.Wyt>9ǻ;|6J}?{իW^_ۿK.؏<ys8>>~_E^kk|y{gٟY4Mɲk׮pM.]ķ _B9x_·?a>W R= K_R͛_5}{=ثWoJC]k[򓧫fh~RUzիb]qyFcwQzիV?[+_JWj[[[ȏ5^ׯ_ޞz7o\]z*??Z>wڵ'`nݺu7p ]2FV`HLXAC6&rP:KvTX&Ҹ.B%0]j>"gAuR1,AuːlvB,  SA 4._$rC Q1s-4-DPeA: o]|Q%i㸺p,ՈքDMpWwuYkWɳ+TMЂ󞶭ilƁuL%9bA5d)7)F%]JxKrewIFfGW%(m]0w0zs 锑1}s8e8S7#jIQ$a<sMnv<t\Е6bBy':CqmSF$4c{{mI;_n>4`9>:`vr9O>; -ٗիW^z}iMoo| |po_`_ϯʯO|//x_ڗw~wx{^2{ n78o//s?s_m7;߱zɊ|ž +rQk .'^'uk2yz,~d ]Z2=}D6h$.^Vvmq+CluJ2T-1 ԷbD *r΍B4mDnA bctp{pTAV+te <,Q!!M#&!ш=]jǛVŤyK/Ĵ)|ƄwL,%/iǙ& 4x 3dT] 4 gR b@P|saf8u^rdzgkbGN3#֔M,TFE ٜrAf 5 F+t'yV as22H3v7BqD'ؒ |d0"M "\4(28}#(~:bϺ4 Ӳ7?hvh8`pG:?}iMK<a!I"F)Ky10 $ڄK[q9); uEZ[ӬO(rQgM۰{Ki׌ IDAT,Q9yQ c_-T%ֶC&xˍ?;>%X8m[|1(,cVWXE\B%quc &1,CB.Wb<(KժGaɎZZMeIYvuZRhcVTJ%MsWx"u Jljk=icBe4ֶ(Y4uͩ-բe67qϞ%U hHUW`+~ozիAЇx⓲7 _Iy/C׿ hގWc2|J/}VO4ykx_vf3> ._-`peKLk/_R?MPHDp/_ooo6$"B۶?.\Л齾.Z~8xܹsw}41i. :V@Ī]b\CPZp֢T4IBXCY9ѱTKJh@6-:^ '|"(VD!xPiJh }D8Q jb!1qѭLy EAPT4">ʤGA)q,9aٴ'Is(G sx` '"Gg w?O3Ѷ 3pcvAse1g;bD1-89*KꊣIa A gcGXRuK$8-T1 7)PZ1 kif%1mm[Gl llywEEG)kLyOP9)s  ˊbpP.+3qGQl>wEĻ\ݽřw ><E\@;{1ILh+:LLDLwǂtmRK 9ұcO:t u;Zz׺8Ъ[,U%-Q".YY: L/YIpݱZZʪ& mPJ8{fG}3 v]ט$jj޸l>8ka6/Ylpt|Di-[ IիW^)x{CqYxZ^OzCpw{{{|[=sָY__^* e!)]wݵdc^z}qA DuABĬՕgjGE EIW.(ѠFE^4D\D!޶sVa[L/,@:#@w+VѨ@Xm O>*b*ȅ@0uEH"%8 d b]㠭1Ą0xPE-ޣN REp]=nU!64*;${[E Gpި8~mb JpB89F ф,Ygv9]})F ͼ"AgO~Xs|p}䤩8ZQ ( h14ޑ"-$Asc7g'$iGwk% ,\K4Yruf0bVdyμZ=ZkIhLtY2js4,3ֱ b,$$B5|pm6"=Z3-(3ud# 7YL9sCֆ#)MӰ6MۀybB0ixmt>WhgTC4bmI1s'$ p]1kbkcnbouGwǵCD%`AԕSBiM@lRֶu.Zbd$`&mWh$`imKbk^QBjϹhMiMQTU[uFC8sǮ_j1ܸqu666obOhЧzիWgFx+V^i g<'21u]?$1,(Ǽ4=?o0yv, 1$A !5b-"&2;3-ov7ۡd1 Z#Fu%]馒ֆ@ۀW-: u J!"TZd&&ڵa,9TBǜ!L焦,"Y {dZʼnqNc%x,zo=A ⺇bU(vS>3*ҕF.e=bmE(ediA`<$$rUWMpyx89< `\p wnn5`D8G.{.߼t1#(8wj"ٛMi0$42M 4kX{GGYFb uR;12d8bj[!h[ L#֌"d6_ZWeRCƘX̙$8者XX+J#O3AT:rcai#F)d >p?gXh|1'9뛨i|`wwh`hҌ+5&i*NN888HSLـ,/>G}kڦ#F"Ɉin+b/ұɕZ=O1+ytltx]n5{,㲇[A/;DQm4U\`6F =IWvXΪ5yV 4,K N / 2-KڄWsO!J$IJSiڪW^zիO 0  ի[ 5ďx%H1xbZ'.ZwYҀHGyPa1*/:x1މH䨣ULKޣt zoAcbb%f+|dC4[S*Fc]Ul|*gT71y/^P[Hw-bT:!9{իW^zڨ7{z *MSYa{z=u圣X9D;KhVHW]TuUdn'sg XCW $2}õP.Dӻ+J܍l\4%qfcXqIXjQ(߻>ImBtH\s. UЕ `cWr`7>{SJqsecY&?"MRfm}U{իW^zF7{z jkkG}/b`6=eU5>lH: wfzx +,wI ^yĵw"bAk\?Qqtu%19;@tv.x,kǎ *& xP&tm{Bh#ix *Ĵn"SNUץ\ZcEP ژW:"kq(Ѹd&>Bl81@>)AA8>A5 ° zjE-ݸ,Zg 6&w=<a 21;\zvQS;Hh"XGV:h>pumq&x(-8im0sjI,Wo`ȓ lFTJS*癷5>MHԌD U@ #ʺ"!%)F+’n#:$ژESMf'dEAF`>C1YA,Y1 Zm[%b `@>hrI!]`kEQp211) ضbmIhgeY1S 1Z>B|YΓYJX7=h|.:xLaeP&ⱜ$d JCdDwFRhјܡ@fzw>Nlj6d٠;u!b!*>՝x=ˉ9ץm\3G1QOmK0qBH'ƶ4J .]"*)oyi}t"hHM!P h"yW^zիWzCWΞ=ԧ>E4>6 ǻpHS7ԠD*BUQ/ZfGLwQMbI[S:Ǽ9/HtMml,9J؟q.,*6hmԶABQ6-u=CC^$iY-qVjCfٌQVP]C,MF 0c騵 uY99GUsg9Ӫ$9eY2x>MҔjP\[#Q J"h>_pz4m {1IX,x9<8ĕ%.xt>F<n:>>FI Fg W:#8 -[t29w͛FIJŕUR&ӻI3Y&CD9)KTT9qG~a}4DQ9iy)իW^zSovvvCe7ӟY(⫔F"!CE01aiXA#D E!/A4Oed(h<,Ɍfg$FflCѢG s$(1|`PhqO.J4IQUE6{$1I`c2S\SdR7֝S/nΣ:[0!(tk>C$IP*^;jKgnzXxm8}t Q[[Xgq=qbk ;f91Ǖ[7hWG#Ξ9K#2b4 իW^ziPիW^>O؎X՚<2xYðt,@٭<%d%&aWq;".DZ 8O Ec5tD |4nTY2 }@P !dyL & {ۙ*E%&zI ($5xQH581:8a hǭ 2.ѐP:}>I !B0ƉjCJ|hkٺx[ۂxu  kdrm'P7qEa9Mؚ`H0p SnQ,)ڒ$Kb%sf3u@"kqK"K$ 5 iFSW i0+hD"2U,690M ,Ng-m5& IDATm,M҄9dzXk=x \-cin f\~Qp\:s.=:&8 {Y1 t+ ɘxיgZnᐢ((>ŢDkA$Y]#Lhc4I:Cҭhyܡ;4fA7tZ>P5-Mb^M*VjX_c9h&și*t]Yb@YVXgGGcU nwt?= >.Fh L Mkz^zիWzCW^zK"e[Kp5/UUxo4)=Jl.d1hm FLgE1>olSyą>FhkzN4X\ݠű:I8Ts(qޓrʢ*Γ&09eӠLBnRYMrx{,N`4Y>);"gVh) ' IQ%]sMayzQ0sM]d0{RBSZk\2H%35%ךQ^Pƶ,+rUvNmsjZAbx,ӓ#ڦ7PݥGᅂu]HӜ`D&LOӔ$qD6FDKH|Ε} 7?@hX.¹5_jlM4oLuets֒&*YDMFJ/0;GE{%zZu6Z&nmୣm0lnmqw,Iږ&],xDu(W!J@ \蒬]Yrc(:xb)#y 8/F &cn^f֥uv꾾*b ; laD͹ ^$J7xa❉Br9`ÉPD(ڪ(f3wUZɉORI}Zߜc9Z>?b"Ƣs7A@5=6.̗4]fS֨$( _Ֆ,Iaz͡C O1_r9alb`n ڐbVU5Yͦān0K51$(j܅ Iۆ!yfVQZZ?̋i*3q14 AkkGlm8܃$~ =a(,vБ$`amX%br_{BYUQ|U.`wvjMM?KBc\:?8ggn1qւ6OK1\q7C2. p:9FzHJk =֣ i{ J&;k="1t0mc[/N>PׄHB#l7+\R8(MJvwYV,;b5mrq++ا|H=o`wSIU5D牉zCa '&&&&&^C]i<vMDitaƯJ=:Dp%vE.Uѹ Te,D D3N5$94GtB'&$&g'".bĠ&DmtdcĄ&nBB. bRʀ2ɞtkrЈ\ '7B "egk)d1#+6@iPC-IH!K0qW }'! u'أ`fz,HP֡;l6GF *96+Csx.wjln݃vvÀI E]r9F%E9^6ClAi-/aPnl6E٬8}, \Qw eYR%;%Ik(Kn&1/*ʲt]GD?+V3XAN_[ٌwɕ{f1_SI)V횾8v_x|K釂Y]!*?qߣS$t nboG7o2 3lcsCxuz?Puipp~tÀ<) F+fUDᇆŦٌ9{o<˵/~d6Ĕ(+ւ6{̍hchIsQ=B1cLQ4JYbc֎YSIy&+P7UZXmI=j6G3Mxг [TPg@kFlE\ E Qu|^ )Mߝn<ƥ t )5EQ"!0%; LTeETko[/w{vv[ U8Ymipxnٲϝ1HDCB1%3#꼓E67ѣf9l3`|˭7 PY]bͦeqNzkA {9s-=KvY5=U  Y*C;(QBaFvÉh5׾,Ԣfo1`$W,Y jY"urx;UUSWe&6f> Iΰ_ES"?& >":UUa= ΁yHd7yU޽1O/qP&+e e1B{O1cH 6Fo;x10 >_'ހՎW}kqPhs4<nݸk^:>;E]'u]̪<}з.\;pttLU?zOLLLLLLLL|1/BA.Tcq^ryJ\)Pb}dmΡq g2O3fc`%FӐHZ)Rd"j et\:[<(/h CEb^P"Mv5k ` +%Eߩ\FѨP1R;@Ҡ *]QȺ00bBDC7 g0y!B*J|1\orw(:]@"0a1r$Qe@GJR<P*GɆtZ1E^|E.Jj3s;α=w*seok껸jAy~Ї WX4EA1" 9LQ`˂(CjhVaTA 8Q7+~ŋPuvާN=R=Y٫5˚f=YHt]CX7UYPrhd軎t045Xq]@ꚡ\E;tX[rndQhhv)Fj|dVUx]2tmGp|;nӛ crحǂ؅X)d%&Oc="WgC){٭ZhcrCJ"k\CP9ԶE8Z ߙYw0z ֕& ځ,H1rEvv؞ش[M",^jSnBl:d #ؓ*ZMA1Q5m3V^]v%S܅ >.whIYCBigyM'P9Bs9*xM"1P3hyA[CWr0 PGGC@m@.gs'! @Nh͆ޒ;ܵw%-͖.SUמMHV5w.(!(!YP5zvǛ”YQrrtLD$8kQ$njJጥi.^o^gz,;醁~؆eIYd6qxV•1'ulVSJi|nAH1VxV(:JeE T^W}k3:t5LE\lRd:1V3c,{68ڶŖ6FK{6|ΝC EZK|-(c<+ME5cCz}!r.9y+q'gƫقŬhl6ǖBo-}bbbbbbbbbߒ)PP5{cVُ*,D eL֬ıHɮ\+IXBɌ>S)`ԫIr;NbhƢ% aM9tj$@RH9ˁ7YΓ)%9ͯY uBAa 2PֈGSD!صF0< qv!scyZp)P R.h {ppn0X`o+EֆjCo,pxcARV4Y{!YDO\uZ|$aT75+8@q u}Ge b9*6}+*)gsVs;(cʖheќ "/` Ugໞ`%}DItҳωz$|~fQV0D54mâp?0h}|̶k8uラe](zoD3N[+z8i<\ATp6װu8csUvv0ZSV5Uи1lY=)%nb>/eak\AOãa$Zn9RJ(S jܝ.Ő5*Z8>>Ƹ07ލv$ɊFkױ,B$;\1, w",K^{.]f^ψܔ{Hl:q !ڮeV(s(YMnRS;@V}BMLLLLLLLLL|1;11111b$ZL.AW]H94/ו&S6)zp5q~T>R:kG"8 Q9PiZ~DcDPq ٍFVl&+= QkCH wQ rIjZvU8s)!6ZPuyiU6`,JYq<9B.?(NhkȶhE(M 5 Y!S8Xm*H*s`i(L- :h7uE_<].ТI10HL#JzM{ҠITqDSMŋ||IfC+RaQJ($D@%+?PjXeɦmA5{nF"tZޜPmۀKGsQYΒ1ۆ{﹇愣f-+9FX.S5]ġ7=gq]ws߽_a^qr& $vwB8ˬ>qpCb,Ku9łG>rÅsTN?O?A)bm|y+s$k,"7Bt-(׹Uk}1Y}R^cTŤsVO^Ki,6MY9Cu- E9w qL%J E_1889>b/ߟB344iVvvzMQhvgb#w}/bZ4e]ރR sO7d '&&&&&^Qjɍv4z Jabsd. MdZMo :<ɮT'+T.ićYr:A*CPPY3߉c nMa ]8D XQˡ<#8(ԾRA%]X!ۼ ʀ;fsBZk!0`4$d ꬸPN' N#)4qE' 'yy3'u>UW`,gvlhD2H (H@Jz8 o[l1PZ:h@YG6C˺II/(A'Hp9uJOd3=fkmحHLC %Vaշsx0toVlGY.r!cn^k:.z=C=ffsrDNj]GǨko>xk؜9ARb6);c g5u]SVCqxs Qxλ낡oy?Gx񞤄Y6CuEb;o3_(앱TtN\Go鄹dyٓS)P_ZRJ}8o{PGM/)€BQ%0mV;=R< bDR ZC:oXmrϒ[*e(I))} EYR:+\52Ja4k-J+gŞ%/^Ih^(#XZLvaȅ˝%o7Ѵ-5)r0^D& u5YG}k"1>;git-7o9r IDAT6͖;ַ󅧞f l@Nf5}…K%OLLLLLLLLLTLċ1&b ~oj n# Y}J}*DBLJ'KI=,V eg2yT5 =J+HLPs-Xd <,1A ȨTY !l@u}~AXg}C< c$eIa繁j:9i 6 t@}^@,PQC"5kLR#Ĉ -P{3+7 9/: i!z&zOl`г:+y·-sѬ3ĘPF,Gwm b NlN]M.(1J Cs[`Ga K{NةJ,a gѬ]S Jf.ۮeiUŽ=6f˹zέfw=뾡l/{['G<^O7 | gs1/jJ˚/p=jE]cfw6+O> gn9^hnuxzѣ}\ZMQ W'4.)RH/!xtm6Cc_*قͯ. vww#@QKcVw󉉉__ƍ{ܿǤ888_2}?///>!/ix衇xߍs||Lċ0ܧ: BI 0:y]QY >ɞu%:OeKB%rq'iTeBiiqJTǓRðoeAXC\pcdg\z|>ĭ!ʥkV!sς(1Ob [U.T4i D|YE";@\hj ~@R@  gEq54Oh$1bzKZ5>&4[4w$r +DAkz-XЅIyE)HHSY$&b7@(gg@BͰ)E){'+Riu[U0Rh͠rjƖ%;.R`3[RDm,ngU5o)=}ZT@vN$P-'jr^va:z躖 vrtx3)\rnhc-PMm0GV\?M; F)MLy5ǺޭO$rǝq]6 ]G?i 6(ɥՔeVԳ9"= ?F Hh'ҍҔUk',LSu gJ+ c.?UyUM"g,_׸t"(rخe@C@%|ɧÏ '͖+Q~\}Q9˗/6 eUsΡ‡@YlV'fsۦyin{9O|> %~~WV+>s'>+W|K.~>ࣜc '&&&&&^26hk(@vQz6XchZ.wFϦ͐Ce41(-nt-T52r'<,i(Z[jV5yҿtX7}ZG 4y1EAҹU9!.|H0fn?]P;"}%Im1\d#>Ph^Vb`a *kٮפ-;absN s]UE,z6a3tbu.)Q3lRMC:푘/j+sW+_WmMTfDb3lNhٜ@ NNNn6s宻x@+r1מG?A{7?9(J~`|ߢR$w!i!Vk,Jk\Edipn4 t<>>AЧӎɡ&_cBa,) C}7/^̻YTɢd\u2ZilYRUՙ%&O#:D{_m^W"o3ƍ,֐д !>bgw8ֲ\Ωs@:QMLLLLL| |W|c?c?>ˇ>!7OB~x>(wǫ^*~~c|mo@xЇ>ĵk׸;!vww`^~ovrr?yᇙfG哟$O7)??O>=<{ :o@}bbbbbEHK15$~B,|/f̪\wQS'ըAQ)gJ]'hUVYԡ3T9 i]"*\U2ftq |> ?DMg݋v&= 9]wC@=QuvZiRYFlIw0` h)4!.U8Weh6D=HB $J$R}r"mث 1*WK<RjpҡHe:D\GeYD1F 4ܾuHQUo[e+ʷ =_}|SO?EQ+/")͘$$i[.c7]r>=eL>@Y)keY1Yb-z.._|?œmi`1ϏT>YRYM]l0PZ:P"kCCA碁<>jRJXkZis9[Y1}.8Eɋy:%+mڧ{~ EYdg` Ź"L_/~| ! V➗?Hzn"_}?`MP{ONM&^JYkZlAk&>11111 #Z~~w|#9 ԯ^#3𖷼rI۶W=}?OOw gg'?}?ۿۜ;w=|#?#O$>,ϟOOΔr/':l[V}Q>OO ^k_o|0/Bi'1hSAW ]~T*I82f@Lȕu5G(mhҨRQ)!f,MY2դFLn*̎v~|.C~$8 cPc¨PJ[f z uUh` 6₏y\kkA]~6+1Fv~-Aϳk((hCjABDYMQWuE -iis6dK~Ńో((@w& ChPQ0GbsiP1]ArL ؄=eER $ H x*Qs?;~@K?[1AۓW!dJ%%DbL6ǘi$1 lOlV)uU^R%!zF3: Cqz MC68p oBM}EPW^K5ݝQ ]מ|ζR`c13]Bd= wvsf9ۦ mˊ+/aDX.:Gg?kWW|;?&*JO!R6h$OqN|b<{ヌk_{j=EgO>8햃=Ŝv͓m5uv 쟿|gͶ|MOLLLLL| SOSO7￟W~g~=<կ}{<?}??go~3__?_ݸql~m?}{YV|_~~ߟ)PxZ0* [C Q~!&T #GC DD)Ь.qYIy\%0GwIL2 e,804U mJ;H*x!!.+ORP Uro#sң?:Q3NC.sU*?zA9'UEd9s #jlFYJc9:f 7-riuyҢ\RB$ӆZIA )0Қ !>FF9u0 ! ڂhr{]Tġѓ͋ :TԾ(QcP{{غrH]G,)%bH+bP%ʲB$^0sAǁB.,X !ps MC"YQbw='G}˪0y/glh6|ኒi/y'EYa,KV}vFI^g Q$KgHBT!nϸ| D],Kb?ۛ7QMKzSD(ڶZ)Ҡ~ȓ丱.w h+,;sT=~nljp5Z8R3/Ѭ^1Ǝj|8@? 8^X)J)b@/}wA~ƛS"x !`M~#DR7||K_ロ׮_kq׽ .4-?n6l7[f밣ɧ;K A51 G_KG?QfGy;y}oy[Y/׿(p> _999'o|#ߍ֚'xBK_t]ug{{xސ{M;;;4m[vww3?Zk~l0? Sey衇ᛆbv =L8$>B1ٵ {Wb|'!#bT8b Qq&N9dxizEV_k,kPTIAďSbrk`>#5[REy|s?"U04HD\u'd)mZEnLVƸQsST0\ECfKrU%."MH.`t rQ4*1:|8ϣ¶kH1E5vH(PCc,i\tK_A!F\ >/D( ъ5gt^|V]-0+QCnO iZT?`ˊ嬦O!QԷ 8wp0v m!Ba{CBdQT hG<>pN5{gGGVaŖ%f՛79eaێfM$]y@av$l7%;5Ejww윙N[ˀAUnʔ\辔ATHɀh1HH Dѕ HPii|l9yݬ.9_̽6bX:{NJ+FsxpHS?|ӛAcGjw\J jbe:*+h6FoQ`9ѧ Oʢ\t熯Eh6:D"bE v)&{sFBQ .]=wm^gݟ|ϝ?~衇>4GZ~Gy{@mo{۰kO_rF5jn޼ޅ/eAL5Q=j].| u+$cS# k_ZR'>3e1뛸s]VmG( NO9wK]GJjE], ^cT {Xo6 ;"F5kLO>$< /y;yO^$?)]u'xΝ;oVw< ׼5q_W`z1W= W^~888uF}u)OOַo)>QF53$a&51rCYi/J1 p'-d$ESM&KW 9g8GH5#5W^Ju`GڈqdѨd7 ،[@5%k?& xLozLC] A) l@"gcnf0{Gpv ҵ:dBZ G̚^&7-fE^SLI >8r=Fv-"~1iXhrFrĴubܶF c/I>B[ HAYaPR3ҶprL1SZ.JTiqkUQ`Hj#9hڦ%,* 5h1,mʒ.Xl>r93uC 9RK!uӀLKIE9e)Iɝ;wIjB( LRW 1>f.!cGQUXc+l6+-<|^ ~il0Hm;˼ cG IDATpV?[C}#f{a2w6q)2v( :HҢb=ivxɟ򲗽ww"7ٟyGx[ 6~~"w}wܺuxW\ᕯ|%z׻>~? ==<1ʲ֨*UU;/n|Y_Y.?|}uyF57o|ooW oHIu r/~yk>Α3IMsbXĢ,YNS΋L#`k5Eb#&"`- `qN @kE_0L0 08٭,0C14'ߏLix,Zj z$h"u$}"8`ɫ[\+ZتСSGr>[aA!b@4"$jyhlHH"K!"H* LV&4FL;csD L M==I;:N^E99!n6`ZbC6[)锺-k:7Z$@dH][)]%wLBAق+v`}mw<{r,iv[羫8/q[ZHgh{K5]8lEU<5\;* >;L%Q}Ĵ,ȀD)ǘLNk ZؐsD% Ӣ`c /;AbWtn>7bTDH}ϭ[qew)_}v@uB)nMUt(EtQ{%|K{Xc4%?yy}OyۖnV/mcҴ<أg-5]SM'?7}waԨQF;x^]^/HuLwu]3L>ly~Jbu磳3ڵkk/(x?4_|~ƄQFZekqva1P#8kRgmQ"qX)۫GMkJ4}Z)E1&# Lw/) #]ςPo5 :j:lH ) [AբҜrɭHQ\Τa<"nZ5i}"=X2)vHm)fL{@@q;Bm b,ȩUc#mK r_GwXpFEsu8o;vk-%͉^?ZA2}zk8X{a !s&8<:"+񉜕kck)R_.mK1" BMS_n\ iٵ-F VgXknԻ9'ζ^`89=%z{^c^, 5J1nȨQFړs?pxxY頃 zoo+&5jԿbG5jԨT78blb:1j3e`Hue|X)E85٭wH9Qv:=&Er߫9Q9YY-PC:F ZI9]ôToe ;Mˮ)i㜾^Z:k &N;(<E*`mۋQ 4mS@9iEAu :X5 )=Rx=ΡdZ-uCw[:(< c21z>`Ҁz@('}8;S2$,lz={CPN`o5H:E8tf;{ JŦj<EEkqӪG6 eQѧH-jzeoĻc,PP7 Ow-1E, *Jdֽ$H8!n`ېRf}XٚPd:v-bɤܽm[f{wYR5]Yvt:I:&` Պ|黆{$k%MBONr8H9'gFWsXc9O>8PE{Ί}I֑s"Ljnb)!Ot-+592b#u]y^Gﰥ ]1899߿G5jԨQF"k4G5jԨϐIE 5ox3!. ;jcxXZ)Er_nDcpXdc4 4> uM3bJ~Լc(KD x1 ٭TƆf"}ȅCg!xf@L&j4Ou"wnLa P7Tе]qA2=gC'e'5$.M&,dZnc>,P!۝{~95nEƐkܺw&9]CYV,Zw]oYeH"wpߵ8[Ig5PYϭgo0i{xxIqR2rvr̵KmGo>㾽%Yĺ(J!P٬7 Bu4ǘctm 'چq]s:{u-{>D /8 >_>8mOY.̦3>r/|a0L/9)%|9:z㩛7yիn?L5jԨQF5+L>jԨQF}di`ECmL0, (d*\n{QNj"FV%f-(K]lma08j%_q yc5ymU3!n1ǜ5u}0-`R3N ( zq#YdDbS&PNmi[lFBAy}d|%dISHB6UOIhش=eSl4.!EA X:P1ʺ'f=ޑ״s b#-x02\0(^'&"/Q`&A3L'Bl B SLݐ7"lR"˺o]^Qj9g Er2ri(ST2M_g1t1L 19Ѥryl.%rs'!)Ro7,'SE=3M)CIk/]BR"%@4ľmrXry=NUԵ4uCSXO1)3)JՊj|:eRPUn}SR%'Cr 1k1&?{j(+ 0`=Ci@?9#I2 okA`ǡ<Lv$|9 fo[w'U.XLUMH9Zcl:c1_pM޿|=xztr!eQ2*ݎnq?q6!g5GW.shQF5jԨQ QF53t;Ϋ{n(yCq0,4 )S#<$ Ș4xjvC)8dQ jH:ٗ"n4;>h`ZE0eMҵj0z^y]W܋|$F-L|Rf2y@`'u[X,X8M1*,Ȓ퐮ǹmKz|[LAK+LP00ӣ z@ <ð͌5UeWŲbЕLȤLJd[t@Vkr9!fk' ӘkJ{ ٔwi[&nŇ@GIQN)`=UE="aGNNNlW\YSdZN9#51&)&swZȒ5XX,Xפ`~]"TҶ\:8d{ RrzrLl{ʲd||$ãKL'{xO!L' RRyP"H,8?Ej^Q;t R托K Vqn!^#g!1d9 锜3MSs) y}>mڮ*K4r7,Kkׯrfs|+^GHnKYm7hh,۷y>>3֫ a>Z?5jԨQFh5jԨQA1H d#ؘ\xMM;)朰"ԮFYiowC9|cHՄrFq 9)>$+PsjϱdPp67HbQ2U0 I6Ѣ֌|g3MT5'2hj]f&FduzM35h,ju%"B\o0K5v SzRRvʡ+4 w8`6ٴ%@2萅Aʦ[=EBE\P\5w𙪱LAZmu=bA`%&z<-qԈ?g=͖tV,]=$E}4xZx$N@鼲%CΔ>P%yװ7_]rPX/Qhۖ8c隆-P;Z)]۱ZQoK LʂYYluY6'SՄ^jb>c9RtNX) &=O `Cz-e:gRJX^Ή躎ʕr0ӟ7V;e%ι {ڏ`)MG$x&ʊ?p%fd>q b3͹tbk-wo򗼘=|>8{pb,{rʋz/g{ޒ挽>)eet>c|nF5jԨQF}q5F5jgJVQ< FdrN &6Ch}81:@U!Q,)nVz9e lw,b-X;G.^1-j̣Il;i`lȒWSl}yeA0m"{ wmylUzH@W8IHt"2ː~ͩw5ۤ1;t&"bb8g0$OaPL=O3P$xL!n-wPCZYRE[2m@ HXNua ,Jrvʲ6e IED; _SvL&SŘ8t2K>b] L<{G)yRTU|AwZvi'MMݵ%/ oO= ˗ZݎYV&SEۺ:#6cRXL*PxVPrGmv Ӫ =ζ+c'tmkױ4-a6Ӽ#zK\z?16ܼ}{{4M+,ul6/_eYQM>@uUIWLf>jԨQF5j^>ݻ G5Wzիx{%ޓbI !m()"D&ƒ`^i0˲ /R., (;:HIS!vkRx`!يnyϷo5 tnIS-~dM[3p-(9 xy/`F; zeҋA"r55I}XH>=LeV,nlPnÒjHm4SM71dF"8<&8-2p1ŘjEDŦX Ea݃>q(Cbte@CtCr(?OK_M f2'&sfd1YDzzˤRsY㜣{)|`VM؛Ϙ(b<{tI{,4q|rB7\?dZMmK#{3ٜzWD 󄢠,Kv˭bu6{{KLBA=Cz)H( Ʉp 5/|KNf< B647aQx}LEFӕ"2CYe`0cLx^N蠊sV^^1@U#6zɈ>HWgku=ۺ橧 vMÍcn`cG;fްX.}"ƈGyn˳nG$k9?Ae,"~7pT%EUQw-V& PT:s#|'+زMQF'R¨QB5cܬ IDAToxxyMM/{x.w|Ǘ`G5jԗBA Wt&VAȃ+# Jx-baRIYQ 3j܉wC]> Oh)^kȢa+GT޸i{,bŢ`bE,vc^Yƪx ]}8lc0Ia]BVғ 39EeX3DeCB@pD'O+(=Or"mFwJU'_`i M:hp,u@"sjQ|JH9]ҊXg:ev9>gl|z rLݼw=]a-bbFt@(R6)mACB{Ռ,`eSOu锉W4L;{Cct ibm ea}zRlѴ ﻎO1MQ9KYik|䜹t ł˗X?syss>pvOUl7jds˗٬θ}|}{dX0)5O|`=1ED2]0|%9']aze> $k(@f qΑNplҘ1u0\re2t!)6`k0 go |gyG-y|͊tf%.e{w,hQUcwz뾎R29GĔ8>;eX*k !Pb L%WNTݮo8rP)ѧ/|Կzv˽{Ի2jԨQ_o/.5+D_3j}/{{{\rvˣ>}W{<\|QFRVcˠtf8$ &`fHcP(bH煕C4}-D9]@Mkbjgaȁ5jI朵5ltsj Gv5f@8kui ]AƟŬ]4ˠduB&o ~0 7фyZh:x)= j,&X0P ~)w5lZV| 7t F,%lsMZV:lke@/~`՛1R1hCv-FrÊ8\&֍w䔑V%Lbٛ7y駘ϗV<󘔎p۞Vn0ЎzRJgS3 G)`b{yj=DJY'UNW{k& RdacyDx$[=\;-Lg+:X('Yڞ٬bX6-y^LʙW|7m9rjt$&eٰ۵,KaUfmN-ܼɷ!| D2_.XovTE`_e7__n;_z6 l6n+u_F}yWxy{r5jԨQ-1׾-SO=[E˳>˟ɟprrC=QFjPhŜ'`dv$s6v0Ѭ&ŝJ(aab6 wFy8ؤȔ+4 iɐHù_e!1&bE ^$H6`#[^9)e05m$1> =ItxCa2H/㤅XH}Ig@&WOrI$dU$ &Rgت)v,5dvHRbh2INFIع}s>i;Pc N/;h!e_C %+Nȸ?^aꚸQ^;"kpeɽMop֓tqeh-I23YgGW)>]>[aco:cJ6kf &H΄`8[o@ ;ں޵{˥CbӰX,z߃c$g e(GG؜隖dʦmh~aJ ݖyvÏ<~:zC.9[p  9 eY #9ӵ"g2 c`#{CK^{ $ѧ)"XhRN]$ae<"Dn^^k]LY]]60ɑ2i1qrz}1ω{rn`}]4c$-ef(-|;OW~ jG*202-֨/~~ ??/ضw{nܸ ^/ضeԗq7󖷼__RҨQF*ל^5wܹ7ox_Yg{{q{{]WW]{ԨQ_:gkϏL/ G5̈8ƴMPlk94ҩ(O9)[Y2ڱFa-/x g4~N( Q\3ia)LN P"i֍7WY3@ULľaPNZ28l)tlDx"Y\H\ /}Mc8Ρ)"b$9k-tHp."as#OPw+,XlVtWSS^;MzL`˦zOL`N*X$Վhk6\UEW7,E4 ΀DQ``[׸IMǝ;w% 8[qzi9aYg2}bk]KN">4M͖iXLfw>fՄ{([|ڵ\?Ks!`[+Wq1LHMKْ|ɔwK^^RY? .FlYR=>W\$"Թ[,ƨ.Q di>EyU?w[/IQ@eŰȌZZィXZnX6N90 :aQA0لh}.g}Ca q7ާ*T}]9GW&i96(HD N #@i/2a1_pqԛMƷl>9ZrJlY>{Ww͛3w.j Q12s8X*jI9ǶPf LS%3gb9dYJ́!4W䴒ylF%YYoWm=áʝwɕW^]vVŗesW+䵯}-{ꫯ\qŋYxJ{zy晼};`ƍE!W_}GUfǒ^Biţ8xa. (d9Z D A;R"d!YIBtIlKCiYjuI?1}PA"z<‚-Uo jb'$%pm" r5Ul Րt*<@-Iu!{PUzBj5)LtxR IcIRK,o=΢&{|5p\ U`t,yk+sF]RR;&nK+ <* B!] 5s id4N%^UJaʓZG .щ9ji`MӬD,1^v=ԒeK|@EY uLP1yCrjizA^g\,((YC#l̤CG=e6>=t&ɝcbDNɱqh4yAgޒ)7oVlz_FAgs5QA !"JW q֢+7 EhɐQec"ٵ<W u1Q`#J`P zInPJuqLVk&RC{bed0!xVx5I1lR:I<hw_j-Z׿ufz_}GҥKdR[g!V aUy<Xb;^JKq/K-P΢>3]Pzvl(pWiQN"AcYwp9sG1J446 2Fў`WfW0~4[ZR +/b@ * $q><⣇VL:WSL~%QD8K%B㽔:--v&v;^YOŴ)xnzǯٰ~,HxznyIXv6s3fPZK .x:@71e`,~nݍ}:yPkh 0lJ2^ g|_Dv̝;c9Eq}q-9x׹kyGG>1{9#xӛC>u]bxxx(#8a.=~g2<<~mn/˒/N8y1o2쵕b)7**W.DUIi0oTFTV$u Q7mkW!8ʂ1*Ti{(Qaj:U7K+(+޳U!aQ ;ů&z0s@jT-$@T=[d<*M*#EFA$8<sbj5IP^ BZ 4j)y B`%`KT15tT3<$ V{\GܨړؼDZ)ݘ.`{pϫ"e[ASt{t&.n6$@sfs^%ҚZ0<8MHfR?LshZ-evgys=E8bpAVPmےC Zlp!e 1ӄΖ f6[ 1אף,rHނ6{hm81R,&; @m|׭ b[)JOU D)ܗhZcm JD`^_6n@d"gx51gG|4OY{,]-|Czʏݸq#z+g}6eYrn7o}~_𲗽ZaGAo8˗/>N=TT/zыzX+VItN+o{۶9Ͻ<c>ls~/N;mf5aٲes95w_y;ʕ+o~Ò%Kko}}C\ /ps>H> o9i'̕W^ 7'?eцXi4u<Ìݻ,,'cߒf`t\8Q"ri-`]˙h3fΡ>8H])QJ*lN o ڐ){ʢYvI2w0(v###G?3 CCCOz=o}[/^Wng>V\ɛ&-Zf̘}^o}N8F1}ի9xK_b˖-|_6V^S:ӹ?5K,u^ n[n<9o6,㤓NVM~%KpOOǶlk^~}~;r-q\tE Lk8x7{c7o}ǒ%K)=3x^ƅ^?Ϸyy|.R122ݑk/FGGY~=wvǏ9J,Y7ꫯzFOQz*я~DF_}W_KJ|QleO_N%'h JEp3)Bd*tRRNZ& | .Te(T IDAT($-Ue)%z(g%y(918hhr2uT`m`8C<[HSƊMAxкZ1bUO +CD ZJI[$t-4RA3[6bDG$I#@ !eK>VI:ME)m+i^&x7Ÿ] R4l UK F gt(yI(KojuT!ҤDb2#%>Qy)kI@i5HPag`pzOd=c eNgMEt6ofr|Yמ$SgNmx{ʬY $I#$P*MveI˨S[tzʼ`#YoC6c͛ΑzR8'B!Ȃgxp}zV}fRNvPghh&3FfwCRC2hZ1Qr{=c{LEEZ[=k1cLUQhcn2{Pq,i|5@NvXgirYآNmއbŪU$: ģb5 ``p+Wqnb "9Z"y1jFMǨjQD,$M7}=3~u]y0_Wp|g:Dz{~^/yjƍuQ\z饘|R~>|Ri>o/})>ԧ˿lw?3gwgʕwy<|N:$:~߰hѢ^jXlnw8ꨣկ~s3[֝zW]|%}S1s2:ď}c?l>諯RCҒNf2F[]1L2'N4A(ܛC$ZI:QSY1ȳ { 43!@՗Ԕ/ϡ[Q$ÁZ"_Q\|ҢjuI8DWc5BNTZ\hTe{EALF]vg+~SN:x- 4V'F^H~Yw \Y +I[/:Z֢x^ RȪHARXOKA 8PpD4R#1,QC6ޓ6B\+s,H x Q$,0E,) Mkԇ^#8O 1ZATogV;(/nǕ 5pЃ t&'V 1::Y-JyAl""px:v5e'*dxx&f#Ѷ"+r7m2p {"qNE cLJF\`XʲA5y@i/ tUA!j |h-(kK1潰mQnz9w#~~q`ÚcqEfA- KD14a CW5qG`^&ڬxx9`B(S)C#nM7HhCO&О`>jc1hկ~6U/+ء>>1 ?x.OOEQe!nvS pGw\tE,dy'rwpM7MWfٲevic>03/^s%ۘSiZl޼+Vp§'xK_>׾|S/x rbM6=>j6iGkw`ڵOxzzΚ}ןN1Rn諯돨୘Q .T4)*Mׅ4tׂt2WN8Zi̴a:%<{0Z~vR hKT VA<SBE~WZO0zޒKޢ y.X)xQ D @幜/IU+]u*/%n"1杇 b*$HѨ7ZTFb"-9Ksgsy|$uAVU|p.rDJL˼#>sQ *l5pvhXf",yVRd%$5039qq*]%qi)ɉY'dyHA0q Z4%8KP,pNRe3h&MSA!(D['Ɛ4'4 Z&eYF16y 4qiFQxHn̙I̦uLv2?XV?kVSB|q`XRԎ@kEd 2,FitBS+ /'S%R.LwahxָԹA煉w9夓ذ~E^p _?vVn䤣`yh 4EG lYBYR~f5' nnc>{,Z.$I#L_r O3g̠0Q8qy2Җ̘1[y#:[i (D(Qﲟj\uUj5>mr!<׿5~v| _| MwmG>n_5\=vy*;һ./_ε^)k_ZN9"xzyI'}nwS-ZGy$K.e̟?^(zֳu/~/~Ox7of…Ok?t;::ʌ3ظq#7nd֬Y;w>nj?Jaֻj6iJmP7}uwo|s=>O|E}׮TP﫯ꫯ(TiU*.SŢX M"ao%ijFUh)]PU52(K))JF *Haw`8ZXSEYj*J%eර~G{Ei $Q -{FfM/?;[Y;ӏ==Yئ ̛5F1\Z$!NRmZzNV#rz݌8,g[aʌ8IatTtW<^y{vE]Vc7nO稣{7f^z)?wAO7⋹Xx1{\GAõ^R38O?KruqytRʲܦ8&ߏ?iώ4z:t:WSh䏗$.Y3 6l`||oG7 BK.ٮ? 6^:$UwAb\UհEIy)B 0] _+֡v>ɀDLr.ՔBMe2BF( \/_OPytarݥ3:thP#[XlE%5Ԁ"/ J|3/!ӟ4?|+⋷;~uzы^ċ^"V^_W>pmq饗L;ne˖pB.]( ??rsyqM7y0,rt}W{-dSئ3Yho6ꫯ3uD[).}{oywԗW_\}Cꫯ5.T&s[& N( \l{GUZ\7W &~m%CqTwq_q AZbAIA{)q1*id RHL8kd}!b `)(ŐF +%2 W0bTZ+:H X#:7fkyimF`$ʤk+UBY!^Z"^DAt'Cɲ H d 30FVJ4/2IHS0CQB vR s&& J+9HVUV[ 5O qum"TZCiI |)4M9Au%IG&{b1x:ݜ,qi $3zM8#ĊYLQ=rѵ+́a8@:֯Nf3cxc 4^iS͊af:yFS% "|8WiMnm0ׄ* $qBPZ&JFKz}+ZD^adL}ϖeQdd.V1|$&{1.gYKQZ_-_Fq-2fB8%1<*ǘtJ eYrs)]ɡf_6nC{Y#XJ[l6IA`„Wn4%#(,F~ڵ1s]9xvz.Y&%N޾osK.^O#㩪c9d=3?)˖-iof}e/{t~c9($_Ͻ˞{əgN<ϕW^ٳoXl^{-zիvZIV;ꫯzBpP:RUΨґZ J;HoŸx) FJh6D7bV_\@U01) estmTjw9b.;_($鮔_5Y*9Ob1M$\UűF$ts(*i$)=Ia'('Qe|x[`d )d JGgkŐVeP:A˘`-=z=Bzэ*MUy?e%o"[WRV; W]¡E$^ WBނ-QF qZ-Tk0B̀ARN tn<Mi q=t;ОDhqccG2r=9|Q g~EҸteRℲ#Ϥ9Oi˪HS!8+.ҳ_!{DZ:#~3Ij)B($M,F25QQohhi z=Z'x]7(:eY#4[M:I&&&l9u645QE4ҪSWvVSe574c5e/=k׮o}.OUNqvv / /pze_W’%KvdYe]WUcis='>wAu㡇Cf~~_s!xb/я~oC9d:XZm~~= }M}Cꫯ v4XLs$ q&£: *){=S q%+ijATh@Y%ڗhA]tFP=UXP]F >QW#]!iT"VШ`dF5q^T/c(AL¥`KBi TiK"#2PPYN8Iz% 2t$k( L7Cusa ]9(mWZي u2\A [YKu|`rb=IK¥d.e^H9gp:@jb I0o|6`ڵlLEAfi100@k$I5Mәgݚ5LNh6 >zJpo{&'nŃlܴ$+7'd#Es͡XpKZJgQƠM\ᙨJk5A@YcZ{7Kes9kFy\t=::[6my睷]ŋg?KVܵJzwIrhկx/B,_;3W]u|0\p/?.yn{^򥯾ꫯ[;?=hPQ$tUZDW+k]BZ2zR5b9)`{ӆ4!5pbxPʠI'FqBnxD B=4}6Z)J0H /PJ3u A <(_!R )KK|Ki7J'Ns |5axP 3#=IR6ZgD^&PMtyx ƷLZB ڱtx_Wkk_Z>OqW~j|_O䓟${,G}.w\wu\vevm<9a˖-tM}=9.rnF>`<@:֭㦛n"2>ѮN6\pv?pfϞ-:g?Y֬YOS9g3w\6mʕ+Y~=g}6/~wjGYb/~6{,VmW!)LOw;Ҋ+Xv- ;:m,{zzˏ~#<#Z .?>? ### ?wxxxseq]wɿْd=y;Ӄx,˶ Xb6CV5]z?H@ 5ZEW~Q_QUViRQ)Up@ݨHH&!{ 3 $@G}|9I}K@Ķt~FHNɚQeetQWቘ@uL\wt7} QJgeBDG`ٺ r0-L ea`Bs A0CP{$_N6].qWE`twxЃ.uq[ 4QAt ]U:gtI4Θw'?|0 =L6ӝ>AaIv5:uZ`;@QA:9mlNu oWa|#yy*,'Dϕx~|^J)Wd1L-ƈtQ2ArLS0 |#a+L$1LS)D?"X4JvQ1kjQJQPP@Ȳ=Fl&PT#'M&Ia+D*L"b$]%DMEǶm F()'IAAyyy|7UŅcS)}@n.=ZX5R$q\/g`e&Lz.z{bSN ?}TTؾC%ct!v :4t]B)}<]]X]Y{Mm 45 DBQxe]/P{gݺw˲14>={^,=q\bYQ F,;$Sq(!˦?OWVPң'0asw?87|sf :o.?^{-S.ynV/^g}Fii)wW^y%k׮q%;üyp]Fg͉'Cyg 槷2 c9|H$ɓhٳg3{lӧrJL}ݑH~{Yfdٳ's\r  {lݔ=ܓ< ?6_V!vS_<>X,F$:~05\Ô)SK)//gɀ.ZΦnh4~ii)+W$LOݻzEBt.) !닄t.N}.^"0t oQk*;t19]<'X6fO,#eLPcB]GaX~=~zobDBY;D`Gt 瀓8 J"5 sFCzꔃ2t93әABYLG~'2|,K A`ٺ=' nW?aׂަ};IOS? YK,5GBmt{L?O}D1?׬7`[&݊1 n{PS]CN~.UJPzhd">iq\! c6keNfeeЈ2 ={x!/?{!;Wn'}w+l={U}ٜ}|SioɈL@{l9;0;vcSuvvf=uTN5Ѯn083-}_GI(* =DT!zu742]JfET*ݝ^BAk+i1t17]7I?@sٺCeB#vҙp09=>ʶ 2Stqq18)^?in_tgO4PN@c$@a~HaꟋ@|E)=4PxOT@`jp1l[ܔkۨH J,hi?\Ѱ>`Le[}Ku;׮]K8&ܜ\p]r\ND2$ S)VUV>aF(*,[Q>rr!iiiw**DuHĉa(b(uu54eРKC}=pqQ8OsK4 }P>?YFKxCX.uM5auAY> ɵm1L eC .:]_m$}l,[4IPe r~X1p\Gw&aX&e&{7me8ٱ 9F΢;dSYYI~^+/deѣ[hGޤ\wE]c#kvp!X}E]+]ɯ~^Bȑ#y8eСmHiӦqw3c Fɓˈb477sglkeҤI̙3q߿F!:ԅBz'(WlQju,P1#J)SQ[ AWzidzMݩ .t֌Ӌ- " xw=M:ЅVeM (n:6qu9B9>V2o^H' Y~: MlsquRh\g2[*8]`aC^, setܴm< B L0Lu3ɕҝEѱ8*0uy@s?dsԍz)H xC;)'mt7O i:;^Yo:?' qpֈ"CH%ZZP<0LD*8,H.G(dc[6i[647DeKn^n2EzaH|JRnxD"I$6KjG),LjFQTLCC ϣgĢQVWB ۶IRc{PmL8  @C}#7Y%~BG**w!}=H6>Yb(Nv.ti[:J6L#JG_@z(~ 1m JQ[yw%H$T԰~P__G*ЫWoWA)J)tV:9⾫⑎;Q:Pa#]t e{o(pC ]M%孋xuHj$ٺ ?W:FyAN*ǯðt[a u =u̍t!tB9\S~<#ȵtm>JLb:QOi(ՆΪ&ПrH K-3C3Kz#>;փ=4inyCfeZntJka勵IOCչ~22'QPD2*!Ѓ)1t'Ln;YYOhJw%BC < CF !v;?ʰu\Nҳ|ɤC0d 4M KA*<\Ƕ,C,4Y! H< bYGQw eЫD"W"&`thb1¶EV(B6oRXjˢ 7xZBM,;XxCHHp,D҃|u< Gp E3Ka=YU`| 3LT)|}Pz)AXO )LÖLԑ1!PlwL <<%@G̨'=,oSqilhdGq{PXXH$I$%Yy47b6lưlzG"BVU;F1L}JMm-5\CII w}wg/Gt;Sg7\z 6aÆ{_rٯ =~KZؙ푓']]cccg/a7őΩnOg%M= NgCT6<ݙm ׁ P cGEL\_wH+Cw[utՇ!ԙ끂nQ! "ʰt\$[  $=]!E}?]- 5*FwNIt1ev+=Wb}PXwenk[B移ӹ:~Oe@2;a¶Nw\T:7\PP)٪ 󞯣RRx c|' uP: "L/W s]4|P;O_:z2{W33Z QA)1|u eT$!^=_1LSw']UJ9K=7W! ta=5 alZRIC<8 ka&Ma ++,RW*|SI1-P( uLY!QrrrXlYg/Ct!;3}G0 ?,\?xrrr:{iBvB])݉lNu ?ݤn,]NI%uvP$聝be1~ )eX:KO]n} ojBm R| OP [ 4ӹ h +7I: =@p[0DH(*#DveZ @g#{6o\)m .v+|.AOBׅ|nEI0t繥鎫cWB6!^ rU F:tĊ:K a肿?\E[! <y^'>Ѥ * $7ࣇ檔 a9.["hidJ_yux 3Dx3+︄ 3[&;'; '6 L石zvW^M<_~ض!U8իYz5%%%[~~nNUU=zi-B!B!ؽtz{&&(*n[osGB>a~tB! oM=2/S[[˞{Iqq1%~|u],/hwUMH.IElk޾P(뺙bqeU-~:B!B!.Uݫ"7mQۣs|Goڶ7~:B!B!ںDAtxkoV~*ӦMGL8r73B!B!bW% Zl!Xv-]vpKf(ϟ 7ܰB:6_xNZB!B! 7]ߥ---|l[pX:hnnu YYYfϞ1:wN̚5 ңGƏO߾}j޼y<3AG@CCwK.W^򗿤O>:f"7a0j(po&Gqi״3<^x/44hG}4F0:e_!B!]{[[|BTAt73;jwPx'9cYh+V  q%|o_z1clqz.vAw֖QXX^mm-]wH?I&'p裏ۮ5oj=yOrS]]7Lnn.|0]wݺuꫯ7d„ ̙3۶x܇~jRZuݝsp1l~z|W9;í?UW]U'$E!B!+T*fʃ:c=vD(" mennoy=-GnbGu34^Q9s&\r J)멫z|ܭ;òeꫯXz5K.e"Rv\r sisJƍGYYY)SN!77d2ٳyG޽; c޼yuYAYl}oSzvg> w}7L2q/RҶ{|'\ve,[ &V)ĖuZL?~<3g$C1a\%J목_{ O?e}gΜɡʐ!C68ƪU(//^#77>M!twyxXr%EEEt=y73I$7:^z%***8p ?O0 x<O<ʿ/,O&//u7o1qѣGf6Vd'xznݺ{rYR%KN5UklNa#"+2/RC{~:k֬aĉg1q>˗/g<Ôopn#G;pc2o'?I8[SSAjYd ?1MѣGsqDZ|r ֬YCSSwy'guk֬ /|ksiW @QQ555I^^|g5;۶937z2;裷LZt)@vk;3D"!B*ogСr]w裏r!}ݷ /d:׽-B!b8Nnn q8y7Yh3ZZZ8#xWxW:u*{&//޽{ӿ$/Ȱax''G1rH^~e,YŒ3꫉D"5^xKlz믿c: /^N!KԡmK:Ͷuu֯k[}'"̙3/~3k-2o8g}keY,^/p8ҥK)++#nf.L?+V/sxg`bss3999|$L7@<oq=+˲Xvm. 'x/<߭JAA?}#<23@v̘1<{< 0D"?Y(Xh/fB!B!_&77z)N>d***x3gi2j(ƍi&x0 #8~q:t(=z`bذanѣXo[)--C#rJ>ϟa~uWSSC~~~7l7UvuW com{ݼbzgZd /"EEE|D">x뭷Xl<<MMMX}  9fii)uuu?ƍkӑ^ZZʕ+I&a>SzMvv6eeetMmFY^D"g׽{0[\z5wyVx1d|gsa1gN:$$w~ sv9_Xwyv9ĉ+H&ktAL8?OXť^ k@$|O!B!؜?h4oѣ9餓/H$\p}+Vu]{R087<,]x<& !///3-//L#98 u[PΦcm{%% mwے+Vp '0n8u~ӟGqy1dn68{ͽޛٿx GS)s1TUUꫯfο{LsIֳfbTUU1w\f̘Anݸ[fssWoq=p8̈#xG83ijjbܱٙ~~{Q/ѣ?qaYA`iy~I;ޛg##Ook:qB!B!v_|1ݺu㭷bʔ) {ɓxihhh?znF.***4-n///O6u_iիW^;B*W$]@K{UѰAKSI{^> ӟ2gvyvRVVo&X,=SLaL:uݝ~ 'lp^ˤI3gpgdN<.X,Fss3gqYYY]+kᡇ"1cdr(cǎ?qLN{,\P(RR/_N<Ϝ)twuSLᦛnC<.\;À+\!B!BLj#ӧ>({./v555 0zN w_nf-[СCY|9W_}5߱mp8̪U=O>1k=Æ C=7x>hؗͭs|8z!?|7oӦMN[Kԡmww6[̘16];~8sfkx|dܹՑW\c׿&bX|Ml+++' L 6m/,,ܠc}yyy_/ u{w͔Bt.XP_w(imޞzMM _~%o !2.]}wZB!B{ŢMnk*(..ު}I&RVV|_~Y6L)DGR%w+&+ru=zhsgE-*WWnv텅;^z:k !vwuWg/A!B!h0 N믿βeٳ'_.v+]m3;#}1J)Z-,B!B!D'?1?;{)B]`(NJd}B!B!B|DA])R K>$^ %Rifޣ- BR)_!B!B{VyF D q@Y6kjjA4d-nWd?X,b fH+6;c}~nZKK MMM;ͱB!B!ݾ" Kyu넣yջ;-Yҡ-ZiW}I$[nR!J-[F*e2BEEE~#i-B!B!ؽu6%';ӎۗy.﹅#G))bvwOii){]xUу=zUIB!B!]W)v`geeF= xnFiǒy[U4B!B!BA(÷EKx֯.B!B!.SPo At^>!B!Bt4۶;{ B]D*ڙ;ڄB!B!+3:{B!B!B!Į@ B!B!B!D;HA]!B!B!h) !B!B!% !!B!Bm&B!B!B!D;HA]!B!B!h|B!B!b;r]W_}ŋj*JKK!eIIN] !B!B1}t 9ӧ+V`,\.N^b[HA]!B!Bu]OGf /G}Bt) !BlgMe)x\3^Q(B!vzSN9eyL!B^:9 +|0.}ٜr) 6N:|$L:@<MA=;;6LNNζD!vZRPB!NJ쓽΁I) !BnF XP_`y7PoT*EmmmV";[#3weTWWS\\LYY7tS?䴴+WL& |{)j(+!x!v ~;!6B!C=E1|ƌ}ϟO}}=rH[={.ͼK\z饬Z3g#G[og1zhn8p ~\}ՄB19蠃5kǏs2cƌN{BEA%!. .oga[KwB!Ʋ,."O9#ׯ,Xz&L&}kqƷmW\qÇoc󩮮Ncfms)뮻f\veb193^{-&MbΜ98_Lu 3^6vQX~W3JB60,J=]^Bta,]#GvR ./gȐ!͜~<Ә)k;/K*u_QmmW2T!b'h"ӧv=,\ŋ_ЫW/q!|bwQ[[i)G"LlFG}ill /̙3Yt)SVV/Krrrxw5k xι瞻5yb1ONyy9pOȄ 0`+WO{^,YwDQz-nFfΜI$=}䷿-r %%%L4 9r$Jgnvޙ3g~1tЭzB!Bu!g3<yapfݻ]ZNaa!䐓C(l,"֬YCII o& , JPQQA|;{5ԐxEEE][w}pUW!B!b&u!&J/2sL 3߿[xW ajS]k׮ms" ihh JeR[[KnO6m~;L8ͱ]CAAet644luϴip*!B!B$E!Dy䓍>O;`s9z衘ɸqo~ڵk),,L4??Dz, ^>|8 . . ppQGmvW^y%s?bرoh" g|xB!B!v>ݏ6r{c_vojZ@(}R)P!.nO,]#Gn &H0f̘^B!XϢE(++O>!y@ ?{wV]}L2ڙiZR mDz+^.x(xCx^A-PQjYԖbwZ]+mv- idz>y䜓Od23|yj9()tvHuI]G/'ZoGty;TuuuZPmm/xȼu9]Q0zww֮]s9ڹs׿jժUzꩧׯׄ r,y9]Q0zW_K* ;Ԟ={ݭJ+WEƍӒ%K4n8_zu3`}rݚ>}}YO~ll}{gBUU%cXerLWW% \矗$566S$iڴin}_իtR=[$ 'ݻ%I .$͟?_.kd$]uUjll$Oh޽4mڴ@j Lj+v}s=\$iN iZ)Ni2M3av8~UWW'>ࠣGj۶mZhQ*cՊ+400;Rc`͚55k&Lt)@Az*$%$Bn$YQ׊m:z9Ѻ\;jkkmv󩾾hl Pul Pul Pul Pul PK7o#bi`ULה /r6)#P M*++$z%Po|*r2OcyTldd S m4TuWIãս^\C@L:U74MӱA65> +>Z{K~F\C@XC}W}.@ IP߃>W.1g)S4|!@CjtRT#-+0 Ic_[qmءlTl^Ʀdv|,w6 TnYH`Ma B#cU[ X8.8eWC袋d jɐ3G8AS/O: ˥A u6|~撢ዯWӒ{Hj>~6 [wdN [PmY`u˲dB7ש>/HG555?~\.ǵ,KGUGGhkH?~!3w0\gY+noQ!P9g[)A6T<|鯖:~_vT}D%W NԔ}w(=)TO_0+OY*@ݲ,B![53k|K*,*6#+h"n\ckjmmj``@SLQQQјԙ+ڪVM0}8;vLYs|}=:00LiՆJ\1$ㆼg-UO-X{ijfj[zΛX >51 r) X׫fmڴI#_ioo矯q)m`PG{r>3M3mz:5/[HHm70@U @J;O>r' )@qblB;(܏< Y.˯t=NJU0񇆆TVVFQYYYJ[8c4__/kRϫө*C+?Kjig ],~Y+hߒBʾKt|97 a ,fh Yl;RaԿDVGByIUV;Ե^9kvcc3T6m53Rdr[ ^l~ttt賟|>m6Ҏ^$}k_KG__|ѡJ 궷:$@A;6]rfĠzYf  #zgDz,kgl{WϢ(oW___{YY}ٱ(  ke@WvtTcy_:Wy JQpd+Q?/}CRggi۪ϲ,_\SLќ9sK/TW\qE}~i577kc=m۶sѽޫI&I|I]V뮻hѢ$۞Ț](/Km޼YwG[zJu=hVLԋ/+W7ߔVss,YZ.WjaI0lEr'~>(+. o#s=Hͫk_ jgK3[\o-_$g7߬5k$׫Oi(ξ^{M3gΔ$[N7tS}٣*Iҗe _֮]O~ZlCO;|+Ӈ'۞Țى'tRUWWkƍm{G}v=ڱc>OW*++vXBt7{ѷm$G -Q/5ӥ2R .P$eܛgS?.I?-0եNM:UW^yez L_7oΝ;uAj۶m;wN<:A-_\;Phӄ|3*//:tnPeefΜ+Vh۶m#ye^Ν;5ydVQ_jwmmmG?3goYV/РfmٲE?>&=~#͟?_7n{ h+u駟VCC,Yɧ8*+W@_חeA}_={;ӷ-͚5C>=2cw7JQn2aG}zPUk({G?JJJOkʔ)  ;pN<^{M}}}ڲe֭[cǎi׮]#&.]7jΜ9Zb^uI\٩Α/}{GFGo߾].첑Nԫ9s挌WS1c/^|zKuuujhhYweiΝi&7ԩS}ve~iŊZvfϞͶo߮~ GG}Twu֮]wݺ+400/~ڵkU#콧Etz=FPϗII$?azf4ĉu]wޮmٲE/\.Z]wug' _QW_}|e$lO}߾}ڰa~vk-ܢ{* ڪk_{9?Ϊ+V&dɒFGk۶m4MXѾippPxb=C ޮկ~ŋ^K^|őH#KP HHm|ڷ{Qpe* B˲F.رc$D}Ls¡hKKKV^-ǣkϞ=|ڶmf͚kܹ#/\.͝;|VMM>r/l٢G}T^޽[G>2߯`0hBR^^~}}}} ~1B!yOk.{fiÆ eYz)566kՓO>K.DͣoL[cG{K˱~-]T~_W֥^_?x|FzjIRqq:d!5![Dۿ5Hdne%߮'pK)SS/hƌ{F&={Z[["Iڽ{3rڴizZ{W˗/4<瑖.ɶϙ3GoN8z! %UWWK/SO=%I:v옖/_[o1ΝzKg]wݥ}R/wk#SO!̜9S_z?QVu]72… so|>ojƌN8kӑ2\ho?,Ju+4|&O?Hl~M~*--U__LTȾ/вe444OSN}:}]YY{w֛Ng/=K/To}K7xb͟?_iW_͛5m4}sӴiHaYp?Us7@|Yn}Q555e?GW]u/^֞+zÆ q;o<-[L*..>cdϟg}V>qTjkkjժ?z{{UZZudR&uI>}{1\R/~rYt5yUC>lGLq+ '1 L:5GVe٬Nc4% 0ğa0 y\jw@@n{%zdnT;LӔ}g[8>kXí`jYz̥BoԤ-gz#Yu:S]*_dHAEahTnVeͿϺ pl~޽[SWWhҤIrY:pl߇_z{{XN>,]򬥢Aj8.-0ԙABn4>jvViŸDEŚ<i7uL(@0 Y%˥şMk_^YFn[.WrVqqG3Y?a=zT;wT 2sU]]&LP޿p>;tPk4__IIޒ{JAZzScŭ INq#d3TԽOtؘ:Q@]z{wye.ԠLӔeeu1 Ԥs=w =PHicc/W#Tɞ0==4\; uMpdKAM6~]ƭt9#WOBB ^Qץ+0eee*))%rmfLL)4vi޲ CҼg,jA&5Pͮ LPt9rLAۡzK64c,WP%O6Mh`x 1s^~uNׄ.`&UP&;]R0vplYVc][M_e*8>\w3(xUhJV~}{֫U!䈱2˄l8U ?TJ8]}_*9]ҭܩƗΗ'&V]WSR䐂 73^ddO7 K*IGUeMNb[&Tf:] A@ߛH9]RO_:BRcy1I㦮 pZ׎mv`ӥl|=n90*UՇ"a\&*H :9i{ϡեK;VRd9ur]NWpƷ8]FMe{!JթſKH,wK^8{RiU`ʇ:T2ZeKʆڝ.@#P Gr=t-=''#VvV>7:Qm{"K!q+ 49]YdDu : }J'OWeT2d1urTI=s2Y,.@#P GyNW>l$Ly.#mA[9, *dy.@#P G T9]AW;]F#h(P=tiPP%N j }U`UeM_CVeb@'K!1;]YeH!@|NW>퓜֪ReIN j%UJzޢuO?tg{IH@zcy @^}SO.eBE@Rd9urؑ{̔OPz9]ʨ6)`Vɤ:$a= RgU^9Rs^]~2FCtr:9n7kz?9&'.~Ov$G@k&u7:]E:Sa=UGt!1,^Gip@rr( iǵ9T0&hPG.ŶG4PVHp:yQ:4*;8o; :v+NP堎_Wm .@!P O\eDH((`UӘM2,ˉrY:隬!ruD#mPt%J ҥ)qM.%7Rou4RuH ENWr&HzCUNWL; tb~K9ÉE1[].@"P tMMY4\S+XɣVcQN3}j[xTG]($ASM54Tt%Pp-':] ƒ)u|qi,s=-#7tĸL!y@nch lx{iZ. DKey u6I>h-UwFq,S^u]*mlܬI%O6ԡnSoU.SHdG_㽿 tYZPdH`G-S5vK' fU. T_CWYE2heHIdBGۯ[WS֦I&:.>ګN䬜֠G@3ʤLHYzeLI]#Б/[: mPOCfKS4лvG4T6#7]@[my38`7> :qL^i:KG{&iJG|BG\U;ZvoU #xvSXz.8_i=MV\vy@6MjfMjRq5X)N\dw\zDƫըҚ6pXVƩ`> &{IO=Y.[o) Pz]WuT!*[*؋%O`xߠW*jCd8 _%P٤[d yJ,H,%g*Xb*P3`U,7kWT2^F(up8Ψ^=S>QIOdʐ)IT ZM Ze2ܒB ʴ[ rv?P /$cﳽr7: \\a~F;\WajRwȺI03"ـ_(@fKJi6߭ۯwtA AS׭ .oـ@ @ @ @ @ @ @ @ @  c¥q5zT3T3qNMд4uDP=!Gsk=}WunK26TQjTjqky>6=~k7.@ P Oy܆.X6ҭw+աAǠtIraK\jn*˘. UjՖW6yWdKӁhe.y;6yU^ʏx R.v 9#=_KG7 uMl@!]s '='/RD@hqe%.W.@nĹEN䔉 }uD]?ցTV1B@jU. s'L_MKsMޯr=jPϐm8]6ARcA9TgoH7<up2{'_AARgo@.$oEw9|ق$*ffy~v߃d:I .@^ۏ@ P D{?.k}gxeBa [o0  xlPMWv [9I +eye{0B$Q6ck?T}8 W|y$斧ޏɛ ^QTb:ER{#D[$@ӼRѠ}e)!PeFo2K} bW*־wI.@N*OSR;dul0}_ΰ?2_}WY@}XF sN]ZU?h3R3X P&9.U-ϸUKvd 9MiFW쓷_loc%2R9EK-@K@0:F7٭ҹ' tIR  k5mfHmNҙn&_ !P E=rvKt&* aIJ^ ڿ¥ҋh`ly.\cXH ٿߴҴ^ꌕaᒪ) d*uFRÇKFu+~jiӖi. -FKRJH 1BQjDջ~(RUtc%o5ٔ"d\Aiֳ|aDZ: l6t>toiEA8l)eS@o jv+(H ~1|3W:v!(ta'Knѿ^O{㿿{zA#P e&$j8&˾1٬e?3YH*_Xtr@;T{2@41<<\{J &%5[U!t5REҤeٰ]j%׆d4־+sf"dwEj璞ULה /r,) P M*++,UMԻaH}[R06HFҽ^ZD@4:uLv$~Sm7Lgjh-ocDk`5pᑪo#Nt(@ MqpoN<= 3dWZnjmbB 0FM.5=P )UϚ^w}P@+w|A*-R^ %~ =;xfw:H^I70?PЀ%IMs ^rҐĐԐo[).&U:#3[ؑE@W T|M]HYPmh濗jWJǠ*dx^$0\Y R=̒ @ @ @ @ @ @ @ qYN.K%2_F`C.9@RgrBs@7[u;''+O L>-:Y-Wu+5 d+z"9q|zN}jn6V%z= ~ceY#TNTVXRu*@=pX'$vtmɺ͍4+ζR/H'\/M gl ciCHYxBqYv#oG^gL9't˒smzm@nsOZ ԓ=Y;=pωlB!:P%>r}Fݖl$N)DA{x%Phz'Yq" EgљoY@0NtVXibvN'gz'oNHksPmb~>ޘ&aI2nG iCO-B>-|^6N-یǎ^u Jp;H(rk3jyj9lƸohyx4G{vv;$YNG^8#MIS=:؏+ss#xy}c}!ayj?3j~!zx䡺@]8%Ddazt;ztЮjv=+NPBXazx9Oxyj{x;ڊB2B]z|]92 E;B=VD##GG'[7fwzH0=24'ztzzAzdM&t%ddszꑽPO4B=:T~D;EJoKLjn"#G?z$z}zXڽ(Dx %k/H ͨnγ0~,F'룞l]0џGJ5 Tv/uŹ$ &n'PO%\c=վe|-_yakIDATA.>J=r}_Q#LD+XF)FGfQ#գk\k-=| A@>>zzȖ/KKutN#/|;m^b=/uNӇnXzP]z;OG_qxcÃM-_V|ۑ'9<:=?=##[DT\ˑ׊s;:pB:CxzRǎWGLv'L+؎yuKFmء:9\KX BcRP=X/lWwr)VIEa"1RP=28)vv0BI4:яkc.p:GKg92=RrX!xA̱&9+`jmԜ cmbg7TO =~/% ӣ+OX\UI'Zk=2a:BhbD˱x-_h?n;+N걶KdcxvB^wtvXoncg{zRlxXmN&'t);X$nX=ؓ-ǫ A ;Qo4{&Ew;>N=z }Ϧ6' c% 飭-2(Nwkv(4F]oKNg3= 5.3.0') gee_dependency = dependency('gee-0.8') libxml_dependency = dependency('libxml-2.0') cairo_dependency = dependency('cairo', version: '>=1.14') goocanvas_dependency = dependency('goocanvas-3.0') libarchive_dependency = dependency('libarchive') json_glib_dependency = dependency('json-glib-1.0') # Optional dependencies desktop_file_validate = find_program('desktop-file-validate', required: false) appstream_util = find_program('appstream-util', required: false) # Include the gnome module gnome = import('gnome') asresources = gnome.compile_resources( 'as-resources', 'data/assets.gresource.xml', source_dir: 'data', c_name: 'as' ) cc = meson.get_compiler('c') m_dep = cc.find_library('m', required: true) vala_lint = find_program('io.elementary.vala-lint', required : false) if vala_lint.found() test ( 'Vala lint', vala_lint, args: ['-d', join_paths(meson.source_root(), 'src')] ) endif # Set up the profile profile = get_option('profile') if profile == 'development' application_id = meson.project_name() + 'Devel' schema_path = '/com/github/akiraux/akiraDevel/' else application_id = meson.project_name() schema_path = '/com/github/akiraux/akira/' endif gettext_package = application_id # Set our translation domain add_global_arguments('-DGETTEXT_PACKAGE="@0@"'.format (gettext_package), language:'c') add_global_arguments(['-DG_LOG_DOMAIN="Akira"'], language:'c') subdir('src') subdir('data') subdir('po') if install_tests subdir('tests') endif meson.add_install_script('build-aux/meson/post_install.py') Akira-0.0.16/meson_options.txt000066400000000000000000000003051410625726100162640ustar00rootroot00000000000000option('profile', type: 'combo', choices: ['default', 'development'], value: 'default') option('install-tests', type : 'boolean', value : 'false', description : 'install test executables') Akira-0.0.16/po/000077500000000000000000000000001410625726100132475ustar00rootroot00000000000000Akira-0.0.16/po/LINGUAS000066400000000000000000000011501410625726100142710ustar00rootroot00000000000000da mh ps rm sn uk si mk hu nv id mo zh_HK my he eu ia km jv as cr ay kl vi ak uz kr zu gl is ha lo la ii kv so zh_CN sa ro ff cu fi lg sm te ig sw iu mt ki ky zh kk oc ko su ar fr ce mi bs am bn dz ny tl ty br ks hi th sr co bg io nl gd hy ch ta oj nn wa bh bm pa ur az yi hr bo cs fa wo cy eo pt li nr fr_CA lv pi lu ho ee kw tt ts sl mg om ae ug ve pl sg mr tw nd lt ast af ms se ti fo sma ht kn nb en_AU lb kj sq na et qu ku sd en_CA mn to fj st pt_BR ja xh ab ik av hz ckb ng gv ss aa kg rue en_GB tg ba ln ga cv sc el tr sk za fy ie dv it rw ml es ca os gn zh_TW vo bi or ru be no gu an tk ka ne rn tn de sv yo Akira-0.0.16/po/aa.po000066400000000000000000000001251410625726100141660ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/ab.po000066400000000000000000000001251410625726100141670ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/ae.po000066400000000000000000000001251410625726100141720ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/af.po000066400000000000000000000001251410625726100141730ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/ak.po000066400000000000000000000001251410625726100142000ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/am.po000066400000000000000000000001251410625726100142020ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/an.po000066400000000000000000000001251410625726100142030ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/ar.po000066400000000000000000000416661410625726100142260ustar00rootroot00000000000000msgid "" msgstr "" "Project-Id-Version: \n" "POT-Creation-Date: 2020-09-06 14:27+0300\n" "PO-Revision-Date: \n" "Last-Translator: \n" "Language-Team: \n" "Language: ar\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Poedit 2.4.1\n" "X-Poedit-Basepath: ../src\n" "X-Poedit-SearchPath-0: .\n" #: Dialogs/ExportDialog.vala:151 msgid "Export to:" msgstr "التصدير الى:" #: Dialogs/ExportDialog.vala:157 msgid "Select Folder" msgstr "اختر مجلد" #: Dialogs/ExportDialog.vala:166 msgid "Format:" msgstr "الصيغة:" #: Dialogs/ExportDialog.vala:179 msgid "Quality:" msgstr "الجودة:" #: Dialogs/ExportDialog.vala:191 msgid "Compression:" msgstr "الضغط:" #: Dialogs/ExportDialog.vala:205 msgid "Transparency:" msgstr "الشفافية:" #: Dialogs/ExportDialog.vala:218 msgid "Scale:" msgstr "الحجم:" #: Dialogs/ExportDialog.vala:242 FileFormat/FileManager.vala:49 #: FileFormat/FileManager.vala:105 msgid "Cancel" msgstr "إلغاء" #: Dialogs/ExportDialog.vala:249 Dialogs/ShortcutsDialog.vala:63 #: Layouts/HeaderBar.vala:112 msgid "Export" msgstr "تصدير" #: Dialogs/ReleaseDialog.vala:47 Dialogs/SettingsDialog.vala:217 msgid "" "WARNING!\n" "Akira is still under development and not ready for production. Missing " "features, random bugs, and black holes opening in your kitchen are to be " "expected." msgstr "" "تحدير!\n" "لا يزال أكيرا تحت التطوير وغير جاهز للاستخدام النهائي.عليك توقع العديد " "من المزايا المفقودة والمشاكل البرمجية، وقد تؤدي الى ثقوب سوداء في مطبخك." #: Dialogs/ReleaseDialog.vala:100 Dialogs/SettingsDialog.vala:249 msgid "Make a Donation" msgstr "قم بالتبرع" #: Dialogs/ReleaseDialog.vala:109 Dialogs/SettingsDialog.vala:258 msgid "Suggest Translations" msgstr "اقترح ترجمة" #: Dialogs/ReleaseDialog.vala:118 Dialogs/SettingsDialog.vala:267 msgid "Report a Problem" msgstr "بلغ عن مشكلة" #: Dialogs/SettingsDialog.vala:40 msgid "Preferences" msgstr "التفضيلات" #: Dialogs/SettingsDialog.vala:50 Dialogs/SettingsDialog.vala:73 #: Dialogs/ShortcutsDialog.vala:45 msgid "General" msgstr "عام" #: Dialogs/SettingsDialog.vala:51 Dialogs/SettingsDialog.vala:86 msgid "Interface" msgstr "الواجهة" #: Dialogs/SettingsDialog.vala:52 Layouts/HeaderBar.vala:280 msgid "Shapes" msgstr "الأشكال" #: Dialogs/SettingsDialog.vala:53 msgid "About" msgstr "عن" #: Dialogs/SettingsDialog.vala:74 msgid "Auto Reopen Latest File:" msgstr "فتح آخر ملف تلقائياً:" #: Dialogs/SettingsDialog.vala:88 msgid "Use Dark Theme:" msgstr "استخدام السمة الداكنة:" #: Dialogs/SettingsDialog.vala:92 msgid "Invert Panels Order:" msgstr "عكس ترتيب اللوحات:" #: Dialogs/SettingsDialog.vala:96 msgid "Restart application to apply this change." msgstr "عليك اعادة تشغيل البرنامج لتطبيق التغييرات." #: Dialogs/SettingsDialog.vala:100 msgid "ToolBar Style" msgstr "نمط شريط الادوات" #: Dialogs/SettingsDialog.vala:102 msgid "Show Button Labels:" msgstr "أظهر اسماء الأزرار:" #: Dialogs/SettingsDialog.vala:106 msgid "Use Symbolic Icons:" msgstr "إستخدم ايقونات رمزية:" #: Dialogs/SettingsDialog.vala:129 msgid "Default Colors" msgstr "الألوان الافتراضية" #: Dialogs/SettingsDialog.vala:131 msgid "Define the default style used when creating a new shape." msgstr "تحديد النمط الافتراضي المستخدم عند إنشاء شكل جديد." #: Dialogs/SettingsDialog.vala:136 msgid "Fill Color:" msgstr "لون الملء:" #: Dialogs/SettingsDialog.vala:157 msgid "Enable Border Style:" msgstr "تفعيل نمط الحد الخارجي:" #: Dialogs/SettingsDialog.vala:160 msgid "Border Color:" msgstr "لون الحدود:" #: Dialogs/SettingsDialog.vala:181 msgid "Border Width:" msgstr "سماكة الحدود:" #: Dialogs/SettingsDialog.vala:209 msgid "The Linux Design Tool" msgstr "أداة تصميم لينكس" #: Dialogs/SettingsDialog.vala:226 msgid "Thanks to our awesome supporters!" msgstr "شكراً لداعمينا الرائعين!" #: Dialogs/SettingsDialog.vala:231 msgid "View the list of supporters" msgstr "عرض قائمة الداعمين" #: Dialogs/ShortcutsDialog.vala:46 msgid "New window:" msgstr "نافذة جديدة:" #: Dialogs/ShortcutsDialog.vala:48 msgid "Preferences:" msgstr "التفضيلات:" #: Dialogs/ShortcutsDialog.vala:50 msgid "Quit:" msgstr "خروج:" #: Dialogs/ShortcutsDialog.vala:52 msgid "Presentation mode:" msgstr "وضع التقديم:" #: Dialogs/ShortcutsDialog.vala:55 msgid "File" msgstr "ملف" #: Dialogs/ShortcutsDialog.vala:56 msgid "Open:" msgstr "فتح:" #: Dialogs/ShortcutsDialog.vala:58 msgid "Save:" msgstr "حفظ:" #: Dialogs/ShortcutsDialog.vala:60 msgid "Save as:" msgstr "حفظ باسم:" #: Dialogs/ShortcutsDialog.vala:64 msgid "Export artboards:" msgstr "تصدير اللوحات:" #: Dialogs/ShortcutsDialog.vala:66 msgid "Export selection:" msgstr "تصدير العناصر المحددة:" #: Dialogs/ShortcutsDialog.vala:68 msgid "Highlight area to export:" msgstr "حدد المنطقة المراد تصديرها:" #: Dialogs/ShortcutsDialog.vala:77 msgid "Canvas" msgstr "مساحة العمل" #: Dialogs/ShortcutsDialog.vala:78 msgid "Zoom in:" msgstr "تكبير:" #: Dialogs/ShortcutsDialog.vala:80 msgid "Zoom out:" msgstr "تصغير:" #: Dialogs/ShortcutsDialog.vala:82 msgid "Zoom reset:" msgstr "اعادة تعيين الحجم:" #: Dialogs/ShortcutsDialog.vala:85 msgid "Item creation" msgstr "إنشاء غرض" #: Dialogs/ShortcutsDialog.vala:86 msgid "Artboard:" msgstr "المساحة الفنية:" #: Dialogs/ShortcutsDialog.vala:88 msgid "Rectangle:" msgstr "مستطيل:" #: Dialogs/ShortcutsDialog.vala:90 msgid "Ellipse:" msgstr "شكل بيضاوي:" #: Dialogs/ShortcutsDialog.vala:92 msgid "Text:" msgstr "نص:" #: Dialogs/ShortcutsDialog.vala:94 msgid "Image:" msgstr "صورة:" #: Dialogs/ShortcutsDialog.vala:97 Layouts/Partials/TransformPanel.vala:174 msgid "Transform" msgstr "التحول" #: Dialogs/ShortcutsDialog.vala:98 msgid "Raise selection:" msgstr "ارفع المحدد:" #: Dialogs/ShortcutsDialog.vala:100 msgid "Lower selection:" msgstr "اخفض المحدد:" #: Dialogs/ShortcutsDialog.vala:102 msgid "Raise selection to top:" msgstr "ارفع المحدد للقمة:" #: Dialogs/ShortcutsDialog.vala:104 msgid "Lower selection to bottom:" msgstr "اخفض المحدد للقاع:" #: Dialogs/ShortcutsDialog.vala:106 msgid "Flip horizontally:" msgstr "قلب افقي:" #: Dialogs/ShortcutsDialog.vala:108 msgid "Flip vertically:" msgstr "قلب عمودي:" #: FileFormat/FileManager.vala:46 msgid "Save Akira file" msgstr "حفظ ملف أكيرا" #: FileFormat/FileManager.vala:48 Layouts/HeaderBar.vala:190 msgid "Save" msgstr "حفظ" #: FileFormat/FileManager.vala:71 msgid "Akira files" msgstr "ملفات أكيرا" #: FileFormat/FileManager.vala:76 msgid "All files" msgstr "كل الملفات" #: FileFormat/FileManager.vala:103 msgid "Open Akira file" msgstr "فتح ملف أكيرا" #: FileFormat/FileManager.vala:105 Layouts/HeaderBar.vala:170 msgid "Open" msgstr "فتح" #: Layouts/HeaderBar.vala:69 Lib/Managers/ExportManager.vala:296 msgid "Untitled" msgstr "بدون عنوان" #: Layouts/HeaderBar.vala:71 msgid "Menu" msgstr "القائمة" #: Layouts/HeaderBar.vala:75 msgid "Insert" msgstr "ادراج" #: Layouts/HeaderBar.vala:82 msgid "Group" msgstr "تجميع" #: Layouts/HeaderBar.vala:84 msgid "Ungroup" msgstr "تفكيك" #: Layouts/HeaderBar.vala:87 msgid "Up" msgstr "للأعلى" #: Layouts/HeaderBar.vala:92 msgid "Down" msgstr "للأسفل" #: Layouts/HeaderBar.vala:97 msgid "Top" msgstr "للقمة" #: Layouts/HeaderBar.vala:102 msgid "Bottom" msgstr "للقاع" #: Layouts/HeaderBar.vala:107 msgid "Settings" msgstr "الاعدادات" #: Layouts/HeaderBar.vala:118 msgid "Difference" msgstr "الفرق" #: Layouts/HeaderBar.vala:120 msgid "Exclusion" msgstr "استثناء" #: Layouts/HeaderBar.vala:122 msgid "Intersect" msgstr "تداخل" #: Layouts/HeaderBar.vala:124 msgid "Union" msgstr "اتحاد" #: Layouts/HeaderBar.vala:161 msgid "New Window" msgstr "نافذة جديدة" #: Layouts/HeaderBar.vala:182 msgid "Open Recent" msgstr "فتح المستندات الاخيرة" #: Layouts/HeaderBar.vala:195 msgid "Save As" msgstr "حفظ باسم" #: Layouts/HeaderBar.vala:204 msgid "Quit" msgstr "خروج" #: Layouts/HeaderBar.vala:237 msgid "Artboard" msgstr "مساحة فنية" #: Layouts/HeaderBar.vala:254 msgid "Add Items" msgstr "اضافة عناصر" #: Layouts/HeaderBar.vala:262 msgid "Rectangle" msgstr "مستطيل" #: Layouts/HeaderBar.vala:268 msgid "Ellipse" msgstr "شكل بيضاوي" #: Layouts/HeaderBar.vala:286 msgid "Vector" msgstr "متجه" #: Layouts/HeaderBar.vala:288 msgid "Pencil" msgstr "قلم رصاص" #: Layouts/HeaderBar.vala:291 msgid "Text" msgstr "نص" #: Layouts/HeaderBar.vala:297 msgid "Image" msgstr "صورة" #: Layouts/HeaderBar.vala:330 msgid "Export Current Selection" msgstr "تصدير العناصر المحددة" #: Layouts/HeaderBar.vala:336 msgid "Export Artboards" msgstr "تصدير اللوحات" #: Layouts/HeaderBar.vala:345 msgid "Highlight Area to Export" msgstr "حدد المنطقة المراد تصديرها" #: Layouts/HeaderBar.vala:391 msgid "Main Menu" msgstr "القائمة الرئيسة" #: Layouts/HeaderBar.vala:468 Services/ActionManager.vala:224 #: Services/ActionManager.vala:243 Services/ActionManager.vala:262 #, c-format msgid "Unable to open file at '%s'" msgstr "غير قادر فتح الملف في '%s'" #: Layouts/MainCanvas.vala:46 msgid "Button was pressed!" msgstr "تم ضغط زر!" #: Layouts/MainCanvas.vala:206 msgid "Export completed!" msgstr "انتهى التصدير!" #: Layouts/Partials/AlignItemsPanel.vala:48 msgid "Distribute Horizontally" msgstr "توزيع بشكل أفقي" #: Layouts/Partials/AlignItemsPanel.vala:50 msgid "Distribute Vertically" msgstr "توزيع بشكل عمودي" #: Layouts/Partials/AlignItemsPanel.vala:52 msgid "Align Left" msgstr "محاذاة يساراً" #: Layouts/Partials/AlignItemsPanel.vala:53 msgid "Align Center" msgstr "توسيط" #: Layouts/Partials/AlignItemsPanel.vala:54 msgid "Align Right" msgstr "محاذاة يميناً" #: Layouts/Partials/AlignItemsPanel.vala:56 msgid "Align Top" msgstr "محاذاة للقمة" #: Layouts/Partials/AlignItemsPanel.vala:57 msgid "Align Middle" msgstr "توسيط عمودي" #: Layouts/Partials/AlignItemsPanel.vala:58 msgid "Align Bottom" msgstr "محاذة للأسفل" #: Layouts/Partials/Artboard.vala:144 Layouts/Partials/Artboard.vala:487 #: Layouts/Partials/Layer.vala:139 Layouts/Partials/Layer.vala:687 msgid "Lock Layer" msgstr "قفل الطبقة" #: Layouts/Partials/Artboard.vala:155 Layouts/Partials/Artboard.vala:529 #: Layouts/Partials/Layer.vala:156 Layouts/Partials/Layer.vala:729 msgid "Hide Layer" msgstr "اخفاء الطبقة" #: Layouts/Partials/Artboard.vala:487 Layouts/Partials/Layer.vala:687 msgid "Unlock Layer" msgstr "فك قفل الطبقة" #: Layouts/Partials/Artboard.vala:529 Layouts/Partials/Layer.vala:729 msgid "Show Layer" msgstr "اظهار الطبقة" #: Layouts/Partials/BorderItem.vala:121 msgid "Choose border color" msgstr "اختر لون الحدود" #: Layouts/Partials/BorderItem.vala:176 Layouts/Partials/FillItem.vala:178 msgid "Pick color" msgstr "اختر لون" #: Layouts/Partials/BorderItem.vala:191 msgid "Remove border" msgstr "ازالة الحدود" #: Layouts/Partials/BorderItem.vala:275 msgid "Show border" msgstr "اظهار الحدود" #: Layouts/Partials/BorderItem.vala:279 msgid "Hide border" msgstr "اخفاء الحدود" #: Layouts/Partials/BorderRadiusPanel.vala:86 msgid "Style" msgstr "النمط" #: Layouts/Partials/BorderRadiusPanel.vala:103 msgid "Border Radius" msgstr "استدارة الحدود" #: Layouts/Partials/BorderRadiusPanel.vala:137 msgid "Border radius options" msgstr "خيارات استدارة الحدود" #: Layouts/Partials/BorderRadiusPanel.vala:199 msgid "Autoscale Corners" msgstr "حجم تلقائي للزوايا" #: Layouts/Partials/BorderRadiusPanel.vala:208 msgid "Uniform Corners" msgstr "توحيد الزوايا" #: Layouts/Partials/BordersPanel.vala:53 msgid "Borders" msgstr "الحدود" #: Layouts/Partials/BordersPanel.vala:64 msgid "Add border" msgstr "اضافة حد" #: Layouts/Partials/FillItem.vala:114 msgid "Choose fill color" msgstr "اختر لون الملء" #: Layouts/Partials/FillItem.vala:193 msgid "Remove fill color" msgstr "ازالة لون الملء" #: Layouts/Partials/FillItem.vala:277 msgid "Show fill color" msgstr "أظهار لون الملء" #: Layouts/Partials/FillItem.vala:281 msgid "Hide fill color" msgstr "اخفاء لون الملئ" #: Layouts/Partials/FillsPanel.vala:54 msgid "Fills" msgstr "التعبئات" #: Layouts/Partials/FillsPanel.vala:65 msgid "Add fill color" msgstr "اضف لون ملئ" #: Layouts/Partials/TransformPanel.vala:96 msgid "X" msgstr "س" #: Layouts/Partials/TransformPanel.vala:96 msgid "Horizontal position" msgstr "الموقع الأفقي" #: Layouts/Partials/TransformPanel.vala:98 msgid "Y" msgstr "ص" #: Layouts/Partials/TransformPanel.vala:98 msgid "Vertical position" msgstr "الموقع العمودي" #: Layouts/Partials/TransformPanel.vala:100 msgid "W" msgstr "ع" #: Layouts/Partials/TransformPanel.vala:100 msgid "Width" msgstr "العرض" #: Layouts/Partials/TransformPanel.vala:102 msgid "H" msgstr "ط" #: Layouts/Partials/TransformPanel.vala:102 msgid "Height" msgstr "الطول" #: Layouts/Partials/TransformPanel.vala:107 msgid "Lock Ratio" msgstr "قفل النسبة" #: Layouts/Partials/TransformPanel.vala:114 msgid "R" msgstr "ر" #: Layouts/Partials/TransformPanel.vala:114 msgid "Rotation degrees" msgstr "درجات التدوير" #: Layouts/Partials/TransformPanel.vala:126 msgid "Flip Horizontally" msgstr "قلب افقي" #: Layouts/Partials/TransformPanel.vala:137 msgid "Flip Vertically" msgstr "قلب عمودي" #: Layouts/Partials/TransformPanel.vala:165 msgid "Position" msgstr "الموقع" #: Layouts/Partials/TransformPanel.vala:169 msgid "Size" msgstr "الحجم" #: Layouts/Partials/TransformPanel.vala:178 msgid "Opacity" msgstr "الشفافية" #: Layouts/RightSideBar.vala:111 msgid "Search Layer" msgstr "البحث عن طبقة" #: Lib/Managers/ExportManager.vala:192 Lib/Managers/ExportManager.vala:219 msgid "Generating preview, please wait…" msgstr "تكوين العرض، الرجاء الانتظار..." #: Lib/Managers/ExportManager.vala:313 #, c-format msgid "Untitled %i" msgstr "بدون عنوان %i" #: Lib/Managers/ExportManager.vala:484 msgid "Exporting images…" msgstr "تصدير الصور..." #: Partials/ExportWidget.vala:117 #, c-format msgid "%i × %i px · %s" msgstr "%i × %i بكسل · %s" #: Partials/ExportWidget.vala:124 msgid "Fetching image size…" msgstr "جاري احضار حجم الصورة..." #: Partials/ZoomButton.vala:49 msgid "Zoom Out" msgstr "تصغير" #: Partials/ZoomButton.vala:55 msgid "Reset Zoom" msgstr "اعادة تعيين التكبير" #: Partials/ZoomButton.vala:62 msgid "Zoom In" msgstr "تكبير" #: Partials/ZoomButton.vala:68 msgid "Zoom" msgstr "تكبير" #: Services/ActionManager.vala:217 msgid "No recently opened file available!" msgstr "لا يوجد ملف مفتوح مؤخراً!" #: Services/ActionManager.vala:236 msgid "No second most recently opened file available!" msgstr "لا يوجد ملف ثاني مفتوح مؤخراً!" #: Services/ActionManager.vala:255 msgid "No third most recently opened file available!" msgstr "لا يوجد ملف ثالث مفتوح مؤخراً!" #: Services/ActionManager.vala:293 msgid "Nothing selected to export!" msgstr "لم يتم تحديد شيء لتصديره!" #: Services/ActionManager.vala:302 msgid "Export of Artboards currently unavailable…sorry 😑️" msgstr "تصدير المساحات الفنية حاليا غير متوف...آسف 😑️" #: Services/ActionManager.vala:373 msgid "Choose image file" msgstr "اختر ملف صورة" #: Services/ActionManager.vala:373 msgid "Select" msgstr "اختر" #: Services/ActionManager.vala:373 msgid "Close" msgstr "اغلاق" #: Services/ActionManager.vala:442 #, c-format msgid "Error! .%s files are not supported!" msgstr "خطأ . ملفات %s غير مدعومة!" #: Window.vala:121 msgid "Are you sure you want to quit?" msgstr "هل أنت متأكد انك تريد الخروج؟" #: Window.vala:122 msgid "All unsaved data will be lost and impossible to recover." msgstr "كل البيانات التي لم يتم حفظها ستفقد ويستحيل استعادتها." #: Window.vala:124 msgid "Quit without saving!" msgstr "الخروج دون حفظ!" #: Window.vala:125 msgid "Save file" msgstr "حفظ ملف " Akira-0.0.16/po/as.po000066400000000000000000000001251410625726100142100ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/ast.po000066400000000000000000000001251410625726100143740ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/av.po000066400000000000000000000001251410625726100142130ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/ay.po000066400000000000000000000001251410625726100142160ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/az.po000066400000000000000000000001251410625726100142170ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/ba.po000066400000000000000000000001251410625726100141670ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/be.po000066400000000000000000000003141410625726100141730ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" Akira-0.0.16/po/bg.po000066400000000000000000000002021410625726100141710ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" Akira-0.0.16/po/bh.po000066400000000000000000000001251410625726100141760ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/bi.po000066400000000000000000000001251410625726100141770ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/bm.po000066400000000000000000000001251410625726100142030ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/bn.po000066400000000000000000000001251410625726100142040ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/bo.po000066400000000000000000000001251410625726100142050ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/br.po000066400000000000000000000001251410625726100142100ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/bs.po000066400000000000000000000001251410625726100142110ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/ca.po000066400000000000000000000001251410625726100141700ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/ce.po000066400000000000000000000001251410625726100141740ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/ch.po000066400000000000000000000001251410625726100141770ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/ckb.po000066400000000000000000000001251410625726100143440ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/co.po000066400000000000000000000001251410625726100142060ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/cr.po000066400000000000000000000001251410625726100142110ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/cs.po000066400000000000000000000002371410625726100142160ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" Akira-0.0.16/po/cu.po000066400000000000000000000001251410625726100142140ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/cv.po000066400000000000000000000001251410625726100142150ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/cy.po000066400000000000000000000001251410625726100142200ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/da.po000066400000000000000000000001251410625726100141710ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/de.po000066400000000000000000000356671410625726100142200ustar00rootroot00000000000000# # XP312 < >, 2020. # msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" "Project-Id-Version: unnamed project\n" "Last-Translator: XP312 < >\n" "Language-Team: German < >\n" "Language: de\n" "Content-Transfer-Encoding: 8bit\n" "PO-Revision-Date: 2020-09-03 14:38+0200\n" "X-Generator: Gtranslator 3.36.0\n" #: Dialogs/ExportDialog.vala:151 msgid "Export to:" msgstr "Exportiere nach:" #: Dialogs/ExportDialog.vala:157 msgid "Select Folder" msgstr "Ordner auswählen" #: Dialogs/ExportDialog.vala:166 msgid "Format:" msgstr "Format:" #: Dialogs/ExportDialog.vala:180 msgid "Quality:" msgstr "Qualität:" #: Dialogs/ExportDialog.vala:192 msgid "Compression:" msgstr "Kompression:" #: Dialogs/ExportDialog.vala:206 msgid "Transparency:" msgstr "Transparenz:" #: Dialogs/ExportDialog.vala:219 msgid "Scale:" msgstr "Größe:" #: Dialogs/ExportDialog.vala:243 FileFormat/FileManager.vala:49 #: FileFormat/FileManager.vala:105 msgid "Cancel" msgstr "Abbrechen" #: Dialogs/ExportDialog.vala:250 Dialogs/ShortcutsDialog.vala:63 #: Layouts/HeaderBar.vala:112 msgid "Export" msgstr "Exportieren" #: Dialogs/ReleaseDialog.vala:47 Dialogs/SettingsDialog.vala:217 msgid "" "WARNING!\n" "Akira is still under development and not ready for production. Missing " "features, random bugs, and black holes opening in your kitchen are to be " "expected." msgstr "" "ACHTUNG:\n" "Akira ist noch in Entwicklung und deshalb noch nicht für die Verwendung in der Produktion geeignet." "Fehlende Funktionen, Bugs und schwarze Löcher die sich in der Küche öffnen " "sind zu erwarten." #: Dialogs/ReleaseDialog.vala:100 Dialogs/SettingsDialog.vala:249 msgid "Make a Donation" msgstr "Für das Projekt spenden" #: Dialogs/ReleaseDialog.vala:109 Dialogs/SettingsDialog.vala:258 msgid "Suggest Translations" msgstr "Übersetzungen vorschlagen" #: Dialogs/ReleaseDialog.vala:118 Dialogs/SettingsDialog.vala:267 msgid "Report a Problem" msgstr "Fehler melden" #: Dialogs/SettingsDialog.vala:40 msgid "Preferences" msgstr "Einstellungen" #: Dialogs/SettingsDialog.vala:50 Dialogs/SettingsDialog.vala:73 #: Dialogs/ShortcutsDialog.vala:45 msgid "General" msgstr "Allgemein" #: Dialogs/SettingsDialog.vala:51 Dialogs/SettingsDialog.vala:86 msgid "Interface" msgstr "Oberfläche" #: Dialogs/SettingsDialog.vala:52 Layouts/HeaderBar.vala:280 msgid "Shapes" msgstr "Formen" #: Dialogs/SettingsDialog.vala:53 msgid "About" msgstr "Über" #: Dialogs/SettingsDialog.vala:74 msgid "Auto Reopen Latest File:" msgstr "Automatisch die letzte Datei erneut öffnen:" #: Dialogs/SettingsDialog.vala:88 msgid "Use Dark Theme:" msgstr "Schwarzes Thema nutzen:" #: Dialogs/SettingsDialog.vala:92 msgid "Invert Panels Order:" msgstr "Reihenfolge der Panels umkehren:" #: Dialogs/SettingsDialog.vala:96 msgid "Restart application to apply this change." msgstr "Anwendungen neustarten um Änderungen zu übernehmen." #: Dialogs/SettingsDialog.vala:100 msgid "ToolBar Style" msgstr "Werkzeugleistenstil" #: Dialogs/SettingsDialog.vala:102 msgid "Show Button Labels:" msgstr "Knopfbeschreibungen anzeigen:" #: Dialogs/SettingsDialog.vala:106 msgid "Use Symbolic Icons:" msgstr "Symbolische Icons nutzen:" #: Dialogs/SettingsDialog.vala:129 msgid "Default Colors" msgstr "Standardfarben" #: Dialogs/SettingsDialog.vala:131 msgid "Define the default style used when creating a new shape." msgstr "Definierung des Standardaussehens einer neuen Form." #: Dialogs/SettingsDialog.vala:136 msgid "Fill Color:" msgstr "Füllfarbe:" #: Dialogs/SettingsDialog.vala:157 msgid "Enable Border Style:" msgstr "Aktiviere Ränderstil:" #: Dialogs/SettingsDialog.vala:160 msgid "Border Color:" msgstr "Ränder Farbe:" #: Dialogs/SettingsDialog.vala:181 msgid "Border Width:" msgstr "Ränder Breite:" #: Dialogs/SettingsDialog.vala:209 msgid "The Linux Design Tool" msgstr "Das Linux Designwerkzeug" #: Dialogs/SettingsDialog.vala:226 msgid "Thanks to our awesome supporters!" msgstr "Danke an unsere tollen Unterstützer!" #: Dialogs/SettingsDialog.vala:231 msgid "View the list of supporters" msgstr "Liste aller Unterstützer" #: Dialogs/ShortcutsDialog.vala:46 msgid "New window:" msgstr "Neues Fenster:" #: Dialogs/ShortcutsDialog.vala:48 msgid "Preferences:" msgstr "Einstellungen:" #: Dialogs/ShortcutsDialog.vala:50 msgid "Quit:" msgstr "Beenden:" #: Dialogs/ShortcutsDialog.vala:52 msgid "Presentation mode:" msgstr "Präsentationsmodus:" #: Dialogs/ShortcutsDialog.vala:55 msgid "File" msgstr "Datei" #: Dialogs/ShortcutsDialog.vala:56 msgid "Open:" msgstr "Öffnen:" #: Dialogs/ShortcutsDialog.vala:58 msgid "Save:" msgstr "Speichern:" #: Dialogs/ShortcutsDialog.vala:60 msgid "Save as:" msgstr "Speichern als:" #: Dialogs/ShortcutsDialog.vala:64 msgid "Export artboards:" msgstr "Zeichenbrett exportieren:" #: Dialogs/ShortcutsDialog.vala:66 msgid "Export selection:" msgstr "Auswahl exportieren:" #: Dialogs/ShortcutsDialog.vala:68 msgid "Highlight area to export:" msgstr "Bereich zum exportieren auswählen:" #: Dialogs/ShortcutsDialog.vala:77 msgid "Canvas" msgstr "Leinwand" #: Dialogs/ShortcutsDialog.vala:78 msgid "Zoom in:" msgstr "Vergrößern" #: Dialogs/ShortcutsDialog.vala:80 msgid "Zoom out:" msgstr "Verkleinern" #: Dialogs/ShortcutsDialog.vala:82 msgid "Zoom reset:" msgstr "Zoom zurücksetzen" #: Dialogs/ShortcutsDialog.vala:85 msgid "Item creation" msgstr "Objekterstellung" #: Dialogs/ShortcutsDialog.vala:86 msgid "Artboard:" msgstr "Zeichenbrett:" #: Dialogs/ShortcutsDialog.vala:88 msgid "Rectangle:" msgstr "Rechteck:" #: Dialogs/ShortcutsDialog.vala:90 msgid "Ellipse:" msgstr "Ellipse:" #: Dialogs/ShortcutsDialog.vala:92 msgid "Text:" msgstr "Text:" #: Dialogs/ShortcutsDialog.vala:94 msgid "Image:" msgstr "Foto:" #: Dialogs/ShortcutsDialog.vala:97 Layouts/Partials/TransformPanel.vala:174 msgid "Transform" msgstr "Transformieren" #: Dialogs/ShortcutsDialog.vala:98 msgid "Raise selection:" msgstr "Auswahl erhöhen:" #: Dialogs/ShortcutsDialog.vala:100 msgid "Lower selection:" msgstr "Auswahl verringern:" #: Dialogs/ShortcutsDialog.vala:102 msgid "Raise selection to top:" msgstr "Auswahl nach oben erhöhen:" #: Dialogs/ShortcutsDialog.vala:104 msgid "Lower selection to bottom:" msgstr "Auswahl nach unten verringern:" #: Dialogs/ShortcutsDialog.vala:106 msgid "Flip horizontally:" msgstr "Horizontal drehen:" #: Dialogs/ShortcutsDialog.vala:108 msgid "Flip vertically:" msgstr "Vertikal drehen:" #: FileFormat/FileManager.vala:46 msgid "Save Akira file" msgstr "Akira-Datei speichern" #: FileFormat/FileManager.vala:48 Layouts/HeaderBar.vala:190 msgid "Save" msgstr "Speichern" #: FileFormat/FileManager.vala:71 msgid "Akira files" msgstr "Akira-Dateien" #: FileFormat/FileManager.vala:76 msgid "All files" msgstr "Alle Dateien" #: FileFormat/FileManager.vala:103 msgid "Open Akira file" msgstr "Akira-Datei öffnen" #: FileFormat/FileManager.vala:105 Layouts/HeaderBar.vala:170 msgid "Open" msgstr "Öffnen" #: Layouts/HeaderBar.vala:69 Lib/Managers/ExportManager.vala:296 msgid "Untitled" msgstr "Nicht gespeichert" #: Layouts/HeaderBar.vala:71 msgid "Menu" msgstr "Menü" #: Layouts/HeaderBar.vala:75 msgid "Insert" msgstr "Einfügen" #: Layouts/HeaderBar.vala:82 msgid "Group" msgstr "Gruppieren" #: Layouts/HeaderBar.vala:84 msgid "Ungroup" msgstr "Gruppierung aufheben" #: Layouts/HeaderBar.vala:87 msgid "Up" msgstr "Hoch" #: Layouts/HeaderBar.vala:92 msgid "Down" msgstr "Runter" #: Layouts/HeaderBar.vala:97 msgid "Top" msgstr "Oben" #: Layouts/HeaderBar.vala:102 msgid "Bottom" msgstr "Unten" #: Layouts/HeaderBar.vala:107 msgid "Settings" msgstr "Einstellungen" # ? #: Layouts/HeaderBar.vala:118 #, fuzzy msgid "Difference" msgstr "Differenz" #: Layouts/HeaderBar.vala:120 #, fuzzy msgid "Exclusion" msgstr "Ausgrenzen" #: Layouts/HeaderBar.vala:122 #, fuzzy msgid "Intersect" msgstr "Überschneiden" #: Layouts/HeaderBar.vala:124 msgid "Union" msgstr "Verbinden" #: Layouts/HeaderBar.vala:161 msgid "New Window" msgstr "Neues Fenster" #: Layouts/HeaderBar.vala:182 msgid "Open Recent" msgstr "Zuletzt geöffnet" #: Layouts/HeaderBar.vala:195 msgid "Save As" msgstr "Speichern als" #: Layouts/HeaderBar.vala:204 msgid "Quit" msgstr "Schließen" #: Layouts/HeaderBar.vala:237 msgid "Artboard" msgstr "Zeichenbrett" #: Layouts/HeaderBar.vala:254 msgid "Add Items" msgstr "Objekt hinzufügen" #: Layouts/HeaderBar.vala:262 msgid "Rectangle" msgstr "Rechteck" #: Layouts/HeaderBar.vala:268 msgid "Ellipse" msgstr "Ellipse" #: Layouts/HeaderBar.vala:286 msgid "Vector" msgstr "Vektor" #: Layouts/HeaderBar.vala:288 msgid "Pencil" msgstr "Stift" #: Layouts/HeaderBar.vala:291 msgid "Text" msgstr "Text" #: Layouts/HeaderBar.vala:297 msgid "Image" msgstr "Bild" #: Layouts/HeaderBar.vala:330 msgid "Export Current Selection" msgstr "Aktuelle Auswahl exportieren" #: Layouts/HeaderBar.vala:336 msgid "Export Artboards" msgstr "Aktuelles Zeichenbrett exportieren" #: Layouts/HeaderBar.vala:345 msgid "Highlight Area to Export" msgstr "Bereich zum Exportieren auswählen" #: Layouts/HeaderBar.vala:391 msgid "Main Menu" msgstr "Hauptmenü" #: Layouts/HeaderBar.vala:468 Services/ActionManager.vala:218 #: Services/ActionManager.vala:237 Services/ActionManager.vala:256 #, c-format msgid "Unable to open file at '%s'" msgstr "Konnte Datei \"%s\" nicht öffnen" #: Layouts/MainCanvas.vala:52 msgid "Button was pressed!" msgstr "Knopf wurde gedrückt!" #: Layouts/MainCanvas.vala:160 msgid "Export completed!" msgstr "Export abgeschlossen!" #: Layouts/Partials/AlignItemsPanel.vala:48 #, fuzzy msgid "Distribute Horizontally" msgstr "Horizontall verteilen" #: Layouts/Partials/AlignItemsPanel.vala:50 #, fuzzy msgid "Distribute Vertically" msgstr "Vertikal verteilen" #: Layouts/Partials/AlignItemsPanel.vala:52 msgid "Align Left" msgstr "Links ausrichten" #: Layouts/Partials/AlignItemsPanel.vala:53 msgid "Align Center" msgstr "Zentral ausrichten" #: Layouts/Partials/AlignItemsPanel.vala:54 msgid "Align Right" msgstr "Rechts ausrichten" #: Layouts/Partials/AlignItemsPanel.vala:56 msgid "Align Top" msgstr "Nach oben ausrichten" #: Layouts/Partials/AlignItemsPanel.vala:57 msgid "Align Middle" msgstr "Mittig ausrichten" #: Layouts/Partials/AlignItemsPanel.vala:58 msgid "Align Bottom" msgstr "Nach unten ausrichten" #: Layouts/Partials/Artboard.vala:144 Layouts/Partials/Artboard.vala:487 #: Layouts/Partials/Layer.vala:139 Layouts/Partials/Layer.vala:687 msgid "Lock Layer" msgstr "Ebene sperren" #: Layouts/Partials/Artboard.vala:155 Layouts/Partials/Artboard.vala:529 #: Layouts/Partials/Layer.vala:156 Layouts/Partials/Layer.vala:729 msgid "Hide Layer" msgstr "Ebene verstecken" #: Layouts/Partials/Artboard.vala:487 Layouts/Partials/Layer.vala:687 msgid "Unlock Layer" msgstr "Ebene entsperren" #: Layouts/Partials/Artboard.vala:529 Layouts/Partials/Layer.vala:729 msgid "Show Layer" msgstr "Ebene anzeigen" #: Layouts/Partials/BorderRadiusPanel.vala:86 msgid "Style" msgstr "Stil" #: Layouts/Partials/BorderRadiusPanel.vala:103 msgid "Border Radius" msgstr "Randradius" #: Layouts/Partials/BorderRadiusPanel.vala:198 msgid "Autoscale Corners" msgstr "Ecken Automatisch skallieren" #: Layouts/Partials/BorderRadiusPanel.vala:207 msgid "Uniform Corners" msgstr "Ecken angleichen" #: Layouts/Partials/BordersPanel.vala:53 msgid "Borders" msgstr "Ränder" #: Layouts/Partials/FillsPanel.vala:54 msgid "Fills" msgstr "Füllungen" #: Layouts/Partials/TransformPanel.vala:96 msgid "X" msgstr "X" #: Layouts/Partials/TransformPanel.vala:96 msgid "Horizontal position" msgstr "Horizontale Position" #: Layouts/Partials/TransformPanel.vala:98 msgid "Y" msgstr "Y" #: Layouts/Partials/TransformPanel.vala:98 msgid "Vertical position" msgstr "Vertikale Position" #: Layouts/Partials/TransformPanel.vala:100 msgid "W" msgstr "W" #: Layouts/Partials/TransformPanel.vala:100 msgid "Width" msgstr "Breite" #: Layouts/Partials/TransformPanel.vala:102 msgid "H" msgstr "H" #: Layouts/Partials/TransformPanel.vala:102 msgid "Height" msgstr "Höhe" #: Layouts/Partials/TransformPanel.vala:107 msgid "Lock Ratio" msgstr "Rotation sperren" #: Layouts/Partials/TransformPanel.vala:114 msgid "R" msgstr "R" #: Layouts/Partials/TransformPanel.vala:114 #, fuzzy msgid "Rotation degrees" msgstr "Rotationsgrad" #: Layouts/Partials/TransformPanel.vala:126 msgid "Flip Horizontally" msgstr "Horizontahl drehen" #: Layouts/Partials/TransformPanel.vala:137 msgid "Flip Vertically" msgstr "Vertikal drehen" #: Layouts/Partials/TransformPanel.vala:165 msgid "Position" msgstr "Position" #: Layouts/Partials/TransformPanel.vala:169 msgid "Size" msgstr "Größe" #: Layouts/Partials/TransformPanel.vala:178 msgid "Opacity" msgstr "Deckkraft" #: Layouts/RightSideBar.vala:111 msgid "Search Layer" msgstr "Ebenensuche" #: Lib/Managers/ExportManager.vala:192 Lib/Managers/ExportManager.vala:219 msgid "Generating preview, please wait…" msgstr "Vorschau wird generiert, bitte warten..." #: Lib/Managers/ExportManager.vala:313 #, c-format msgid "Untitled %i" msgstr "Unbenannt %i" #: Lib/Managers/ExportManager.vala:484 msgid "Exporting images…" msgstr "Exportiere Bilder..." #: Partials/ExportWidget.vala:117 #, c-format msgid "%i × %i px · %s" msgstr "%i × %i px · %s" #: Partials/ExportWidget.vala:124 msgid "Fetching image size…" msgstr "Frage Bildgröße ab..." #: Partials/ZoomButton.vala:49 msgid "Zoom Out" msgstr "Verkleinern" #: Partials/ZoomButton.vala:55 msgid "Reset Zoom" msgstr "Zoom zurücksetzen" #: Partials/ZoomButton.vala:62 msgid "Zoom In" msgstr "Vergrößern" #: Partials/ZoomButton.vala:68 msgid "Zoom" msgstr "Zoom" #: Services/ActionManager.vala:211 msgid "No recently opened file available!" msgstr "Keine zuletzt geöffnete Datei vorhanden!" #: Services/ActionManager.vala:230 msgid "No second most recently opened file available!" msgstr "Keine zweit zuletzt geöffnete Datei vorhanden!" #: Services/ActionManager.vala:249 msgid "No third most recently opened file available!" msgstr "Keine dritt zuletzt geöffnete Datei vorhanden!" #: Services/ActionManager.vala:287 msgid "Nothing selected to export!" msgstr "Nichts zum Exportieren ausgewählt!" #: Services/ActionManager.vala:296 msgid "Export of Artboards currently unavailable…sorry 😑️" msgstr "Das Exportieren von Zeichenbrettern ist momentan leider nicht möglich… 😑️" #: Services/ActionManager.vala:363 msgid "Choose image file" msgstr "Bilddatei auswählen" #: Services/ActionManager.vala:363 msgid "Select" msgstr "Auswählen" #: Services/ActionManager.vala:363 msgid "Close" msgstr "Schließen" #: Services/ActionManager.vala:432 #, c-format msgid "Error! .%s files are not supported!" msgstr "Fehler: .%s Dateien werden nicht Unterstützt." #: Window.vala:119 msgid "Are you sure you want to quit?" msgstr "Soll das Programm wirklich geschlossen werden?" #: Window.vala:120 msgid "All unsaved data will be lost and impossible to recover." msgstr "Alle nicht gespeicherten Dateien gehen verloren und können nicht wiederhergestellt werden." #: Window.vala:122 msgid "Quit without saving!" msgstr "Ohne speichern schließen!" #: Window.vala:123 msgid "Save file" msgstr "Datei speichern" Akira-0.0.16/po/dv.po000066400000000000000000000001251410625726100142160ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/dz.po000066400000000000000000000001251410625726100142220ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/ee.po000066400000000000000000000001251410625726100141760ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/el.po000066400000000000000000000001251410625726100142050ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/en_AU.po000066400000000000000000000001251410625726100145740ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/en_CA.po000066400000000000000000000001251410625726100145520ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/en_GB.po000066400000000000000000000001251410625726100145570ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/eo.po000066400000000000000000000002021410625726100142040ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" Akira-0.0.16/po/es.po000066400000000000000000000356531410625726100142320ustar00rootroot00000000000000msgid "" msgstr "" "Project-Id-Version: \n" "POT-Creation-Date: 2020-08-12 22:06-0500\n" "PO-Revision-Date: \n" "Last-Translator: Adolfo Jayme Barrientos \n" "Language-Team: \n" "Language: es\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" "X-Generator: Poedit 2.4.1\n" "X-Poedit-Basepath: ../src\n" "X-Poedit-SearchPath-0: .\n" #: Dialogs/ExportDialog.vala:151 msgid "Export to:" msgstr "Exportar en:" #: Dialogs/ExportDialog.vala:157 msgid "Select Folder" msgstr "Seleccionar carpeta" #: Dialogs/ExportDialog.vala:166 msgid "Format:" msgstr "Formato:" #: Dialogs/ExportDialog.vala:180 msgid "Quality:" msgstr "Calidad:" #: Dialogs/ExportDialog.vala:192 msgid "Compression:" msgstr "Compresión:" #: Dialogs/ExportDialog.vala:206 msgid "Transparency:" msgstr "Transparencia:" #: Dialogs/ExportDialog.vala:219 msgid "Scale:" msgstr "Escala:" #: Dialogs/ExportDialog.vala:243 FileFormat/FileManager.vala:49 #: FileFormat/FileManager.vala:105 msgid "Cancel" msgstr "Cancelar" #: Dialogs/ExportDialog.vala:250 Dialogs/ShortcutsDialog.vala:63 #: Layouts/HeaderBar.vala:112 msgid "Export" msgstr "Exportar" #: Dialogs/ReleaseDialog.vala:47 Dialogs/SettingsDialog.vala:217 msgid "" "WARNING!\n" "Akira is still under development and not ready for production. Missing " "features, random bugs, and black holes opening in your kitchen are to be " "expected." msgstr "" "ATENCIÓN:\n" "Akira se encuentra en desarrollo y no está destinado a entornos de " "producción. Es de esperar que falten funciones y haya defectos inesperados." #: Dialogs/ReleaseDialog.vala:100 Dialogs/SettingsDialog.vala:249 msgid "Make a Donation" msgstr "Donar" #: Dialogs/ReleaseDialog.vala:109 Dialogs/SettingsDialog.vala:258 msgid "Suggest Translations" msgstr "Sugerir traducciones" #: Dialogs/ReleaseDialog.vala:118 Dialogs/SettingsDialog.vala:267 msgid "Report a Problem" msgstr "Informar de un problema" #: Dialogs/SettingsDialog.vala:40 msgid "Preferences" msgstr "Preferencias" #: Dialogs/SettingsDialog.vala:50 Dialogs/SettingsDialog.vala:73 #: Dialogs/ShortcutsDialog.vala:45 msgid "General" msgstr "Generales" #: Dialogs/SettingsDialog.vala:51 Dialogs/SettingsDialog.vala:86 msgid "Interface" msgstr "Interfaz" #: Dialogs/SettingsDialog.vala:52 Layouts/HeaderBar.vala:280 msgid "Shapes" msgstr "Formas" #: Dialogs/SettingsDialog.vala:53 msgid "About" msgstr "Acerca de" #: Dialogs/SettingsDialog.vala:74 msgid "Auto Reopen Latest File:" msgstr "Reabrir automáticamente archivo más reciente:" #: Dialogs/SettingsDialog.vala:88 msgid "Use Dark Theme:" msgstr "Utilizar tema oscuro:" #: Dialogs/SettingsDialog.vala:92 msgid "Invert Panels Order:" msgstr "Intercambiar posición de paneles:" #: Dialogs/SettingsDialog.vala:96 msgid "Restart application to apply this change." msgstr "Reinicie la aplicación para aplicar el cambio." #: Dialogs/SettingsDialog.vala:100 msgid "ToolBar Style" msgstr "Estilo de barra de herramientas" #: Dialogs/SettingsDialog.vala:102 msgid "Show Button Labels:" msgstr "Mostrar etiquetas de botones:" #: Dialogs/SettingsDialog.vala:106 msgid "Use Symbolic Icons:" msgstr "Utilizar iconos monocromáticos:" #: Dialogs/SettingsDialog.vala:129 msgid "Default Colors" msgstr "Colores predeterminados" #: Dialogs/SettingsDialog.vala:131 msgid "Define the default style used when creating a new shape." msgstr "" "Defina el estilo que se utilizará de manera predeterminada al crear formas." #: Dialogs/SettingsDialog.vala:136 msgid "Fill Color:" msgstr "Color de relleno:" #: Dialogs/SettingsDialog.vala:157 msgid "Enable Border Style:" msgstr "Activar estilo con borde:" #: Dialogs/SettingsDialog.vala:160 msgid "Border Color:" msgstr "Color de borde:" #: Dialogs/SettingsDialog.vala:181 msgid "Border Width:" msgstr "Anchura de borde:" #: Dialogs/SettingsDialog.vala:209 msgid "The Linux Design Tool" msgstr "La herramienta de diseño para Linux" #: Dialogs/SettingsDialog.vala:226 msgid "Thanks to our awesome supporters!" msgstr "¡Gracias a nuestros geniales partidarios!" #: Dialogs/SettingsDialog.vala:231 msgid "View the list of supporters" msgstr "Ver lista de partidarios" #: Dialogs/ShortcutsDialog.vala:46 msgid "New window:" msgstr "Ventana nueva:" #: Dialogs/ShortcutsDialog.vala:48 msgid "Preferences:" msgstr "Preferencias:" #: Dialogs/ShortcutsDialog.vala:50 msgid "Quit:" msgstr "Salir:" #: Dialogs/ShortcutsDialog.vala:52 msgid "Presentation mode:" msgstr "Modo de presentación:" #: Dialogs/ShortcutsDialog.vala:55 msgid "File" msgstr "Archivo" #: Dialogs/ShortcutsDialog.vala:56 msgid "Open:" msgstr "Abrir:" #: Dialogs/ShortcutsDialog.vala:58 msgid "Save:" msgstr "Guardar:" #: Dialogs/ShortcutsDialog.vala:60 msgid "Save as:" msgstr "Guardar como:" #: Dialogs/ShortcutsDialog.vala:64 msgid "Export artboards:" msgstr "Exportar mesas de trabajo:" #: Dialogs/ShortcutsDialog.vala:66 msgid "Export selection:" msgstr "Exportar selección:" #: Dialogs/ShortcutsDialog.vala:68 msgid "Highlight area to export:" msgstr "Resaltar área que exportar:" #: Dialogs/ShortcutsDialog.vala:77 msgid "Canvas" msgstr "Lienzo" #: Dialogs/ShortcutsDialog.vala:78 msgid "Zoom in:" msgstr "Acercar" #: Dialogs/ShortcutsDialog.vala:80 msgid "Zoom out:" msgstr "Alejar" #: Dialogs/ShortcutsDialog.vala:82 msgid "Zoom reset:" msgstr "Restablecer escala:" #: Dialogs/ShortcutsDialog.vala:85 msgid "Item creation" msgstr "Creación de elemento" #: Dialogs/ShortcutsDialog.vala:86 msgid "Artboard:" msgstr "Mesa de trabajo:" #: Dialogs/ShortcutsDialog.vala:88 msgid "Rectangle:" msgstr "Rectángulo:" #: Dialogs/ShortcutsDialog.vala:90 msgid "Ellipse:" msgstr "Elipse:" #: Dialogs/ShortcutsDialog.vala:92 msgid "Text:" msgstr "Texto:" #: Dialogs/ShortcutsDialog.vala:94 msgid "Image:" msgstr "Imagen:" #: Dialogs/ShortcutsDialog.vala:97 Layouts/Partials/TransformPanel.vala:174 msgid "Transform" msgstr "Transformar" #: Dialogs/ShortcutsDialog.vala:98 msgid "Raise selection:" msgstr "Subir selección:" #: Dialogs/ShortcutsDialog.vala:100 msgid "Lower selection:" msgstr "Bajar selección:" #: Dialogs/ShortcutsDialog.vala:102 msgid "Raise selection to top:" msgstr "Traer selección hasta arriba:" #: Dialogs/ShortcutsDialog.vala:104 msgid "Lower selection to bottom:" msgstr "Enviar selección hasta abajo:" #: Dialogs/ShortcutsDialog.vala:106 msgid "Flip horizontally:" msgstr "Voltear horizontalmente:" #: Dialogs/ShortcutsDialog.vala:108 msgid "Flip vertically:" msgstr "Voltear verticalmente:" #: FileFormat/FileManager.vala:46 msgid "Save Akira file" msgstr "Guardar archivo de Akira" #: FileFormat/FileManager.vala:48 Layouts/HeaderBar.vala:190 msgid "Save" msgstr "Guardar" #: FileFormat/FileManager.vala:71 msgid "Akira files" msgstr "Archivos de Akira" #: FileFormat/FileManager.vala:76 msgid "All files" msgstr "Todos los archivos" #: FileFormat/FileManager.vala:103 msgid "Open Akira file" msgstr "Abrir archivo de Akira" #: FileFormat/FileManager.vala:105 Layouts/HeaderBar.vala:170 msgid "Open" msgstr "Abrir" #: Layouts/HeaderBar.vala:69 Lib/Managers/ExportManager.vala:296 msgid "Untitled" msgstr "Sin título" #: Layouts/HeaderBar.vala:71 msgid "Menu" msgstr "Menú" #: Layouts/HeaderBar.vala:75 msgid "Insert" msgstr "Insertar" #: Layouts/HeaderBar.vala:82 msgid "Group" msgstr "Agrupar" #: Layouts/HeaderBar.vala:84 msgid "Ungroup" msgstr "Desagrupar" #: Layouts/HeaderBar.vala:87 msgid "Up" msgstr "Subir" #: Layouts/HeaderBar.vala:92 msgid "Down" msgstr "Bajar" #: Layouts/HeaderBar.vala:97 msgid "Top" msgstr "Al principio" #: Layouts/HeaderBar.vala:102 msgid "Bottom" msgstr "Al final" #: Layouts/HeaderBar.vala:107 msgid "Settings" msgstr "Configuración" #: Layouts/HeaderBar.vala:118 msgid "Difference" msgstr "Diferencia" #: Layouts/HeaderBar.vala:120 msgid "Exclusion" msgstr "Exclusión" #: Layouts/HeaderBar.vala:122 msgid "Intersect" msgstr "Intersección" #: Layouts/HeaderBar.vala:124 msgid "Union" msgstr "Unión" #: Layouts/HeaderBar.vala:161 msgid "New Window" msgstr "Ventana nueva" #: Layouts/HeaderBar.vala:182 msgid "Open Recent" msgstr "Abrir recientes" #: Layouts/HeaderBar.vala:195 msgid "Save As" msgstr "Guardar como" #: Layouts/HeaderBar.vala:204 msgid "Quit" msgstr "Salir" #: Layouts/HeaderBar.vala:237 msgid "Artboard" msgstr "Mesa de trabajo" #: Layouts/HeaderBar.vala:254 msgid "Add Items" msgstr "Añadir elementos" #: Layouts/HeaderBar.vala:262 msgid "Rectangle" msgstr "Rectángulo" #: Layouts/HeaderBar.vala:268 msgid "Ellipse" msgstr "Elipse" #: Layouts/HeaderBar.vala:286 msgid "Vector" msgstr "Vector" #: Layouts/HeaderBar.vala:288 msgid "Pencil" msgstr "Lápiz" #: Layouts/HeaderBar.vala:291 msgid "Text" msgstr "Texto" #: Layouts/HeaderBar.vala:297 msgid "Image" msgstr "Imagen" #: Layouts/HeaderBar.vala:330 msgid "Export Current Selection" msgstr "Exportar selección actual" #: Layouts/HeaderBar.vala:336 msgid "Export Artboards" msgstr "Exportar mesas de trabajo" #: Layouts/HeaderBar.vala:345 msgid "Highlight Area to Export" msgstr "Resaltar área que exportar" #: Layouts/HeaderBar.vala:391 msgid "Main Menu" msgstr "Menú principal" #: Layouts/HeaderBar.vala:468 Services/ActionManager.vala:218 #: Services/ActionManager.vala:237 Services/ActionManager.vala:256 #, c-format msgid "Unable to open file at '%s'" msgstr "No se puede abrir el archivo en «%s»" #: Layouts/MainCanvas.vala:52 msgid "Button was pressed!" msgstr "Se ha presionado el botón." #: Layouts/MainCanvas.vala:160 msgid "Export completed!" msgstr "Finalizó la exportación." #: Layouts/Partials/AlignItemsPanel.vala:48 msgid "Distribute Horizontally" msgstr "Distribuir horizontalmente" #: Layouts/Partials/AlignItemsPanel.vala:50 msgid "Distribute Vertically" msgstr "Distribuir verticalmente" #: Layouts/Partials/AlignItemsPanel.vala:52 msgid "Align Left" msgstr "Alinear a la izquierda" #: Layouts/Partials/AlignItemsPanel.vala:53 msgid "Align Center" msgstr "Centrar horizontalmente" #: Layouts/Partials/AlignItemsPanel.vala:54 msgid "Align Right" msgstr "Alinear a la derecha" #: Layouts/Partials/AlignItemsPanel.vala:56 msgid "Align Top" msgstr "Alinear arriba" #: Layouts/Partials/AlignItemsPanel.vala:57 msgid "Align Middle" msgstr "Centrar verticalmente" #: Layouts/Partials/AlignItemsPanel.vala:58 msgid "Align Bottom" msgstr "Alinear abajo" #: Layouts/Partials/Artboard.vala:144 Layouts/Partials/Artboard.vala:487 #: Layouts/Partials/Layer.vala:139 Layouts/Partials/Layer.vala:687 msgid "Lock Layer" msgstr "Bloquear capa" #: Layouts/Partials/Artboard.vala:155 Layouts/Partials/Artboard.vala:529 #: Layouts/Partials/Layer.vala:156 Layouts/Partials/Layer.vala:729 msgid "Hide Layer" msgstr "Ocultar capa" #: Layouts/Partials/Artboard.vala:487 Layouts/Partials/Layer.vala:687 msgid "Unlock Layer" msgstr "Desbloquear capa" #: Layouts/Partials/Artboard.vala:529 Layouts/Partials/Layer.vala:729 msgid "Show Layer" msgstr "Mostrar capa" #: Layouts/Partials/BorderRadiusPanel.vala:86 msgid "Style" msgstr "Estilo" #: Layouts/Partials/BorderRadiusPanel.vala:103 msgid "Border Radius" msgstr "Radio de borde" #: Layouts/Partials/BorderRadiusPanel.vala:198 msgid "Autoscale Corners" msgstr "Escalar esquinas automáticamente" #: Layouts/Partials/BorderRadiusPanel.vala:207 msgid "Uniform Corners" msgstr "Esquinas uniformes" #: Layouts/Partials/BordersPanel.vala:53 msgid "Borders" msgstr "Bordes" #: Layouts/Partials/FillsPanel.vala:54 msgid "Fills" msgstr "Rellenos" #: Layouts/Partials/TransformPanel.vala:96 msgid "X" msgstr "X" #: Layouts/Partials/TransformPanel.vala:96 msgid "Horizontal position" msgstr "Posición horizontal" #: Layouts/Partials/TransformPanel.vala:98 msgid "Y" msgstr "Y" #: Layouts/Partials/TransformPanel.vala:98 msgid "Vertical position" msgstr "Posición vertical" #: Layouts/Partials/TransformPanel.vala:100 msgid "W" msgstr "↔" #: Layouts/Partials/TransformPanel.vala:100 msgid "Width" msgstr "Anchura" #: Layouts/Partials/TransformPanel.vala:102 msgid "H" msgstr "↕" #: Layouts/Partials/TransformPanel.vala:102 msgid "Height" msgstr "Altura" #: Layouts/Partials/TransformPanel.vala:107 msgid "Lock Ratio" msgstr "Bloquear relación" #: Layouts/Partials/TransformPanel.vala:114 msgid "R" msgstr "↻" #: Layouts/Partials/TransformPanel.vala:114 msgid "Rotation degrees" msgstr "Grados de giro" #: Layouts/Partials/TransformPanel.vala:126 msgid "Flip Horizontally" msgstr "Voltear horizontalmente" #: Layouts/Partials/TransformPanel.vala:137 msgid "Flip Vertically" msgstr "Voltear verticalmente" #: Layouts/Partials/TransformPanel.vala:165 msgid "Position" msgstr "Posición" #: Layouts/Partials/TransformPanel.vala:169 msgid "Size" msgstr "Tamaño" #: Layouts/Partials/TransformPanel.vala:178 msgid "Opacity" msgstr "Opacidad" #: Layouts/RightSideBar.vala:111 msgid "Search Layer" msgstr "Buscar capa" #: Lib/Managers/ExportManager.vala:192 Lib/Managers/ExportManager.vala:219 msgid "Generating preview, please wait…" msgstr "Generando previsualización; espere…" #: Lib/Managers/ExportManager.vala:313 #, c-format msgid "Untitled %i" msgstr "Sin título %i" #: Lib/Managers/ExportManager.vala:484 msgid "Exporting images…" msgstr "Exportando imágenes…" #: Partials/ExportWidget.vala:117 #, c-format msgid "%i × %i px · %s" msgstr "%i × %i px · %s" #: Partials/ExportWidget.vala:124 msgid "Fetching image size…" msgstr "Recuperando tamaño de imagen…" #: Partials/ZoomButton.vala:49 msgid "Zoom Out" msgstr "Alejar" #: Partials/ZoomButton.vala:55 msgid "Reset Zoom" msgstr "Restablecer escala" #: Partials/ZoomButton.vala:62 msgid "Zoom In" msgstr "Acercar" #: Partials/ZoomButton.vala:68 msgid "Zoom" msgstr "Escala" #: Services/ActionManager.vala:211 msgid "No recently opened file available!" msgstr "No hay ningún archivo reciente." #: Services/ActionManager.vala:230 msgid "No second most recently opened file available!" msgstr "No hay ningún segundo archivo reciente." #: Services/ActionManager.vala:249 msgid "No third most recently opened file available!" msgstr "No hay ningún tercer archivo reciente." #: Services/ActionManager.vala:287 msgid "Nothing selected to export!" msgstr "No se ha seleccionado nada para exportar." #: Services/ActionManager.vala:296 msgid "Export of Artboards currently unavailable…sorry 😑️" msgstr "" "La exportación de mesas de trabajo no está disponible por el momento… 😑️" #: Services/ActionManager.vala:363 msgid "Choose image file" msgstr "Seleccionar archivo de imagen" #: Services/ActionManager.vala:363 msgid "Select" msgstr "Seleccionar" #: Services/ActionManager.vala:363 msgid "Close" msgstr "Cerrar" #: Services/ActionManager.vala:432 #, c-format msgid "Error! .%s files are not supported!" msgstr "Error: no se admiten los archivos .%s." #: Window.vala:119 msgid "Are you sure you want to quit?" msgstr "¿Confirma que quiere salir?" #: Window.vala:120 msgid "All unsaved data will be lost and impossible to recover." msgstr "Se perderán los datos no guardados y no podrán recuperarse." #: Window.vala:122 msgid "Quit without saving!" msgstr "Salir sin guardar" #: Window.vala:123 msgid "Save file" msgstr "Guardar archivo" Akira-0.0.16/po/et.po000066400000000000000000000002021410625726100142110ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" Akira-0.0.16/po/eu.po000066400000000000000000000001251410625726100142160ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/fa.po000066400000000000000000000001251410625726100141730ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/ff.po000066400000000000000000000001251410625726100142000ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/fi.po000066400000000000000000000002021410625726100141770ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" Akira-0.0.16/po/fj.po000066400000000000000000000001251410625726100142040ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/fo.po000066400000000000000000000002021410625726100142050ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" Akira-0.0.16/po/fr.po000066400000000000000000000427201410625726100142230ustar00rootroot00000000000000msgid "" msgstr "" "Project-Id-Version: \n" "POT-Creation-Date: 2020-10-07 21:17+0200\n" "PO-Revision-Date: 2020-10-31 14:08+0100\n" "Last-Translator: Yannicka\n" "Language-Team: \n" "Language: fr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Poedit 2.4.1\n" "X-Poedit-Basepath: .\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" "X-Poedit-SearchPath-0: .\n" #: src/Dialogs/ExportDialog.vala:151 msgid "Export to:" msgstr "Exporter vers :" #: src/Dialogs/ExportDialog.vala:157 msgid "Select Folder" msgstr "Sélectionner un dossier" #: src/Dialogs/ExportDialog.vala:166 msgid "Format:" msgstr "Format :" #: src/Dialogs/ExportDialog.vala:179 msgid "Quality:" msgstr "Qualité :" #: src/Dialogs/ExportDialog.vala:191 msgid "Compression:" msgstr "Compression :" #: src/Dialogs/ExportDialog.vala:205 msgid "Transparency:" msgstr "Transparence :" #: src/Dialogs/ExportDialog.vala:218 msgid "Scale:" msgstr "Échelle :" #: src/Dialogs/ExportDialog.vala:242 src/FileFormat/FileManager.vala:49 #: src/FileFormat/FileManager.vala:105 msgid "Cancel" msgstr "Annuler" #: src/Dialogs/ExportDialog.vala:249 src/Dialogs/ShortcutsDialog.vala:63 #: src/Layouts/HeaderBar.vala:112 msgid "Export" msgstr "Exporter" #: src/Dialogs/ReleaseDialog.vala:47 src/Dialogs/SettingsDialog.vala:217 msgid "" "WARNING!\n" "Akira is still under development and not ready for production. Missing " "features, random bugs, and black holes opening in your kitchen are to be " "expected." msgstr "" "ATTENTION !\n" "Akira est encore en cours de développement et n'est pas prêt à être " "utilisé en production. Attendez-vous à ce que des fonctionnalités " "manquent, des bugs se produisent voire qu'un trou noir s'ouvre dans votre " "cuisine." #: src/Dialogs/ReleaseDialog.vala:100 src/Dialogs/SettingsDialog.vala:249 msgid "Make a Donation" msgstr "Faire un don" #: src/Dialogs/ReleaseDialog.vala:109 src/Dialogs/SettingsDialog.vala:258 msgid "Suggest Translations" msgstr "Suggérer des traductions" #: src/Dialogs/ReleaseDialog.vala:118 src/Dialogs/SettingsDialog.vala:267 msgid "Report a Problem" msgstr "Signaler un problème" #: src/Dialogs/SettingsDialog.vala:40 msgid "Preferences" msgstr "Préférences" #: src/Dialogs/SettingsDialog.vala:50 src/Dialogs/SettingsDialog.vala:73 #: src/Dialogs/ShortcutsDialog.vala:45 msgid "General" msgstr "Général" #: src/Dialogs/SettingsDialog.vala:51 src/Dialogs/SettingsDialog.vala:86 msgid "Interface" msgstr "Interface" #: src/Dialogs/SettingsDialog.vala:52 src/Layouts/HeaderBar.vala:280 msgid "Shapes" msgstr "Formes" #: src/Dialogs/SettingsDialog.vala:53 msgid "About" msgstr "À propos" #: src/Dialogs/SettingsDialog.vala:74 msgid "Auto Reopen Latest File:" msgstr "Rouvrir automatiquement le dernier fichier :" #: src/Dialogs/SettingsDialog.vala:88 msgid "Use Dark Theme:" msgstr "Utiliser le thème sombre :" #: src/Dialogs/SettingsDialog.vala:92 msgid "Invert Panels Order:" msgstr "Inverser l'ordre des barres latérales :" #: src/Dialogs/SettingsDialog.vala:96 msgid "Restart application to apply this change." msgstr "Redémarrez l'application pour appliquer ce changement." #: src/Dialogs/SettingsDialog.vala:100 msgid "ToolBar Style" msgstr "Style de la barre d'outils" #: src/Dialogs/SettingsDialog.vala:102 msgid "Show Button Labels:" msgstr "Afficher l'étiquette des boutons :" #: src/Dialogs/SettingsDialog.vala:106 msgid "Use Symbolic Icons:" msgstr "Utiliser les icônes symboliques :" #: src/Dialogs/SettingsDialog.vala:129 msgid "Default Colors" msgstr "Couleurs par défaut" #: src/Dialogs/SettingsDialog.vala:131 msgid "Define the default style used when creating a new shape." msgstr "" "Définit le style par défaut utilisé lors de la création d'une nouvelle " "forme." #: src/Dialogs/SettingsDialog.vala:136 msgid "Fill Color:" msgstr "Couleur de remplissage :" #: src/Dialogs/SettingsDialog.vala:157 msgid "Enable Border Style:" msgstr "Activer le style de bordure :" #: src/Dialogs/SettingsDialog.vala:160 msgid "Border Color:" msgstr "Couleur de la bordure :" #: src/Dialogs/SettingsDialog.vala:181 msgid "Border Width:" msgstr "Largeur de la bordure :" #: src/Dialogs/SettingsDialog.vala:209 msgid "The Linux Design Tool" msgstr "L'outil de conception Linux" #: src/Dialogs/SettingsDialog.vala:226 msgid "Thanks to our awesome supporters!" msgstr "Merci à toutes les merveilleuses personnes qui nous soutiennent !" #: src/Dialogs/SettingsDialog.vala:231 msgid "View the list of supporters" msgstr "Voir la liste des personnes qui soutiennent le projet" #: src/Dialogs/ShortcutsDialog.vala:46 msgid "New window:" msgstr "Nouvelle fenêtre :" #: src/Dialogs/ShortcutsDialog.vala:48 msgid "Preferences:" msgstr "Préférences :" #: src/Dialogs/ShortcutsDialog.vala:50 msgid "Quit:" msgstr "Quitter :" #: src/Dialogs/ShortcutsDialog.vala:52 msgid "Presentation mode:" msgstr "Mode présentation :" #: src/Dialogs/ShortcutsDialog.vala:55 msgid "File" msgstr "Ficher" #: src/Dialogs/ShortcutsDialog.vala:56 msgid "Open:" msgstr "Ouvrir :" #: src/Dialogs/ShortcutsDialog.vala:58 msgid "Save:" msgstr "Enregistrer :" #: src/Dialogs/ShortcutsDialog.vala:60 msgid "Save as:" msgstr "Enregistrer sous :" #: src/Dialogs/ShortcutsDialog.vala:64 msgid "Export artboards:" msgstr "Exporter les espaces de travail :" #: src/Dialogs/ShortcutsDialog.vala:66 msgid "Export selection:" msgstr "Exporter la sélection :" #: src/Dialogs/ShortcutsDialog.vala:68 msgid "Highlight area to export:" msgstr "Sélectionner la zone à exporter :" #: src/Dialogs/ShortcutsDialog.vala:77 msgid "Canvas" msgstr "Canevas" #: src/Dialogs/ShortcutsDialog.vala:78 msgid "Zoom in:" msgstr "Zoomer :" #: src/Dialogs/ShortcutsDialog.vala:80 msgid "Zoom out:" msgstr "Dézoomer :" #: src/Dialogs/ShortcutsDialog.vala:82 msgid "Zoom reset:" msgstr "Réinitialiser le zoom :" #: src/Dialogs/ShortcutsDialog.vala:85 msgid "Item creation" msgstr "Création d'élément" #: src/Dialogs/ShortcutsDialog.vala:86 msgid "Artboard:" msgstr "Espace de travail :" #: src/Dialogs/ShortcutsDialog.vala:88 msgid "Rectangle:" msgstr "Rectangle :" #: src/Dialogs/ShortcutsDialog.vala:90 msgid "Ellipse:" msgstr "Ellipse :" #: src/Dialogs/ShortcutsDialog.vala:92 msgid "Text:" msgstr "Texte :" #: src/Dialogs/ShortcutsDialog.vala:94 msgid "Image:" msgstr "Image :" #: src/Dialogs/ShortcutsDialog.vala:97 #: src/Layouts/Partials/TransformPanel.vala:174 msgid "Transform" msgstr "Transformer" #: src/Dialogs/ShortcutsDialog.vala:98 msgid "Raise selection:" msgstr "Monter la sélection :" #: src/Dialogs/ShortcutsDialog.vala:100 msgid "Lower selection:" msgstr "Descendre la sélection :" #: src/Dialogs/ShortcutsDialog.vala:102 msgid "Raise selection to top:" msgstr "Monter la sélection tout en haut :" #: src/Dialogs/ShortcutsDialog.vala:104 msgid "Lower selection to bottom:" msgstr "Descendre la sélection tout en bas :" #: src/Dialogs/ShortcutsDialog.vala:106 msgid "Flip horizontally:" msgstr "Retourner horizontalement :" #: src/Dialogs/ShortcutsDialog.vala:108 msgid "Flip vertically:" msgstr "Retourner verticalement :" #: src/FileFormat/FileManager.vala:46 msgid "Save Akira file" msgstr "Enregistrer un fichier Akira" #: src/FileFormat/FileManager.vala:48 src/Layouts/HeaderBar.vala:190 msgid "Save" msgstr "Enregistrer" #: src/FileFormat/FileManager.vala:71 msgid "Akira files" msgstr "Fichiers Akira" #: src/FileFormat/FileManager.vala:76 msgid "All files" msgstr "Tous les fichiers" #: src/FileFormat/FileManager.vala:103 msgid "Open Akira file" msgstr "Ouvrir un fichier Akira" #: src/FileFormat/FileManager.vala:105 src/Layouts/HeaderBar.vala:170 msgid "Open" msgstr "Ouvrir" #: src/Layouts/HeaderBar.vala:69 src/Lib/Managers/ExportManager.vala:296 msgid "Untitled" msgstr "Sans titre" #: src/Layouts/HeaderBar.vala:71 msgid "Menu" msgstr "Menu" #: src/Layouts/HeaderBar.vala:75 msgid "Insert" msgstr "Insérer" #: src/Layouts/HeaderBar.vala:82 msgid "Group" msgstr "Grouper" #: src/Layouts/HeaderBar.vala:84 msgid "Ungroup" msgstr "Dégrouper" #: src/Layouts/HeaderBar.vala:87 msgid "Up" msgstr "Monter" #: src/Layouts/HeaderBar.vala:92 msgid "Down" msgstr "Descendre" #: src/Layouts/HeaderBar.vala:97 msgid "Top" msgstr "Devant" #: src/Layouts/HeaderBar.vala:102 msgid "Bottom" msgstr "Derrière" #: src/Layouts/HeaderBar.vala:107 msgid "Settings" msgstr "Paramètres" #: src/Layouts/HeaderBar.vala:118 msgid "Difference" msgstr "Différence" #: src/Layouts/HeaderBar.vala:120 msgid "Exclusion" msgstr "Exclusion" #: src/Layouts/HeaderBar.vala:122 msgid "Intersect" msgstr "Intersection" #: src/Layouts/HeaderBar.vala:124 msgid "Union" msgstr "Union" #: src/Layouts/HeaderBar.vala:161 msgid "New Window" msgstr "Nouvelle fenêtre" #: src/Layouts/HeaderBar.vala:182 msgid "Open Recent" msgstr "Ouvert récemment" #: src/Layouts/HeaderBar.vala:195 msgid "Save As" msgstr "Enregistrer sous..." #: src/Layouts/HeaderBar.vala:204 msgid "Quit" msgstr "Quitter" #: src/Layouts/HeaderBar.vala:237 msgid "Artboard" msgstr "Espace de travail" #: src/Layouts/HeaderBar.vala:254 msgid "Add Items" msgstr "Ajouter des éléments" #: src/Layouts/HeaderBar.vala:262 msgid "Rectangle" msgstr "Rectangle" #: src/Layouts/HeaderBar.vala:268 msgid "Ellipse" msgstr "Ellipse" #: src/Layouts/HeaderBar.vala:286 msgid "Vector" msgstr "Vecteur" #: src/Layouts/HeaderBar.vala:288 msgid "Pencil" msgstr "Crayon" #: src/Layouts/HeaderBar.vala:291 msgid "Text" msgstr "Texte" #: src/Layouts/HeaderBar.vala:297 msgid "Image" msgstr "Image" #: src/Layouts/HeaderBar.vala:330 msgid "Export Current Selection" msgstr "Exporter la sélection courante" #: src/Layouts/HeaderBar.vala:336 msgid "Export Artboards" msgstr "Exporter les espaces de travail" #: src/Layouts/HeaderBar.vala:345 msgid "Highlight Area to Export" msgstr "Sélectionner la zone à exporter" #: src/Layouts/HeaderBar.vala:391 msgid "Main Menu" msgstr "Menu principal" #: src/Layouts/HeaderBar.vala:468 src/Services/ActionManager.vala:224 #: src/Services/ActionManager.vala:243 src/Services/ActionManager.vala:262 #, c-format msgid "Unable to open file at '%s'" msgstr "Impossible d'ouvrir le fichier « %s »" #: src/Layouts/MainCanvas.vala:46 msgid "Button was pressed!" msgstr "Un bouton a été pressé !" #: src/Layouts/MainCanvas.vala:206 msgid "Export completed!" msgstr "Export terminée !" #: src/Layouts/Partials/AlignItemsPanel.vala:48 msgid "Distribute Horizontally" msgstr "Distribuer horizontalement" #: src/Layouts/Partials/AlignItemsPanel.vala:50 msgid "Distribute Vertically" msgstr "Distribuer verticalement" #: src/Layouts/Partials/AlignItemsPanel.vala:52 msgid "Align Left" msgstr "Aligner à gauche" #: src/Layouts/Partials/AlignItemsPanel.vala:53 msgid "Align Center" msgstr "Aligner au centre" #: src/Layouts/Partials/AlignItemsPanel.vala:54 msgid "Align Right" msgstr "Aligner à droite" #: src/Layouts/Partials/AlignItemsPanel.vala:56 msgid "Align Top" msgstr "Aligner en haut" #: src/Layouts/Partials/AlignItemsPanel.vala:57 msgid "Align Middle" msgstr "Aligner au milieu" #: src/Layouts/Partials/AlignItemsPanel.vala:58 msgid "Align Bottom" msgstr "Aligner en bas" #: src/Layouts/Partials/Artboard.vala:144 #: src/Layouts/Partials/Artboard.vala:487 src/Layouts/Partials/Layer.vala:139 #: src/Layouts/Partials/Layer.vala:687 msgid "Lock Layer" msgstr "Verrouiller le calque" #: src/Layouts/Partials/Artboard.vala:155 #: src/Layouts/Partials/Artboard.vala:529 src/Layouts/Partials/Layer.vala:156 #: src/Layouts/Partials/Layer.vala:729 msgid "Hide Layer" msgstr "Cacher le calque" #: src/Layouts/Partials/Artboard.vala:487 src/Layouts/Partials/Layer.vala:687 msgid "Unlock Layer" msgstr "Dévérouiller le calque" #: src/Layouts/Partials/Artboard.vala:529 src/Layouts/Partials/Layer.vala:729 msgid "Show Layer" msgstr "Afficher le calque" #: src/Layouts/Partials/BorderItem.vala:121 msgid "Choose border color" msgstr "Choisir la couleur de la bordure" #: src/Layouts/Partials/BorderItem.vala:176 #: src/Layouts/Partials/FillItem.vala:178 msgid "Pick color" msgstr "Choisir une couleur" #: src/Layouts/Partials/BorderItem.vala:191 msgid "Remove border" msgstr "Supprimer la bordure" #: src/Layouts/Partials/BorderItem.vala:275 msgid "Show border" msgstr "Afficher la bordure" #: src/Layouts/Partials/BorderItem.vala:279 msgid "Hide border" msgstr "Masquer la bordure" #: src/Layouts/Partials/BorderRadiusPanel.vala:86 msgid "Style" msgstr "Style" #: src/Layouts/Partials/BorderRadiusPanel.vala:103 msgid "Border Radius" msgstr "Arrondi" #: src/Layouts/Partials/BorderRadiusPanel.vala:137 msgid "Border radius options" msgstr "Options de l'arrondi" #: src/Layouts/Partials/BorderRadiusPanel.vala:199 msgid "Autoscale Corners" msgstr "Mise à l'échelle automatique des coins" #: src/Layouts/Partials/BorderRadiusPanel.vala:208 msgid "Uniform Corners" msgstr "Coins uniformes" #: src/Layouts/Partials/BordersPanel.vala:53 msgid "Borders" msgstr "Bordures" #: src/Layouts/Partials/BordersPanel.vala:64 msgid "Add border" msgstr "Ajouter une bordure" #: src/Layouts/Partials/FillItem.vala:114 msgid "Choose fill color" msgstr "Choisir la couleur de remplissage" #: src/Layouts/Partials/FillItem.vala:193 msgid "Remove fill color" msgstr "Supprimer la couleur de remplissage" #: src/Layouts/Partials/FillItem.vala:277 msgid "Show fill color" msgstr "Afficher la couleur de remplissage" #: src/Layouts/Partials/FillItem.vala:281 msgid "Hide fill color" msgstr "Masquer la couleur de remplissage" #: src/Layouts/Partials/FillsPanel.vala:54 msgid "Fills" msgstr "Remplissages" #: src/Layouts/Partials/FillsPanel.vala:65 msgid "Add fill color" msgstr "Ajouter une couleur de remplissage" #: src/Layouts/Partials/TransformPanel.vala:96 msgid "X" msgstr "X" #: src/Layouts/Partials/TransformPanel.vala:96 msgid "Horizontal position" msgstr "Position horizontale" #: src/Layouts/Partials/TransformPanel.vala:98 msgid "Y" msgstr "Y" #: src/Layouts/Partials/TransformPanel.vala:98 msgid "Vertical position" msgstr "Position verticale" #: src/Layouts/Partials/TransformPanel.vala:100 msgid "W" msgstr "L" #: src/Layouts/Partials/TransformPanel.vala:100 msgid "Width" msgstr "Largeur" #: src/Layouts/Partials/TransformPanel.vala:102 msgid "H" msgstr "H" #: src/Layouts/Partials/TransformPanel.vala:102 msgid "Height" msgstr "Hauteur" #: src/Layouts/Partials/TransformPanel.vala:107 msgid "Lock Ratio" msgstr "Verrouiller le ratio" #: src/Layouts/Partials/TransformPanel.vala:114 msgid "R" msgstr "A" #: src/Layouts/Partials/TransformPanel.vala:114 msgid "Rotation degrees" msgstr "Angle de rotation" #: src/Layouts/Partials/TransformPanel.vala:126 msgid "Flip Horizontally" msgstr "Retourner horizontalement" #: src/Layouts/Partials/TransformPanel.vala:137 msgid "Flip Vertically" msgstr "Retourner verticalement" #: src/Layouts/Partials/TransformPanel.vala:165 msgid "Position" msgstr "Position" #: src/Layouts/Partials/TransformPanel.vala:169 msgid "Size" msgstr "Taille" #: src/Layouts/Partials/TransformPanel.vala:178 msgid "Opacity" msgstr "Opacité" #: src/Layouts/RightSideBar.vala:111 msgid "Search Layer" msgstr "Rechercher un calque" #: src/Lib/Managers/ExportManager.vala:192 #: src/Lib/Managers/ExportManager.vala:219 msgid "Generating preview, please wait…" msgstr "Génération de l'aperçu, veuillez patienter…" #: src/Lib/Managers/ExportManager.vala:313 #, c-format msgid "Untitled %i" msgstr "Sans titre %i" #: src/Lib/Managers/ExportManager.vala:484 msgid "Exporting images…" msgstr "Export des images en cours…" #: src/Partials/ExportWidget.vala:117 #, c-format msgid "%i × %i px · %s" msgstr "%i × %i px · %s" #: src/Partials/ExportWidget.vala:124 msgid "Fetching image size…" msgstr "Récupération de la taille de l'image…" #: src/Partials/ZoomButton.vala:49 msgid "Zoom Out" msgstr "Dézoomer" #: src/Partials/ZoomButton.vala:55 msgid "Reset Zoom" msgstr "Réinitialiser le zoom" #: src/Partials/ZoomButton.vala:62 msgid "Zoom In" msgstr "Zoomer" #: src/Partials/ZoomButton.vala:68 msgid "Zoom" msgstr "Zoom" #: src/Services/ActionManager.vala:217 msgid "No recently opened file available!" msgstr "Aucun dossier récemment ouvert n'est disponible !" #: src/Services/ActionManager.vala:236 msgid "No second most recently opened file available!" msgstr "Pas de deuxième fichier le plus récemment ouvert disponible !" #: src/Services/ActionManager.vala:255 msgid "No third most recently opened file available!" msgstr "Pas de troisième fichier le plus récemment ouvert disponible !" #: src/Services/ActionManager.vala:293 msgid "Nothing selected to export!" msgstr "Aucun élément sélectionné pour l'export !" #: src/Services/ActionManager.vala:302 msgid "Export of Artboards currently unavailable…sorry 😑️" msgstr "" "L'export des espaces de travail est actuellement indisponible… pardon 😑️" #: src/Services/ActionManager.vala:373 msgid "Choose image file" msgstr "Choisir un fichier image" #: src/Services/ActionManager.vala:373 msgid "Select" msgstr "Sélectionner" #: src/Services/ActionManager.vala:373 msgid "Close" msgstr "Fermer" #: src/Services/ActionManager.vala:442 #, c-format msgid "Error! .%s files are not supported!" msgstr "Erreur ! Les fichiers .%s ne sont pas pris en charge !" #: src/Window.vala:121 msgid "Are you sure you want to quit?" msgstr "Êtes-vous sûr de vouloir quitter ?" #: src/Window.vala:122 msgid "All unsaved data will be lost and impossible to recover." msgstr "" "Toutes les données non sauvegardées seront perdues et impossibles à " "récupérer." #: src/Window.vala:124 msgid "Quit without saving!" msgstr "Quitter sans sauvegarder !" #: src/Window.vala:125 msgid "Save file" msgstr "Enregistrer le fichier" Akira-0.0.16/po/fr_CA.po000066400000000000000000000001771410625726100145660ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Plural-Forms: nplurals=2; plural=n>1;\n" Akira-0.0.16/po/fy.po000066400000000000000000000001251410625726100142230ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/ga.po000066400000000000000000000001251410625726100141740ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/gd.po000066400000000000000000000001251410625726100141770ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/gl.po000066400000000000000000000001251410625726100142070ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/gn.po000066400000000000000000000001251410625726100142110ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/gu.po000066400000000000000000000001251410625726100142200ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/gv.po000066400000000000000000000001251410625726100142210ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/ha.po000066400000000000000000000001251410625726100141750ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/he.po000066400000000000000000000002021410625726100141750ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" Akira-0.0.16/po/hi.po000066400000000000000000000001251410625726100142050ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/ho.po000066400000000000000000000001251410625726100142130ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/hr.po000066400000000000000000000003141410625726100142160ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" Akira-0.0.16/po/ht.po000066400000000000000000000001251410625726100142200ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/hu.po000066400000000000000000000002021410625726100142150ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" Akira-0.0.16/po/hy.po000066400000000000000000000001251410625726100142250ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/hz.po000066400000000000000000000001251410625726100142260ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/ia.po000066400000000000000000000001251410625726100141760ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/id.po000066400000000000000000000001251410625726100142010ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/ie.po000066400000000000000000000001251410625726100142020ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/ig.po000066400000000000000000000001251410625726100142040ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/ii.po000066400000000000000000000001251410625726100142060ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/ik.po000066400000000000000000000001251410625726100142100ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/io.po000066400000000000000000000001251410625726100142140ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/is.po000066400000000000000000000001251410625726100142200ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/it.po000066400000000000000000000363061410625726100142330ustar00rootroot00000000000000# # XP312 < >, 2020. # Saverio , 2021. # msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" "Project-Id-Version: unnamed project\n" "Last-Translator: Saverio \n" "Language-Team: Italian \n" "Language: it\n" "Content-Transfer-Encoding: 8bit\n" "PO-Revision-Date: 2021-06-28 18:59+0200\n" "X-Generator: Gtranslator 40.0\n" #: Dialogs/ExportDialog.vala:151 msgid "Export to:" msgstr "Esporta come:" #: Dialogs/ExportDialog.vala:157 msgid "Select Folder" msgstr "Seleziona la cartella" #: Dialogs/ExportDialog.vala:166 msgid "Format:" msgstr "Formato:" #: Dialogs/ExportDialog.vala:180 msgid "Quality:" msgstr "Qualità:" #: Dialogs/ExportDialog.vala:192 msgid "Compression:" msgstr "Compressione:" #: Dialogs/ExportDialog.vala:206 msgid "Transparency:" msgstr "Trasparenza:" #: Dialogs/ExportDialog.vala:219 msgid "Scale:" msgstr "Scala:" #: Dialogs/ExportDialog.vala:243 FileFormat/FileManager.vala:49 #: FileFormat/FileManager.vala:105 msgid "Cancel" msgstr "Annulla" #: Dialogs/ExportDialog.vala:250 Dialogs/ShortcutsDialog.vala:63 #: Layouts/HeaderBar.vala:112 msgid "Export" msgstr "Esporta" #: Dialogs/ReleaseDialog.vala:47 Dialogs/SettingsDialog.vala:217 msgid "" "WARNING!\n" "Akira is still under development and not ready for production. Missing " "features, random bugs, and black holes opening in your kitchen are to be " "expected." msgstr "" "ATTENZIONE!\n" "Akira è ancora in fase di sviluppo e non è pronta per la produzione. " "Potrebbero verificarsi bug casuali, funzionalità mancanti, o apertura di " "buchi neri nella tua cucina." #: Dialogs/ReleaseDialog.vala:100 Dialogs/SettingsDialog.vala:249 msgid "Make a Donation" msgstr "Fai una donazione" #: Dialogs/ReleaseDialog.vala:109 Dialogs/SettingsDialog.vala:258 msgid "Suggest Translations" msgstr "Suggerisci traduzione" #: Dialogs/ReleaseDialog.vala:118 Dialogs/SettingsDialog.vala:267 msgid "Report a Problem" msgstr "Segnala un problema" #: Dialogs/SettingsDialog.vala:40 msgid "Preferences" msgstr "Preferenze" #: Dialogs/SettingsDialog.vala:50 Dialogs/SettingsDialog.vala:73 #: Dialogs/ShortcutsDialog.vala:45 msgid "General" msgstr "Generale" #: Dialogs/SettingsDialog.vala:51 Dialogs/SettingsDialog.vala:86 msgid "Interface" msgstr "Interfaccia" #: Dialogs/SettingsDialog.vala:52 Layouts/HeaderBar.vala:280 msgid "Shapes" msgstr "Figure" #: Dialogs/SettingsDialog.vala:53 msgid "About" msgstr "Informazioni" # In Italian the literal translation would be a little weird, so I've added a "edited" at the end of the sentence #: Dialogs/SettingsDialog.vala:74 msgid "Auto Reopen Latest File:" msgstr "Apri automaticamente l'ultimo file modificato" #: Dialogs/SettingsDialog.vala:88 msgid "Use Dark Theme:" msgstr "Utilizza il tema scuro:" #: Dialogs/SettingsDialog.vala:92 msgid "Invert Panels Order:" msgstr "Inverti l'ordine dei pannelli:" #: Dialogs/SettingsDialog.vala:96 msgid "Restart application to apply this change." msgstr "Riavvia l'applicazione applicare questa modifica" #: Dialogs/SettingsDialog.vala:100 msgid "ToolBar Style" msgstr "Stile della barra degli strumenti" #: Dialogs/SettingsDialog.vala:102 msgid "Show Button Labels:" msgstr "Mostra le etichette dei pulsanti:" #: Dialogs/SettingsDialog.vala:106 msgid "Use Symbolic Icons:" msgstr "Utilizza le icone simboliche:" #: Dialogs/SettingsDialog.vala:129 msgid "Default Colors" msgstr "Colori predefiniti" #: Dialogs/SettingsDialog.vala:131 msgid "Define the default style used when creating a new shape." msgstr "" "Definisci lo stile predefinito usato quando viene creata una nuova figura." #: Dialogs/SettingsDialog.vala:136 msgid "Fill Color:" msgstr "Colore di riempimento:" #: Dialogs/SettingsDialog.vala:157 msgid "Enable Border Style:" msgstr "Attiva lo stile dei bordi:" #: Dialogs/SettingsDialog.vala:160 msgid "Border Color:" msgstr "Colore dei bordi:" #: Dialogs/SettingsDialog.vala:181 msgid "Border Width:" msgstr "Spessore dei bordi:" #: Dialogs/SettingsDialog.vala:209 msgid "The Linux Design Tool" msgstr "Lo strumento di design di Linux" #: Dialogs/SettingsDialog.vala:226 msgid "Thanks to our awesome supporters!" msgstr "Grazie ai nostri meravigliosi collaboratori!" #: Dialogs/SettingsDialog.vala:231 msgid "View the list of supporters" msgstr "Visualizza la lista dei collaboratori" #: Dialogs/ShortcutsDialog.vala:46 msgid "New window:" msgstr "Nuova finestra:" #: Dialogs/ShortcutsDialog.vala:48 msgid "Preferences:" msgstr "Preferenze:" #: Dialogs/ShortcutsDialog.vala:50 msgid "Quit:" msgstr "Esci:" #: Dialogs/ShortcutsDialog.vala:52 msgid "Presentation mode:" msgstr "Modalità presentazione:" #: Dialogs/ShortcutsDialog.vala:55 msgid "File" msgstr "File" #: Dialogs/ShortcutsDialog.vala:56 msgid "Open:" msgstr "Apri:" #: Dialogs/ShortcutsDialog.vala:58 msgid "Save:" msgstr "Salva:" #: Dialogs/ShortcutsDialog.vala:60 msgid "Save as:" msgstr "Salva come:" #: Dialogs/ShortcutsDialog.vala:64 msgid "Export artboards:" msgstr "Esporta artboard:" #: Dialogs/ShortcutsDialog.vala:66 msgid "Export selection:" msgstr "Esporta la selezione:" #: Dialogs/ShortcutsDialog.vala:68 msgid "Highlight area to export:" msgstr "Evidenzia l'area da esportare:" #: Dialogs/ShortcutsDialog.vala:77 msgid "Canvas" msgstr "Canvas" #: Dialogs/ShortcutsDialog.vala:78 msgid "Zoom in:" msgstr "Aumenta lo zoom:" #: Dialogs/ShortcutsDialog.vala:80 msgid "Zoom out:" msgstr "Riduci lo zoom:" #: Dialogs/ShortcutsDialog.vala:82 msgid "Zoom reset:" msgstr "Reimposta lo zoom:" #: Dialogs/ShortcutsDialog.vala:85 msgid "Item creation" msgstr "Creazione elemento" #: Dialogs/ShortcutsDialog.vala:86 msgid "Artboard:" msgstr "Artboard:" #: Dialogs/ShortcutsDialog.vala:88 msgid "Rectangle:" msgstr "Rettangolo:" #: Dialogs/ShortcutsDialog.vala:90 msgid "Ellipse:" msgstr "Ellisse:" #: Dialogs/ShortcutsDialog.vala:92 msgid "Text:" msgstr "Testo:" #: Dialogs/ShortcutsDialog.vala:94 msgid "Image:" msgstr "Immagine:" #: Dialogs/ShortcutsDialog.vala:97 Layouts/Partials/TransformPanel.vala:174 msgid "Transform" msgstr "Trasforma:" #: Dialogs/ShortcutsDialog.vala:98 msgid "Raise selection:" msgstr "Porta la selezione sopra:" #: Dialogs/ShortcutsDialog.vala:100 msgid "Lower selection:" msgstr "Porta la selezione in basso:" #: Dialogs/ShortcutsDialog.vala:102 msgid "Raise selection to top:" msgstr "Porta la selezione in primo piano:" #: Dialogs/ShortcutsDialog.vala:104 msgid "Lower selection to bottom:" msgstr "Porta la selezione in ultimo piano:" #: Dialogs/ShortcutsDialog.vala:106 msgid "Flip horizontally:" msgstr "Capovolgi orizzontalmente:" #: Dialogs/ShortcutsDialog.vala:108 msgid "Flip vertically:" msgstr "Capovolgi verticalmente:" #: FileFormat/FileManager.vala:46 msgid "Save Akira file" msgstr "Salva file Akira" #: FileFormat/FileManager.vala:48 Layouts/HeaderBar.vala:190 msgid "Save" msgstr "Salva" #: FileFormat/FileManager.vala:71 msgid "Akira files" msgstr "File Akira" #: FileFormat/FileManager.vala:76 msgid "All files" msgstr "Tutti i file" #: FileFormat/FileManager.vala:103 msgid "Open Akira file" msgstr "Apri file Akira" #: FileFormat/FileManager.vala:105 Layouts/HeaderBar.vala:170 msgid "Open" msgstr "Apri" #: Layouts/HeaderBar.vala:69 Lib/Managers/ExportManager.vala:296 msgid "Untitled" msgstr "Senza titolo" #: Layouts/HeaderBar.vala:71 msgid "Menu" msgstr "Menu" #: Layouts/HeaderBar.vala:75 msgid "Insert" msgstr "Inserisci" #: Layouts/HeaderBar.vala:82 msgid "Group" msgstr "Ragruppa" #: Layouts/HeaderBar.vala:84 msgid "Ungroup" msgstr "Separa" #: Layouts/HeaderBar.vala:87 msgid "Up" msgstr "Sopra" #: Layouts/HeaderBar.vala:92 msgid "Down" msgstr "Sotto" #: Layouts/HeaderBar.vala:97 msgid "Top" msgstr "Più in alto" #: Layouts/HeaderBar.vala:102 msgid "Bottom" msgstr "Più in basso" #: Layouts/HeaderBar.vala:107 msgid "Settings" msgstr "Impostazioni" # ? #: Layouts/HeaderBar.vala:118 msgid "Difference" msgstr "Differenza" #: Layouts/HeaderBar.vala:120 msgid "Exclusion" msgstr "Esclusione" #: Layouts/HeaderBar.vala:122 msgid "Intersect" msgstr "Intersezione" #: Layouts/HeaderBar.vala:124 msgid "Union" msgstr "Unione" #: Layouts/HeaderBar.vala:161 msgid "New Window" msgstr "Nuova finestra" #: Layouts/HeaderBar.vala:182 msgid "Open Recent" msgstr "Apri recenti" #: Layouts/HeaderBar.vala:195 msgid "Save As" msgstr "Salva come" #: Layouts/HeaderBar.vala:204 msgid "Quit" msgstr "Esci" #: Layouts/HeaderBar.vala:237 msgid "Artboard" msgstr "Artboard" #: Layouts/HeaderBar.vala:254 msgid "Add Items" msgstr "Aggiungi elementi" #: Layouts/HeaderBar.vala:262 msgid "Rectangle" msgstr "Rettangolo" #: Layouts/HeaderBar.vala:268 msgid "Ellipse" msgstr "Ellisse" #: Layouts/HeaderBar.vala:286 msgid "Vector" msgstr "Vettore" #: Layouts/HeaderBar.vala:288 msgid "Pencil" msgstr "Matita" #: Layouts/HeaderBar.vala:291 msgid "Text" msgstr "Testo" #: Layouts/HeaderBar.vala:297 msgid "Image" msgstr "Immagine" #: Layouts/HeaderBar.vala:330 msgid "Export Current Selection" msgstr "Esporta selezione corrente" #: Layouts/HeaderBar.vala:336 msgid "Export Artboards" msgstr "Esporta le artboard" #: Layouts/HeaderBar.vala:345 msgid "Highlight Area to Export" msgstr "Evidenza l'area da esportare" #: Layouts/HeaderBar.vala:391 msgid "Main Menu" msgstr "Menu principale" #: Layouts/HeaderBar.vala:468 Services/ActionManager.vala:218 #: Services/ActionManager.vala:237 Services/ActionManager.vala:256 #, c-format msgid "Unable to open file at '%s'" msgstr "Non è possibile aprirle il file “%s”" #: Layouts/MainCanvas.vala:52 msgid "Button was pressed!" msgstr "Il pulsante è stato premuto!" #: Layouts/MainCanvas.vala:160 msgid "Export completed!" msgstr "Esportazione completata!" #: Layouts/Partials/AlignItemsPanel.vala:48 msgid "Distribute Horizontally" msgstr "Distribuisci orizzontalmente" #: Layouts/Partials/AlignItemsPanel.vala:50 msgid "Distribute Vertically" msgstr "Distribuisci verticalmente" #: Layouts/Partials/AlignItemsPanel.vala:52 msgid "Align Left" msgstr "Allineamento a sinistra" #: Layouts/Partials/AlignItemsPanel.vala:53 msgid "Align Center" msgstr "Allineamento al centro" #: Layouts/Partials/AlignItemsPanel.vala:54 msgid "Align Right" msgstr "Allicenamento a destra" #: Layouts/Partials/AlignItemsPanel.vala:56 msgid "Align Top" msgstr "Allineamento in alto" #: Layouts/Partials/AlignItemsPanel.vala:57 msgid "Align Middle" msgstr "Allineamento al centro" #: Layouts/Partials/AlignItemsPanel.vala:58 msgid "Align Bottom" msgstr "Allineamento in basso" #: Layouts/Partials/Artboard.vala:144 Layouts/Partials/Artboard.vala:487 #: Layouts/Partials/Layer.vala:139 Layouts/Partials/Layer.vala:687 msgid "Lock Layer" msgstr "Blocca livello" #: Layouts/Partials/Artboard.vala:155 Layouts/Partials/Artboard.vala:529 #: Layouts/Partials/Layer.vala:156 Layouts/Partials/Layer.vala:729 msgid "Hide Layer" msgstr "Nascondi livello" #: Layouts/Partials/Artboard.vala:487 Layouts/Partials/Layer.vala:687 msgid "Unlock Layer" msgstr "Sblocca livello" #: Layouts/Partials/Artboard.vala:529 Layouts/Partials/Layer.vala:729 msgid "Show Layer" msgstr "Mostra livello" #: Layouts/Partials/BorderRadiusPanel.vala:86 msgid "Style" msgstr "Stile" #: Layouts/Partials/BorderRadiusPanel.vala:103 msgid "Border Radius" msgstr "Raggio bordo" #: Layouts/Partials/BorderRadiusPanel.vala:198 msgid "Autoscale Corners" msgstr "Angoli automaticamente scalati" #: Layouts/Partials/BorderRadiusPanel.vala:207 msgid "Uniform Corners" msgstr "Angoli uniformati" #: Layouts/Partials/BordersPanel.vala:53 msgid "Borders" msgstr "Bordi" #: Layouts/Partials/FillsPanel.vala:54 msgid "Fills" msgstr "Riempi" #: Layouts/Partials/TransformPanel.vala:96 msgid "X" msgstr "X" #: Layouts/Partials/TransformPanel.vala:96 msgid "Horizontal position" msgstr "Posizione orizzontale" #: Layouts/Partials/TransformPanel.vala:98 msgid "Y" msgstr "Y" #: Layouts/Partials/TransformPanel.vala:98 msgid "Vertical position" msgstr "Posizione verticale" #: Layouts/Partials/TransformPanel.vala:100 msgid "W" msgstr "W" #: Layouts/Partials/TransformPanel.vala:100 msgid "Width" msgstr "Larghezza" #: Layouts/Partials/TransformPanel.vala:102 msgid "H" msgstr "H" #: Layouts/Partials/TransformPanel.vala:102 msgid "Height" msgstr "Altezza" #: Layouts/Partials/TransformPanel.vala:107 msgid "Lock Ratio" msgstr "Blocca proporzioni" #: Layouts/Partials/TransformPanel.vala:114 msgid "R" msgstr "R" #: Layouts/Partials/TransformPanel.vala:114 msgid "Rotation degrees" msgstr "Angolo di rotazione" #: Layouts/Partials/TransformPanel.vala:126 msgid "Flip Horizontally" msgstr "Capovolgi orizzontalmente" #: Layouts/Partials/TransformPanel.vala:137 msgid "Flip Vertically" msgstr "Capovolgi verticalmente" #: Layouts/Partials/TransformPanel.vala:165 msgid "Position" msgstr "Posizione" #: Layouts/Partials/TransformPanel.vala:169 msgid "Size" msgstr "Grandezza" #: Layouts/Partials/TransformPanel.vala:178 msgid "Opacity" msgstr "Opacità" #: Layouts/RightSideBar.vala:111 msgid "Search Layer" msgstr "Cerca livello" #: Lib/Managers/ExportManager.vala:192 Lib/Managers/ExportManager.vala:219 msgid "Generating preview, please wait…" msgstr "Generazione dell'anteprima in corso…" #: Lib/Managers/ExportManager.vala:313 #, c-format msgid "Untitled %i" msgstr "Senza titolo %i" #: Lib/Managers/ExportManager.vala:484 msgid "Exporting images…" msgstr "Esportazione delle immagini in corso…" #: Partials/ExportWidget.vala:117 #, c-format msgid "%i × %i px · %s" msgstr "%i × %i px · %s" #: Partials/ExportWidget.vala:124 msgid "Fetching image size…" msgstr "Calcolo delle dimensioni dell'immagine in corso…" #: Partials/ZoomButton.vala:49 msgid "Zoom Out" msgstr "Riduci zoom" #: Partials/ZoomButton.vala:55 msgid "Reset Zoom" msgstr "Reimposta zoom" #: Partials/ZoomButton.vala:62 msgid "Zoom In" msgstr "Aumenta zoom" #: Partials/ZoomButton.vala:68 msgid "Zoom" msgstr "Zoom" #: Services/ActionManager.vala:211 msgid "No recently opened file available!" msgstr "Nessun file aperto recentemente disponibile!" #: Services/ActionManager.vala:230 msgid "No second most recently opened file available!" msgstr "Nessun secondo file aperto recentemente disponibile!" #: Services/ActionManager.vala:249 msgid "No third most recently opened file available!" msgstr "Nessun terzo file aperto recentemente disponibile!" #: Services/ActionManager.vala:287 msgid "Nothing selected to export!" msgstr "Nessuna selezione da esportare!" #: Services/ActionManager.vala:296 msgid "Export of Artboards currently unavailable…sorry 😑️" msgstr "" "Spiacente, l'esportazione delle artboard non è al momento disponibile 😑️" #: Services/ActionManager.vala:363 msgid "Choose image file" msgstr "Scegli l'immagine" #: Services/ActionManager.vala:363 msgid "Select" msgstr "Seleziona" #: Services/ActionManager.vala:363 msgid "Close" msgstr "Chiudi" #: Services/ActionManager.vala:432 #, c-format msgid "Error! .%s files are not supported!" msgstr "Errore! I file %s non sono supportati." #: Window.vala:119 msgid "Are you sure you want to quit?" msgstr "Sei sicuro di voler uscire?" #: Window.vala:120 msgid "All unsaved data will be lost and impossible to recover." msgstr "" "Tutti i dati non salvati saranno persi e non sarà possibile recuperarli." #: Window.vala:122 msgid "Quit without saving!" msgstr "Esci senza salvare!" #: Window.vala:123 msgid "Save file" msgstr "Salva file" Akira-0.0.16/po/iu.po000066400000000000000000000001251410625726100142220ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/ja.po000066400000000000000000000002121410625726100141740ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Plural-Forms: nplurals=2; plural=n == 1 ? 0 : 1;\n" Akira-0.0.16/po/jv.po000066400000000000000000000001251410625726100142240ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/ka.po000066400000000000000000000001251410625726100142000ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/kg.po000066400000000000000000000001251410625726100142060ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/ki.po000066400000000000000000000001251410625726100142100ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/kj.po000066400000000000000000000001251410625726100142110ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/kk.po000066400000000000000000000001251410625726100142120ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/kl.po000066400000000000000000000001251410625726100142130ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/km.po000066400000000000000000000001251410625726100142140ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/kn.po000066400000000000000000000001251410625726100142150ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/ko.po000066400000000000000000000420301410625726100142170ustar00rootroot00000000000000msgid "" msgstr "" "Project-Id-Version: \n" "POT-Creation-Date: 2020-10-07 21:17+0200\n" "PO-Revision-Date: 2021-04-05 15:52+0900\n" "Last-Translator: 이정희 \n" "Language-Team: \n" "Language: ko\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Poedit 2.4.1\n" "X-Poedit-Basepath: .\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" "X-Poedit-SearchPath-0: .\n" #: src/Dialogs/ExportDialog.vala:151 msgid "Export to:" msgstr "다음으로 내보내기:" #: src/Dialogs/ExportDialog.vala:157 msgid "Select Folder" msgstr "폴더 선택" #: src/Dialogs/ExportDialog.vala:166 msgid "Format:" msgstr "형식:" #: src/Dialogs/ExportDialog.vala:179 msgid "Quality:" msgstr "품질:" #: src/Dialogs/ExportDialog.vala:191 msgid "Compression:" msgstr "압축:" #: src/Dialogs/ExportDialog.vala:205 msgid "Transparency:" msgstr "투명도:" #: src/Dialogs/ExportDialog.vala:218 msgid "Scale:" msgstr "크기 조정:" #: src/Dialogs/ExportDialog.vala:242 src/FileFormat/FileManager.vala:49 #: src/FileFormat/FileManager.vala:105 msgid "Cancel" msgstr "취소" #: src/Dialogs/ExportDialog.vala:249 src/Dialogs/ShortcutsDialog.vala:63 #: src/Layouts/HeaderBar.vala:112 msgid "Export" msgstr "내보내기" #: src/Dialogs/ReleaseDialog.vala:47 src/Dialogs/SettingsDialog.vala:217 msgid "" "WARNING!\n" "Akira is still under development and not ready for production. Missing " "features, random bugs, and black holes opening in your kitchen are to be " "expected." msgstr "" "경고!\n" "아키라는 아직 개발 중이며 제품 준비가 되지 않았습니다. 누락된 기능, 임의의 " "버그 및 부엌에서 열리는 블랙홀이 예상됩니다." #: src/Dialogs/ReleaseDialog.vala:100 src/Dialogs/SettingsDialog.vala:249 msgid "Make a Donation" msgstr "기부하기" #: src/Dialogs/ReleaseDialog.vala:109 src/Dialogs/SettingsDialog.vala:258 msgid "Suggest Translations" msgstr "번역 제안" #: src/Dialogs/ReleaseDialog.vala:118 src/Dialogs/SettingsDialog.vala:267 msgid "Report a Problem" msgstr "문제 보고" #: src/Dialogs/SettingsDialog.vala:40 msgid "Preferences" msgstr "환경설정" #: src/Dialogs/SettingsDialog.vala:50 src/Dialogs/SettingsDialog.vala:73 #: src/Dialogs/ShortcutsDialog.vala:45 msgid "General" msgstr "일반" #: src/Dialogs/SettingsDialog.vala:51 src/Dialogs/SettingsDialog.vala:86 msgid "Interface" msgstr "인터페이스" #: src/Dialogs/SettingsDialog.vala:52 src/Layouts/HeaderBar.vala:280 msgid "Shapes" msgstr "모양" #: src/Dialogs/SettingsDialog.vala:53 msgid "About" msgstr "정보" #: src/Dialogs/SettingsDialog.vala:74 msgid "Auto Reopen Latest File:" msgstr "최근 파일 자동 다시 열기:" #: src/Dialogs/SettingsDialog.vala:88 msgid "Use Dark Theme:" msgstr "어두운 테마 사용:" #: src/Dialogs/SettingsDialog.vala:92 msgid "Invert Panels Order:" msgstr "패널 순서 반전:" #: src/Dialogs/SettingsDialog.vala:96 msgid "Restart application to apply this change." msgstr "이 변경 내용을 적용하려면 응용 프로그램을 다시 시작하십시오." #: src/Dialogs/SettingsDialog.vala:100 msgid "ToolBar Style" msgstr "도구모음 스타일" #: src/Dialogs/SettingsDialog.vala:102 msgid "Show Button Labels:" msgstr "버튼 레이블 표시:" #: src/Dialogs/SettingsDialog.vala:106 msgid "Use Symbolic Icons:" msgstr "기호 아이콘 사용:" #: src/Dialogs/SettingsDialog.vala:129 msgid "Default Colors" msgstr "기본 색상" #: src/Dialogs/SettingsDialog.vala:131 msgid "Define the default style used when creating a new shape." msgstr "새 모양을 만들 때 사용되는 기본 스타일을 정의합니다." #: src/Dialogs/SettingsDialog.vala:136 msgid "Fill Color:" msgstr "색상 채우기:" #: src/Dialogs/SettingsDialog.vala:157 msgid "Enable Border Style:" msgstr "테두리 스타일 사용:" #: src/Dialogs/SettingsDialog.vala:160 msgid "Border Color:" msgstr "테두리 색상:" #: src/Dialogs/SettingsDialog.vala:181 msgid "Border Width:" msgstr "테두리 너비:" #: src/Dialogs/SettingsDialog.vala:209 msgid "The Linux Design Tool" msgstr "리눅스 디자인 도구" #: src/Dialogs/SettingsDialog.vala:226 msgid "Thanks to our awesome supporters!" msgstr "멋진 서포터들에게 감사드립니다!" #: src/Dialogs/SettingsDialog.vala:231 msgid "View the list of supporters" msgstr "서포터 목록보기" #: src/Dialogs/ShortcutsDialog.vala:46 msgid "New window:" msgstr "새 창:" #: src/Dialogs/ShortcutsDialog.vala:48 msgid "Preferences:" msgstr "환경설정:" #: src/Dialogs/ShortcutsDialog.vala:50 msgid "Quit:" msgstr "종료:" #: src/Dialogs/ShortcutsDialog.vala:52 msgid "Presentation mode:" msgstr "프레젠테이션 모드:" #: src/Dialogs/ShortcutsDialog.vala:55 msgid "File" msgstr "파일" #: src/Dialogs/ShortcutsDialog.vala:56 msgid "Open:" msgstr "열기:" #: src/Dialogs/ShortcutsDialog.vala:58 msgid "Save:" msgstr "저장:" #: src/Dialogs/ShortcutsDialog.vala:60 msgid "Save as:" msgstr "다른 이름으로 저장:" #: src/Dialogs/ShortcutsDialog.vala:64 msgid "Export artboards:" msgstr "아트보드 내보내기:" #: src/Dialogs/ShortcutsDialog.vala:66 msgid "Export selection:" msgstr "내보내기 선택:" #: src/Dialogs/ShortcutsDialog.vala:68 msgid "Highlight area to export:" msgstr "내보낼 영역 강조표시:" #: src/Dialogs/ShortcutsDialog.vala:77 msgid "Canvas" msgstr "캔버스" #: src/Dialogs/ShortcutsDialog.vala:78 msgid "Zoom in:" msgstr "확대:" #: src/Dialogs/ShortcutsDialog.vala:80 msgid "Zoom out:" msgstr "축소:" #: src/Dialogs/ShortcutsDialog.vala:82 msgid "Zoom reset:" msgstr "확대/축소 재설정" #: src/Dialogs/ShortcutsDialog.vala:85 msgid "Item creation" msgstr "항목 만들기" #: src/Dialogs/ShortcutsDialog.vala:86 msgid "Artboard:" msgstr "아트보드:" #: src/Dialogs/ShortcutsDialog.vala:88 msgid "Rectangle:" msgstr "직사각형:" #: src/Dialogs/ShortcutsDialog.vala:90 msgid "Ellipse:" msgstr "타원형:" #: src/Dialogs/ShortcutsDialog.vala:92 msgid "Text:" msgstr "텍스트:" #: src/Dialogs/ShortcutsDialog.vala:94 msgid "Image:" msgstr "이미지:" #: src/Dialogs/ShortcutsDialog.vala:97 #: src/Layouts/Partials/TransformPanel.vala:174 msgid "Transform" msgstr "변환" #: src/Dialogs/ShortcutsDialog.vala:98 msgid "Raise selection:" msgstr "선택 항목 올리기:" #: src/Dialogs/ShortcutsDialog.vala:100 msgid "Lower selection:" msgstr "선택 항목 내리기:" #: src/Dialogs/ShortcutsDialog.vala:102 msgid "Raise selection to top:" msgstr "선택 항목을 맨 위로 올리기 :" #: src/Dialogs/ShortcutsDialog.vala:104 msgid "Lower selection to bottom:" msgstr "선택 항목을 맨 아래로 내리기:" #: src/Dialogs/ShortcutsDialog.vala:106 msgid "Flip horizontally:" msgstr "수평으로 뒤집기:" #: src/Dialogs/ShortcutsDialog.vala:108 msgid "Flip vertically:" msgstr "수직으로 뒤집기:" #: src/FileFormat/FileManager.vala:46 msgid "Save Akira file" msgstr "아키라 파일 저장" #: src/FileFormat/FileManager.vala:48 src/Layouts/HeaderBar.vala:190 msgid "Save" msgstr "저장" #: src/FileFormat/FileManager.vala:71 msgid "Akira files" msgstr "아키라 파일" #: src/FileFormat/FileManager.vala:76 msgid "All files" msgstr "모든 파일" #: src/FileFormat/FileManager.vala:103 msgid "Open Akira file" msgstr "아키라 파일 열기" #: src/FileFormat/FileManager.vala:105 src/Layouts/HeaderBar.vala:170 msgid "Open" msgstr "열기" #: src/Layouts/HeaderBar.vala:69 src/Lib/Managers/ExportManager.vala:296 msgid "Untitled" msgstr "제목 없음" #: src/Layouts/HeaderBar.vala:71 msgid "Menu" msgstr "메뉴" #: src/Layouts/HeaderBar.vala:75 msgid "Insert" msgstr "삽입" #: src/Layouts/HeaderBar.vala:82 msgid "Group" msgstr "그룹" #: src/Layouts/HeaderBar.vala:84 msgid "Ungroup" msgstr "그룹 해제" #: src/Layouts/HeaderBar.vala:87 msgid "Up" msgstr "위로" #: src/Layouts/HeaderBar.vala:92 msgid "Down" msgstr "아래로" #: src/Layouts/HeaderBar.vala:97 msgid "Top" msgstr "맨 위로" #: src/Layouts/HeaderBar.vala:102 msgid "Bottom" msgstr "맨 아래로" #: src/Layouts/HeaderBar.vala:107 msgid "Settings" msgstr "설정" #: src/Layouts/HeaderBar.vala:118 msgid "Difference" msgstr "차이" #: src/Layouts/HeaderBar.vala:120 msgid "Exclusion" msgstr "제외" #: src/Layouts/HeaderBar.vala:122 msgid "Intersect" msgstr "교차" #: src/Layouts/HeaderBar.vala:124 msgid "Union" msgstr "결합" #: src/Layouts/HeaderBar.vala:161 msgid "New Window" msgstr "새 창" #: src/Layouts/HeaderBar.vala:182 msgid "Open Recent" msgstr "최근 파일 열기" #: src/Layouts/HeaderBar.vala:195 msgid "Save As" msgstr "다른 이름으로 저장" #: src/Layouts/HeaderBar.vala:204 msgid "Quit" msgstr "종료" #: src/Layouts/HeaderBar.vala:237 msgid "Artboard" msgstr "아트보드" #: src/Layouts/HeaderBar.vala:254 msgid "Add Items" msgstr "항목 추가" #: src/Layouts/HeaderBar.vala:262 msgid "Rectangle" msgstr "직사각" #: src/Layouts/HeaderBar.vala:268 msgid "Ellipse" msgstr "타원" #: src/Layouts/HeaderBar.vala:286 msgid "Vector" msgstr "벡터" #: src/Layouts/HeaderBar.vala:288 msgid "Pencil" msgstr "연필" #: src/Layouts/HeaderBar.vala:291 msgid "Text" msgstr "텍스트" #: src/Layouts/HeaderBar.vala:297 msgid "Image" msgstr "이미지" #: src/Layouts/HeaderBar.vala:330 msgid "Export Current Selection" msgstr "현재 선택 내보내기" #: src/Layouts/HeaderBar.vala:336 msgid "Export Artboards" msgstr "아트보드 내보내기" #: src/Layouts/HeaderBar.vala:345 msgid "Highlight Area to Export" msgstr "내보낼 영역 강조 표시" #: src/Layouts/HeaderBar.vala:391 msgid "Main Menu" msgstr "기본 메뉴" #: src/Layouts/HeaderBar.vala:468 src/Services/ActionManager.vala:224 #: src/Services/ActionManager.vala:243 src/Services/ActionManager.vala:262 #, c-format msgid "Unable to open file at '%s'" msgstr "'%s'에서 파일을 열 수 없습니다." #: src/Layouts/MainCanvas.vala:46 msgid "Button was pressed!" msgstr "버튼을 눌렀습니다!" #: src/Layouts/MainCanvas.vala:206 msgid "Export completed!" msgstr "내보내기 완료!" #: src/Layouts/Partials/AlignItemsPanel.vala:48 msgid "Distribute Horizontally" msgstr "수평으로 분배" #: src/Layouts/Partials/AlignItemsPanel.vala:50 msgid "Distribute Vertically" msgstr "수직으로 분배" #: src/Layouts/Partials/AlignItemsPanel.vala:52 msgid "Align Left" msgstr "왼쪽 정렬" #: src/Layouts/Partials/AlignItemsPanel.vala:53 msgid "Align Center" msgstr "가운데 정렬" #: src/Layouts/Partials/AlignItemsPanel.vala:54 msgid "Align Right" msgstr "오른쪽 정렬" #: src/Layouts/Partials/AlignItemsPanel.vala:56 msgid "Align Top" msgstr "상단 정렬" #: src/Layouts/Partials/AlignItemsPanel.vala:57 msgid "Align Middle" msgstr "중간 정렬" #: src/Layouts/Partials/AlignItemsPanel.vala:58 msgid "Align Bottom" msgstr "하단 정렬" #: src/Layouts/Partials/Artboard.vala:144 #: src/Layouts/Partials/Artboard.vala:487 src/Layouts/Partials/Layer.vala:139 #: src/Layouts/Partials/Layer.vala:687 msgid "Lock Layer" msgstr "레이어 잠금" #: src/Layouts/Partials/Artboard.vala:155 #: src/Layouts/Partials/Artboard.vala:529 src/Layouts/Partials/Layer.vala:156 #: src/Layouts/Partials/Layer.vala:729 msgid "Hide Layer" msgstr "레이어 숨김" #: src/Layouts/Partials/Artboard.vala:487 src/Layouts/Partials/Layer.vala:687 msgid "Unlock Layer" msgstr "레이어 잠금 해제" #: src/Layouts/Partials/Artboard.vala:529 src/Layouts/Partials/Layer.vala:729 msgid "Show Layer" msgstr "레이어 표시" #: src/Layouts/Partials/BorderItem.vala:121 msgid "Choose border color" msgstr "테두리 색상 선택" #: src/Layouts/Partials/BorderItem.vala:176 #: src/Layouts/Partials/FillItem.vala:178 msgid "Pick color" msgstr "색상 선택" #: src/Layouts/Partials/BorderItem.vala:191 msgid "Remove border" msgstr "테두리 제거" #: src/Layouts/Partials/BorderItem.vala:275 msgid "Show border" msgstr "테두리 표시" #: src/Layouts/Partials/BorderItem.vala:279 msgid "Hide border" msgstr "테두리 숨김" #: src/Layouts/Partials/BorderRadiusPanel.vala:86 msgid "Style" msgstr "스타일" #: src/Layouts/Partials/BorderRadiusPanel.vala:103 msgid "Border Radius" msgstr "테두리 반경" #: src/Layouts/Partials/BorderRadiusPanel.vala:137 msgid "Border radius options" msgstr "테두리 반경 옵션" #: src/Layouts/Partials/BorderRadiusPanel.vala:199 msgid "Autoscale Corners" msgstr "모서리 자동 크기조정" #: src/Layouts/Partials/BorderRadiusPanel.vala:208 msgid "Uniform Corners" msgstr "균일한 모서리" #: src/Layouts/Partials/BordersPanel.vala:53 msgid "Borders" msgstr "테두리" #: src/Layouts/Partials/BordersPanel.vala:64 msgid "Add border" msgstr "테두리 추가" #: src/Layouts/Partials/FillItem.vala:114 msgid "Choose fill color" msgstr "채우기 색상 선택" #: src/Layouts/Partials/FillItem.vala:193 msgid "Remove fill color" msgstr "채우기 색상 제거" #: src/Layouts/Partials/FillItem.vala:277 msgid "Show fill color" msgstr "채우기 색상 표시" #: src/Layouts/Partials/FillItem.vala:281 msgid "Hide fill color" msgstr "채우기 색상 숨김" #: src/Layouts/Partials/FillsPanel.vala:54 msgid "Fills" msgstr "채우기" #: src/Layouts/Partials/FillsPanel.vala:65 msgid "Add fill color" msgstr "채우기 색상 추가" #: src/Layouts/Partials/TransformPanel.vala:96 msgid "X" msgstr "X" #: src/Layouts/Partials/TransformPanel.vala:96 msgid "Horizontal position" msgstr "수평 위치" #: src/Layouts/Partials/TransformPanel.vala:98 msgid "Y" msgstr "Y" #: src/Layouts/Partials/TransformPanel.vala:98 msgid "Vertical position" msgstr "수직 위치" #: src/Layouts/Partials/TransformPanel.vala:100 msgid "W" msgstr "W" #: src/Layouts/Partials/TransformPanel.vala:100 msgid "Width" msgstr "너비" #: src/Layouts/Partials/TransformPanel.vala:102 msgid "H" msgstr "H" #: src/Layouts/Partials/TransformPanel.vala:102 msgid "Height" msgstr "높이" #: src/Layouts/Partials/TransformPanel.vala:107 msgid "Lock Ratio" msgstr "비율 잠금" #: src/Layouts/Partials/TransformPanel.vala:114 msgid "R" msgstr "R" #: src/Layouts/Partials/TransformPanel.vala:114 msgid "Rotation degrees" msgstr "회전 각도" #: src/Layouts/Partials/TransformPanel.vala:126 msgid "Flip Horizontally" msgstr "수평으로 뒤집기" #: src/Layouts/Partials/TransformPanel.vala:137 msgid "Flip Vertically" msgstr "수직으로 뒤집기" #: src/Layouts/Partials/TransformPanel.vala:165 msgid "Position" msgstr "위치" #: src/Layouts/Partials/TransformPanel.vala:169 msgid "Size" msgstr "크기" #: src/Layouts/Partials/TransformPanel.vala:178 msgid "Opacity" msgstr "불투명도" #: src/Layouts/RightSideBar.vala:111 msgid "Search Layer" msgstr "레이어 검색" #: src/Lib/Managers/ExportManager.vala:192 #: src/Lib/Managers/ExportManager.vala:219 msgid "Generating preview, please wait…" msgstr "미리보기를 생성하는 중입니다. 잠시 기다려주세요…" #: src/Lib/Managers/ExportManager.vala:313 #, c-format msgid "Untitled %i" msgstr "%i 제목 없음" #: src/Lib/Managers/ExportManager.vala:484 msgid "Exporting images…" msgstr "이미지 내보내는 중…" #: src/Partials/ExportWidget.vala:117 #, c-format msgid "%i × %i px · %s" msgstr "%i × %i px · %s" #: src/Partials/ExportWidget.vala:124 msgid "Fetching image size…" msgstr "이미지 크기 가져오는 중..." #: src/Partials/ZoomButton.vala:49 msgid "Zoom Out" msgstr "축소" #: src/Partials/ZoomButton.vala:55 msgid "Reset Zoom" msgstr "확대/축소 재설정" #: src/Partials/ZoomButton.vala:62 msgid "Zoom In" msgstr "확대" #: src/Partials/ZoomButton.vala:68 msgid "Zoom" msgstr "확대/축소" #: src/Services/ActionManager.vala:217 msgid "No recently opened file available!" msgstr "최근에 연 파일을 사용할 수 없습니다!" #: src/Services/ActionManager.vala:236 msgid "No second most recently opened file available!" msgstr "두 번째로 가장 최근에 연 파일을 사용할 수 없습니다!" #: src/Services/ActionManager.vala:255 msgid "No third most recently opened file available!" msgstr "세 번째로 가장 최근에 연 파일을 사용할 수 없습니다!" #: src/Services/ActionManager.vala:293 msgid "Nothing selected to export!" msgstr "내보낼 항목을 선택하지 않았습니다!" #: src/Services/ActionManager.vala:302 msgid "Export of Artboards currently unavailable…sorry 😑️" msgstr "현재 아트보드 내보내기를 사용할 수 없습니다... 미안해요 😑️" #: src/Services/ActionManager.vala:373 msgid "Choose image file" msgstr "이미지 파일 선택" #: src/Services/ActionManager.vala:373 msgid "Select" msgstr "선택" #: src/Services/ActionManager.vala:373 msgid "Close" msgstr "닫기" #: src/Services/ActionManager.vala:442 #, c-format msgid "Error! .%s files are not supported!" msgstr "오류! .%s 파일은 지원되지 않습니다!" #: src/Window.vala:121 msgid "Are you sure you want to quit?" msgstr "종료 하시겠습니까?" #: src/Window.vala:122 msgid "All unsaved data will be lost and impossible to recover." msgstr "저장되지 않은 모든 데이터는 손실되고 복구할 수 없습니다." #: src/Window.vala:124 msgid "Quit without saving!" msgstr "저장하지 않고 종료!" #: src/Window.vala:125 msgid "Save file" msgstr "파일 저장" Akira-0.0.16/po/kr.po000066400000000000000000000001251410625726100142210ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/ks.po000066400000000000000000000001251410625726100142220ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/ku.po000066400000000000000000000001251410625726100142240ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/kv.po000066400000000000000000000001251410625726100142250ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/kw.po000066400000000000000000000001251410625726100142260ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/ky.po000066400000000000000000000001251410625726100142300ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/la.po000066400000000000000000000001251410625726100142010ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/lb.po000066400000000000000000000001251410625726100142020ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/lg.po000066400000000000000000000001251410625726100142070ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/li.po000066400000000000000000000001251410625726100142110ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/ln.po000066400000000000000000000001251410625726100142160ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/lo.po000066400000000000000000000001251410625726100142170ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/lt.po000066400000000000000000000003011410625726100142200ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2;\n" Akira-0.0.16/po/lu.po000066400000000000000000000001251410625726100142250ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/lv.po000066400000000000000000000002451410625726100142310ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2;\n" Akira-0.0.16/po/meson.build000066400000000000000000000000561410625726100154120ustar00rootroot00000000000000i18n.gettext(gettext_package, preset: 'glib') Akira-0.0.16/po/mg.po000066400000000000000000000001251410625726100142100ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/mh.po000066400000000000000000000001251410625726100142110ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/mi.po000066400000000000000000000001251410625726100142120ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/mk.po000066400000000000000000000001251410625726100142140ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/ml.po000066400000000000000000000537651410625726100142370ustar00rootroot00000000000000msgid "" msgstr "" "Project-Id-Version: \n" "POT-Creation-Date: 2020-09-27 19:02+0300\n" "PO-Revision-Date: \n" "Language-Team: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Poedit 2.3\n" "X-Poedit-Basepath: ../src\n" "Language: ml\n" "Last-Translator: \n" "X-Poedit-SearchPath-0: .\n" #: Dialogs/ExportDialog.vala:151 msgid "Export to:" msgstr "കയറ്റുമതി ചെയ്യുക:" #: Dialogs/ExportDialog.vala:157 msgid "Select Folder" msgstr "ഫോള്‍ഡര്‍ തിരഞ്ഞെടുക്കുക" #: Dialogs/ExportDialog.vala:166 msgid "Format:" msgstr "തരം:" #: Dialogs/ExportDialog.vala:179 msgid "Quality:" msgstr "മേന്‍മ:" #: Dialogs/ExportDialog.vala:191 msgid "Compression:" msgstr "ചുരുക്കല്‍:" #: Dialogs/ExportDialog.vala:205 msgid "Transparency:" msgstr "സുതാര്യത:" #: Dialogs/ExportDialog.vala:218 msgid "Scale:" msgstr "തോത്:" #: Dialogs/ExportDialog.vala:242 FileFormat/FileManager.vala:49 #: FileFormat/FileManager.vala:105 msgid "Cancel" msgstr "റദ്ദാക്കുക" #: Dialogs/ExportDialog.vala:249 Dialogs/ShortcutsDialog.vala:63 Layouts/HeaderBar.vala:112 msgid "Export" msgstr "കയറ്റുമതി" #: Dialogs/ReleaseDialog.vala:47 Dialogs/SettingsDialog.vala:217 msgid "" "WARNING!\n" "Akira is still under development and not ready for production. Missing features, random " "bugs, and black holes opening in your kitchen are to be expected." msgstr "" "മുന്നറിയിപ്പ്\n" "ജോലിക്കുപാകത്തിന് അകിര ഇനിയും പണിതു തീര്‍ന്നിട്ടില്ല. സൗകര്യക്കുറവുകളും തുടരെത്തടസ്സങ്ങളും അടുക്കള കാലിയാക്കുന്ന " "തമോഗര്‍ത്തങ്ങള്‍ വരെയും പ്രതീക്ഷിക്കാം." #: Dialogs/ReleaseDialog.vala:100 Dialogs/SettingsDialog.vala:249 msgid "Make a Donation" msgstr "സംഭാവന നല്കുക" #: Dialogs/ReleaseDialog.vala:109 Dialogs/SettingsDialog.vala:258 msgid "Suggest Translations" msgstr "തര്‍ജ്ജമ നിര്‍ദ്ദേശിക്കുക" #: Dialogs/ReleaseDialog.vala:118 Dialogs/SettingsDialog.vala:267 msgid "Report a Problem" msgstr "പ്രശ്നങ്ങള്‍ അറിയിക്കുക" #: Dialogs/SettingsDialog.vala:40 msgid "Preferences" msgstr "സജ്ജീകരണങ്ങള്‍" #: Dialogs/SettingsDialog.vala:50 Dialogs/SettingsDialog.vala:73 #: Dialogs/ShortcutsDialog.vala:45 msgid "General" msgstr "പൊതുസജ്ജീകരങ്ങള്‍" #: Dialogs/SettingsDialog.vala:51 Dialogs/SettingsDialog.vala:86 msgid "Interface" msgstr "ദൃശ്യമുഖം" #: Dialogs/SettingsDialog.vala:52 Layouts/HeaderBar.vala:280 msgid "Shapes" msgstr "രൂപങ്ങള്‍" #: Dialogs/SettingsDialog.vala:53 msgid "About" msgstr "സംബന്ധിച്ച്" #: Dialogs/SettingsDialog.vala:74 msgid "Auto Reopen Latest File:" msgstr "പുതിയ രേഖ താനേ തുറക്കുക:" #: Dialogs/SettingsDialog.vala:88 msgid "Use Dark Theme:" msgstr "ഇരുണ്ട അലങ്കാരങ്ങള്‍ ഉപയോഗിക്കുക:" #: Dialogs/SettingsDialog.vala:92 msgid "Invert Panels Order:" msgstr "പാനലുകള്‍ വിപരീതക്രമത്തിലാക്കുക:" #: Dialogs/SettingsDialog.vala:96 msgid "Restart application to apply this change." msgstr "മാറ്റം നടപ്പിലാക്കാനായി അകിര പുനര്‍പ്രവര്‍ത്തിപ്പിക്കുക." #: Dialogs/SettingsDialog.vala:100 msgid "ToolBar Style" msgstr "ഉപകരണത്തട്ടിന്റെ രൂപം" #: Dialogs/SettingsDialog.vala:102 msgid "Show Button Labels:" msgstr "ബട്ടണില്‍ എഴുത്തുകള്‍ കാണിക്കുക:" #: Dialogs/SettingsDialog.vala:106 msgid "Use Symbolic Icons:" msgstr "പ്രതീകാത്മക ചിന്ഹങ്ങള്‍ ഉപയോഗിക്കുക:" #: Dialogs/SettingsDialog.vala:129 msgid "Default Colors" msgstr "തനത് നിറങ്ങള്‍" #: Dialogs/SettingsDialog.vala:131 msgid "Define the default style used when creating a new shape." msgstr "രൂപം വരയ്ക്കുമ്പോള്‍ ഉപയോഗിക്കേണ്ട തനത് ഭംഗി നിര്‍വചിക്കുക." #: Dialogs/SettingsDialog.vala:136 msgid "Fill Color:" msgstr "അകനിറം:" #: Dialogs/SettingsDialog.vala:157 msgid "Enable Border Style:" msgstr "അതിര്‍ ഭംഗി വേണം:" #: Dialogs/SettingsDialog.vala:160 msgid "Border Color:" msgstr "അതിര്‍നിറം:" #: Dialogs/SettingsDialog.vala:181 msgid "Border Width:" msgstr "അതിര്‍വീതി:" #: Dialogs/SettingsDialog.vala:209 msgid "The Linux Design Tool" msgstr "ലിനക്സിനു വേണ്ടിയുള്ള രൂപകല്‍പ്പനാതന്ത്രം" #: Dialogs/SettingsDialog.vala:226 msgid "Thanks to our awesome supporters!" msgstr "ഞങ്ങളെ പിന്താങ്ങുന്നവര്‍ക്ക് നന്ദി!" #: Dialogs/SettingsDialog.vala:231 msgid "View the list of supporters" msgstr "ദാതാക്കളുടെ പട്ടിക കാണുക" #: Dialogs/ShortcutsDialog.vala:46 msgid "New window:" msgstr "പുതിയ ജാലകം:" #: Dialogs/ShortcutsDialog.vala:48 msgid "Preferences:" msgstr "സജ്ജീകരണങ്ങള്‍:" #: Dialogs/ShortcutsDialog.vala:50 msgid "Quit:" msgstr "പുറത്തിരങ്ങുക:" #: Dialogs/ShortcutsDialog.vala:52 msgid "Presentation mode:" msgstr "അവതരണ രൂപം:" #: Dialogs/ShortcutsDialog.vala:55 msgid "File" msgstr "രേഖ" #: Dialogs/ShortcutsDialog.vala:56 msgid "Open:" msgstr "തുറക്കുക:" #: Dialogs/ShortcutsDialog.vala:58 msgid "Save:" msgstr "സൂക്ഷിക്കുക:" #: Dialogs/ShortcutsDialog.vala:60 msgid "Save as:" msgstr "മറ്റൊന്നായി സൂക്ഷിക്കുക:" #: Dialogs/ShortcutsDialog.vala:64 msgid "Export artboards:" msgstr "കലാഫലകങ്ങള്‍ കയറ്റുമതി ചെയ്യുക:" #: Dialogs/ShortcutsDialog.vala:66 msgid "Export selection:" msgstr "തിരഞ്ഞെടുത്തത് സൂക്ഷിക്കുക:" #: Dialogs/ShortcutsDialog.vala:68 msgid "Highlight area to export:" msgstr "കയറ്റുമതി ചെയ്യേണ്ടിടം എടുത്തുകാട്ടുക:" #: Dialogs/ShortcutsDialog.vala:77 msgid "Canvas" msgstr "ചിത്രത്തുണി" #: Dialogs/ShortcutsDialog.vala:78 msgid "Zoom in:" msgstr "വലുതാക്കുക:" #: Dialogs/ShortcutsDialog.vala:80 msgid "Zoom out:" msgstr "ചെറുതാക്കുക:" #: Dialogs/ShortcutsDialog.vala:82 msgid "Zoom reset:" msgstr "പഴയ വലുപ്പത്തിലാക്കുക:" #: Dialogs/ShortcutsDialog.vala:85 msgid "Item creation" msgstr "വസ്തു നിര്‍മാണം" #: Dialogs/ShortcutsDialog.vala:86 msgid "Artboard:" msgstr "കലാഫലകം:" #: Dialogs/ShortcutsDialog.vala:88 msgid "Rectangle:" msgstr "ചതുരം:" #: Dialogs/ShortcutsDialog.vala:90 msgid "Ellipse:" msgstr "വട്ടം:" #: Dialogs/ShortcutsDialog.vala:92 msgid "Text:" msgstr "എഴുത്ത്:" #: Dialogs/ShortcutsDialog.vala:94 msgid "Image:" msgstr "ചിത്രം:" #: Dialogs/ShortcutsDialog.vala:97 Layouts/Partials/TransformPanel.vala:174 msgid "Transform" msgstr "മാറ്റുക" #: Dialogs/ShortcutsDialog.vala:98 msgid "Raise selection:" msgstr "തിരഞ്ഞെടുത്തത് പൊക്കുക:" #: Dialogs/ShortcutsDialog.vala:100 msgid "Lower selection:" msgstr "തിരഞ്ഞെടുത്തത് താഴ്ത്തുക:" #: Dialogs/ShortcutsDialog.vala:102 msgid "Raise selection to top:" msgstr "തിരഞ്ഞെടുത്തത് ഏറ്റവും മുകളിലാക്കുക:" #: Dialogs/ShortcutsDialog.vala:104 msgid "Lower selection to bottom:" msgstr "തിരഞ്ഞെടുത്തത് ഏറ്റവും അടിയിലാക്കുക:" #: Dialogs/ShortcutsDialog.vala:106 msgid "Flip horizontally:" msgstr "വിലങ്ങനെ മറിക്കുക:" #: Dialogs/ShortcutsDialog.vala:108 msgid "Flip vertically:" msgstr "കുത്തനെ മറിക്കുക:" #: FileFormat/FileManager.vala:46 msgid "Save Akira file" msgstr "അകിര രേഖയാക്കി സൂക്ഷിക്കുക" #: FileFormat/FileManager.vala:48 Layouts/HeaderBar.vala:190 msgid "Save" msgstr "സുക്ഷിക്കുക" #: FileFormat/FileManager.vala:71 msgid "Akira files" msgstr "അകിര രേഖക" #: FileFormat/FileManager.vala:76 msgid "All files" msgstr "എല്ലാ രേഖകളും" #: FileFormat/FileManager.vala:103 msgid "Open Akira file" msgstr "ഒരു അകിര രേഖ തുറക്കുക" #: FileFormat/FileManager.vala:105 Layouts/HeaderBar.vala:170 msgid "Open" msgstr "തുറക്കുക" #: Layouts/HeaderBar.vala:69 Lib/Managers/ExportManager.vala:296 msgid "Untitled" msgstr "പേരില്ലാത്തത്" #: Layouts/HeaderBar.vala:71 msgid "Menu" msgstr "മെനു" #: Layouts/HeaderBar.vala:75 msgid "Insert" msgstr "തിരുകുക" #: Layouts/HeaderBar.vala:82 msgid "Group" msgstr "കൂട്ടമാക്കുക" #: Layouts/HeaderBar.vala:84 msgid "Ungroup" msgstr "കൂട്ടം തെറ്റിക്കുക" #: Layouts/HeaderBar.vala:87 msgid "Up" msgstr "മേലെ" #: Layouts/HeaderBar.vala:92 msgid "Down" msgstr "താഴെ" #: Layouts/HeaderBar.vala:97 msgid "Top" msgstr "മുകളില്‍" #: Layouts/HeaderBar.vala:102 msgid "Bottom" msgstr "അടിയില്‍" #: Layouts/HeaderBar.vala:107 msgid "Settings" msgstr "സജ്ജീകരണങ്ങള്‍" #: Layouts/HeaderBar.vala:118 msgid "Difference" msgstr "വ്യത്യാസം" #: Layouts/HeaderBar.vala:120 msgid "Exclusion" msgstr "ഒഴിവാക്കിയത്" #: Layouts/HeaderBar.vala:122 msgid "Intersect" msgstr "നുറുക്കുക" #: Layouts/HeaderBar.vala:124 msgid "Union" msgstr "ഏകീകരിക്കുക" #: Layouts/HeaderBar.vala:161 msgid "New Window" msgstr "പുതിയ ജാലകം" #: Layouts/HeaderBar.vala:182 msgid "Open Recent" msgstr "അടുത്തിടെയുള്ളവ തുറക്കുക" #: Layouts/HeaderBar.vala:195 msgid "Save As" msgstr "മറ്റൊന്നായി സൂക്ഷിക്കുക" #: Layouts/HeaderBar.vala:204 msgid "Quit" msgstr "പുറത്ത് കടക്കുക" #: Layouts/HeaderBar.vala:237 msgid "Artboard" msgstr "കലാഫലകം" #: Layouts/HeaderBar.vala:254 msgid "Add Items" msgstr "സാധനങ്ങള്‍ ചേര്‍ക്കുക" #: Layouts/HeaderBar.vala:262 msgid "Rectangle" msgstr "ചതുരം" #: Layouts/HeaderBar.vala:268 msgid "Ellipse" msgstr "വട്ടം" #: Layouts/HeaderBar.vala:286 msgid "Vector" msgstr "ജ്യാമിത്ചിത്രം(വെക്ടര്‍)" #: Layouts/HeaderBar.vala:288 msgid "Pencil" msgstr "പെന്‍സില്‍" #: Layouts/HeaderBar.vala:291 msgid "Text" msgstr "എഴുത്ത്" #: Layouts/HeaderBar.vala:297 msgid "Image" msgstr "ചിത്രം" #: Layouts/HeaderBar.vala:330 msgid "Export Current Selection" msgstr "തിരഞ്ഞെടുത്തിരിക്കുന്നവ കയറ്റുമതി ചെയ്യുക" #: Layouts/HeaderBar.vala:336 msgid "Export Artboards" msgstr "കലാഫലകങ്ങള്‍ ഇറക്കുമതി ചെയ്യുക" #: Layouts/HeaderBar.vala:345 msgid "Highlight Area to Export" msgstr "കയറ്റുമതി ചെയ്യാനുള്ള സ്ഥലം എടുത്തുകാട്ടുക" #: Layouts/HeaderBar.vala:391 msgid "Main Menu" msgstr "പ്രധാന മെനു" #: Layouts/HeaderBar.vala:468 Services/ActionManager.vala:224 Services/ActionManager.vala:243 #: Services/ActionManager.vala:262 #, c-format msgid "Unable to open file at '%s'" msgstr "'%s'ലുള്ള രേഖ തുറക്കുവാന്‍ സാധിക്കുന്നില്ല" #: Layouts/MainCanvas.vala:46 msgid "Button was pressed!" msgstr "ബട്ടണ്‍ അമര്‍ത്തി!" #: Layouts/MainCanvas.vala:206 msgid "Export completed!" msgstr "കയറ്റുമതി ചെയ്തു കഴിഞ്ഞു!" #: Layouts/Partials/AlignItemsPanel.vala:48 msgid "Distribute Horizontally" msgstr "വരിയില്‍ അടുക്കുക" #: Layouts/Partials/AlignItemsPanel.vala:50 msgid "Distribute Vertically" msgstr "നിരയില്‍ അടുക്കുക" #: Layouts/Partials/AlignItemsPanel.vala:52 msgid "Align Left" msgstr "ഇടതു ചേര്‍ക്കുക" #: Layouts/Partials/AlignItemsPanel.vala:53 msgid "Align Center" msgstr "നടുക്കു വയ്ക്കുക" #: Layouts/Partials/AlignItemsPanel.vala:54 msgid "Align Right" msgstr "വലതു ചേര്‍ക്കുക" #: Layouts/Partials/AlignItemsPanel.vala:56 msgid "Align Top" msgstr "മേലെ ചേര്‍ത്തു വയ്ക്കുക" #: Layouts/Partials/AlignItemsPanel.vala:57 msgid "Align Middle" msgstr "ഇടയില്‍ വയ്ക്കുക" #: Layouts/Partials/AlignItemsPanel.vala:58 msgid "Align Bottom" msgstr "അടിചേര്‍ക്കുക" #: Layouts/Partials/Artboard.vala:144 Layouts/Partials/Artboard.vala:487 #: Layouts/Partials/Layer.vala:139 Layouts/Partials/Layer.vala:687 msgid "Lock Layer" msgstr "പാളി പൂട്ടുക" #: Layouts/Partials/Artboard.vala:155 Layouts/Partials/Artboard.vala:529 #: Layouts/Partials/Layer.vala:156 Layouts/Partials/Layer.vala:729 msgid "Hide Layer" msgstr "പാളി ഒളിപ്പിക്കുക" #: Layouts/Partials/Artboard.vala:487 Layouts/Partials/Layer.vala:687 msgid "Unlock Layer" msgstr "പാളി തുറന്നിടുക" #: Layouts/Partials/Artboard.vala:529 Layouts/Partials/Layer.vala:729 msgid "Show Layer" msgstr "പാളി കാണിക്കുക" #: Layouts/Partials/BorderItem.vala:121 msgid "Choose border color" msgstr "അതിര്‍ നിറം തിരഞ്ഞെടുക്കുക" #: Layouts/Partials/BorderItem.vala:176 Layouts/Partials/FillItem.vala:178 msgid "Pick color" msgstr "നിറം എടുക്കുക" #: Layouts/Partials/BorderItem.vala:191 msgid "Remove border" msgstr "അതിര് നീക്കം ചെയ്യുക" #: Layouts/Partials/BorderItem.vala:275 msgid "Show border" msgstr "അതിര് കാണിക്കുക" #: Layouts/Partials/BorderItem.vala:279 msgid "Hide border" msgstr "അതിര് ഒളിപ്പിക്കുക" #: Layouts/Partials/BorderRadiusPanel.vala:86 msgid "Style" msgstr "ഭംഗി" #: Layouts/Partials/BorderRadiusPanel.vala:103 msgid "Border Radius" msgstr "അതിരിന്റെ ആരം" #: Layouts/Partials/BorderRadiusPanel.vala:137 msgid "Border radius options" msgstr "അതിര്‍ ആരത്തിന്റെ സജ്ജീകരണങ്ങള്‍" #: Layouts/Partials/BorderRadiusPanel.vala:199 msgid "Autoscale Corners" msgstr "മൂലകള്‍ താനേ വിസ്തൃതമാക്കുക" #: Layouts/Partials/BorderRadiusPanel.vala:208 msgid "Uniform Corners" msgstr "മൂലകള്‍ ഏകികരിക്കുക" #: Layouts/Partials/BordersPanel.vala:53 msgid "Borders" msgstr "അതിരുകള്‍" #: Layouts/Partials/BordersPanel.vala:64 msgid "Add border" msgstr "അതിരു ചേര്‍ക്കുക" #: Layouts/Partials/FillItem.vala:114 msgid "Choose fill color" msgstr "അകനിറം തിരഞ്ഞെടുക്കുക" #: Layouts/Partials/FillItem.vala:193 msgid "Remove fill color" msgstr "അകനിറം ഒഴിവാക്കുക" #: Layouts/Partials/FillItem.vala:277 msgid "Show fill color" msgstr "അകനിറം കാണിക്കുക" #: Layouts/Partials/FillItem.vala:281 msgid "Hide fill color" msgstr "അകനിറം ഒളിപ്പിക്കുക" #: Layouts/Partials/FillsPanel.vala:54 msgid "Fills" msgstr "അകനിറങ്ങള്‍" #: Layouts/Partials/FillsPanel.vala:65 msgid "Add fill color" msgstr "അകനിറം ചേര്‍ക്കുക" #: Layouts/Partials/TransformPanel.vala:96 msgid "X" msgstr "X" #: Layouts/Partials/TransformPanel.vala:96 msgid "Horizontal position" msgstr "വിലങ്ങനെയുള്ള സ്ഥാനം" #: Layouts/Partials/TransformPanel.vala:98 msgid "Y" msgstr "Y" #: Layouts/Partials/TransformPanel.vala:98 msgid "Vertical position" msgstr "കുത്തനെയുള്ള സ്ഥാനം" #: Layouts/Partials/TransformPanel.vala:100 msgid "W" msgstr "W" #: Layouts/Partials/TransformPanel.vala:100 msgid "Width" msgstr "വീതി" #: Layouts/Partials/TransformPanel.vala:102 msgid "H" msgstr "H" #: Layouts/Partials/TransformPanel.vala:102 msgid "Height" msgstr "ഉയരം" #: Layouts/Partials/TransformPanel.vala:107 msgid "Lock Ratio" msgstr "സ്ഥിര അംശബന്ധം" #: Layouts/Partials/TransformPanel.vala:114 msgid "R" msgstr "R" #: Layouts/Partials/TransformPanel.vala:114 msgid "Rotation degrees" msgstr "കറക്കം ഡിഗ്രിയില്‍" #: Layouts/Partials/TransformPanel.vala:126 msgid "Flip Horizontally" msgstr "വിലങ്ങനെ മറിക്കുക" #: Layouts/Partials/TransformPanel.vala:137 msgid "Flip Vertically" msgstr "കുത്തനെ മറിക്കുക" #: Layouts/Partials/TransformPanel.vala:165 msgid "Position" msgstr "സ്ഥാനം" #: Layouts/Partials/TransformPanel.vala:169 msgid "Size" msgstr "വലുപ്പം" #: Layouts/Partials/TransformPanel.vala:178 msgid "Opacity" msgstr "സുതാര്യത" #: Layouts/RightSideBar.vala:111 msgid "Search Layer" msgstr "പാളി പരതുക" #: Lib/Managers/ExportManager.vala:192 Lib/Managers/ExportManager.vala:219 msgid "Generating preview, please wait…" msgstr "പൂര്‍വ്വദൃശ്യം രുപികരിക്കുന്നു, ദയവായി കാക്കുക…" #: Lib/Managers/ExportManager.vala:313 #, c-format msgid "Untitled %i" msgstr "പേരില്ലാത്തത് %i" #: Lib/Managers/ExportManager.vala:484 msgid "Exporting images…" msgstr "ചിത്രങ്ങള്‍ കയറ്റുമതി ചെയ്യുന്നു…" #: Partials/ExportWidget.vala:117 #, c-format msgid "%i × %i px · %s" msgstr "%i × %i px · %s" #: Partials/ExportWidget.vala:124 msgid "Fetching image size…" msgstr "ചിത്രവലുപ്പം കണ്ടെത്തുന്നു…" #: Partials/ZoomButton.vala:49 msgid "Zoom Out" msgstr "ചെറുതാക്കിക്കാണിക്കുക" #: Partials/ZoomButton.vala:55 msgid "Reset Zoom" msgstr "പഴയ വലുപ്പത്തിലാക്കുക" #: Partials/ZoomButton.vala:62 msgid "Zoom In" msgstr "വലുതാക്കിക്കാണിക്കുക" #: Partials/ZoomButton.vala:68 msgid "Zoom" msgstr "വലുപ്പം ക്രമീകരിക്കുക" #: Services/ActionManager.vala:217 msgid "No recently opened file available!" msgstr "അവസാനം തുറന്ന ഒരു രേഖയും കിട്ടാനില്ല!" #: Services/ActionManager.vala:236 msgid "No second most recently opened file available!" msgstr "അവസാനം രണ്ടാമതായി തുറന്ന ഒരു രേഖയും കിട്ടാനില്ല!" #: Services/ActionManager.vala:255 msgid "No third most recently opened file available!" msgstr "അവസാനം മൂന്നാമതായി തുറന്ന ഒരു രേഖയും കിട്ടാനില്ല!" #: Services/ActionManager.vala:293 msgid "Nothing selected to export!" msgstr "കയറ്റുമതി ചെയ്യാന്‍ ഒന്നും തിരഞ്ഞെടുത്തിട്ടില്ല!" #: Services/ActionManager.vala:302 msgid "Export of Artboards currently unavailable…sorry 😑️" msgstr "ക്ഷമിക്കണം…കലാഫലകങ്ങളുടെ കയറ്റുമതി ഇപ്പോള്‍ സാധ്യമല്ല 😑️" #: Services/ActionManager.vala:373 msgid "Choose image file" msgstr "ചിത്രരേഖ തുറക്കുക" #: Services/ActionManager.vala:373 msgid "Select" msgstr "തിരഞ്ഞെടുക്കുക" #: Services/ActionManager.vala:373 msgid "Close" msgstr "അടക്കുക" #: Services/ActionManager.vala:442 #, c-format msgid "Error! .%s files are not supported!" msgstr "പ്രശ്നമായി! .%s രേഖകള്‍ പിന്തുണക്കപ്പെടുന്നവയല്ല!" #: Window.vala:121 msgid "Are you sure you want to quit?" msgstr "പുറത്തിറങ്ങുകയാണെന്നുറപ്പാണോ?" #: Window.vala:122 msgid "All unsaved data will be lost and impossible to recover." msgstr "സൂക്ഷിക്കാത്ത എല്ലാ വിവരങ്ങളും തിരിച്ചെടുക്കാനാകാത്തവിധത്തില്‍ നഷ്ടപ്പെടും." #: Window.vala:124 msgid "Quit without saving!" msgstr "സൂക്ഷിക്കാതെ പുറത്തുറങ്ങുക!" #: Window.vala:125 msgid "Save file" msgstr "രേഖ സൂക്ഷിക്കുക" Akira-0.0.16/po/mn.po000066400000000000000000000001251410625726100142170ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/mo.po000066400000000000000000000001251410625726100142200ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/mr.po000066400000000000000000000001251410625726100142230ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/ms.po000066400000000000000000000001251410625726100142240ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/mt.po000066400000000000000000000001251410625726100142250ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/my.po000066400000000000000000000001251410625726100142320ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/na.po000066400000000000000000000001251410625726100142030ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/nb.po000066400000000000000000000002021410625726100142000ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" Akira-0.0.16/po/nd.po000066400000000000000000000001251410625726100142060ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/ne.po000066400000000000000000000001251410625726100142070ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/ng.po000066400000000000000000000001251410625726100142110ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/nl.po000066400000000000000000000373171410625726100142330ustar00rootroot00000000000000msgid "" msgstr "" "Project-Id-Version: \n" "POT-Creation-Date: 2020-09-03 18:20+0200\n" "PO-Revision-Date: \n" "Last-Translator: Heimen Stoffels \n" "Language-Team: \n" "Language: nl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" "X-Generator: Poedit 2.4.1\n" "X-Poedit-Basepath: ../src\n" "X-Poedit-SearchPath-0: .\n" #: Dialogs/ExportDialog.vala:151 msgid "Export to:" msgstr "Exporteren naar:" #: Dialogs/ExportDialog.vala:157 msgid "Select Folder" msgstr "Kies een map" #: Dialogs/ExportDialog.vala:166 msgid "Format:" msgstr "Formaat:" #: Dialogs/ExportDialog.vala:179 msgid "Quality:" msgstr "Kwaliteit:" #: Dialogs/ExportDialog.vala:191 msgid "Compression:" msgstr "Compressie:" #: Dialogs/ExportDialog.vala:205 msgid "Transparency:" msgstr "Doorzichtigheid:" #: Dialogs/ExportDialog.vala:218 msgid "Scale:" msgstr "Schaal:" #: Dialogs/ExportDialog.vala:242 FileFormat/FileManager.vala:49 #: FileFormat/FileManager.vala:105 msgid "Cancel" msgstr "Annuleren" #: Dialogs/ExportDialog.vala:249 Dialogs/ShortcutsDialog.vala:63 #: Layouts/HeaderBar.vala:112 msgid "Export" msgstr "Exporteren" #: Dialogs/ReleaseDialog.vala:47 Dialogs/SettingsDialog.vala:217 msgid "" "WARNING!\n" "Akira is still under development and not ready for production. Missing " "features, random bugs, and black holes opening in your kitchen are to be " "expected." msgstr "" #: Dialogs/ReleaseDialog.vala:100 Dialogs/SettingsDialog.vala:249 msgid "Make a Donation" msgstr "Doneren" #: Dialogs/ReleaseDialog.vala:109 Dialogs/SettingsDialog.vala:258 msgid "Suggest Translations" msgstr "Vertalen" #: Dialogs/ReleaseDialog.vala:118 Dialogs/SettingsDialog.vala:267 msgid "Report a Problem" msgstr "Probleem melden" #: Dialogs/SettingsDialog.vala:40 msgid "Preferences" msgstr "Voorkeuren" #: Dialogs/SettingsDialog.vala:50 Dialogs/SettingsDialog.vala:73 #: Dialogs/ShortcutsDialog.vala:45 msgid "General" msgstr "Algemeen" #: Dialogs/SettingsDialog.vala:51 Dialogs/SettingsDialog.vala:86 msgid "Interface" msgstr "Uiterlijk" #: Dialogs/SettingsDialog.vala:52 Layouts/HeaderBar.vala:280 msgid "Shapes" msgstr "Vormen" #: Dialogs/SettingsDialog.vala:53 msgid "About" msgstr "Over" #: Dialogs/SettingsDialog.vala:74 msgid "Auto Reopen Latest File:" msgstr "Recentste bestand automatisch openen:" #: Dialogs/SettingsDialog.vala:88 msgid "Use Dark Theme:" msgstr "Donker thema gebruiken:" #: Dialogs/SettingsDialog.vala:92 msgid "Invert Panels Order:" msgstr "Paneelvolgorde omkeren:" #: Dialogs/SettingsDialog.vala:96 msgid "Restart application to apply this change." msgstr "Herstart de toepassing om de wijzigingen toe te passen." #: Dialogs/SettingsDialog.vala:100 msgid "ToolBar Style" msgstr "Werkbalkstijl" #: Dialogs/SettingsDialog.vala:102 msgid "Show Button Labels:" msgstr "Knopteksten tonen:" #: Dialogs/SettingsDialog.vala:106 msgid "Use Symbolic Icons:" msgstr "Symbolische pictogrammen gebruiken:" #: Dialogs/SettingsDialog.vala:129 msgid "Default Colors" msgstr "Standaardkleuren" #: Dialogs/SettingsDialog.vala:131 msgid "Define the default style used when creating a new shape." msgstr "" "Geef op welke stijl moet worden gebruikt bij het maken van een nieuwe " "vorm." #: Dialogs/SettingsDialog.vala:136 msgid "Fill Color:" msgstr "Opvulkleur:" #: Dialogs/SettingsDialog.vala:157 msgid "Enable Border Style:" msgstr "Randstijl gebruiken:" #: Dialogs/SettingsDialog.vala:160 msgid "Border Color:" msgstr "Randkleur:" #: Dialogs/SettingsDialog.vala:181 msgid "Border Width:" msgstr "Randbreedte:" #: Dialogs/SettingsDialog.vala:209 msgid "The Linux Design Tool" msgstr "Hét Linux-ontwerpprogramma" #: Dialogs/SettingsDialog.vala:226 msgid "Thanks to our awesome supporters!" msgstr "Met dank aan onze geweldige ondersteuners!" #: Dialogs/SettingsDialog.vala:231 msgid "View the list of supporters" msgstr "Ondersteunerlijst bekijken" #: Dialogs/ShortcutsDialog.vala:46 msgid "New window:" msgstr "Nieuw venster:" #: Dialogs/ShortcutsDialog.vala:48 msgid "Preferences:" msgstr "Voorkeuren:" #: Dialogs/ShortcutsDialog.vala:50 msgid "Quit:" msgstr "Afsluiten:" #: Dialogs/ShortcutsDialog.vala:52 msgid "Presentation mode:" msgstr "Presentatiemodus:" #: Dialogs/ShortcutsDialog.vala:55 msgid "File" msgstr "Bestand" #: Dialogs/ShortcutsDialog.vala:56 msgid "Open:" msgstr "Openen:" #: Dialogs/ShortcutsDialog.vala:58 msgid "Save:" msgstr "Opslaan:" #: Dialogs/ShortcutsDialog.vala:60 msgid "Save as:" msgstr "Opslaan als:" #: Dialogs/ShortcutsDialog.vala:64 msgid "Export artboards:" msgstr "Ontwerpborden exporteren:" #: Dialogs/ShortcutsDialog.vala:66 msgid "Export selection:" msgstr "Selectie exporteren:" #: Dialogs/ShortcutsDialog.vala:68 msgid "Highlight area to export:" msgstr "Markeer het te exporteren gebied:" #: Dialogs/ShortcutsDialog.vala:77 msgid "Canvas" msgstr "Canvas" #: Dialogs/ShortcutsDialog.vala:78 msgid "Zoom in:" msgstr "Inzoomen:" #: Dialogs/ShortcutsDialog.vala:80 msgid "Zoom out:" msgstr "Uitzoomen:" #: Dialogs/ShortcutsDialog.vala:82 msgid "Zoom reset:" msgstr "Standaard zoomniveau:" #: Dialogs/ShortcutsDialog.vala:85 msgid "Item creation" msgstr "Items maken" #: Dialogs/ShortcutsDialog.vala:86 msgid "Artboard:" msgstr "Ontwerpbord:" #: Dialogs/ShortcutsDialog.vala:88 msgid "Rectangle:" msgstr "Rechthoek:" #: Dialogs/ShortcutsDialog.vala:90 msgid "Ellipse:" msgstr "Ellips:" #: Dialogs/ShortcutsDialog.vala:92 msgid "Text:" msgstr "Tekst:" #: Dialogs/ShortcutsDialog.vala:94 msgid "Image:" msgstr "Afbeelding:" #: Dialogs/ShortcutsDialog.vala:97 Layouts/Partials/TransformPanel.vala:174 msgid "Transform" msgstr "Transformeren" #: Dialogs/ShortcutsDialog.vala:98 msgid "Raise selection:" msgstr "Selectie verhogen:" #: Dialogs/ShortcutsDialog.vala:100 msgid "Lower selection:" msgstr "Selectie verlagen:" #: Dialogs/ShortcutsDialog.vala:102 msgid "Raise selection to top:" msgstr "Selectie naar bovenkant:" #: Dialogs/ShortcutsDialog.vala:104 msgid "Lower selection to bottom:" msgstr "Selectie naar onderkant:" #: Dialogs/ShortcutsDialog.vala:106 msgid "Flip horizontally:" msgstr "Horizontaal spiegelen:" #: Dialogs/ShortcutsDialog.vala:108 msgid "Flip vertically:" msgstr "Verticaal spiegelen:" #: FileFormat/FileManager.vala:46 msgid "Save Akira file" msgstr "Akira-bestand opslaan" #: FileFormat/FileManager.vala:48 Layouts/HeaderBar.vala:190 msgid "Save" msgstr "Opslaan" #: FileFormat/FileManager.vala:71 msgid "Akira files" msgstr "Akira-bestanden" #: FileFormat/FileManager.vala:76 msgid "All files" msgstr "Alle bestanden" #: FileFormat/FileManager.vala:103 msgid "Open Akira file" msgstr "Akira-bestand openen" #: FileFormat/FileManager.vala:105 Layouts/HeaderBar.vala:170 msgid "Open" msgstr "Openen" #: Layouts/HeaderBar.vala:69 Lib/Managers/ExportManager.vala:296 msgid "Untitled" msgstr "Naamloos" #: Layouts/HeaderBar.vala:71 msgid "Menu" msgstr "Menu" #: Layouts/HeaderBar.vala:75 msgid "Insert" msgstr "Invoegen" #: Layouts/HeaderBar.vala:82 msgid "Group" msgstr "Groeperen" #: Layouts/HeaderBar.vala:84 msgid "Ungroup" msgstr "Degroeperen" #: Layouts/HeaderBar.vala:87 msgid "Up" msgstr "Omhoog" #: Layouts/HeaderBar.vala:92 msgid "Down" msgstr "Omlaag" #: Layouts/HeaderBar.vala:97 msgid "Top" msgstr "Bovenkant" #: Layouts/HeaderBar.vala:102 msgid "Bottom" msgstr "Onderkant" #: Layouts/HeaderBar.vala:107 msgid "Settings" msgstr "Instellingen" #: Layouts/HeaderBar.vala:118 msgid "Difference" msgstr "Verschil" #: Layouts/HeaderBar.vala:120 msgid "Exclusion" msgstr "Uitsluiten" #: Layouts/HeaderBar.vala:122 msgid "Intersect" msgstr "Kruisen" #: Layouts/HeaderBar.vala:124 msgid "Union" msgstr "Verenigen" #: Layouts/HeaderBar.vala:161 msgid "New Window" msgstr "Nieuw venster" #: Layouts/HeaderBar.vala:182 msgid "Open Recent" msgstr "Recent bestand openen" #: Layouts/HeaderBar.vala:195 msgid "Save As" msgstr "Opslaan als" #: Layouts/HeaderBar.vala:204 msgid "Quit" msgstr "Afsluiten" #: Layouts/HeaderBar.vala:237 msgid "Artboard" msgstr "Ontwerpbord" #: Layouts/HeaderBar.vala:254 msgid "Add Items" msgstr "Items toevoegen" #: Layouts/HeaderBar.vala:262 msgid "Rectangle" msgstr "Rechthoek" #: Layouts/HeaderBar.vala:268 msgid "Ellipse" msgstr "Ellips" #: Layouts/HeaderBar.vala:286 msgid "Vector" msgstr "Vector" #: Layouts/HeaderBar.vala:288 msgid "Pencil" msgstr "Potlood" #: Layouts/HeaderBar.vala:291 msgid "Text" msgstr "Tekst" #: Layouts/HeaderBar.vala:297 msgid "Image" msgstr "Afbeelding" #: Layouts/HeaderBar.vala:330 msgid "Export Current Selection" msgstr "Huidige selectie exporteren" #: Layouts/HeaderBar.vala:336 msgid "Export Artboards" msgstr "Ontwerpborden exporteren" #: Layouts/HeaderBar.vala:345 msgid "Highlight Area to Export" msgstr "Markeer het te exporteren gebied" #: Layouts/HeaderBar.vala:391 msgid "Main Menu" msgstr "Hoofdmenu" #: Layouts/HeaderBar.vala:468 Services/ActionManager.vala:224 #: Services/ActionManager.vala:243 Services/ActionManager.vala:262 #, c-format msgid "Unable to open file at '%s'" msgstr "Het bestand in '%s' kan niet worden geopend" #: Layouts/MainCanvas.vala:46 msgid "Button was pressed!" msgstr "De knop is ingedrukt!" #: Layouts/MainCanvas.vala:206 msgid "Export completed!" msgstr "Exporteren voltooid!" #: Layouts/Partials/AlignItemsPanel.vala:48 msgid "Distribute Horizontally" msgstr "Horizontaal opdelen" #: Layouts/Partials/AlignItemsPanel.vala:50 msgid "Distribute Vertically" msgstr "Verticaal opdelen" #: Layouts/Partials/AlignItemsPanel.vala:52 msgid "Align Left" msgstr "Links uitlijnen" #: Layouts/Partials/AlignItemsPanel.vala:53 msgid "Align Center" msgstr "Centreren" #: Layouts/Partials/AlignItemsPanel.vala:54 msgid "Align Right" msgstr "Rechts uitlijnen" #: Layouts/Partials/AlignItemsPanel.vala:56 msgid "Align Top" msgstr "Aan bovenkant uitlijnen" #: Layouts/Partials/AlignItemsPanel.vala:57 msgid "Align Middle" msgstr "Gecentreerd uitlijnen" #: Layouts/Partials/AlignItemsPanel.vala:58 msgid "Align Bottom" msgstr "Aan onderkant uitlijnen" #: Layouts/Partials/Artboard.vala:144 Layouts/Partials/Artboard.vala:487 #: Layouts/Partials/Layer.vala:139 Layouts/Partials/Layer.vala:687 msgid "Lock Layer" msgstr "Laag vergrendelen" #: Layouts/Partials/Artboard.vala:155 Layouts/Partials/Artboard.vala:529 #: Layouts/Partials/Layer.vala:156 Layouts/Partials/Layer.vala:729 msgid "Hide Layer" msgstr "Laag verbergen" #: Layouts/Partials/Artboard.vala:487 Layouts/Partials/Layer.vala:687 msgid "Unlock Layer" msgstr "Laag ontgrendelen" #: Layouts/Partials/Artboard.vala:529 Layouts/Partials/Layer.vala:729 msgid "Show Layer" msgstr "Laag tonen" #: Layouts/Partials/BorderItem.vala:121 msgid "Choose border color" msgstr "Kies een randkleur" #: Layouts/Partials/BorderItem.vala:176 Layouts/Partials/FillItem.vala:178 msgid "Pick color" msgstr "Kleur kiezen" #: Layouts/Partials/BorderItem.vala:191 msgid "Remove border" msgstr "Rand verwijderen" #: Layouts/Partials/BorderItem.vala:275 msgid "Show border" msgstr "Rand tonen" #: Layouts/Partials/BorderItem.vala:279 msgid "Hide border" msgstr "Rand verbergen" #: Layouts/Partials/BorderRadiusPanel.vala:86 msgid "Style" msgstr "Stijl" #: Layouts/Partials/BorderRadiusPanel.vala:103 msgid "Border Radius" msgstr "Randstraal" #: Layouts/Partials/BorderRadiusPanel.vala:137 msgid "Border radius options" msgstr "Randstraalopties" #: Layouts/Partials/BorderRadiusPanel.vala:199 msgid "Autoscale Corners" msgstr "Hoeken automatisch schalen" #: Layouts/Partials/BorderRadiusPanel.vala:208 msgid "Uniform Corners" msgstr "Hoeken verenigen" #: Layouts/Partials/BordersPanel.vala:53 msgid "Borders" msgstr "Randen" #: Layouts/Partials/BordersPanel.vala:64 msgid "Add border" msgstr "Rand toevoegen" #: Layouts/Partials/FillItem.vala:114 msgid "Choose fill color" msgstr "Kies een opvulkleur" #: Layouts/Partials/FillItem.vala:193 msgid "Remove fill color" msgstr "Opvulkleur verwijderen" #: Layouts/Partials/FillItem.vala:277 msgid "Show fill color" msgstr "Opvulkleur tonen" #: Layouts/Partials/FillItem.vala:281 msgid "Hide fill color" msgstr "Opvulkleur verbergen" #: Layouts/Partials/FillsPanel.vala:54 msgid "Fills" msgstr "Opvullen" #: Layouts/Partials/FillsPanel.vala:65 msgid "Add fill color" msgstr "Opvulkleur toevoegen" #: Layouts/Partials/TransformPanel.vala:96 msgid "X" msgstr "X" #: Layouts/Partials/TransformPanel.vala:96 msgid "Horizontal position" msgstr "Horizontale positie" #: Layouts/Partials/TransformPanel.vala:98 msgid "Y" msgstr "Y" #: Layouts/Partials/TransformPanel.vala:98 msgid "Vertical position" msgstr "Verticale positie" #: Layouts/Partials/TransformPanel.vala:100 msgid "W" msgstr "W" #: Layouts/Partials/TransformPanel.vala:100 msgid "Width" msgstr "Breedte" #: Layouts/Partials/TransformPanel.vala:102 msgid "H" msgstr "H" #: Layouts/Partials/TransformPanel.vala:102 msgid "Height" msgstr "Hoogte" #: Layouts/Partials/TransformPanel.vala:107 msgid "Lock Ratio" msgstr "Verhouding vergrendelen" #: Layouts/Partials/TransformPanel.vala:114 msgid "R" msgstr "R" #: Layouts/Partials/TransformPanel.vala:114 msgid "Rotation degrees" msgstr "Aantal graden draaien" #: Layouts/Partials/TransformPanel.vala:126 msgid "Flip Horizontally" msgstr "Horizontaal spiegelen" #: Layouts/Partials/TransformPanel.vala:137 msgid "Flip Vertically" msgstr "Verticaal spiegelen" #: Layouts/Partials/TransformPanel.vala:165 msgid "Position" msgstr "Positie" #: Layouts/Partials/TransformPanel.vala:169 msgid "Size" msgstr "Grootte" #: Layouts/Partials/TransformPanel.vala:178 msgid "Opacity" msgstr "Doorzichtigheid" #: Layouts/RightSideBar.vala:111 msgid "Search Layer" msgstr "Laag zoeken" #: Lib/Managers/ExportManager.vala:192 Lib/Managers/ExportManager.vala:219 msgid "Generating preview, please wait…" msgstr "Bezig met samenstellen van voorvertoning…" #: Lib/Managers/ExportManager.vala:313 #, c-format msgid "Untitled %i" msgstr "Naamloos %i" #: Lib/Managers/ExportManager.vala:484 msgid "Exporting images…" msgstr "Bezig met exporteren…" #: Partials/ExportWidget.vala:117 #, c-format msgid "%i × %i px · %s" msgstr "%i × %i px · %s" #: Partials/ExportWidget.vala:124 msgid "Fetching image size…" msgstr "Bezig met ophalen van afbeeldingsgrootte…" #: Partials/ZoomButton.vala:49 msgid "Zoom Out" msgstr "Uitzoomen" #: Partials/ZoomButton.vala:55 msgid "Reset Zoom" msgstr "Standaard zoomniveau" #: Partials/ZoomButton.vala:62 msgid "Zoom In" msgstr "Inzoomen" #: Partials/ZoomButton.vala:68 msgid "Zoom" msgstr "Zoom" #: Services/ActionManager.vala:217 msgid "No recently opened file available!" msgstr "Er is geen onlangs geopend bestand!" #: Services/ActionManager.vala:236 msgid "No second most recently opened file available!" msgstr "Er is geen tweede onlangs geopend bestand!" #: Services/ActionManager.vala:255 msgid "No third most recently opened file available!" msgstr "Er is geen derde onlangs geopend bestand!" #: Services/ActionManager.vala:293 msgid "Nothing selected to export!" msgstr "Niets geselecteerd om te exporteren!" #: Services/ActionManager.vala:302 msgid "Export of Artboards currently unavailable…sorry 😑️" msgstr "Ontwerpborden kunnen momenteel niet worden geëxporteerd… 😑️" #: Services/ActionManager.vala:373 msgid "Choose image file" msgstr "Kies een afbeelding" #: Services/ActionManager.vala:373 msgid "Select" msgstr "Kiezen" #: Services/ActionManager.vala:373 msgid "Close" msgstr "Sluiten" #: Services/ActionManager.vala:442 #, c-format msgid "Error! .%s files are not supported!" msgstr "Fout: .%s-bestanden worden niet ondersteund!" #: Window.vala:121 msgid "Are you sure you want to quit?" msgstr "Weet je zeker dat je wilt afsluiten?" #: Window.vala:122 msgid "All unsaved data will be lost and impossible to recover." msgstr "Alle niet-opgeslagen gegevens gaan permanent verloren." #: Window.vala:124 msgid "Quit without saving!" msgstr "Sluiten zonder opslaan" #: Window.vala:125 msgid "Save file" msgstr "Bestand opslaan" Akira-0.0.16/po/nn.po000066400000000000000000000002021410625726100142140ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" Akira-0.0.16/po/no.po000066400000000000000000000002021410625726100142150ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" Akira-0.0.16/po/nr.po000066400000000000000000000001251410625726100142240ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/nv.po000066400000000000000000000001251410625726100142300ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/ny.po000066400000000000000000000001251410625726100142330ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/oc.po000066400000000000000000000001251410625726100142060ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/oj.po000066400000000000000000000001251410625726100142150ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/om.po000066400000000000000000000001251410625726100142200ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/or.po000066400000000000000000000001251410625726100142250ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/os.po000066400000000000000000000001251410625726100142260ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/pa.po000066400000000000000000000001251410625726100142050ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/pi.po000066400000000000000000000001251410625726100142150ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/pl.po000066400000000000000000000002741410625726100142250ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" Akira-0.0.16/po/ps.po000066400000000000000000000001251410625726100142270ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/pt.po000066400000000000000000000002021410625726100142240ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" Akira-0.0.16/po/pt_BR.po000066400000000000000000000354231410625726100146240ustar00rootroot00000000000000msgid "" msgstr "" "Language: pt_BR\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" "Project-Id-Version: \n" "POT-Creation-Date: \n" "PO-Revision-Date: \n" "Last-Translator: codedracula <62944284+codedracula4ec@users.noreply." "github.com>\n" "Language-Team: \n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Poedit 2.4.1\n" #: Dialogs/ExportDialog.vala:151 msgid "Export to:" msgstr "Exportar para:" #: Dialogs/ExportDialog.vala:157 msgid "Select Folder" msgstr "Selecionar pasta" #: Dialogs/ExportDialog.vala:166 msgid "Format:" msgstr "Formato:" #: Dialogs/ExportDialog.vala:180 msgid "Quality:" msgstr "Qualidade:" #: Dialogs/ExportDialog.vala:192 msgid "Compression:" msgstr "Compressão:" #: Dialogs/ExportDialog.vala:206 msgid "Transparency:" msgstr "Transparência:" #: Dialogs/ExportDialog.vala:219 msgid "Scale:" msgstr "Escala:" #: Dialogs/ExportDialog.vala:243 FileFormat/FileManager.vala:49 #: FileFormat/FileManager.vala:105 msgid "Cancel" msgstr "Cancelar" #: Dialogs/ExportDialog.vala:250 Dialogs/ShortcutsDialog.vala:63 #: Layouts/HeaderBar.vala:112 msgid "Export" msgstr "Exportar" #: Dialogs/ReleaseDialog.vala:47 Dialogs/SettingsDialog.vala:217 msgid "" "WARNING!\n" "Akira is still under development and not ready for production. Missing " "features, random bugs, and black holes opening in your kitchen are to be " "expected." msgstr "" "ATENÇÃO!\n" "Akira está sob desenvolvimento e não está pronto para produção. É de se " "esperar o mau funcionamento e a inexistência de algumas funcionalidades." #: Dialogs/ReleaseDialog.vala:100 Dialogs/SettingsDialog.vala:249 msgid "Make a Donation" msgstr "Doar" #: Dialogs/ReleaseDialog.vala:109 Dialogs/SettingsDialog.vala:258 msgid "Suggest Translations" msgstr "Sugerir traduções" #: Dialogs/ReleaseDialog.vala:118 Dialogs/SettingsDialog.vala:267 msgid "Report a Problem" msgstr "Reportar um problema" #: Dialogs/SettingsDialog.vala:40 msgid "Preferences" msgstr "Preferências" #: Dialogs/SettingsDialog.vala:50 Dialogs/SettingsDialog.vala:73 #: Dialogs/ShortcutsDialog.vala:45 msgid "General" msgstr "Geral" #: Dialogs/SettingsDialog.vala:51 Dialogs/SettingsDialog.vala:86 msgid "Interface" msgstr "Interface" #: Dialogs/SettingsDialog.vala:52 Layouts/HeaderBar.vala:280 msgid "Shapes" msgstr "Formas" #: Dialogs/SettingsDialog.vala:53 msgid "About" msgstr "Sobre" #: Dialogs/SettingsDialog.vala:74 msgid "Auto Reopen Latest File:" msgstr "Reabrir automaticamente arquivo mais recente:" #: Dialogs/SettingsDialog.vala:88 msgid "Use Dark Theme:" msgstr "Usar tema escuro:" #: Dialogs/SettingsDialog.vala:92 msgid "Invert Panels Order:" msgstr "Inverter ordem dos painéis:" #: Dialogs/SettingsDialog.vala:96 msgid "Restart application to apply this change." msgstr "Reinicie a aplicação para aplicar a mudança." #: Dialogs/SettingsDialog.vala:100 msgid "ToolBar Style" msgstr "Estilo da barra de ferramentas" #: Dialogs/SettingsDialog.vala:102 msgid "Show Button Labels:" msgstr "Mostrar legendas de botões:" #: Dialogs/SettingsDialog.vala:106 msgid "Use Symbolic Icons:" msgstr "Usar ícones monocromáticos:" #: Dialogs/SettingsDialog.vala:129 msgid "Default Colors" msgstr "Cores padrão" #: Dialogs/SettingsDialog.vala:131 msgid "Define the default style used when creating a new shape." msgstr "Define o estilo padrão a ser usado para criar uma nova forma." #: Dialogs/SettingsDialog.vala:136 msgid "Fill Color:" msgstr "Cor de preenchimento:" #: Dialogs/SettingsDialog.vala:157 msgid "Enable Border Style:" msgstr "Ativar estilo com bordas:" #: Dialogs/SettingsDialog.vala:160 msgid "Border Color:" msgstr "Cor da borda:" #: Dialogs/SettingsDialog.vala:181 msgid "Border Width:" msgstr "Largura da borda:" #: Dialogs/SettingsDialog.vala:209 msgid "The Linux Design Tool" msgstr "A ferramenta de design para Linux" #: Dialogs/SettingsDialog.vala:226 msgid "Thanks to our awesome supporters!" msgstr "Obrigado aos nossos apoiadores incríveis!" #: Dialogs/SettingsDialog.vala:231 msgid "View the list of supporters" msgstr "Ver lista de apoiadores" #: Dialogs/ShortcutsDialog.vala:46 msgid "New window:" msgstr "Nova Janela:" #: Dialogs/ShortcutsDialog.vala:48 msgid "Preferences:" msgstr "Preferências:" #: Dialogs/ShortcutsDialog.vala:50 msgid "Quit:" msgstr "Sair:" #: Dialogs/ShortcutsDialog.vala:52 msgid "Presentation mode:" msgstr "Modo de apresentação:" #: Dialogs/ShortcutsDialog.vala:55 msgid "File" msgstr "Arquivo" #: Dialogs/ShortcutsDialog.vala:56 msgid "Open:" msgstr "Abrir:" #: Dialogs/ShortcutsDialog.vala:58 msgid "Save:" msgstr "Salvar:" #: Dialogs/ShortcutsDialog.vala:60 msgid "Save as:" msgstr "Salvar como:" #: Dialogs/ShortcutsDialog.vala:64 msgid "Export artboards:" msgstr "Exportar pranchetas:" #: Dialogs/ShortcutsDialog.vala:66 msgid "Export selection:" msgstr "Exportar seleção:" #: Dialogs/ShortcutsDialog.vala:68 msgid "Highlight area to export:" msgstr "Selecionar área para exportar:" #: Dialogs/ShortcutsDialog.vala:77 msgid "Canvas" msgstr "Tela" #: Dialogs/ShortcutsDialog.vala:78 msgid "Zoom in:" msgstr "Aumentar zoom:" #: Dialogs/ShortcutsDialog.vala:80 msgid "Zoom out:" msgstr "Reduzir zoom:" #: Dialogs/ShortcutsDialog.vala:82 msgid "Zoom reset:" msgstr "Redefinir zoom:" #: Dialogs/ShortcutsDialog.vala:85 msgid "Item creation" msgstr "Criação de item" #: Dialogs/ShortcutsDialog.vala:86 msgid "Artboard:" msgstr "Prancheta:" #: Dialogs/ShortcutsDialog.vala:88 msgid "Rectangle:" msgstr "Retângulo:" #: Dialogs/ShortcutsDialog.vala:90 msgid "Ellipse:" msgstr "Elipse:" #: Dialogs/ShortcutsDialog.vala:92 msgid "Text:" msgstr "Texto:" #: Dialogs/ShortcutsDialog.vala:94 msgid "Image:" msgstr "Imagem:" #: Dialogs/ShortcutsDialog.vala:97 Layouts/Partials/TransformPanel.vala:174 msgid "Transform" msgstr "Transformar" #: Dialogs/ShortcutsDialog.vala:98 msgid "Raise selection:" msgstr "Subir seleção:" #: Dialogs/ShortcutsDialog.vala:100 msgid "Lower selection:" msgstr "Descer seleção:" #: Dialogs/ShortcutsDialog.vala:102 msgid "Raise selection to top:" msgstr "Trazer seleção para frente:" #: Dialogs/ShortcutsDialog.vala:104 msgid "Lower selection to bottom:" msgstr "Enviar seleção para trás:" #: Dialogs/ShortcutsDialog.vala:106 msgid "Flip horizontally:" msgstr "Inverter horizontalmente:" #: Dialogs/ShortcutsDialog.vala:108 msgid "Flip vertically:" msgstr "Inverter verticalmente:" #: FileFormat/FileManager.vala:46 msgid "Save Akira file" msgstr "Salvar arquivo Akira" #: FileFormat/FileManager.vala:48 Layouts/HeaderBar.vala:190 msgid "Save" msgstr "Salvar" #: FileFormat/FileManager.vala:71 msgid "Akira files" msgstr "Arquivos Akira" #: FileFormat/FileManager.vala:76 msgid "All files" msgstr "Todos os arquivos" #: FileFormat/FileManager.vala:103 msgid "Open Akira file" msgstr "Abrir arquivo Akira" #: FileFormat/FileManager.vala:105 Layouts/HeaderBar.vala:170 msgid "Open" msgstr "Abrir" #: Layouts/HeaderBar.vala:69 Lib/Managers/ExportManager.vala:296 msgid "Untitled" msgstr "Sem título" #: Layouts/HeaderBar.vala:71 msgid "Menu" msgstr "Menu" #: Layouts/HeaderBar.vala:75 msgid "Insert" msgstr "Inserir" #: Layouts/HeaderBar.vala:82 msgid "Group" msgstr "Agrupar" #: Layouts/HeaderBar.vala:84 msgid "Ungroup" msgstr "Desagrupar" #: Layouts/HeaderBar.vala:87 msgid "Up" msgstr "Cima" #: Layouts/HeaderBar.vala:92 msgid "Down" msgstr "Baixo" #: Layouts/HeaderBar.vala:97 msgid "Top" msgstr "Acima" #: Layouts/HeaderBar.vala:102 msgid "Bottom" msgstr "Abaixo" #: Layouts/HeaderBar.vala:107 msgid "Settings" msgstr "Configuração" #: Layouts/HeaderBar.vala:118 msgid "Difference" msgstr "Diferença" #: Layouts/HeaderBar.vala:120 msgid "Exclusion" msgstr "Exclusão" #: Layouts/HeaderBar.vala:122 msgid "Intersect" msgstr "Interseção" #: Layouts/HeaderBar.vala:124 msgid "Union" msgstr "União" #: Layouts/HeaderBar.vala:161 msgid "New Window" msgstr "Nova Janela" #: Layouts/HeaderBar.vala:182 msgid "Open Recent" msgstr "Abrir Recente" #: Layouts/HeaderBar.vala:195 msgid "Save As" msgstr "Salvar Como" #: Layouts/HeaderBar.vala:204 msgid "Quit" msgstr "Sair" #: Layouts/HeaderBar.vala:237 msgid "Artboard" msgstr "Prancheta" #: Layouts/HeaderBar.vala:254 msgid "Add Items" msgstr "Adicionar Itens" #: Layouts/HeaderBar.vala:262 msgid "Rectangle" msgstr "Retângulo" #: Layouts/HeaderBar.vala:268 msgid "Ellipse" msgstr "Elipse" #: Layouts/HeaderBar.vala:286 msgid "Vector" msgstr "Vetor" #: Layouts/HeaderBar.vala:288 msgid "Pencil" msgstr "Lápis" #: Layouts/HeaderBar.vala:291 msgid "Text" msgstr "Texto" #: Layouts/HeaderBar.vala:297 msgid "Image" msgstr "Imagem" #: Layouts/HeaderBar.vala:330 msgid "Export Current Selection" msgstr "Exportar Seleção Atual" #: Layouts/HeaderBar.vala:336 msgid "Export Artboards" msgstr "Exportar Pranchetas" #: Layouts/HeaderBar.vala:345 msgid "Highlight Area to Export" msgstr "Selecionar Área para Exportar" #: Layouts/HeaderBar.vala:391 msgid "Main Menu" msgstr "Menu Principal" #: Layouts/HeaderBar.vala:468 Services/ActionManager.vala:218 #: Services/ActionManager.vala:237 Services/ActionManager.vala:256 #, c-format msgid "Unable to open file at '%s'" msgstr "Não foi possível abrir o arquivo em «%s»" #: Layouts/MainCanvas.vala:52 msgid "Button was pressed!" msgstr "Botão pressionado!" #: Layouts/MainCanvas.vala:160 msgid "Export completed!" msgstr "Exportação finalizada!" #: Layouts/Partials/AlignItemsPanel.vala:48 msgid "Distribute Horizontally" msgstr "Distribuir Horizontalmente" #: Layouts/Partials/AlignItemsPanel.vala:50 msgid "Distribute Vertically" msgstr "Distribuir Verticalmente" #: Layouts/Partials/AlignItemsPanel.vala:52 msgid "Align Left" msgstr "Alinhar à Esquerda" #: Layouts/Partials/AlignItemsPanel.vala:53 msgid "Align Center" msgstr "Alinhar Horizontalmente" #: Layouts/Partials/AlignItemsPanel.vala:54 msgid "Align Right" msgstr "Alinhar à Direita" #: Layouts/Partials/AlignItemsPanel.vala:56 msgid "Align Top" msgstr "Alinhar Acima" #: Layouts/Partials/AlignItemsPanel.vala:57 msgid "Align Middle" msgstr "Centralizar Verticalmente" #: Layouts/Partials/AlignItemsPanel.vala:58 msgid "Align Bottom" msgstr "Alinhar Abaixo" #: Layouts/Partials/Artboard.vala:144 Layouts/Partials/Artboard.vala:487 #: Layouts/Partials/Layer.vala:139 Layouts/Partials/Layer.vala:687 msgid "Lock Layer" msgstr "Bloquear Camada" #: Layouts/Partials/Artboard.vala:155 Layouts/Partials/Artboard.vala:529 #: Layouts/Partials/Layer.vala:156 Layouts/Partials/Layer.vala:729 msgid "Hide Layer" msgstr "Ocultar Camada" #: Layouts/Partials/Artboard.vala:487 Layouts/Partials/Layer.vala:687 msgid "Unlock Layer" msgstr "Desbloquear Camada" #: Layouts/Partials/Artboard.vala:529 Layouts/Partials/Layer.vala:729 msgid "Show Layer" msgstr "Mostrar Camada" #: Layouts/Partials/BorderRadiusPanel.vala:86 msgid "Style" msgstr "Estilo" #: Layouts/Partials/BorderRadiusPanel.vala:103 msgid "Border Radius" msgstr "Raio da Borda" #: Layouts/Partials/BorderRadiusPanel.vala:198 msgid "Autoscale Corners" msgstr "Escalar Cantos Automaticamente" #: Layouts/Partials/BorderRadiusPanel.vala:207 msgid "Uniform Corners" msgstr "Cantos Uniformes" #: Layouts/Partials/BordersPanel.vala:53 msgid "Borders" msgstr "Bordas" #: Layouts/Partials/FillsPanel.vala:54 msgid "Fills" msgstr "Preenchimentos" #: Layouts/Partials/TransformPanel.vala:96 msgid "X" msgstr "X" #: Layouts/Partials/TransformPanel.vala:96 msgid "Horizontal position" msgstr "Posição horizontal" #: Layouts/Partials/TransformPanel.vala:98 msgid "Y" msgstr "Y" #: Layouts/Partials/TransformPanel.vala:98 msgid "Vertical position" msgstr "Posição vertical" #: Layouts/Partials/TransformPanel.vala:100 msgid "W" msgstr "↔" #: Layouts/Partials/TransformPanel.vala:100 msgid "Width" msgstr "Largura" #: Layouts/Partials/TransformPanel.vala:102 msgid "H" msgstr "↕" #: Layouts/Partials/TransformPanel.vala:102 msgid "Height" msgstr "Altura" #: Layouts/Partials/TransformPanel.vala:107 msgid "Lock Ratio" msgstr "Bloquear Aspecto" #: Layouts/Partials/TransformPanel.vala:114 msgid "R" msgstr "↻" #: Layouts/Partials/TransformPanel.vala:114 msgid "Rotation degrees" msgstr "Graus de rotação" #: Layouts/Partials/TransformPanel.vala:126 msgid "Flip Horizontally" msgstr "Inverter Horizontalmente" #: Layouts/Partials/TransformPanel.vala:137 msgid "Flip Vertically" msgstr "Inverter Verticalmente" #: Layouts/Partials/TransformPanel.vala:165 msgid "Position" msgstr "Posição" #: Layouts/Partials/TransformPanel.vala:169 msgid "Size" msgstr "Tamanho" #: Layouts/Partials/TransformPanel.vala:178 msgid "Opacity" msgstr "Opacidade" #: Layouts/RightSideBar.vala:111 msgid "Search Layer" msgstr "Buscar Camada" #: Lib/Managers/ExportManager.vala:192 Lib/Managers/ExportManager.vala:219 msgid "Generating preview, please wait…" msgstr "Gerando pré-visualização, aguarde por favor…" #: Lib/Managers/ExportManager.vala:313 #, c-format msgid "Untitled %i" msgstr "Sem título %i" #: Lib/Managers/ExportManager.vala:484 msgid "Exporting images…" msgstr "Exportando imagens…" #: Partials/ExportWidget.vala:117 #, c-format msgid "%i × %i px · %s" msgstr "%i × %i px · %s" #: Partials/ExportWidget.vala:124 msgid "Fetching image size…" msgstr "Recuperando tamanho de imagem…" #: Partials/ZoomButton.vala:49 msgid "Zoom Out" msgstr "Reduzir Zoom" #: Partials/ZoomButton.vala:55 msgid "Reset Zoom" msgstr "Redefinir Zoom" #: Partials/ZoomButton.vala:62 msgid "Zoom In" msgstr "Aumentar Zoom" #: Partials/ZoomButton.vala:68 msgid "Zoom" msgstr "Zoom" #: Services/ActionManager.vala:211 msgid "No recently opened file available!" msgstr "Não há arquivos recentes!" #: Services/ActionManager.vala:230 msgid "No second most recently opened file available!" msgstr "Não há nenhum segundo arquivo recente!" #: Services/ActionManager.vala:249 msgid "No third most recently opened file available!" msgstr "Não há nenhum terceiro arquivo recente!" #: Services/ActionManager.vala:287 msgid "Nothing selected to export!" msgstr "Nada selecionado para exportar!" #: Services/ActionManager.vala:296 msgid "Export of Artboards currently unavailable…sorry 😑️" msgstr "Exportação de Pranchetas atualmente está indisponível... 😑️" #: Services/ActionManager.vala:363 msgid "Choose image file" msgstr "Selecionar um arquivo de imagem" #: Services/ActionManager.vala:363 msgid "Select" msgstr "Selecionar" #: Services/ActionManager.vala:363 msgid "Close" msgstr "Fechar" #: Services/ActionManager.vala:432 #, c-format msgid "Error! .%s files are not supported!" msgstr "Erro! Arquivos .%s não são suportados!" #: Window.vala:119 msgid "Are you sure you want to quit?" msgstr "Tem certeza que quer sair?" #: Window.vala:120 msgid "All unsaved data will be lost and impossible to recover." msgstr "" "Todos os dados não salvos serão perdidos e será impossível recuperar." #: Window.vala:122 msgid "Quit without saving!" msgstr "Sair sem salvar!" #: Window.vala:123 msgid "Save file" msgstr "Salvar arquivo" Akira-0.0.16/po/qu.po000066400000000000000000000001251410625726100142320ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/rm.po000066400000000000000000000001251410625726100142230ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/rn.po000066400000000000000000000001251410625726100142240ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/ro.po000066400000000000000000000002621410625726100142270ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Plural-Forms: nplurals=3; plural=n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < 20)) ? 1 : 2;\n" Akira-0.0.16/po/ru.po000066400000000000000000000003141410625726100142330ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" Akira-0.0.16/po/rue.po000066400000000000000000000001251410625726100144000ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/rw.po000066400000000000000000000001251410625726100142350ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/sa.po000066400000000000000000000001251410625726100142100ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/sc.po000066400000000000000000000001251410625726100142120ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/sd.po000066400000000000000000000001251410625726100142130ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/se.po000066400000000000000000000001251410625726100142140ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/sg.po000066400000000000000000000001251410625726100142160ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/si.po000066400000000000000000000001251410625726100142200ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/sk.po000066400000000000000000000002371410625726100142260ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" Akira-0.0.16/po/sl.po000066400000000000000000000002661410625726100142310ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Plural-Forms: nplurals=4; plural=n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3;\n" Akira-0.0.16/po/sm.po000066400000000000000000000001251410625726100142240ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/sma.po000066400000000000000000000001251410625726100143650ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/sn.po000066400000000000000000000001251410625726100142250ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/so.po000066400000000000000000000001251410625726100142260ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/sq.po000066400000000000000000000001251410625726100142300ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/sr.po000066400000000000000000000003141410625726100142310ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" Akira-0.0.16/po/ss.po000066400000000000000000000001251410625726100142320ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/st.po000066400000000000000000000001251410625726100142330ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/su.po000066400000000000000000000001251410625726100142340ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/sv.po000066400000000000000000000002021410625726100142310ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" Akira-0.0.16/po/sw.po000066400000000000000000000001251410625726100142360ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/ta.po000066400000000000000000000001251410625726100142110ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/te.po000066400000000000000000000001251410625726100142150ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/tg.po000066400000000000000000000001251410625726100142170ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/th.po000066400000000000000000000001251410625726100142200ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/ti.po000066400000000000000000000001251410625726100142210ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/tk.po000066400000000000000000000001251410625726100142230ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/tl.po000066400000000000000000000001251410625726100142240ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/tn.po000066400000000000000000000001251410625726100142260ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/to.po000066400000000000000000000001251410625726100142270ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/tr.po000066400000000000000000000402201410625726100142320ustar00rootroot00000000000000msgid "" msgstr "" "Project-Id-Version: \n" "POT-Creation-Date: 2020-09-27 19:02+0300\n" "PO-Revision-Date: \n" "Language-Team: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Poedit 2.4.1\n" "X-Poedit-Basepath: ../src\n" "Last-Translator: Nazım Gediz Aydındoğmuş \n" "Language: tr\n" "X-Poedit-SearchPath-0: .\n" #: Dialogs/ExportDialog.vala:151 msgid "Export to:" msgstr "Aktarılacak konum:" #: Dialogs/ExportDialog.vala:157 msgid "Select Folder" msgstr "Dizin Seç" #: Dialogs/ExportDialog.vala:166 msgid "Format:" msgstr "Biçim:" #: Dialogs/ExportDialog.vala:179 msgid "Quality:" msgstr "Kalite:" #: Dialogs/ExportDialog.vala:191 msgid "Compression:" msgstr "Sıkıştırma:" #: Dialogs/ExportDialog.vala:205 msgid "Transparency:" msgstr "Saydamlık:" #: Dialogs/ExportDialog.vala:218 msgid "Scale:" msgstr "Ölçek:" #: Dialogs/ExportDialog.vala:242 FileFormat/FileManager.vala:49 #: FileFormat/FileManager.vala:105 msgid "Cancel" msgstr "İptal" #: Dialogs/ExportDialog.vala:249 Dialogs/ShortcutsDialog.vala:63 #: Layouts/HeaderBar.vala:112 msgid "Export" msgstr "Dışarı Aktar" #: Dialogs/ReleaseDialog.vala:47 Dialogs/SettingsDialog.vala:217 msgid "" "WARNING!\n" "Akira is still under development and not ready for production. Missing " "features, random bugs, and black holes opening in your kitchen are to be " "expected." msgstr "" "UYARI!\n" "Akira hala geliştirme aşamasındadır ve son ürün oluşturmaya yönelik " "kullanıma hazır değildir. Kullanım esnasında eksik özellikler, rastgele " "hatalar ve mutfağınızda zuhur eden kara delikler ile karşılaşabilirsiniz." #: Dialogs/ReleaseDialog.vala:100 Dialogs/SettingsDialog.vala:249 msgid "Make a Donation" msgstr "Bağış Yap" #: Dialogs/ReleaseDialog.vala:109 Dialogs/SettingsDialog.vala:258 msgid "Suggest Translations" msgstr "Çeviri Öner" #: Dialogs/ReleaseDialog.vala:118 Dialogs/SettingsDialog.vala:267 msgid "Report a Problem" msgstr "Sorun Bildir" #: Dialogs/SettingsDialog.vala:40 msgid "Preferences" msgstr "Tercihler" #: Dialogs/SettingsDialog.vala:50 Dialogs/SettingsDialog.vala:73 #: Dialogs/ShortcutsDialog.vala:45 msgid "General" msgstr "Genel" #: Dialogs/SettingsDialog.vala:51 Dialogs/SettingsDialog.vala:86 msgid "Interface" msgstr "Arayüz" #: Dialogs/SettingsDialog.vala:52 Layouts/HeaderBar.vala:280 msgid "Shapes" msgstr "Şekiller" #: Dialogs/SettingsDialog.vala:53 msgid "About" msgstr "Hakkında" #: Dialogs/SettingsDialog.vala:74 msgid "Auto Reopen Latest File:" msgstr "Başlangıçta Son Dosyayı Aç:" #: Dialogs/SettingsDialog.vala:88 msgid "Use Dark Theme:" msgstr "Karanlık Temayı Kullan:" #: Dialogs/SettingsDialog.vala:92 msgid "Invert Panels Order:" msgstr "Panel Düzenini Tersine Çevir:" #: Dialogs/SettingsDialog.vala:96 msgid "Restart application to apply this change." msgstr "" "Bu değişikliği geçerli hale getirmek için uygulamayı yeniden başlat." #: Dialogs/SettingsDialog.vala:100 msgid "ToolBar Style" msgstr "Araç Çubuğu Biçimi" #: Dialogs/SettingsDialog.vala:102 msgid "Show Button Labels:" msgstr "Buton Metinlerini Göster:" #: Dialogs/SettingsDialog.vala:106 msgid "Use Symbolic Icons:" msgstr "Sembolik Simgeleri Kullan:" #: Dialogs/SettingsDialog.vala:129 msgid "Default Colors" msgstr "Varsayılan Renkler" #: Dialogs/SettingsDialog.vala:131 msgid "Define the default style used when creating a new shape." msgstr "" "Yeni bir simge oluşturulurken kullanılacak varsayılan biçimi tanımla." #: Dialogs/SettingsDialog.vala:136 msgid "Fill Color:" msgstr "Dolgu Rengi:" #: Dialogs/SettingsDialog.vala:157 msgid "Enable Border Style:" msgstr "Kenar Biçimini Etkinleştir:" #: Dialogs/SettingsDialog.vala:160 msgid "Border Color:" msgstr "Kenar Rengi:" #: Dialogs/SettingsDialog.vala:181 msgid "Border Width:" msgstr "Kenar Genişliği:" #: Dialogs/SettingsDialog.vala:209 msgid "The Linux Design Tool" msgstr "Linux'un Tasarım Aracı" #: Dialogs/SettingsDialog.vala:226 msgid "Thanks to our awesome supporters!" msgstr "Harika destekçilerimiz sayesinde!" #: Dialogs/SettingsDialog.vala:231 msgid "View the list of supporters" msgstr "Destekleyenlerin listesini görüntüle" #: Dialogs/ShortcutsDialog.vala:46 msgid "New window:" msgstr "Yeni pencere:" #: Dialogs/ShortcutsDialog.vala:48 msgid "Preferences:" msgstr "Tercihler:" #: Dialogs/ShortcutsDialog.vala:50 msgid "Quit:" msgstr "Çıkış Yap:" #: Dialogs/ShortcutsDialog.vala:52 msgid "Presentation mode:" msgstr "Sunum modu:" #: Dialogs/ShortcutsDialog.vala:55 msgid "File" msgstr "Dosya" #: Dialogs/ShortcutsDialog.vala:56 msgid "Open:" msgstr "Aç:" #: Dialogs/ShortcutsDialog.vala:58 msgid "Save:" msgstr "Kaydet:" #: Dialogs/ShortcutsDialog.vala:60 msgid "Save as:" msgstr "Farklı Kaydet:" #: Dialogs/ShortcutsDialog.vala:64 msgid "Export artboards:" msgstr "Çalışma yüzeylerini dışarı aktar:" #: Dialogs/ShortcutsDialog.vala:66 msgid "Export selection:" msgstr "Seçimi dışarı aktar:" #: Dialogs/ShortcutsDialog.vala:68 msgid "Highlight area to export:" msgstr "Dışa aktarılacak alanı vurgula:" #: Dialogs/ShortcutsDialog.vala:77 msgid "Canvas" msgstr "Tuval" #: Dialogs/ShortcutsDialog.vala:78 msgid "Zoom in:" msgstr "Büyüt:" #: Dialogs/ShortcutsDialog.vala:80 msgid "Zoom out:" msgstr "Küçült:" #: Dialogs/ShortcutsDialog.vala:82 msgid "Zoom reset:" msgstr "Yakınlaştırmayı sıfırla:" #: Dialogs/ShortcutsDialog.vala:85 msgid "Item creation" msgstr "Öğe oluşturma" #: Dialogs/ShortcutsDialog.vala:86 msgid "Artboard:" msgstr "Çalışma yüzeyi:" #: Dialogs/ShortcutsDialog.vala:88 msgid "Rectangle:" msgstr "Dikdörtgen:" #: Dialogs/ShortcutsDialog.vala:90 msgid "Ellipse:" msgstr "Elips:" #: Dialogs/ShortcutsDialog.vala:92 msgid "Text:" msgstr "Metin:" #: Dialogs/ShortcutsDialog.vala:94 msgid "Image:" msgstr "Resim:" #: Dialogs/ShortcutsDialog.vala:97 Layouts/Partials/TransformPanel.vala:174 msgid "Transform" msgstr "Dönüştürme" #: Dialogs/ShortcutsDialog.vala:98 msgid "Raise selection:" msgstr "Seçimi yükselt:" #: Dialogs/ShortcutsDialog.vala:100 msgid "Lower selection:" msgstr "Seçimi alçalt:" #: Dialogs/ShortcutsDialog.vala:102 msgid "Raise selection to top:" msgstr "Seçimi en öne getir:" #: Dialogs/ShortcutsDialog.vala:104 msgid "Lower selection to bottom:" msgstr "Seçimi en arkaya gönder:" #: Dialogs/ShortcutsDialog.vala:106 msgid "Flip horizontally:" msgstr "Yatay olarak çevir:" #: Dialogs/ShortcutsDialog.vala:108 msgid "Flip vertically:" msgstr "Dikey olarak çevir:" #: FileFormat/FileManager.vala:46 msgid "Save Akira file" msgstr "Akira dosyasını kaydet" #: FileFormat/FileManager.vala:48 Layouts/HeaderBar.vala:190 msgid "Save" msgstr "Kaydet" #: FileFormat/FileManager.vala:71 msgid "Akira files" msgstr "Akira dosyaları" #: FileFormat/FileManager.vala:76 msgid "All files" msgstr "Tüm dosyalar" #: FileFormat/FileManager.vala:103 msgid "Open Akira file" msgstr "Akira dosyasını aç" #: FileFormat/FileManager.vala:105 Layouts/HeaderBar.vala:170 msgid "Open" msgstr "Aç" #: Layouts/HeaderBar.vala:69 Lib/Managers/ExportManager.vala:296 msgid "Untitled" msgstr "İsimsiz" #: Layouts/HeaderBar.vala:71 msgid "Menu" msgstr "Menü" #: Layouts/HeaderBar.vala:75 msgid "Insert" msgstr "Ekle" #: Layouts/HeaderBar.vala:82 msgid "Group" msgstr "Gruplandır" #: Layouts/HeaderBar.vala:84 msgid "Ungroup" msgstr "Grubu dağıt" #: Layouts/HeaderBar.vala:87 msgid "Up" msgstr "Yukarı" #: Layouts/HeaderBar.vala:92 msgid "Down" msgstr "Aşağı" #: Layouts/HeaderBar.vala:97 msgid "Top" msgstr "Üst" #: Layouts/HeaderBar.vala:102 msgid "Bottom" msgstr "Alt" #: Layouts/HeaderBar.vala:107 msgid "Settings" msgstr "Ayarlar" #: Layouts/HeaderBar.vala:118 msgid "Difference" msgstr "Fark" #: Layouts/HeaderBar.vala:120 msgid "Exclusion" msgstr "Dışlama" #: Layouts/HeaderBar.vala:122 msgid "Intersect" msgstr "Kesişim" #: Layouts/HeaderBar.vala:124 msgid "Union" msgstr "Birleşim" #: Layouts/HeaderBar.vala:161 msgid "New Window" msgstr "Yeni Pencere" #: Layouts/HeaderBar.vala:182 msgid "Open Recent" msgstr "Son Kullanılan" #: Layouts/HeaderBar.vala:195 msgid "Save As" msgstr "Farklı Kaydet" #: Layouts/HeaderBar.vala:204 msgid "Quit" msgstr "Çıkış Yap" #: Layouts/HeaderBar.vala:237 msgid "Artboard" msgstr "Çalışma Yüzeyi" #: Layouts/HeaderBar.vala:254 msgid "Add Items" msgstr "Öğeleri Ekle" #: Layouts/HeaderBar.vala:262 msgid "Rectangle" msgstr "Dikdörtgen" #: Layouts/HeaderBar.vala:268 msgid "Ellipse" msgstr "Elips" #: Layouts/HeaderBar.vala:286 msgid "Vector" msgstr "Vektör" #: Layouts/HeaderBar.vala:288 msgid "Pencil" msgstr "Kalem" #: Layouts/HeaderBar.vala:291 msgid "Text" msgstr "Metin" #: Layouts/HeaderBar.vala:297 msgid "Image" msgstr "Resim" #: Layouts/HeaderBar.vala:330 msgid "Export Current Selection" msgstr "Mevcut Seçimi Dışarı Aktar" #: Layouts/HeaderBar.vala:336 msgid "Export Artboards" msgstr "Çalışma Yüzeylerini Dışarı Aktar" #: Layouts/HeaderBar.vala:345 msgid "Highlight Area to Export" msgstr "Dışa Aktarılacak Alanı Vurgula" #: Layouts/HeaderBar.vala:391 msgid "Main Menu" msgstr "Ana Menü" #: Layouts/HeaderBar.vala:468 Services/ActionManager.vala:224 #: Services/ActionManager.vala:243 Services/ActionManager.vala:262 #, c-format msgid "Unable to open file at '%s'" msgstr "'%s' konumundaki dosya açılamıyor" #: Layouts/MainCanvas.vala:46 msgid "Button was pressed!" msgstr "Butona basıldı!" #: Layouts/MainCanvas.vala:206 msgid "Export completed!" msgstr "Dışarı aktarma tamamlandı!" #: Layouts/Partials/AlignItemsPanel.vala:48 msgid "Distribute Horizontally" msgstr "Yatay Olarak Dağıt" #: Layouts/Partials/AlignItemsPanel.vala:50 msgid "Distribute Vertically" msgstr "Dikey Olarak Dağıt" #: Layouts/Partials/AlignItemsPanel.vala:52 msgid "Align Left" msgstr "Sola Hizala" #: Layouts/Partials/AlignItemsPanel.vala:53 msgid "Align Center" msgstr "Ortaya Hizala" #: Layouts/Partials/AlignItemsPanel.vala:54 msgid "Align Right" msgstr "Sağa Hizala" #: Layouts/Partials/AlignItemsPanel.vala:56 msgid "Align Top" msgstr "Yukarı Hizala" #: Layouts/Partials/AlignItemsPanel.vala:57 msgid "Align Middle" msgstr "Ortaya Hizala" #: Layouts/Partials/AlignItemsPanel.vala:58 msgid "Align Bottom" msgstr "Aşağı Hizala" #: Layouts/Partials/Artboard.vala:144 Layouts/Partials/Artboard.vala:487 #: Layouts/Partials/Layer.vala:139 Layouts/Partials/Layer.vala:687 msgid "Lock Layer" msgstr "Katmanı Kilitle" #: Layouts/Partials/Artboard.vala:155 Layouts/Partials/Artboard.vala:529 #: Layouts/Partials/Layer.vala:156 Layouts/Partials/Layer.vala:729 msgid "Hide Layer" msgstr "Katmanı Gizle" #: Layouts/Partials/Artboard.vala:487 Layouts/Partials/Layer.vala:687 msgid "Unlock Layer" msgstr "Katmanın Kilidini Aç" #: Layouts/Partials/Artboard.vala:529 Layouts/Partials/Layer.vala:729 msgid "Show Layer" msgstr "Katmanı Göster" #: Layouts/Partials/BorderItem.vala:121 msgid "Choose border color" msgstr "Kenar rengi seç" #: Layouts/Partials/BorderItem.vala:176 Layouts/Partials/FillItem.vala:178 msgid "Pick color" msgstr "Renk seç" #: Layouts/Partials/BorderItem.vala:191 msgid "Remove border" msgstr "Kenarı kaldır" #: Layouts/Partials/BorderItem.vala:275 msgid "Show border" msgstr "Kenarı göster" #: Layouts/Partials/BorderItem.vala:279 msgid "Hide border" msgstr "Kenarı gizle" #: Layouts/Partials/BorderRadiusPanel.vala:86 msgid "Style" msgstr "Biçim" #: Layouts/Partials/BorderRadiusPanel.vala:103 msgid "Border Radius" msgstr "Kenar Yarıçapı" #: Layouts/Partials/BorderRadiusPanel.vala:137 msgid "Border radius options" msgstr "Kenar yarıçapı seçenekleri" #: Layouts/Partials/BorderRadiusPanel.vala:199 msgid "Autoscale Corners" msgstr "Köşeleri Otomatik Ölçeklendir" #: Layouts/Partials/BorderRadiusPanel.vala:208 msgid "Uniform Corners" msgstr "Tüm Köşeler Aynı Biçimde" #: Layouts/Partials/BordersPanel.vala:53 msgid "Borders" msgstr "Kenarlar" #: Layouts/Partials/BordersPanel.vala:64 msgid "Add border" msgstr "Kenar ekle" #: Layouts/Partials/FillItem.vala:114 msgid "Choose fill color" msgstr "Dolgu rengi seç" #: Layouts/Partials/FillItem.vala:193 msgid "Remove fill color" msgstr "Dolgu rengini kaldır" #: Layouts/Partials/FillItem.vala:277 msgid "Show fill color" msgstr "Dolgu rengini göster" #: Layouts/Partials/FillItem.vala:281 msgid "Hide fill color" msgstr "Dolgu rengini gizle" #: Layouts/Partials/FillsPanel.vala:54 msgid "Fills" msgstr "Dolgular" #: Layouts/Partials/FillsPanel.vala:65 msgid "Add fill color" msgstr "Dolgu rengi ekle" #: Layouts/Partials/TransformPanel.vala:96 msgid "X" msgstr "X" #: Layouts/Partials/TransformPanel.vala:96 msgid "Horizontal position" msgstr "Yatay konum" #: Layouts/Partials/TransformPanel.vala:98 msgid "Y" msgstr "Y" #: Layouts/Partials/TransformPanel.vala:98 msgid "Vertical position" msgstr "Dikey konum" #: Layouts/Partials/TransformPanel.vala:100 msgid "W" msgstr "G" #: Layouts/Partials/TransformPanel.vala:100 msgid "Width" msgstr "Genişlik" #: Layouts/Partials/TransformPanel.vala:102 msgid "H" msgstr "Y" #: Layouts/Partials/TransformPanel.vala:102 msgid "Height" msgstr "Yükseklik" #: Layouts/Partials/TransformPanel.vala:107 msgid "Lock Ratio" msgstr "Oranı Sabitle" #: Layouts/Partials/TransformPanel.vala:114 msgid "R" msgstr "D" #: Layouts/Partials/TransformPanel.vala:114 msgid "Rotation degrees" msgstr "Dönme derecesi" #: Layouts/Partials/TransformPanel.vala:126 msgid "Flip Horizontally" msgstr "Yatay Olarak Çevir" #: Layouts/Partials/TransformPanel.vala:137 msgid "Flip Vertically" msgstr "Dikey Olarak Çevir" #: Layouts/Partials/TransformPanel.vala:165 msgid "Position" msgstr "Konum" #: Layouts/Partials/TransformPanel.vala:169 msgid "Size" msgstr "Boyut" #: Layouts/Partials/TransformPanel.vala:178 msgid "Opacity" msgstr "Saydamlık" #: Layouts/RightSideBar.vala:111 msgid "Search Layer" msgstr "Katman Ara" #: Lib/Managers/ExportManager.vala:192 Lib/Managers/ExportManager.vala:219 msgid "Generating preview, please wait…" msgstr "Önizleme oluşturuluyor, lütfen bekleyin…" #: Lib/Managers/ExportManager.vala:313 #, c-format msgid "Untitled %i" msgstr "İsimsiz %i" #: Lib/Managers/ExportManager.vala:484 msgid "Exporting images…" msgstr "Resimler dışarı aktarılıyor…" #: Partials/ExportWidget.vala:117 #, c-format msgid "%i × %i px · %s" msgstr "%i × %i px · %s" #: Partials/ExportWidget.vala:124 msgid "Fetching image size…" msgstr "Resim boyutu getiriliyor…" #: Partials/ZoomButton.vala:49 msgid "Zoom Out" msgstr "Küçült" #: Partials/ZoomButton.vala:55 msgid "Reset Zoom" msgstr "Yakınlaştırmayı Sıfırla" #: Partials/ZoomButton.vala:62 msgid "Zoom In" msgstr "Büyüt" #: Partials/ZoomButton.vala:68 msgid "Zoom" msgstr "Yakınlaştırma" #: Services/ActionManager.vala:217 msgid "No recently opened file available!" msgstr "Yakın zamanda açılmış bir dosya yok!" #: Services/ActionManager.vala:236 msgid "No second most recently opened file available!" msgstr "Yakın zamanda açılmış ikinci bir dosya yok!" #: Services/ActionManager.vala:255 msgid "No third most recently opened file available!" msgstr "Yakın zamanda açılmış üçüncü bir dosya yok!" #: Services/ActionManager.vala:293 msgid "Nothing selected to export!" msgstr "Dışarı aktarılacak bir şey seçilmedi!" #: Services/ActionManager.vala:302 msgid "Export of Artboards currently unavailable…sorry 😑️" msgstr "Çalışma yüzeylerini dışarı aktarmak henüz mümkün değil…üzgünüm 😑️" #: Services/ActionManager.vala:373 msgid "Choose image file" msgstr "Resim dosyası seç" #: Services/ActionManager.vala:373 msgid "Select" msgstr "Seç" #: Services/ActionManager.vala:373 msgid "Close" msgstr "Kapat" #: Services/ActionManager.vala:442 #, c-format msgid "Error! .%s files are not supported!" msgstr "Hata! .%s dosyaları desteklenmemektedir!" #: Window.vala:121 msgid "Are you sure you want to quit?" msgstr "Çıkış yapmak istediğinizden emin misiniz?" #: Window.vala:122 msgid "All unsaved data will be lost and impossible to recover." msgstr "" "Kaydedilmemiş tüm veriler kurtarması mümkün olmayacak şekilde " "kaybolacaktır." #: Window.vala:124 msgid "Quit without saving!" msgstr "Kaydetmeden çık!" #: Window.vala:125 msgid "Save file" msgstr "Dosyayı kaydet" Akira-0.0.16/po/ts.po000066400000000000000000000001251410625726100142330ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/tt.po000066400000000000000000000001251410625726100142340ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/tw.po000066400000000000000000000001251410625726100142370ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/ty.po000066400000000000000000000001251410625726100142410ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/ug.po000066400000000000000000000001251410625726100142200ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/uk.po000066400000000000000000000003141410625726100142240ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" Akira-0.0.16/po/ur.po000066400000000000000000000001251410625726100142330ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/uz.po000066400000000000000000000001251410625726100142430ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/ve.po000066400000000000000000000001251410625726100142170ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/vi.po000066400000000000000000000002121410625726100142200ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Plural-Forms: nplurals=2; plural=n == 1 ? 0 : 1;\n" Akira-0.0.16/po/vo.po000066400000000000000000000001251410625726100142310ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/wa.po000066400000000000000000000001251410625726100142140ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/wo.po000066400000000000000000000001251410625726100142320ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/xh.po000066400000000000000000000001251410625726100142240ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/yi.po000066400000000000000000000001251410625726100142260ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/yo.po000066400000000000000000000001251410625726100142340ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/za.po000066400000000000000000000001251410625726100142170ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/zh.po000066400000000000000000000001251410625726100142260ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/zh_CN.po000066400000000000000000000344271410625726100146220ustar00rootroot00000000000000msgid "" msgstr "" "Project-Id-Version: Akira 0.0.11 alpha\n" "POT-Creation-Date: 2020-08-05 20:25+0800\n" "PO-Revision-Date: \n" "Last-Translator: WhiredPlanck \n" "Language-Team: \n" "Language: zh_CN\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Poedit 2.3.1\n" "X-Poedit-Basepath: ../src\n" "Plural-Forms: nplurals=1; plural=0;\n" "X-Poedit-SearchPath-0: .\n" #: Dialogs/ExportDialog.vala:151 msgid "Export to:" msgstr "导出到:" #: Dialogs/ExportDialog.vala:157 msgid "Select Folder" msgstr "选择文件夹" #: Dialogs/ExportDialog.vala:166 msgid "Format:" msgstr "格式:" #: Dialogs/ExportDialog.vala:180 msgid "Quality:" msgstr "质量:" #: Dialogs/ExportDialog.vala:192 msgid "Compression:" msgstr "压缩等级:" #: Dialogs/ExportDialog.vala:206 msgid "Transparency:" msgstr "透明度:" #: Dialogs/ExportDialog.vala:219 msgid "Scale:" msgstr "比例:" #: Dialogs/ExportDialog.vala:243 FileFormat/FileManager.vala:49 #: FileFormat/FileManager.vala:105 msgid "Cancel" msgstr "取消" #: Dialogs/ExportDialog.vala:250 Dialogs/ShortcutsDialog.vala:63 #: Layouts/HeaderBar.vala:113 msgid "Export" msgstr "导出" #: Dialogs/ReleaseDialog.vala:47 Dialogs/SettingsDialog.vala:217 msgid "" "WARNING!\n" "Akira is still under development and not ready for production. Missing " "features, random bugs, and black holes opening in your kitchen are to be " "expected." msgstr "" "** 警告!**\n" "Akira 仍在开发当中,尚未能正式成为生产工具。请准备好忍受功能上的缺失、随" "机出现的 Bug,以及吞噬劳作成果的“黑洞”。" #: Dialogs/ReleaseDialog.vala:100 Dialogs/SettingsDialog.vala:249 msgid "Make a Donation" msgstr "捐献我们" #: Dialogs/ReleaseDialog.vala:109 Dialogs/SettingsDialog.vala:258 msgid "Suggest Translations" msgstr "提供翻译建议" #: Dialogs/ReleaseDialog.vala:118 Dialogs/SettingsDialog.vala:267 msgid "Report a Problem" msgstr "向我们报告问题" #: Dialogs/SettingsDialog.vala:40 msgid "Preferences" msgstr "偏好设置" #: Dialogs/SettingsDialog.vala:50 Dialogs/SettingsDialog.vala:73 #: Dialogs/ShortcutsDialog.vala:45 msgid "General" msgstr "常规" #: Dialogs/SettingsDialog.vala:51 Dialogs/SettingsDialog.vala:86 msgid "Interface" msgstr "界面" #: Dialogs/SettingsDialog.vala:52 Layouts/HeaderBar.vala:281 msgid "Shapes" msgstr "形状" #: Dialogs/SettingsDialog.vala:53 msgid "About" msgstr "关于" #: Dialogs/SettingsDialog.vala:74 msgid "Auto Reopen Latest File:" msgstr "自动重新打开最新(近)文件:" #: Dialogs/SettingsDialog.vala:88 msgid "Use Dark Theme:" msgstr "使用暗色主题:" #: Dialogs/SettingsDialog.vala:92 msgid "Invert Panels Order:" msgstr "反转面板顺序:" #: Dialogs/SettingsDialog.vala:96 msgid "Restart application to apply this change." msgstr "重启应用程序以应用更改。" #: Dialogs/SettingsDialog.vala:100 msgid "ToolBar Style" msgstr "工具栏样式" #: Dialogs/SettingsDialog.vala:102 msgid "Show Button Labels:" msgstr "显示按钮标签:" #: Dialogs/SettingsDialog.vala:106 msgid "Use Symbolic Icons:" msgstr "使用符号图标:" #: Dialogs/SettingsDialog.vala:129 msgid "Default Colors" msgstr "默认颜色" #: Dialogs/SettingsDialog.vala:131 msgid "Define the default style used when creating a new shape." msgstr "定义创建新形状时使用的默认样式。" #: Dialogs/SettingsDialog.vala:136 msgid "Fill Color:" msgstr "填充颜色:" #: Dialogs/SettingsDialog.vala:157 msgid "Enable Border Style:" msgstr "启用边框样式:" #: Dialogs/SettingsDialog.vala:160 msgid "Border Color:" msgstr "边框颜色:" #: Dialogs/SettingsDialog.vala:181 msgid "Border Width:" msgstr "边框宽度:" #: Dialogs/SettingsDialog.vala:209 msgid "The Linux Design Tool" msgstr "Linux 设计工具" #: Dialogs/SettingsDialog.vala:226 msgid "Thanks to our awesome supporters!" msgstr "感谢我们出色的支持者!" #: Dialogs/SettingsDialog.vala:231 msgid "View the list of supporters" msgstr "查看支持者名单" #: Dialogs/ShortcutsDialog.vala:46 msgid "New window:" msgstr "新建窗口:" #: Dialogs/ShortcutsDialog.vala:48 msgid "Preferences:" msgstr "偏好设置:" #: Dialogs/ShortcutsDialog.vala:50 msgid "Quit:" msgstr "退出:" #: Dialogs/ShortcutsDialog.vala:52 msgid "Presentation mode:" msgstr "演示模式:" #: Dialogs/ShortcutsDialog.vala:55 msgid "File" msgstr "文件" #: Dialogs/ShortcutsDialog.vala:56 msgid "Open:" msgstr "打开:" #: Dialogs/ShortcutsDialog.vala:58 msgid "Save:" msgstr "保存:" #: Dialogs/ShortcutsDialog.vala:60 msgid "Save as:" msgstr "另存为:" #: Dialogs/ShortcutsDialog.vala:64 msgid "Export artboards:" msgstr "导出画板:" #: Dialogs/ShortcutsDialog.vala:66 msgid "Export selection:" msgstr "导出所选:" #: Dialogs/ShortcutsDialog.vala:68 msgid "Highlight area to export:" msgstr "高亮要导出的区域:" #: Dialogs/ShortcutsDialog.vala:77 msgid "Canvas" msgstr "帆布" #: Dialogs/ShortcutsDialog.vala:78 msgid "Zoom in:" msgstr "放大:" #: Dialogs/ShortcutsDialog.vala:80 msgid "Zoom out:" msgstr "缩小:" #: Dialogs/ShortcutsDialog.vala:82 msgid "Zoom reset:" msgstr "重置缩放:" #: Dialogs/ShortcutsDialog.vala:85 msgid "Item creation" msgstr "项目创建" #: Dialogs/ShortcutsDialog.vala:86 msgid "Artboard:" msgstr "画板:" #: Dialogs/ShortcutsDialog.vala:88 msgid "Rectangle:" msgstr "矩形:" #: Dialogs/ShortcutsDialog.vala:90 msgid "Ellipse:" msgstr "椭圆:" #: Dialogs/ShortcutsDialog.vala:92 msgid "Text:" msgstr "文本:" #: Dialogs/ShortcutsDialog.vala:94 msgid "Image:" msgstr "图像:" #: Dialogs/ShortcutsDialog.vala:97 Layouts/Partials/TransformPanel.vala:174 msgid "Transform" msgstr "变换" #: Dialogs/ShortcutsDialog.vala:98 msgid "Raise selection:" msgstr "上移所选:" #: Dialogs/ShortcutsDialog.vala:100 msgid "Lower selection:" msgstr "下移所选:" #: Dialogs/ShortcutsDialog.vala:102 msgid "Raise selection to top:" msgstr "将所选上移到顶层:" #: Dialogs/ShortcutsDialog.vala:104 msgid "Lower selection to bottom:" msgstr "将所选下移到底层:" #: Dialogs/ShortcutsDialog.vala:106 msgid "Flip horizontally:" msgstr "水平翻转:" #: Dialogs/ShortcutsDialog.vala:108 msgid "Flip vertically:" msgstr "垂直翻转:" #: FileFormat/FileManager.vala:46 msgid "Save Akira file" msgstr "保存 Akira 文件" #: FileFormat/FileManager.vala:48 Layouts/HeaderBar.vala:191 msgid "Save" msgstr "保存" #: FileFormat/FileManager.vala:71 msgid "Akira files" msgstr "Akira 文件" #: FileFormat/FileManager.vala:76 msgid "All files" msgstr "所有文件" #: FileFormat/FileManager.vala:103 msgid "Open Akira file" msgstr "打开 Akira 文件" #: FileFormat/FileManager.vala:105 Layouts/HeaderBar.vala:171 msgid "Open" msgstr "打开" #: Layouts/HeaderBar.vala:69 Lib/Managers/ExportManager.vala:296 msgid "Untitled" msgstr "无标题" #: Layouts/HeaderBar.vala:71 msgid "Menu" msgstr "菜单" #: Layouts/HeaderBar.vala:75 msgid "Insert" msgstr "插入" #: Layouts/HeaderBar.vala:82 msgid "Group" msgstr "合并" #: Layouts/HeaderBar.vala:84 msgid "Ungroup" msgstr "取消合并" #: Layouts/HeaderBar.vala:87 msgid "Up" msgstr "上移一层" #: Layouts/HeaderBar.vala:92 msgid "Down" msgstr "下移一层" #: Layouts/HeaderBar.vala:97 msgid "Top" msgstr "置于顶层" #: Layouts/HeaderBar.vala:102 msgid "Bottom" msgstr "置于底层" #: Layouts/HeaderBar.vala:108 msgid "Settings" msgstr "设置" #: Layouts/HeaderBar.vala:119 msgid "Difference" msgstr "差异" #: Layouts/HeaderBar.vala:121 msgid "Exclusion" msgstr "排除" #: Layouts/HeaderBar.vala:123 msgid "Intersect" msgstr "交集" #: Layouts/HeaderBar.vala:125 msgid "Union" msgstr "并集" #: Layouts/HeaderBar.vala:162 msgid "New Window" msgstr "新窗口" #: Layouts/HeaderBar.vala:183 msgid "Open Recent" msgstr "打开最近文件" #: Layouts/HeaderBar.vala:196 msgid "Save As" msgstr "另存为" #: Layouts/HeaderBar.vala:205 msgid "Quit" msgstr "退出" #: Layouts/HeaderBar.vala:238 msgid "Artboard" msgstr "画板" #: Layouts/HeaderBar.vala:255 msgid "Add Items" msgstr "添加项目" #: Layouts/HeaderBar.vala:263 msgid "Rectangle" msgstr "矩形" #: Layouts/HeaderBar.vala:269 msgid "Ellipse" msgstr "椭圆" #: Layouts/HeaderBar.vala:287 msgid "Vector" msgstr "矢量" #: Layouts/HeaderBar.vala:289 msgid "Pencil" msgstr "铅笔" #: Layouts/HeaderBar.vala:292 msgid "Text" msgstr "文本" #: Layouts/HeaderBar.vala:298 msgid "Image" msgstr "图像" #: Layouts/HeaderBar.vala:331 msgid "Export Current Selection" msgstr "导出当前所选" #: Layouts/HeaderBar.vala:337 msgid "Export Artboards" msgstr "导出画板" #: Layouts/HeaderBar.vala:346 msgid "Highlight Area to Export" msgstr "截取要导出的区域" #: Layouts/HeaderBar.vala:394 msgid "Main Menu" msgstr "主菜单" #: Layouts/HeaderBar.vala:471 Services/ActionManager.vala:215 #: Services/ActionManager.vala:234 Services/ActionManager.vala:253 #, c-format msgid "Unable to open file at '%s'" msgstr "无法在 '%s' 打开文件" #: Layouts/MainCanvas.vala:52 #, fuzzy msgid "Button was pressed!" msgstr "按钮被按下!" #: Layouts/MainCanvas.vala:160 msgid "Export completed!" msgstr "导出完毕!" #: Layouts/Partials/AlignItemsPanel.vala:48 msgid "Distribute Horizontally" msgstr "水平分布" #: Layouts/Partials/AlignItemsPanel.vala:50 msgid "Distribute Vertically" msgstr "垂直分布" #: Layouts/Partials/AlignItemsPanel.vala:52 msgid "Align Left" msgstr "左对齐" #: Layouts/Partials/AlignItemsPanel.vala:53 msgid "Align Center" msgstr "居中对齐" #: Layouts/Partials/AlignItemsPanel.vala:54 msgid "Align Right" msgstr "右对齐" #: Layouts/Partials/AlignItemsPanel.vala:56 msgid "Align Top" msgstr "顶端对齐" #: Layouts/Partials/AlignItemsPanel.vala:57 msgid "Align Middle" msgstr "中间对齐" #: Layouts/Partials/AlignItemsPanel.vala:58 msgid "Align Bottom" msgstr "底端对齐" #: Layouts/Partials/Artboard.vala:144 Layouts/Partials/Layer.vala:139 #: Layouts/Partials/Layer.vala:686 msgid "Lock Layer" msgstr "锁定图层" #: Layouts/Partials/Artboard.vala:155 Layouts/Partials/Layer.vala:156 #: Layouts/Partials/Layer.vala:727 msgid "Hide Layer" msgstr "隐藏图层" #: Layouts/Partials/BorderRadiusPanel.vala:86 msgid "Style" msgstr "样式" #: Layouts/Partials/BorderRadiusPanel.vala:103 msgid "Border Radius" msgstr "边框半径" #: Layouts/Partials/BorderRadiusPanel.vala:198 #, fuzzy msgid "Autoscale Corners" msgstr "自动最佳化圆角比例" #: Layouts/Partials/BorderRadiusPanel.vala:207 msgid "Uniform Corners" msgstr "统一圆角半径" #: Layouts/Partials/BordersPanel.vala:53 msgid "Borders" msgstr "边框" #: Layouts/Partials/FillsPanel.vala:54 msgid "Fills" msgstr "填充" #: Layouts/Partials/Layer.vala:686 msgid "Unlock Layer" msgstr "解锁图层" #: Layouts/Partials/Layer.vala:727 msgid "Show Layer" msgstr "显示图层" #: Layouts/Partials/TransformPanel.vala:96 msgid "X" msgstr "X" #: Layouts/Partials/TransformPanel.vala:96 msgid "Horizontal position" msgstr "水平位置" #: Layouts/Partials/TransformPanel.vala:98 msgid "Y" msgstr "Y" #: Layouts/Partials/TransformPanel.vala:98 msgid "Vertical position" msgstr "垂直位置" #: Layouts/Partials/TransformPanel.vala:100 msgid "W" msgstr "W" #: Layouts/Partials/TransformPanel.vala:100 msgid "Width" msgstr "宽度" #: Layouts/Partials/TransformPanel.vala:102 msgid "H" msgstr "H" #: Layouts/Partials/TransformPanel.vala:102 msgid "Height" msgstr "高度" #: Layouts/Partials/TransformPanel.vala:107 msgid "Lock Ratio" msgstr "锁定高宽比" #: Layouts/Partials/TransformPanel.vala:114 msgid "R" msgstr "R" #: Layouts/Partials/TransformPanel.vala:114 msgid "Rotation degrees" msgstr "旋转角度" #: Layouts/Partials/TransformPanel.vala:126 msgid "Flip Horizontally" msgstr "水平翻转" #: Layouts/Partials/TransformPanel.vala:137 msgid "Flip Vertically" msgstr "垂直翻转" #: Layouts/Partials/TransformPanel.vala:165 msgid "Position" msgstr "位置" #: Layouts/Partials/TransformPanel.vala:169 msgid "Size" msgstr "大小" #: Layouts/Partials/TransformPanel.vala:178 msgid "Opacity" msgstr "不透明度" #: Layouts/RightSideBar.vala:111 msgid "Search Layer" msgstr "搜索图层" #: Lib/Managers/ExportManager.vala:192 Lib/Managers/ExportManager.vala:219 msgid "Generating preview, please wait…" msgstr "生成预览中,请稍候…" #: Lib/Managers/ExportManager.vala:313 #, c-format msgid "Untitled %i" msgstr "无标题 %i" #: Lib/Managers/ExportManager.vala:484 msgid "Exporting images…" msgstr "导出图像…" #: Partials/ExportWidget.vala:117 #, c-format msgid "%i × %i px · %s" msgstr "%i × %i px · %s" #: Partials/ExportWidget.vala:124 msgid "Fetching image size…" msgstr "撷取图片大小…" #: Partials/ZoomButton.vala:49 msgid "Zoom Out" msgstr "缩小" #: Partials/ZoomButton.vala:55 msgid "Reset Zoom" msgstr "重置缩放" #: Partials/ZoomButton.vala:62 msgid "Zoom In" msgstr "放大" #: Partials/ZoomButton.vala:68 msgid "Zoom" msgstr "缩放" #: Services/ActionManager.vala:208 msgid "No recently opened file available!" msgstr "没有最近打开的文件!" #: Services/ActionManager.vala:227 msgid "No second most recently opened file available!" msgstr "没有第二个最近打开的文件!" #: Services/ActionManager.vala:246 msgid "No third most recently opened file available!" msgstr "没有第三个最近打开的文件!" #: Services/ActionManager.vala:284 msgid "Nothing selected to export!" msgstr "没有选择要导出的内容!" #: Services/ActionManager.vala:293 msgid "Export of Artboards currently unavailable…sorry 😑️" msgstr "目前无法导出画板…对不起 😑️" #: Services/ActionManager.vala:360 msgid "Choose image file" msgstr "选择图像文件" #: Services/ActionManager.vala:360 msgid "Select" msgstr "选择" #: Services/ActionManager.vala:360 msgid "Close" msgstr "关闭" #: Services/ActionManager.vala:429 #, c-format msgid "Error! .%s files are not supported!" msgstr "错误!不支持 .%s 文件!" #: Window.vala:119 msgid "Are you sure you want to quit?" msgstr "确定要退出吗?" #: Window.vala:120 msgid "All unsaved data will be lost and impossible to recover." msgstr "所有未保存的数据将丢失,并且无法恢复。" #: Window.vala:122 msgid "Quit without saving!" msgstr "不保存并退出!" #: Window.vala:123 msgid "Save file" msgstr "保存文件" Akira-0.0.16/po/zh_HK.po000066400000000000000000000001251410625726100146100ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/zh_TW.po000066400000000000000000000001251410625726100146400ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/po/zu.po000066400000000000000000000001251410625726100142430ustar00rootroot00000000000000msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" Akira-0.0.16/src/000077500000000000000000000000001410625726100134205ustar00rootroot00000000000000Akira-0.0.16/src/Application.vala000066400000000000000000000115001410625726100165250ustar00rootroot00000000000000/* * Copyright (c) 2019-2020 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Alessandro "Alecaddd" Castellani */ namespace Akira { public Akira.Services.Settings settings; } public class Akira.Application : Gtk.Application { public GLib.List windows; construct { flags |= ApplicationFlags.HANDLES_OPEN; settings = new Akira.Services.Settings (); windows = new GLib.List (); application_id = Constants.APP_ID; } public override void open (File[] files, string hint) { // Loop through all selected files. foreach (var file in files) { if (is_file_opened (file)) { // Present active window with currently opened file. // We don't allow opening the same file on multiple windows. var window = get_window_from_file (file); window.show_app (); continue; } // If the current window is empty, load the file in this one. var current_window = active_window as Akira.Window; if (current_window != null && current_window.akira_file == null && !current_window.edited) { current_window.open_file (file); current_window.event_bus.file_saved (file.get_basename ()); continue; } // The application was requested to open some files. Be sure to // initialize the theme in case it wasn't already running. init_theme (); // Open a new window. var window = new Akira.Window (this); this.add_window (window); window.open_file (file); window.show_app (); window.event_bus.file_saved (file.get_basename ()); } } public Akira.Window? get_window_from_file (File file) { foreach (Akira.Window window in windows) { if (window.akira_file != null && window.akira_file.opened_file.get_path () == file.get_path ()) { return window; } } return null; } public bool is_file_opened (File file) { foreach (Akira.Window window in windows) { if (window.akira_file != null && window.akira_file.opened_file.get_path () == file.get_path ()) { return true; } } return false; } public void new_window () { new Akira.Window (this).present (); } public override void window_added (Gtk.Window window) { windows.append (window as Akira.Window); base.window_added (window); } public override void window_removed (Gtk.Window window) { windows.remove (window as Akira.Window); base.window_removed (window); } /** * Update the list of recently opened files in all the currently opened Windows. */ public void update_recent_files_list () { foreach (Akira.Window window in windows) { window.event_bus.update_recent_files_list (); } } protected override void activate () { init_theme (); var window = new Akira.Window (this); this.add_window (window); if (settings.version != Constants.VERSION) { var dialog = new Akira.Dialogs.ReleaseDialog (window); dialog.show_all (); dialog.present (); // Update the settings so we don't show the same dialog again. settings.version = Constants.VERSION; } // Load the most recently opened/saved file. if (settings.open_quick) { window.action_manager.action_load_first (); } } private void init_theme () { // Interrupt if we have at least one existing window, meaning the theme // was previously initialized. if (windows.length () > 0) { return; } Gtk.Settings.get_default ().set_property ("gtk-icon-theme-name", "elementary"); Gtk.Settings.get_default ().set_property ("gtk-theme-name", "io.elementary.stylesheet.blueberry"); weak Gtk.IconTheme default_theme = Gtk.IconTheme.get_default (); default_theme.add_resource_path ("/com/github/akiraux/akira"); } } Akira-0.0.16/src/Dialogs/000077500000000000000000000000001410625726100150025ustar00rootroot00000000000000Akira-0.0.16/src/Dialogs/ExportDialog.vala000066400000000000000000000262521410625726100202570ustar00rootroot00000000000000/* * Copyright (c) 2020 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Alessandro "Alecaddd" Castellani */ public class Akira.Dialogs.ExportDialog : Gtk.Dialog { public weak Akira.Window window { get; construct; } public weak Akira.Lib.Managers.ExportManager manager { get; construct; } public weak Akira.Lib.Managers.ExportManager.Type export_type { get; construct; } public GLib.ListStore list_store; private Gtk.FlowBox export_grid; private Gtk.Grid sidebar; public Gtk.FileChooserButton folder_button; public Gtk.Adjustment quality_adj; public Gtk.Scale quality_scale; public Gtk.Adjustment compression_adj; public Gtk.Scale compression_scale; public Gtk.ComboBoxText file_format; public Gtk.Label jpg_title; public Gtk.Label png_title; public Gtk.Label alpha_title; public Gtk.Switch alpha_switch; private Gtk.Overlay main_overlay; private Granite.Widgets.OverlayBar overlaybar; public ExportDialog ( Akira.Window window, Akira.Lib.Managers.ExportManager manager, Akira.Lib.Managers.ExportManager.Type export_type ) { Object ( window: window, manager: manager, export_type: export_type, border_width: 0, deletable: true, resizable: true, modal: true ); } construct { window.event_bus.export_preview.connect (on_export_preview); window.event_bus.preview_completed.connect (on_preview_completed); transient_for = window; use_header_bar = 1; default_width = settings.export_width; default_height = settings.export_height; var sidebar_header = new Gtk.Grid (); sidebar_header.vexpand = true; sidebar_header.get_style_context ().add_class ("sidebar-export-header"); sidebar_header.height_request = 30; var main_header = new Gtk.Grid (); main_header.vexpand = true; var pane_header = new Gtk.Paned (Gtk.Orientation.HORIZONTAL); pane_header.pack1 (sidebar_header, false, false); pane_header.pack2 (main_header, false, false); pane_header.get_style_context ().add_class ("export-titlebar"); // Hack to remove the default header area and replace it with // a custom widget. var header_area = get_header_bar (); header_area.destroy (); set_titlebar (pane_header); // Another hack to remove the bottom action area. var button = add_button ("OK", 3); var button_area = button.get_parent (); button_area.destroy (); sidebar = new Gtk.Grid (); sidebar.get_style_context ().add_class ("sidebar-export"); build_export_sidebar (); main_overlay = new Gtk.Overlay (); overlaybar = new Granite.Widgets.OverlayBar (main_overlay); overlaybar.active = true; var main = new Gtk.Grid (); main.expand = true; list_store = new GLib.ListStore (typeof (Akira.Models.ExportModel)); export_grid = new Gtk.FlowBox (); export_grid.activate_on_single_click = false; export_grid.max_children_per_line = 1; export_grid.selection_mode = Gtk.SelectionMode.NONE; export_grid.get_style_context ().add_class ("export-panel"); export_grid.bind_model (list_store, model => { return new Widgets.ExportWidget (model as Akira.Models.ExportModel); }); var scrolled = new Gtk.ScrolledWindow (null, null); scrolled.expand = true; scrolled.get_style_context ().add_class (Gtk.STYLE_CLASS_VIEW); scrolled.add (export_grid); main.add (scrolled); main_overlay.add (main); var pane = new Gtk.Paned (Gtk.Orientation.HORIZONTAL); pane.pack1 (sidebar, false, false); pane.pack2 (main_overlay, true, false); var content_area = get_content_area (); content_area.border_width = 0; content_area.add (pane); pane.bind_property ("position", pane_header, "position"); pane_header.notify["position"].connect (() => { pane_header.position = pane.position; }); settings.bind ("export-paned", pane, "position", SettingsBindFlags.DEFAULT); settings.bind ("export-format", file_format, "active_id", SettingsBindFlags.DEFAULT); } private void build_export_sidebar () { var grid = new Gtk.Grid (); grid.expand = true; grid.column_spacing = 12; grid.margin_start = grid.margin_end = grid.margin_bottom = 12; grid.row_spacing = 6; // Folder location. grid.attach (section_title (_("Export to:")), 0, 0, 1, 1); if (settings.export_folder == "") { settings.export_folder = Environment.get_user_special_dir (UserDirectory.PICTURES); } folder_button = new Gtk.FileChooserButton (_("Select Folder"), Gtk.FileChooserAction.SELECT_FOLDER); folder_button.set_current_folder (settings.export_folder); folder_button.hexpand = true; grid.attach (folder_button, 1, 0, 1, 1); folder_button.selection_changed.connect (() => { settings.export_folder = folder_button.get_filename (); }); // File format. var format_title = section_title (_("Format:")); grid.attach (format_title, 0, 2, 1, 1); file_format = new Gtk.ComboBoxText (); file_format.append ("png", "PNG"); file_format.append ("jpg", "JPG"); file_format.changed.connect (update_format_ui); grid.attach (file_format, 1, 2, 1, 1); settings.changed["export-format"].connect (() => { manager.regenerate_pixbuf (export_type); }); // Quality spinbutton. jpg_title = section_title (_("Quality:")); grid.attach (jpg_title, 0, 3, 1, 1); quality_adj = new Gtk.Adjustment (100.0, 0, 100.0, 0, 0, 0); quality_scale = new Gtk.Scale (Gtk.Orientation.HORIZONTAL, quality_adj); quality_scale.hexpand = true; quality_scale.draw_value = true; quality_scale.digits = 0; grid.attach (quality_scale, 1, 3, 1, 1); settings.bind ("export-quality", quality_adj, "value", SettingsBindFlags.DEFAULT); // Compression spinbutton. png_title = section_title (_("Compression:")); grid.attach (png_title, 0, 4, 1, 1); compression_adj = new Gtk.Adjustment (0.0, 0, 9.0, 1, 0, 0); compression_scale = new Gtk.Scale (Gtk.Orientation.HORIZONTAL, compression_adj); compression_scale.hexpand = true; compression_scale.draw_value = true; compression_scale.digits = 0; for (int i = 1; i <= 9; i++) { compression_scale.add_mark (i, Gtk.PositionType.BOTTOM, null); } grid.attach (compression_scale, 1, 4, 1, 1); settings.bind ("export-compression", compression_adj, "value", SettingsBindFlags.DEFAULT); alpha_title = section_title (_("Transparency:")); grid.attach (alpha_title, 0, 5, 1, 1); alpha_switch = new Gtk.Switch (); alpha_switch.valign = Gtk.Align.CENTER; alpha_switch.halign = Gtk.Align.START; grid.attach (alpha_switch, 1, 5, 1, 1); settings.bind ("export-alpha", alpha_switch, "active", SettingsBindFlags.DEFAULT); settings.changed["export-alpha"].connect (() => { manager.regenerate_pixbuf (export_type); }); // Resolution. var size_title = section_title (_("Scale:")); grid.attach (size_title, 0, 6, 1, 1); var scale_button = new Granite.Widgets.ModeButton (); scale_button.halign = Gtk.Align.FILL; scale_button.append_text ("0.5×"); scale_button.append_text ("1×"); scale_button.append_text ("2×"); scale_button.append_text ("4×"); scale_button.set_active (settings.export_scale); settings.bind ("export-scale", scale_button, "selected", SettingsBindFlags.DEFAULT); grid.attach (scale_button, 1, 6, 1, 1); settings.changed["export-scale"].connect (() => { manager.regenerate_pixbuf (export_type); }); // Buttons. var action_area = new Gtk.Grid (); action_area.column_spacing = 6; action_area.halign = Gtk.Align.END; action_area.valign = Gtk.Align.END; action_area.vexpand = true; grid.attach (action_area, 0, 7, 2, 1); var cancel_button = new Gtk.Button.with_label (_("Cancel")); cancel_button.halign = Gtk.Align.START; action_area.add (cancel_button); cancel_button.clicked.connect (() => { close (); }); var export_button = new Gtk.Button.with_label (_("Export")); export_button.get_style_context ().add_class (Gtk.STYLE_CLASS_SUGGESTED_ACTION); export_button.halign = Gtk.Align.END; action_area.add (export_button); export_button.clicked.connect (() => { manager.export_images.begin (); close (); }); sidebar.add (grid); } public void update_format_ui () { jpg_title.visible = (file_format.active_id == "jpg"); quality_scale.visible = (file_format.active_id == "jpg"); png_title.visible = (file_format.active_id == "png"); compression_scale.visible = (file_format.active_id == "png"); alpha_title.visible = (file_format.active_id == "png"); alpha_switch.visible = (file_format.active_id == "png"); } public async void generate_export_preview () { if (list_store.get_n_items () > 0) { var array = manager.pixbufs.values.to_array (); for (int i = 0; i < list_store.get_n_items () ; i++) { var model = (Akira.Models.ExportModel) list_store.get_object (i); model.pixbuf = array[i]; } return; } foreach (var entry in manager.pixbufs.entries) { var model = new Akira.Models.ExportModel (entry.value, entry.key); list_store.append (model); } } private Gtk.Label section_title (string title) { var title_label = new Gtk.Label (title); title_label.halign = Gtk.Align.END; return title_label; } private async void on_export_preview (string message) { overlaybar.label = message; overlaybar.visible = true; sidebar.@foreach ((child) => { child.sensitive = false; }); } private async void on_preview_completed () { sidebar.@foreach ((child) => { child.sensitive = true; }); overlaybar.visible = false; } } Akira-0.0.16/src/Dialogs/ReleaseDialog.vala000066400000000000000000000131611410625726100203510ustar00rootroot00000000000000/* * Copyright (c) 2020 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Alessandro "Alecaddd" Castellani */ public class Akira.Dialogs.ReleaseDialog : Gtk.Dialog { public weak Akira.Window window { get; construct; } public ReleaseDialog (Akira.Window window) { Object ( window: window, border_width: 10, deletable: true, resizable: false, modal: true ); } construct { transient_for = window; default_width = 624; var banner_grid = new Gtk.Grid (); banner_grid.get_style_context ().add_class ("banner"); banner_grid.halign = Gtk.Align.CENTER; banner_grid.width_request = 600; banner_grid.height_request = 200; banner_grid.margin_bottom = 6; var disclaimer = new Gtk.Label ( _("WARNING!\nAkira is still under development and not ready for production. Missing features, random bugs, and black holes opening in your kitchen are to be expected." ) ); disclaimer.justify = Gtk.Justification.CENTER; disclaimer.margin_top = disclaimer.margin_bottom = 6; disclaimer.margin_start = disclaimer.margin_end = 3; disclaimer.max_width_chars = 80; disclaimer.wrap = true; var warning_grid = new Gtk.Grid (); warning_grid.halign = Gtk.Align.CENTER; warning_grid.margin_bottom = 24; warning_grid.get_style_context ().add_class ("warning-message"); warning_grid.add (disclaimer); var app_version = new Gtk.Label ("v" + Constants.VERSION + " - alpha"); app_version.get_style_context ().add_class ("h2"); app_version.selectable = true; var version_title = new Gtk.Label ("Performance improvements and Global colors library"); version_title.get_style_context ().add_class ("h3"); var version_date = new Gtk.Label ("Jul 20th, 2021"); version_date.get_style_context ().add_class ("dim-label"); var header_grid = new Gtk.Grid (); header_grid.halign = Gtk.Align.CENTER; header_grid.margin_bottom = 12; header_grid.attach (app_version, 0, 0); header_grid.attach (version_title, 0, 1); header_grid.attach (version_date, 0, 2); var scrolled = new Gtk.ScrolledWindow (null, null); scrolled.min_content_height = 200; scrolled.expand = true; var release_info = new Gtk.TextView (); release_info.buffer.text = "✓ Improved 'Modes' detection (insert, select, transform).\n✓ Fixed Artboard label issues on zoom.\n✓ Improved Pixel Grid detection and z-index stack with other items.\n✓ Implemented editable zoom value.\n✓ Fix application activation when opening a new file.\n✓ Fix sizing issue when dropping images into the Canvas.\n✓ Implemented Global colors library.\n✓ Italian translation.\n"; release_info.pixels_below_lines = 3; release_info.border_width = 12; release_info.wrap_mode = Gtk.WrapMode.WORD; release_info.cursor_visible = false; release_info.editable = false; release_info.get_style_context ().add_class (Granite.STYLE_CLASS_TERMINAL); scrolled.add (release_info); // Button grid at the bottom of the dialog. var button_grid = new Gtk.ButtonBox (Gtk.Orientation.HORIZONTAL); button_grid.halign = Gtk.Align.CENTER; button_grid.spacing = 6; button_grid.margin_top = 12; var donate_button = new Gtk.Button.with_label (_("Make a Donation")); donate_button.clicked.connect (() => { try { AppInfo.launch_default_for_uri ("https://github.com/akiraux/Akira#-support", null); } catch (Error e) { warning (e.message); } }); var translate_button = new Gtk.Button.with_label (_("Suggest Translations")); translate_button.clicked.connect (() => { try { AppInfo.launch_default_for_uri ("https://github.com/akiraux/Akira/issues", null); } catch (Error e) { warning (e.message); } }); var bug_button = new Gtk.Button.with_label (_("Report a Problem")); bug_button.clicked.connect (() => { try { AppInfo.launch_default_for_uri ("https://github.com/akiraux/Akira/issues", null); } catch (Error e) { warning (e.message); } }); button_grid.add (donate_button); button_grid.add (translate_button); button_grid.add (bug_button); var grid = new Gtk.Grid (); grid.column_spacing = 12; grid.hexpand = true; grid.attach (banner_grid, 0, 0); grid.attach (warning_grid, 0, 1); grid.attach (header_grid, 0, 2); grid.attach (scrolled, 0, 3); grid.attach (button_grid, 0, 4); var content_area = get_content_area (); content_area.border_width = 12; content_area.add (grid); } } Akira-0.0.16/src/Dialogs/SettingsDialog.vala000066400000000000000000000361251410625726100205760ustar00rootroot00000000000000/* * Copyright (c) 2019-2020 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Alessandro "Alecaddd" Castellani */ public class Akira.Dialogs.SettingsDialog : Gtk.Dialog { public weak Akira.Window window { get; construct; } private Gtk.Stack stack; private Gtk.Switch dark_theme_switch; private Gtk.Switch label_switch; private Gtk.Switch symbolic_switch; private Gtk.Switch border_switch; private Gtk.ColorButton grid_color; private Gtk.ColorButton snaps_color; private Gtk.ColorButton fill_color; private Gtk.ColorButton border_color; private Gtk.SpinButton border_size; public SettingsDialog (Akira.Window _window) { Object ( window: _window, border_width: 6, deletable: true, resizable: false, modal: true, title: _("Preferences") ); } construct { transient_for = window; stack = new Gtk.Stack (); stack.margin = 6; stack.margin_bottom = 15; stack.margin_top = 15; stack.add_titled (get_general_box (), "general", _("General")); stack.add_titled (get_interface_box (), "interface", _("Interface")); stack.add_titled (get_canvas_box (), "canvas", _("Canvas")); stack.add_titled (get_shapes_box (), "shapes", _("Shapes")); stack.add_titled (get_about_box (), "about", _("About")); var stack_switcher = new Gtk.StackSwitcher (); stack_switcher.set_stack (stack); stack_switcher.halign = Gtk.Align.CENTER; var grid = new Gtk.Grid (); grid.halign = Gtk.Align.CENTER; grid.attach (stack_switcher, 1, 1, 1, 1); grid.attach (stack, 1, 2, 1, 1); get_content_area ().add (grid); } private Gtk.Widget get_general_box () { var grid = new Gtk.Grid (); grid.row_spacing = 6; grid.column_spacing = 12; grid.column_homogeneous = true; grid.attach (new SettingsHeader (_("General")), 0, 0, 2, 1); grid.attach (new SettingsLabel (_("Auto Reopen Latest File:")), 0, 1, 1, 1); grid.attach (new SettingsSwitch ("open-quick"), 1, 1, 1, 1); return grid; } private Gtk.Widget get_interface_box () { var grid = new Gtk.Grid (); grid.row_spacing = 6; grid.column_spacing = 12; grid.column_homogeneous = true; grid.attach (new SettingsHeader (_("Interface")), 0, 0, 2, 1); grid.attach (new SettingsLabel (_("Use Dark Theme:")), 0, 1, 1, 1); dark_theme_switch = new SettingsSwitch ("dark-theme"); grid.attach (dark_theme_switch, 1, 1, 1, 1); grid.attach (new SettingsLabel (_("Invert Panels Order:")), 0, 2, 1, 1); symbolic_switch = new SettingsSwitch ("invert-sidebar"); grid.attach (symbolic_switch, 1, 2, 1, 1); var panels_helper_label = new Gtk.Label (_("Restart application to apply this change.")); panels_helper_label.get_style_context ().add_class ("dim-label"); grid.attach (panels_helper_label, 1, 3, 1, 1); grid.attach (new SettingsHeader (_("ToolBar Style")), 0, 4, 2, 1); grid.attach (new SettingsLabel (_("Show Button Labels:")), 0, 5, 1, 1); label_switch = new SettingsSwitch ("show-label"); grid.attach (label_switch, 1, 5, 1, 1); grid.attach (new SettingsLabel (_("Use Symbolic Icons:")), 0, 6, 1, 1); symbolic_switch = new SettingsSwitch ("use-symbolic"); grid.attach (symbolic_switch, 1, 6, 1, 1); dark_theme_switch.notify["active"].connect (() => { Gtk.Settings.get_default ().gtk_application_prefer_dark_theme = settings.dark_theme; window.event_bus.change_theme (); }); return grid; } private Gtk.Widget get_canvas_box () { var grid = new Gtk.Grid (); grid.row_spacing = 6; grid.column_spacing = 12; grid.column_homogeneous = true; // Pixel grid. var grid_rgba = Gdk.RGBA (); grid_rgba.parse (settings.grid_color); grid.attach (new SettingsHeader (_("Pixel Grid")), 0, 0, 2, 1); var description = new Gtk.Label (_("Define the default color for the Canvas pixel grid.")); description.halign = Gtk.Align.START; description.margin_bottom = 10; grid.attach (description, 0, 1, 2, 1); grid.attach (new SettingsLabel (_("Pixel Grid Color:")), 0, 2, 1, 1); grid_color = new Gtk.ColorButton.with_rgba (grid_rgba); grid_color.halign = Gtk.Align.START; grid.attach (grid_color, 1, 2, 1, 1); grid_color.color_set.connect (() => { var rgba = grid_color.get_rgba (); // Gdk.RGBA uses rgb() if alpha is 1. string rgba_str = "rgba(%d,%d,%d,%d)".printf ( (int) (rgba.red * 255), (int) (rgba.green * 255), (int) (rgba.blue * 255), (int) (rgba.alpha) ); debug ("pixel grid color: %s", rgba_str); settings.grid_color = rgba_str; window.event_bus.update_pixel_grid (); }); // Snapping guides. var snaps_rgba = Gdk.RGBA (); snaps_rgba.parse (settings.snaps_color); grid.attach (new SettingsHeader (_("Snapping Guides")), 0, 3, 2, 1); var snaps_description = new Gtk.Label (_("Define the default options for the Snapping Guides.")); snaps_description.halign = Gtk.Align.START; snaps_description.margin_bottom = 10; grid.attach (snaps_description, 0, 4, 2, 1); grid.attach (new SettingsLabel (_("Enable Snapping Guides:")), 0, 5, 1, 1); var snaps_switch = new SettingsSwitch ("enable-snaps"); grid.attach (snaps_switch, 1, 5, 1, 1); grid.attach (new SettingsLabel (_("Snapping Guides Color:")), 0, 6, 1, 1); snaps_color = new Gtk.ColorButton.with_rgba (snaps_rgba); snaps_color.halign = Gtk.Align.START; grid.attach (snaps_color, 1, 6, 1, 1); snaps_color.color_set.connect (() => { var rgba = snaps_color.get_rgba (); // Gdk.RGBA uses rgb() if alpha is 1. string rgba_str = "rgba(%d,%d,%d,%d)".printf ( (int) (rgba.red * 255), (int) (rgba.green * 255), (int) (rgba.blue * 255), (int) (rgba.alpha) ); debug ("pixel snaps color: %s", rgba_str); settings.snaps_color = rgba_str; window.event_bus.update_snaps_color (); }); grid.attach (new SettingsLabel (_("Snapping Sensitivity Threshold:")), 0, 7, 1, 1); var snaps_sensitivity = new Gtk.SpinButton.with_range (0, 9999, 1); snaps_sensitivity.halign = Gtk.Align.START; snaps_sensitivity.width_chars = 6; snaps_sensitivity.get_style_context ().add_class ("input-icon-right"); snaps_sensitivity.secondary_icon_name = "input-pixel-symbolic"; snaps_sensitivity.secondary_icon_sensitive = false; snaps_sensitivity.secondary_icon_activatable = false; grid.attach (snaps_sensitivity, 1, 7, 1, 1); settings.bind ("snaps-sensitivity", snaps_sensitivity, "value", SettingsBindFlags.DEFAULT); snaps_switch.bind_property ("active", snaps_color, "sensitive", BindingFlags.SYNC_CREATE); snaps_switch.bind_property ("active", snaps_sensitivity, "sensitive", BindingFlags.SYNC_CREATE); return grid; } private Gtk.Widget get_shapes_box () { var grid = new Gtk.Grid (); grid.row_spacing = 6; grid.column_spacing = 12; grid.column_homogeneous = true; var fill_rgba = Gdk.RGBA (); fill_rgba.parse (settings.fill_color); var border_rgba = Gdk.RGBA (); border_rgba.parse (settings.border_color); grid.attach (new SettingsHeader (_("Default Colors")), 0, 0, 2, 1); var description = new Gtk.Label (_("Define the default style used when creating a new shape.")); description.halign = Gtk.Align.START; description.margin_bottom = 10; grid.attach (description, 0, 1, 2, 1); grid.attach (new SettingsLabel (_("Fill Color:")), 0, 2, 1, 1); fill_color = new Gtk.ColorButton.with_rgba (fill_rgba); fill_color.halign = Gtk.Align.START; grid.attach (fill_color, 1, 2, 1, 1); fill_color.color_set.connect (() => { var rgba = fill_color.get_rgba (); // Gdk.RGBA uses rgb() if alpha is 1. string rgba_str = "rgba(%d,%d,%d,%d)".printf ( (int) (rgba.red * 255), (int) (rgba.green * 255), (int) (rgba.blue * 255), (int) (rgba.alpha) ); debug ("setting color: %s", rgba_str); settings.fill_color = rgba_str; }); grid.attach (new SettingsLabel (_("Enable Border Style:")), 0, 3, 1, 1); border_switch = new SettingsSwitch ("set-border"); grid.attach (border_switch, 1, 3, 1, 1); grid.attach (new SettingsLabel (_("Border Color:")), 0, 4, 1, 1); border_color = new Gtk.ColorButton.with_rgba (border_rgba); border_color.halign = Gtk.Align.START; grid.attach (border_color, 1, 4, 1, 1); border_color.color_set.connect (() => { var rgba = border_color.get_rgba (); // Gdk.RGBA uses rgb() if alpha is 1. string rgba_str = "rgba(%d,%d,%d,%d)".printf ( (int) (rgba.red * 255), (int) (rgba.green * 255), (int) (rgba.blue * 255), (int) (rgba.alpha) ); debug ("setting color: %s", rgba_str); settings.border_color = rgba_str; }); grid.attach (new SettingsLabel (_("Border Width:")), 0, 5, 1, 1); border_size = new Gtk.SpinButton.with_range (1, 9999, 1); border_size.halign = Gtk.Align.START; border_size.width_chars = 6; border_size.get_style_context ().add_class ("input-icon-right"); border_size.secondary_icon_name = "input-pixel-symbolic"; border_size.secondary_icon_sensitive = false; border_size.secondary_icon_activatable = false; grid.attach (border_size, 1, 5, 1, 1); settings.bind ("border-size", border_size, "value", SettingsBindFlags.DEFAULT); border_switch.bind_property ("active", border_color, "sensitive", BindingFlags.SYNC_CREATE); border_switch.bind_property ("active", border_size, "sensitive", BindingFlags.SYNC_CREATE); return grid; } private Gtk.Widget get_about_box () { var grid = new Gtk.Grid (); grid.row_spacing = 6; grid.column_spacing = 12; grid.halign = Gtk.Align.CENTER; var app_icon = new Gtk.Image (); app_icon.gicon = new ThemedIcon (Constants.APP_ID); app_icon.pixel_size = 64; app_icon.margin_top = 12; var app_name = new Gtk.Label (Constants.APP_NAME); app_name.get_style_context ().add_class ("h2"); app_name.margin_top = 6; var app_description = new Gtk.Label (_("The Linux Design Tool")); app_description.get_style_context ().add_class ("h3"); var app_version = new Gtk.Label ("v" + Constants.VERSION + " - alpha"); app_version.get_style_context ().add_class ("dim-label"); app_version.selectable = true; var disclaimer = new Gtk.Label ( _("WARNING!\nAkira is still under development and not ready for production. Missing features, random bugs, and black holes opening in your kitchen are to be expected." ) ); disclaimer.justify = Gtk.Justification.CENTER; disclaimer.get_style_context ().add_class ("warning-message"); disclaimer.max_width_chars = 60; disclaimer.wrap = true; disclaimer.margin_top = disclaimer.margin_bottom = 12; var patreons_label = new Gtk.Label (_("Thanks to our awesome supporters!")); patreons_label.get_style_context ().add_class ("h4"); var patreons_url = new Gtk.LinkButton.with_label ( "https://github.com/akiraux/Akira/blob/master/SUPPORTERS.md", _("View the list of supporters") ); patreons_url.halign = Gtk.Align.CENTER; patreons_url.margin_bottom = 12; grid.attach (app_icon, 0, 0); grid.attach (app_name, 0, 1); grid.attach (app_description, 0, 2); grid.attach (app_version, 0, 3); grid.attach (disclaimer, 0, 4); grid.attach (patreons_label, 0, 5); grid.attach (patreons_url, 0, 6); // Button grid at the bottom of the About page. var button_grid = new Gtk.ButtonBox (Gtk.Orientation.HORIZONTAL); button_grid.halign = Gtk.Align.CENTER; button_grid.spacing = 6; var donate_button = new Gtk.Button.with_label (_("Make a Donation")); donate_button.clicked.connect (() => { try { AppInfo.launch_default_for_uri ("https://github.com/akiraux/Akira#-support", null); } catch (Error e) { warning (e.message); } }); var translate_button = new Gtk.Button.with_label (_("Suggest Translations")); translate_button.clicked.connect (() => { try { AppInfo.launch_default_for_uri ("https://github.com/akiraux/Akira/issues", null); } catch (Error e) { warning (e.message); } }); var bug_button = new Gtk.Button.with_label (_("Report a Problem")); bug_button.clicked.connect (() => { try { AppInfo.launch_default_for_uri ("https://github.com/akiraux/Akira/issues", null); } catch (Error e) { warning (e.message); } }); button_grid.add (donate_button); button_grid.add (translate_button); button_grid.add (bug_button); grid.attach (button_grid, 0, 7); return grid; } private class SettingsHeader : Gtk.Label { public SettingsHeader (string text) { label = text; get_style_context ().add_class ("h4"); halign = Gtk.Align.START; } } private class SettingsLabel : Gtk.Label { public SettingsLabel (string text) { label = text; halign = Gtk.Align.END; } } private class SettingsSwitch : Gtk.Switch { public SettingsSwitch (string setting) { halign = Gtk.Align.START; settings.bind (setting, this, "active", SettingsBindFlags.DEFAULT); } } } Akira-0.0.16/src/Dialogs/ShortcutsDialog.vala000066400000000000000000000151211410625726100207650ustar00rootroot00000000000000/* * Copyright (c) 2020 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Alessandro "Alecaddd" Castellani */ public class Akira.Dialogs.ShortcutsDialog : Gtk.Dialog { public weak Akira.Window window { get; construct; } public ShortcutsDialog (Akira.Window window) { Object ( window: window, border_width: 10, deletable: true, resizable: true, modal: true ); } construct { transient_for = window; default_width = 800; var column_start = new Gtk.Grid (); column_start.column_spacing = 12; column_start.row_spacing = 12; column_start.hexpand = true; column_start.column_homogeneous = true; column_start.attach (new Granite.HeaderLabel (_("General")), 0, 0, 2); column_start.attach (new NameLabel (_("New window:")), 0, 1); column_start.attach (new ShortcutLabel ({"Ctrl", "N"}), 1, 1); column_start.attach (new NameLabel (_("Preferences:")), 0, 2); column_start.attach (new ShortcutLabel ({"Ctrl", ","}), 1, 2); column_start.attach (new NameLabel (_("Quit:")), 0, 3); column_start.attach (new ShortcutLabel ({"Ctrl", "Q"}), 1, 3); column_start.attach (new NameLabel (_("Presentation mode:")), 0, 4); column_start.attach (new ShortcutLabel ({"Ctrl", "."}), 1, 4); column_start.attach (new Granite.HeaderLabel (_("File")), 0, 5, 2); column_start.attach (new NameLabel (_("Open:")), 0, 6); column_start.attach (new ShortcutLabel ({"Ctrl", "O"}), 1, 6); column_start.attach (new NameLabel (_("Save:")), 0, 7); column_start.attach (new ShortcutLabel ({"Ctrl", "S"}), 1, 7); column_start.attach (new NameLabel (_("Save as:")), 0, 8); column_start.attach (new ShortcutLabel ({"Ctrl", "Shift", "S"}), 1, 8); column_start.attach (new Granite.HeaderLabel (_("Export")), 0, 9, 2); column_start.attach (new NameLabel (_("Export artboards:")), 0, 10); column_start.attach (new ShortcutLabel ({"Ctrl", "Alt", "A"}), 1, 10); column_start.attach (new NameLabel (_("Export selection:")), 0, 11); column_start.attach (new ShortcutLabel ({"Ctrl", "Alt", "E"}), 1, 11); column_start.attach (new NameLabel (_("Highlight area to export:")), 0, 12); column_start.attach (new ShortcutLabel ({"Ctrl", "Alt", "G"}), 1, 12); var column_end = new Gtk.Grid (); column_end.column_spacing = 12; column_end.row_spacing = 12; column_end.hexpand = true; column_end.column_homogeneous = true; column_end.attach (new Granite.HeaderLabel (_("Canvas")), 0, 0, 2); column_end.attach (new NameLabel (_("Zoom in:")), 0, 1); column_end.attach (new ShortcutLabel ({"Ctrl", "+"}), 1, 1); column_end.attach (new NameLabel (_("Zoom out:")), 0, 2); column_end.attach (new ShortcutLabel ({"Ctrl", "-"}), 1, 2); column_end.attach (new NameLabel (_("Zoom reset:")), 0, 3); column_end.attach (new ShortcutLabel ({"Ctrl", "0"}), 1, 3); column_end.attach (new Granite.HeaderLabel (_("Item creation")), 0, 4, 2); column_end.attach (new NameLabel (_("Artboard:")), 0, 5); column_end.attach (new ShortcutLabel ({"A"}), 1, 5); column_end.attach (new NameLabel (_("Rectangle:")), 0, 6); column_end.attach (new ShortcutLabel ({"R"}), 1, 6); column_end.attach (new NameLabel (_("Ellipse:")), 0, 7); column_end.attach (new ShortcutLabel ({"E"}), 1, 7); column_end.attach (new NameLabel (_("Text:")), 0, 8); column_end.attach (new ShortcutLabel ({"T"}), 1, 8); column_end.attach (new NameLabel (_("Image:")), 0, 9); column_end.attach (new ShortcutLabel ({"I"}), 1, 9); column_end.attach (new Granite.HeaderLabel (_("Transform")), 0, 10, 2); column_end.attach (new NameLabel (_("Raise selection:")), 0, 11); column_end.attach (new ShortcutLabel ({"Ctrl", "↑"}), 1, 11); column_end.attach (new NameLabel (_("Lower selection:")), 0, 12); column_end.attach (new ShortcutLabel ({"Ctrl", "↓"}), 1, 12); column_end.attach (new NameLabel (_("Raise selection to top:")), 0, 13); column_end.attach (new ShortcutLabel ({"Ctrl", "Shift", "↑"}), 1, 13); column_end.attach (new NameLabel (_("Lower selection to bottom:")), 0, 14); column_end.attach (new ShortcutLabel ({"Ctrl", "Shift", "↓"}), 1, 14); column_end.attach (new NameLabel (_("Flip horizontally:")), 0, 15); column_end.attach (new ShortcutLabel ({"Ctrl", "["}), 1, 15); column_end.attach (new NameLabel (_("Flip vertically:")), 0, 16); column_end.attach (new ShortcutLabel ({"Ctrl", "]"}), 1, 16); var grid = new Gtk.Grid (); grid.column_spacing = 12; grid.hexpand = true; grid.attach (column_start, 0, 0); grid.attach (new Gtk.Separator (Gtk.Orientation.VERTICAL), 1, 0); grid.attach (column_end, 2, 0); var content_area = get_content_area (); content_area.border_width = 12; content_area.add (grid); } private class NameLabel : Gtk.Label { public NameLabel (string label) { Object ( label: label ); } construct { halign = Gtk.Align.END; xalign = 1; } } private class ShortcutLabel : Gtk.Grid { public string[] accels { get; set construct; } public ShortcutLabel (string[] accels) { Object (accels: accels); } construct { column_spacing = 6; foreach (unowned string accel in accels) { if (accel == "") { continue; } var label = new Gtk.Label (accel); label.get_style_context ().add_class ("keycap"); add (label); } halign = Gtk.Align.START; } } } Akira-0.0.16/src/FileFormat/000077500000000000000000000000001410625726100154505ustar00rootroot00000000000000Akira-0.0.16/src/FileFormat/AkiraFile.vala000066400000000000000000000132751410625726100201540ustar00rootroot00000000000000/* * Copyright (c) 2019-2020 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Felipe Escoto * Authored by: Alessandro "Alecaddd" Castellani */ public class Akira.FileFormat.AkiraFile : Akira.FileFormat.ZipArchiveHandler { public weak Akira.Window window { get; construct; } public File pictures_folder { get; private set; } public File thumbnails_folder { get; private set; } public bool overwrite = false; private File content_file { get; set; } public string path { owned get { return opened_file.get_parent ().get_path () + "/" + opened_file.get_basename (); } } public AkiraFile (File _gzipped_file, Akira.Window window) { Object (opened_file: _gzipped_file.dup (), window: window); } public void load_file () { try { open_archive (); var content_json = get_content_as_json (content_file); FileFormat.JsonDeserializer.json_object_to_world (content_json, window); update_recent_list.begin (); debug ("Version from file: %s", content_json.get_string_member ("version")); } catch (Error e) { error ("Could not load file: %s", e.message); } } public void save_file () { try { save_images.begin (); var world_json = FileFormat.JsonSerializer.world_to_json_node (window); write_content_to_file (content_file, FileFormat.JsonSerializer.json_to_string (world_json, true)); write_to_archive (); update_recent_list.begin (); } catch (Error e) { warning ("%s\n", e.message); } } public void close () { try { clean (); } catch (Error e) { warning ("%s\n", e.message); } } public override void prepare () { base.prepare (); var base_path = unarchived_location.get_path (); pictures_folder = File.new_for_path (Path.build_filename (base_path, "Pictures")); thumbnails_folder = File.new_for_path (Path.build_filename (base_path, "Thumbnails")); make_dir (pictures_folder); make_dir (thumbnails_folder); content_file = File.new_for_path (Path.build_filename (base_path, "content.json")); make_file (content_file); } /** * Update the GSettings array of recently opened files. */ private async void update_recent_list () { string[] array = {}; // Add the last opened file always on top. array += path; for (var i = 0; i <= settings.recently_opened.length; i++) { // Skip if the record is empty. if (settings.recently_opened[i] == null) { continue; } // If the file doesn't exist anymore, remove it from the list. var file = File.new_for_path (settings.recently_opened[i]); if (!file.query_exists ()) { continue; } // Don't store more than 10 files. if (i >= 9) { break; } // If the same file was already in the list, don't save it again. if (path == settings.recently_opened[i]) { continue; } array += settings.recently_opened[i]; } settings.set_strv ("recently-opened", array); window.app.update_recent_files_list (); } /** * Save all the images used in the Canvas and make a copy in the Pictures folder. */ public async void save_images () { // Clear potential leftover images if we're overwriting an existing file. if (overwrite) { try { Dir dir = Dir.open (pictures_folder.get_path (), 0); string? name = null; while ((name = dir.read_name ()) != null) { var file = File.new_for_path (Path.build_filename (pictures_folder.get_path (), name)); file_collector.mark_for_deletion (file); } } catch (FileError err) { stderr.printf (err.message); } overwrite = false; } foreach (var image in window.items_manager.images) { var image_file = File.new_for_path ( Path.build_filename (pictures_folder.get_path (), image.manager.filename) ); // Copy the file if it doesn't exist, or increase the reference count. if (!image_file.query_exists ()) { copy_image (image.manager.file, image_file); continue; } } } /** * Decrease the reference count to an existing image, which will cause its * deletion if the count reaches 0. */ public async void remove_image (string filename) { var image_file = File.new_for_path ( Path.build_filename (pictures_folder.get_path (), filename) ); if (image_file.query_exists ()) { file_collector.unref_file (image_file); } } } Akira-0.0.16/src/FileFormat/FileManager.vala000066400000000000000000000103551410625726100204730ustar00rootroot00000000000000/* * Copyright (c) 2020 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Alessandro "Alecaddd" Castellani */ public class Akira.FileFormat.FileManager : Object { public weak Akira.Window window { get; construct; } public FileManager (Akira.Window window) { Object ( window: window ); } // Save file. public void save_file () { // Check if we already have a file open to save or save a new one. if (window.akira_file != null) { window.akira_file.save_file (); window.event_bus.file_saved (null); return; } save_file_as (); } // Save as. public void save_file_as () { var dialog = new Gtk.FileChooserNative ( _("Save Akira file"), window, Gtk.FileChooserAction.SAVE, _("Save"), _("Cancel")); dialog.set_do_overwrite_confirmation (true); add_filters (dialog); dialog.set_modal (true); if (window.akira_file != null) { var file = File.new_for_path (window.akira_file.path); try { dialog.set_file (file); } catch (GLib.Error error) { info ("%s\n", error.message); } } dialog.response.connect ((response_id) => save_file_as_response (dialog, response_id)); dialog.show (); } private void add_filters (Gtk.FileChooserNative chooser) { Gtk.FileFilter filter = new Gtk.FileFilter (); filter.add_pattern ("*.akira"); filter.set_filter_name (_("Akira files")); chooser.add_filter (filter); filter = new Gtk.FileFilter (); filter.add_pattern ("*"); filter.set_filter_name (_("All files")); chooser.add_filter (filter); } private void save_file_as_response (Gtk.FileChooserNative dialog, int response_id) { bool overwrite = false; switch (response_id) { case Gtk.ResponseType.ACCEPT: File file; var save_file = dialog.get_file (); var path = save_file.get_path (); if (path.has_suffix (".akira")) { file = save_file; overwrite = true; } else { file = File.new_for_path (path + ".akira"); } window.save_new_file (file, overwrite); window.event_bus.file_saved (dialog.get_current_name ()); break; } dialog.destroy (); } // Open file. public void open_file () { var dialog = new Gtk.FileChooserNative (_("Open Akira file"), window, Gtk.FileChooserAction.OPEN, _("Open"), _("Cancel")); add_filters (dialog); dialog.local_only = true; dialog.select_multiple = false; dialog.response.connect ((response_id) => open_file_response (dialog, response_id)); dialog.show (); } private void open_file_response (Gtk.FileChooserNative dialog, int response_id) { switch (response_id) { case Gtk.ResponseType.ACCEPT: case Gtk.ResponseType.OK: File[] files = {}; files += dialog.get_file (); window.app.open (files, ""); info ("opened: %s\n", (dialog.get_filename ())); break; case Gtk.ResponseType.CANCEL: info ("Cancelled: FileChooserAction.OPEN\n"); break; } dialog.destroy (); } } Akira-0.0.16/src/FileFormat/JsonDeserializer.vala000066400000000000000000000066031410625726100215760ustar00rootroot00000000000000/* * Copyright (c) 2020-2021 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Alessandro "Alecaddd" Castellani */ public class Akira.FileFormat.JsonDeserializer { /* * Deserialize a Json.Node and apply it to the current world state. * This deserializes a node, which is symmetric with the output of JsonSerializer. */ public static void json_node_to_world (Json.Node node, Akira.Window window, bool items_only = false) { var obj = node.get_object (); if (obj != null) { json_object_to_world (obj, window, items_only); } } /* * Deserialize a Json.Node and apply it to the current world state. */ public static void json_object_to_world (Json.Object obj, Akira.Window window, bool items_only = false) { // Se the canvas to simulate a click + holding state to avoid triggering // redrawing methods connected to that state. window.main_window.main_canvas.canvas.holding = true; // Load saved Artboards. if (obj.get_member ("artboards") != null) { Json.Array artboards = obj.get_member ("artboards").get_array (); var artboards_list = artboards.get_elements (); artboards_list.reverse (); foreach (unowned Json.Node node in artboards_list) { load_item (window, node.get_object (), "artboard"); } } // Load saved Items. if (obj.get_member ("items") != null) { Json.Array items = obj.get_member ("items").get_array (); var items_list = items.get_elements (); items_list.reverse (); foreach (unowned Json.Node node in items_list) { load_item (window, node.get_object (), "item"); } } if (!items_only) { load_window_states (window, obj); } // Reset the holding state at the end of it. window.main_window.main_canvas.canvas.holding = false; } /* * Deserialize window states and apply them to the window. */ private static void load_window_states (Akira.Window window, Json.Object obj) { window.event_bus.set_scale (obj.get_double_member ("scale")); window.main_window.main_canvas.main_scroll.hadjustment.value = obj.get_double_member ("hadjustment"); window.main_window.main_canvas.main_scroll.vadjustment.value = obj.get_double_member ("vadjustment"); } /* * Deserialize item states and apply them to the window. */ private static void load_item (Akira.Window window, Json.Object obj, string type) { var item = obj.get_member (type).get_object (); if (item != null) { window.items_manager.load_item (item); } } } Akira-0.0.16/src/FileFormat/JsonItemSerializer.vala000066400000000000000000000166311410625726100221060ustar00rootroot00000000000000/** * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Felipe Escoto * Authored by: Alessandro "Alecaddd" Castellani */ /** * Converts an item into a JSON Object, converting all the child attributes to string. */ public class Akira.FileFormat.JsonItemSerializer { /* * Serialize an item and return its corresponding Json.Node. */ public static Json.Node serialize_item (Lib.Items.CanvasItem item) { var object = new Json.Object (); serialize_type_specifics (item, ref object); serialize_matrix (item, ref object); serialize_components (item, ref object); var node = new Json.Node.alloc (); node.set_object (object); return node; } /* * Serialize type specifics of an item. */ private static void serialize_type_specifics (Lib.Items.CanvasItem item, ref Json.Object object) { // Set a string of the type so we're not tied to the namespace and location. if (item is Lib.Items.CanvasArtboard) { object.set_string_member ("type", "artboard"); } if (item is Lib.Items.CanvasRect) { object.set_string_member ("type", "rectangle"); } if (item is Lib.Items.CanvasEllipse) { object.set_string_member ("type", "ellipse"); } if (item is Lib.Items.CanvasImage) { object.set_string_member ("type", "image"); object.set_string_member ("image_id", ((Lib.Items.CanvasImage) item).manager.filename); } if (item is Lib.Items.CanvasText) { object.set_string_member ("type", "text"); } // Save the artboard ID if the item belongs to one. if (item.artboard != null) { object.set_string_member ("artboard", item.artboard.name.id); } } /* * Serialize item transform matrix. */ private static void serialize_matrix (Lib.Items.CanvasItem item, ref Json.Object object) { var identity = Cairo.Matrix.identity (); item.get_transform (out identity); var matrix = new Json.Object (); matrix.set_double_member ("xx", identity.xx); matrix.set_double_member ("yx", identity.yx); matrix.set_double_member ("xy", identity.xy); matrix.set_double_member ("yy", identity.yy); matrix.set_double_member ("x0", identity.x0); matrix.set_double_member ("y0", identity.y0); object.set_object_member ("matrix", matrix); } /** * Serialize all the Components used by the item. */ private static void serialize_components (Lib.Items.CanvasItem item, ref Json.Object object) { // Interrupt if this is not a CanvasItem. if (!(item is Lib.Items.CanvasItem)) { return; } // Create the components object. var components = new Json.Object (); if (item.name != null) { var name = new Json.Object (); name.set_string_member ("name", item.name.name); name.set_string_member ("id", item.name.id); name.set_string_member ("icon", item.name.icon); components.set_object_member ("Name", name); } if (item.coordinates != null) { var coordinates = new Json.Object (); coordinates.set_double_member ("x", item.coordinates.x); coordinates.set_double_member ("y", item.coordinates.y); components.set_object_member ("Coordinates", coordinates); } if (item.opacity != null) { var opacity = new Json.Object (); opacity.set_double_member ("opacity", item.opacity.opacity); components.set_object_member ("Opacity", opacity); } if (item.rotation != null) { var rotation = new Json.Object (); rotation.set_double_member ("rotation", item.rotation.rotation); components.set_object_member ("Rotation", rotation); } if (item.size != null) { var size = new Json.Object (); size.set_boolean_member ("locked", item.size.locked); size.set_double_member ("ratio", item.size.ratio); size.set_double_member ("width", item.size.width); size.set_double_member ("height", item.size.height); components.set_object_member ("Size", size); } if (item.flipped != null) { var flipped = new Json.Object (); flipped.set_boolean_member ("horizontal", item.flipped.horizontal); flipped.set_boolean_member ("vertical", item.flipped.vertical); components.set_object_member ("Flipped", flipped); } if (item.border_radius != null) { var border_radius = new Json.Object (); border_radius.set_double_member ("x", item.border_radius.x); border_radius.set_double_member ("y", item.border_radius.y); border_radius.set_boolean_member ("uniform", item.border_radius.uniform); border_radius.set_boolean_member ("autoscale", item.border_radius.autoscale); components.set_object_member ("BorderRadius", border_radius); } if (item.layer != null) { var layer = new Json.Object (); layer.set_boolean_member ("locked", item.layer.locked); components.set_object_member ("Layer", layer); } if (item.fills != null) { var fills = new Json.Object (); foreach (Lib.Components.Fill fill in item.fills.fills) { var obj = new Json.Object (); obj.set_int_member ("id", fill.id); obj.set_string_member ("color", fill.color.to_string ()); obj.set_int_member ("alpha", fill.alpha); obj.set_boolean_member ("hidden", fill.hidden); fills.set_object_member ("Fill-" + fill.id.to_string (), obj); } components.set_object_member ("Fills", fills); } if (item.borders != null) { var borders = new Json.Object (); foreach (Lib.Components.Border border in item.borders.borders) { var obj = new Json.Object (); obj.set_int_member ("id", border.id); obj.set_string_member ("color", border.color.to_string ()); obj.set_int_member ("size", border.size); obj.set_int_member ("alpha", border.alpha); obj.set_boolean_member ("hidden", border.hidden); borders.set_object_member ("Border-" + border.id.to_string (), obj); } components.set_object_member ("Borders", borders); } // Save all the components in the main object. object.set_object_member ("Components", components); } } Akira-0.0.16/src/FileFormat/JsonSerializer.vala000066400000000000000000000077621410625726100212740ustar00rootroot00000000000000/* * Copyright (c) 2020 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Alessandro "Alecaddd" Castellani */ public class Akira.FileFormat.JsonSerializer { /* * Converts the world (window, and canvas item information) to a Json.Node. * Use this and json_to_string to save Akira's file state. */ public static Json.Node world_to_json_node (Akira.Window window, bool items_only = false) { var builder = new Json.Builder (); builder.begin_object (); if (!items_only) { serialize_window_state (window, ref builder); } // Convert Artboards to JSON. serialize_artboards (window, ref builder); // Convert Items to JSON. serialize_items (window, ref builder); builder.end_object (); return builder.get_root (); } /* * Converts a Json.Node to a string */ public static string json_to_string (Json.Node node, bool pretty) { var generator = new Json.Generator (); generator.pretty = pretty; generator.set_root (node); return generator.to_data (null); } /* * Serialize window states to the builder. */ public static void serialize_window_state ( Akira.Window window, ref Json.Builder builder) { // Save the current version of Akira. builder.set_member_name ("version"); builder.add_string_value (Constants.VERSION); // Save the current Canvas status. builder.set_member_name ("scale"); builder.add_double_value (window.main_window.main_canvas.canvas.get_scale ()); builder.set_member_name ("hadjustment"); builder.add_double_value (window.main_window.main_canvas.main_scroll.hadjustment.value); builder.set_member_name ("vadjustment"); builder.add_double_value (window.main_window.main_canvas.main_scroll.vadjustment.value); } /* * Serialize canvas artboards to the builder. */ public static void serialize_artboards ( Akira.Window window, ref Json.Builder builder) { builder.set_member_name ("artboards"); builder.begin_array (); foreach (var artboard in window.items_manager.artboards) { builder.begin_object (); builder.set_member_name ("artboard"); builder.add_value (JsonItemSerializer.serialize_item (artboard)); builder.end_object (); } builder.end_array (); } /* * Serialize canvas items to the builder. */ public static void serialize_items ( Akira.Window window, ref Json.Builder builder) { builder.set_member_name ("items"); builder.begin_array (); foreach (var _item in window.items_manager.free_items) { builder.begin_object (); builder.set_member_name ("item"); builder.add_value (JsonItemSerializer.serialize_item (_item)); builder.end_object (); } // Save all the items inside this Artboard. foreach (var artboard in window.items_manager.artboards) { foreach (var _item in artboard.items) { builder.begin_object (); builder.set_member_name ("item"); builder.add_value (JsonItemSerializer.serialize_item (_item)); builder.end_object (); } } builder.end_array (); } } Akira-0.0.16/src/FileFormat/ZipArchiveHandler.vala000066400000000000000000000402611410625726100216620ustar00rootroot00000000000000/* * Copyright (c) 2019-2020 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Felipe Escoto * Authored by: Alessandro "Alecaddd" Castellani */ public class Akira.FileFormat.ZipArchiveHandler : GLib.Object { // Prefix to be added at the beginning of the folder name when a gzipped file is opened. // Should start with a period to hide the folder by default. private const string UNARCHIVED_PREFIX = ".~lock.akira."; /** * The GZipped File that opened this archive */ public File opened_file { get; construct set; } /** * The Unzipped folder location */ public File unarchived_location { get; private set; } /** * Creates a zipped file for archive purposes */ public ZipArchiveHandler (File gzipped_file) { Object (opened_file: gzipped_file.dup ()); } public FileCollector file_collector { get; private set; } construct { var parent_folder = opened_file.get_parent ().get_path (); unarchived_location = File.new_for_path ( Path.build_filename (parent_folder, UNARCHIVED_PREFIX + opened_file.get_basename ())); file_collector = new FileCollector (unarchived_location); } protected static string get_content_from_file (File file) { try { string data; FileUtils.get_contents (file.get_path (), out data); return data; } catch (Error e) { warning (e.message); return ""; } } protected static Json.Object get_content_as_json (File file) { try { var parser = new Json.Parser (); parser.load_from_data (get_content_from_file (file)); return parser.get_root ().get_object (); } catch (Error e) { return new Json.Object (); } } protected static void write_content_to_file (File file, string data) { try { FileUtils.set_contents (file.get_path (), data); } catch (Error e) { warning (e.message); } } /** * Helper function to create a directory if it does not exist */ protected void make_dir (File file) { if (!file.query_exists ()) { try { file.make_directory_with_parents (); } catch (Error e) { warning ("%s\n", e.message); } } } /** * Helper function to create a file if it does not exist */ protected void make_file (File file) { if (!file.query_exists ()) { try { file.create (FileCreateFlags.REPLACE_DESTINATION); } catch (Error e) { warning ("%s\n", e.message); } } } /** * Used to create all the files needed for this if they do not exist. * * Can be overwritten to add your own files and folders for the internal * file structure you require. If overwritten, make sure to call base.prepare () */ public virtual void prepare () { var parent_folder = opened_file.get_parent (); make_dir (parent_folder); make_file (opened_file); make_dir (unarchived_location); } /** * Used to check if the file was already extracted. Use this to handle recovery for your users. */ protected virtual bool is_opened () { return unarchived_location.query_exists (); } /** * Extracts the contents of the file to unarchived_location */ protected void open_archive () throws Error { extract (opened_file, unarchived_location); } /** * Saves content from the unzipped location to the GZipped file. */ protected void write_to_archive () throws Error { // Clear files marked before archiving anything file_collector.delete_files_marked_for_deletion (); // Saving to a temp file first to avoid dataloss on a crash var tmp_file = File.new_for_path (opened_file.get_path () + ".tmp"); compress (unarchived_location, tmp_file); if (opened_file.query_exists ()) { opened_file.delete (); } FileUtils.rename (tmp_file.get_path (), opened_file.get_path ()); } /** * Removes all files from the unarchived location. Should run before closing the program to cleanup temp files */ protected void clean () throws Error { // Checking if it contains the prefix as a safety to prevent errors if (is_opened () && unarchived_location.get_path ().contains (UNARCHIVED_PREFIX)) { delete_recursive (unarchived_location); unarchived_location.delete (); } } public File get_file_from_basename (File location, string basename) { var path = Path.build_filename (location.get_path (), basename); return File.new_for_path (path); } /** * Gets a random file inside the archive at the location specified * using a guid-like name. * * @param location - Location inside of the archive where the file will live at. * @param extension - The extension the file created will have. * @param format - The format for the file. The character "?" will be replaced * with a random character. For example, XXXX-XX can become a5b7-Df. * The default is "XXXXXXXX-XXXX-XX". */ public File get_random_file_name (File location, string extension, string format = "XXXXXXXX-XXXX-XX") { do { var path = Path.build_filename (location.get_path (), get_guid (format) + "." + extension); var file = File.new_for_path (path); if (!file.query_exists ()) { return file; } } while (true); } private Rand? rand = new Rand (); private const string GUID_CHARS = "0123456789ABCDEFabcdef"; private string get_guid (string format) { var guid = new StringBuilder.sized (format.length); int format_length = format.length; for (int i = 0; i < format_length; i++) { switch (format[i]) { case 'X': var r = rand.next_int () % GUID_CHARS.length; guid.append_c (GUID_CHARS[r]); break; default: guid.append_c (format[i]); break; } } return guid.str; } // DANGEROUS, use with caution private void delete_recursive (File file) { try { var enumerator = file.enumerate_children (FileAttribute.STANDARD_NAME, 0); FileInfo file_info; while ((file_info = enumerator.next_file ()) != null) { var current_file = file.resolve_relative_path (file_info.get_name ()); if (file_info.get_file_type () == FileType.DIRECTORY) { delete_recursive (current_file); } current_file.delete (); } } catch (Error e) { critical ("Error: %s\n", e.message); } } // Extracts all contents of the gzip file to the location private static void extract (File gzipped_file, File location) throws Error { Archive.ExtractFlags flags; flags = Archive.ExtractFlags.TIME; flags |= Archive.ExtractFlags.PERM; flags |= Archive.ExtractFlags.ACL; flags |= Archive.ExtractFlags.FFLAGS; Archive.Read archive = new Archive.Read (); archive.support_format_all (); archive.support_filter_all (); Archive.WriteDisk extractor = new Archive.WriteDisk (); extractor.set_options (flags); extractor.set_standard_lookup (); if (archive.open_filename (gzipped_file.get_path (), 10240) != Archive.Result.OK) { throw new FileError.FAILED ( "Error opening %s: %s (%d)", gzipped_file.get_path (), archive.error_string (), archive.errno () ); } unowned Archive.Entry entry; Archive.Result last_result; while ((last_result = archive.next_header (out entry)) == Archive.Result.OK) { entry.set_perm (0644); entry.set_pathname (Path.build_filename (location.get_path (), entry.pathname ())); if (extractor.write_header (entry) != Archive.Result.OK) { continue; } Posix.off_t offset; uint8[] buffer; while (archive.read_data_block (out buffer, out offset) == Archive.Result.OK) { if (extractor.write_data_block (buffer, offset) != Archive.Result.OK) { break; } } } if (last_result != Archive.Result.EOF) { critical ("Error: %s (%d)", archive.error_string (), archive.errno ()); } } // Compresses all files recursibly from location to the gzipped file. private static void compress (File location, File gzipped_file) throws Error { var to_write = File.new_for_path (gzipped_file.get_path ()); if (to_write.query_exists ()) { to_write.delete (); } to_write.create (FileCreateFlags.REPLACE_DESTINATION); Archive.Write archive = new Archive.Write (); archive.set_format_zip (); archive.open_filename (to_write.get_path ()); add_to_archive_recursive (location, location, archive); if (archive.close () != Archive.Result.OK) { critical ("Error : %s (%d)", archive.error_string (), archive.errno ()); } } private static void add_to_archive_recursive (File initial_folder, File folder, Archive.Write archive) { try { var enumerator = folder.enumerate_children (FileAttribute.STANDARD_NAME, 0); FileInfo current_info; while ((current_info = enumerator.next_file ()) != null) { var current_file = folder.resolve_relative_path (current_info.get_name ()); if (current_info.get_file_type () == FileType.DIRECTORY) { add_to_archive_recursive (initial_folder, current_file, archive); } else { GLib.FileInfo file_info = current_file.query_info (GLib.FileAttribute.STANDARD_SIZE, GLib.FileQueryInfoFlags.NONE); FileInputStream input_stream = current_file.read (); DataInputStream data_input_stream = new DataInputStream (input_stream); // Add an entry to the archive Archive.Entry entry = new Archive.Entry (); entry.set_pathname (initial_folder.get_relative_path (current_file)); entry.set_size ((Archive.int64_t) file_info.get_size ()); entry.set_filetype (Archive.FileType.IFREG); entry.set_perm (0644); if (archive.write_header (entry) != Archive.Result.OK) { critical ( "Error writing '%s': %s (%d)", current_file.get_path (), archive.error_string (), archive.errno () ); return; } // Add the actual content of the file size_t bytes_read; uint8[] buffer = new uint8[64]; while (data_input_stream.read_all (buffer, out bytes_read)) { if (bytes_read <= 0) { break; } archive.write_data (buffer[0:bytes_read]); } } } } catch (Error e) { critical ("Error: %s\n", e.message); } } public virtual void copy_image (GLib.File old_file, GLib.File new_file) { try { old_file.copy (new_file, 0, null, (current_num_bytes, total_num_bytes) => { // Report copy-status: print ("%" + int64.FORMAT + " bytes of %" + int64.FORMAT + " bytes copied.\n", current_num_bytes, total_num_bytes); }); file_collector.ref_file (new_file); } catch (Error e) { print ("Error: %s\n", e.message); } } /** * Takes care of the reference counting for files inside the archive. * This allows to multiple objects to reference the same file, and only * mark the file for deletion if no other object is using it. */ protected class FileCollector { private unowned File unarchived_location; private Gee.HashMap for_deletion; private Gee.HashMap ref_counter; public FileCollector (File _unarchived_location) { unarchived_location = _unarchived_location; for_deletion = new Gee.HashMap (); ref_counter = new Gee.HashMap (); } /** * Gets the number of times a file is being used */ public int file_references (File file) { var file_basename = file.get_basename (); return ref_counter.has_key (file_basename) ? ref_counter.get (file_basename) : 0; } /** * Adds 1 to the ref counter for that file. */ public void ref_file (File file) { var file_basename = file.get_basename (); if (for_deletion.has_key (file_basename)) { unmark_for_deletion (file); } var ref_count = file_references (file); ref_counter.set (file_basename, ref_count + 1); print ("File ref %d %s \n", ref_count + 1, file.get_basename ()); } /** * Subtracts 1 on the ref counter for that file. If set to 0, the file will be marked for deletion */ public void unref_file (File file) { var file_basename = file.get_basename (); var ref_count = file_references (file); if (ref_count > 0) { ref_counter.set (file_basename, ref_count - 1); if (ref_count == 1) { mark_for_deletion (file); } print ("File unref %d %s \n", ref_count - 1, file.get_basename ()); } } /** * Marks a file to be deleted and not saved to the archive. Said files will be deleted * when write_to_archive runs or when you manually call "delete_files_marked_for_deletion". * * Files will only be added to the list when they are inside the unarchived location */ public void mark_for_deletion (File file) { if (file.get_path ().contains (unarchived_location.get_path ())) { for_deletion.set (file.get_basename (), file); print ("Marked for deletion: %s\n", file.get_basename ()); } } /** * Unmarks a file previously marked for deletion. */ public void unmark_for_deletion (File file) { for_deletion.unset (file.get_basename ()); print ("unmarked for deletion: %s\n", file.get_basename ()); } /** * Deletes all files whose ref counter is set to 0, or those marked for deletion */ public void delete_files_marked_for_deletion () { foreach (var file in for_deletion.values) { try { file.delete (); } catch (Error e) { warning ("File could not be deleted %s\n", e.message); } }; for_deletion.clear (); } } } Akira-0.0.16/src/Layouts/000077500000000000000000000000001410625726100150605ustar00rootroot00000000000000Akira-0.0.16/src/Layouts/HeaderBar.vala000066400000000000000000000525341410625726100175530ustar00rootroot00000000000000/* * Copyright (c) 2019-2020 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Alessandro "Alecaddd" Castellani */ public class Akira.Layouts.HeaderBar : Gtk.HeaderBar { public weak Akira.Window window { get; construct; } private Lib.Items.CanvasItem selected_item; public Widgets.HeaderBarButton new_document; public Widgets.HeaderBarButton save_file; public Widgets.HeaderBarButton save_file_as; public Gtk.Grid recent_files_grid; public Widgets.MenuButton menu; public Widgets.MenuButton items; public Widgets.ZoomButton zoom; public Widgets.HeaderBarButton group; public Widgets.HeaderBarButton ungroup; public Widgets.HeaderBarButton move_up; public Widgets.HeaderBarButton move_down; public Widgets.HeaderBarButton move_top; public Widgets.HeaderBarButton move_bottom; public Widgets.HeaderBarButton preferences; public Widgets.HeaderBarButton path_difference; public Widgets.HeaderBarButton path_exclusion; public Widgets.HeaderBarButton path_intersect; public Widgets.HeaderBarButton path_union; public Gtk.PopoverMenu popover_insert; public bool toggled { get { return visible; } set { visible = value; no_show_all = !value; } } public HeaderBar (Akira.Window window) { Object ( toggled: true, window: window ); } construct { set_show_close_button (true); title = _("Untitled"); menu = new Widgets.MenuButton ("document-open", _("Menu"), null); var menu_popover = build_main_menu_popover (); menu.button.popover = menu_popover; items = new Widgets.MenuButton ("insert-object", _("Insert"), null); var items_popover = build_items_popover (); items.button.popover = items_popover; zoom = new Widgets.ZoomButton (window); group =new Widgets.HeaderBarButton (window, "object-group", _("Group"), {"g"}, "multiple"); ungroup = new Widgets.HeaderBarButton (window, "object-ungroup", _("Ungroup"), {"g"}, "group"); move_up = new Widgets.HeaderBarButton (window, "selection-raise", _("Up"), {"Up"}, "single"); move_up.button.action_name = Akira.Services.ActionManager.ACTION_PREFIX + Akira.Services.ActionManager.ACTION_MOVE_UP; move_down = new Widgets.HeaderBarButton (window, "selection-lower", _("Down"), {"Down"}, "single"); move_down.button.action_name = Akira.Services.ActionManager.ACTION_PREFIX + Akira.Services.ActionManager.ACTION_MOVE_DOWN; move_top = new Widgets.HeaderBarButton (window, "selection-top", _("Top"), {"Up"}, "single"); move_top.button.action_name = Akira.Services.ActionManager.ACTION_PREFIX + Akira.Services.ActionManager.ACTION_MOVE_TOP; move_bottom = new Widgets.HeaderBarButton (window, "selection-bottom", _("Bottom"), {"Down"}, "single"); move_bottom.button.action_name = Akira.Services.ActionManager.ACTION_PREFIX + Akira.Services.ActionManager.ACTION_MOVE_BOTTOM; preferences = new Widgets.HeaderBarButton (window, "open-menu", _("Settings"), {"comma"}); preferences.button.action_name = Akira.Services.ActionManager.ACTION_PREFIX + Akira.Services.ActionManager.ACTION_PREFERENCES; preferences.sensitive = true; var export = new Widgets.MenuButton ("document-export", _("Export"), null); var export_popover = build_export_popover (); export.button.popover = export_popover; export.sensitive = true; var layout = new Widgets.MenuButton ("document-layout", _("Layout"), null); var layout_popover = build_layout_popover (); layout.button.popover = layout_popover; layout.sensitive = true; path_difference = new Widgets.HeaderBarButton (window, "path-difference", _("Difference"), null, "multiple"); path_exclusion = new Widgets.HeaderBarButton (window, "path-exclusion", _("Exclusion"), null, "multiple"); path_intersect = new Widgets.HeaderBarButton (window, "path-intersection", _("Intersect"), null, "multiple"); path_union = new Widgets.HeaderBarButton (window, "path-union", _("Union"), null, "multiple"); pack_start (menu); pack_start (items); pack_start (new Gtk.Separator (Gtk.Orientation.VERTICAL)); pack_start (zoom); pack_start (new Gtk.Separator (Gtk.Orientation.VERTICAL)); pack_start (group); pack_start (ungroup); pack_start (new Gtk.Separator (Gtk.Orientation.VERTICAL)); pack_start (move_up); pack_start (move_down); pack_start (move_top); pack_start (move_bottom); pack_start (new Gtk.Separator (Gtk.Orientation.VERTICAL)); pack_end (preferences); pack_end (layout); pack_end (export); pack_end (new Gtk.Separator (Gtk.Orientation.VERTICAL)); pack_end (path_difference); pack_end (path_exclusion); pack_end (path_intersect); pack_end (path_union); pack_end (new Gtk.Separator (Gtk.Orientation.VERTICAL)); build_signals (); } private Gtk.PopoverMenu build_main_menu_popover () { var grid = new Gtk.Grid (); grid.margin_top = 6; grid.margin_bottom = 3; grid.orientation = Gtk.Orientation.VERTICAL; grid.width_request = 240; grid.name = "main"; var new_window_button = create_model_button ( _("New Window"), "window-new-symbolic", Akira.Services.ActionManager.ACTION_PREFIX + Akira.Services.ActionManager.ACTION_NEW_WINDOW); var separator = new Gtk.Separator (Gtk.Orientation.HORIZONTAL); separator.margin_top = separator.margin_bottom = 3; var open_button = create_model_button ( _("Open"), "document-open-symbolic", Akira.Services.ActionManager.ACTION_PREFIX + Akira.Services.ActionManager.ACTION_OPEN); recent_files_grid = new Gtk.Grid (); recent_files_grid.margin_top = 6; recent_files_grid.margin_bottom = 3; recent_files_grid.orientation = Gtk.Orientation.VERTICAL; recent_files_grid.width_request = 220; recent_files_grid.name = "files-menu"; var open_recent_button = new Gtk.ModelButton (); open_recent_button.text = _("Open Recent"); open_recent_button.menu_name = "files-menu"; fetch_recent_files.begin (); var separator2 = new Gtk.Separator (Gtk.Orientation.HORIZONTAL); separator2.margin_top = separator2.margin_bottom = 3; var save_button = create_model_button ( _("Save"), "document-save-symbolic", Akira.Services.ActionManager.ACTION_PREFIX + Akira.Services.ActionManager.ACTION_SAVE); var save_as_button = create_model_button ( _("Save As"), "document-save-as-symbolic", Akira.Services.ActionManager.ACTION_PREFIX + Akira.Services.ActionManager.ACTION_SAVE_AS); var separator3 = new Gtk.Separator (Gtk.Orientation.HORIZONTAL); separator3.margin_top = separator3.margin_bottom = 3; var quit_button = create_model_button ( _("Quit"), "system-shutdown-symbolic", Akira.Services.ActionManager.ACTION_PREFIX + Akira.Services.ActionManager.ACTION_QUIT); grid.add (new_window_button); grid.add (separator); grid.add (open_button); grid.add (open_recent_button); grid.add (separator2); grid.add (save_button); grid.add (save_as_button); grid.add (separator3); grid.add (quit_button); grid.show_all (); var popover = new Gtk.PopoverMenu (); popover.add (grid); popover.add (recent_files_grid); popover.child_set_property (grid, "submenu", "main"); popover.child_set_property (recent_files_grid, "submenu", "files-menu"); return popover; } private Gtk.PopoverMenu build_items_popover () { var grid = new Gtk.Grid (); grid.margin_top = 6; grid.margin_bottom = 3; grid.orientation = Gtk.Orientation.VERTICAL; grid.width_request = 200; grid.name = "main"; var artboard = create_model_button ( _("Artboard"), "window-new-symbolic", Akira.Services.ActionManager.ACTION_PREFIX + Akira.Services.ActionManager.ACTION_ARTBOARD_TOOL); var separator = new Gtk.Separator (Gtk.Orientation.HORIZONTAL); separator.margin_top = separator.margin_bottom = 3; // Create the shapes submenu var shapes_grid = new Gtk.Grid (); shapes_grid.margin_top = 6; shapes_grid.margin_bottom = 3; shapes_grid.orientation = Gtk.Orientation.VERTICAL; shapes_grid.width_request = 200; shapes_grid.name = "shapes-menu"; var back_button = new Gtk.ModelButton (); back_button.text = _("Add Items"); back_button.inverted = true; back_button.menu_name = "main"; var sub_separator = new Gtk.Separator (Gtk.Orientation.HORIZONTAL); sub_separator.margin_top = sub_separator.margin_bottom = 3; var rectangle = create_model_button ( _("Rectangle"), "shape-rectangle-symbolic", Akira.Services.ActionManager.ACTION_PREFIX + Akira.Services.ActionManager.ACTION_RECT_TOOL); var ellipse = create_model_button ( _("Ellipse"), "shape-circle-symbolic", Akira.Services.ActionManager.ACTION_PREFIX + Akira.Services.ActionManager.ACTION_ELLIPSE_TOOL); shapes_grid.add (back_button); shapes_grid.add (sub_separator); shapes_grid.add (rectangle); shapes_grid.add (ellipse); shapes_grid.show_all (); var shapes_button = new Gtk.ModelButton (); shapes_button.text = _("Shapes"); shapes_button.menu_name = "shapes-menu"; var separator2 = new Gtk.Separator (Gtk.Orientation.HORIZONTAL); separator2.margin_top = separator2.margin_bottom = 3; var vector = create_model_button (_("Vector"), "segment-curve", "V"); var pencil = create_model_button (_("Pencil"), "edit-symbolic", "P"); var text = create_model_button ( _("Text"), "shape-text-symbolic", Akira.Services.ActionManager.ACTION_PREFIX + Akira.Services.ActionManager.ACTION_TEXT_TOOL); var image = create_model_button ( _("Image"), "image-x-generic-symbolic", Akira.Services.ActionManager.ACTION_PREFIX + Akira.Services.ActionManager.ACTION_IMAGE_TOOL); grid.add (artboard); grid.add (separator); grid.add (shapes_button); grid.add (separator2); grid.add (vector); grid.add (pencil); grid.add (text); grid.add (image); grid.show_all (); popover_insert = new Gtk.PopoverMenu (); popover_insert.add (grid); popover_insert.add (shapes_grid); popover_insert.child_set_property (grid, "submenu", "main"); popover_insert.child_set_property (shapes_grid, "submenu", "shapes-menu"); return popover_insert; } private Gtk.PopoverMenu build_export_popover () { var grid = new Gtk.Grid (); grid.margin_top = 6; grid.margin_bottom = 3; grid.orientation = Gtk.Orientation.VERTICAL; grid.width_request = 240; grid.name = "main"; var export_selection = create_model_button ( _("Export Current Selection"), null, Akira.Services.ActionManager.ACTION_PREFIX + Akira.Services.ActionManager.ACTION_EXPORT_SELECTION); var export_artboards = create_model_button ( _("Export Artboards"), null, Akira.Services.ActionManager.ACTION_PREFIX + Akira.Services.ActionManager.ACTION_EXPORT_ARTBOARDS); var separator = new Gtk.Separator (Gtk.Orientation.HORIZONTAL); separator.margin_top = separator.margin_bottom = 3; var export_area_grab = create_model_button ( _("Highlight Area to Export"), null, Akira.Services.ActionManager.ACTION_PREFIX + Akira.Services.ActionManager.ACTION_EXPORT_GRAB ); grid.add (export_selection); grid.add (export_artboards); grid.add (separator); grid.add (export_area_grab); grid.show_all (); var popover = new Gtk.PopoverMenu (); popover.add (grid); return popover; } private Gtk.PopoverMenu build_layout_popover () { var grid = new Gtk.Grid (); grid.margin_top = 6; grid.margin_bottom = 3; grid.orientation = Gtk.Orientation.VERTICAL; grid.width_request = 240; grid.name = "main"; var pixel_grid = create_model_button ( _("Toggle Pixel Grid"), null, Akira.Services.ActionManager.ACTION_PREFIX + Akira.Services.ActionManager.ACTION_TOGGLE_PIXEL_GRID); var presentation_mode = create_model_button ( _("Presentation Mode"), null, Akira.Services.ActionManager.ACTION_PREFIX + Akira.Services.ActionManager.ACTION_PRESENTATION); grid.add (pixel_grid); grid.add (presentation_mode); grid.show_all (); var popover = new Gtk.PopoverMenu (); popover.add (grid); return popover; } private void build_signals () { window.event_bus.toggle_presentation_mode.connect (toggle); window.event_bus.file_edited.connect (on_file_edited); window.event_bus.file_saved.connect (on_file_saved); window.event_bus.selected_items_list_changed.connect (on_selected_items_changed); window.event_bus.selected_items_changed.connect (on_selected_items_changed); window.event_bus.z_selected_changed.connect (update_button_sensitivity); window.event_bus.update_recent_files_list.connect (fetch_recent_files); } private void toggle () { toggled = !toggled; if (!toggled) { window.event_bus.canvas_notification (_("Presentation Mode enabled.")); } } /** * Fetch the recently opened files from GSettings and add them to the list * if those files still exists. */ public async void fetch_recent_files () { recent_files_grid.@foreach (child => { recent_files_grid.remove (child); }); // Add default buttons. var back_button = new Gtk.ModelButton (); back_button.text = _("Main Menu"); back_button.inverted = true; back_button.menu_name = "main"; back_button.expand = true; var sub_separator = new Gtk.Separator (Gtk.Orientation.HORIZONTAL); sub_separator.margin_top = sub_separator.margin_bottom = 3; recent_files_grid.add (back_button); recent_files_grid.add (sub_separator); // Loop a first time to clear missing files and prevent wrong accelerators. string[] all_files = {}; for (var i = 0; i <= settings.recently_opened.length; i++) { // Skip if the record is empty. if (settings.recently_opened[i] == null) { continue; } // Skip if the file doesn't exist. var file = File.new_for_path (settings.recently_opened[i]); if (!file.query_exists ()) { continue; } all_files += settings.recently_opened[i]; } // Update the GSettings to prevent loading an unavailable file. settings.set_strv ("recently-opened", all_files); for (var i = 0; i <= all_files.length; i++) { // Skip if the record is empty. if (all_files[i] == null) { continue; } // Store the full path in a variable before the split() method explodes the string. var full_path = all_files[i]; // Get the file name. string[] split_string = all_files[i].split ("/"); var file_name = split_string[split_string.length - 1].replace (".akira", ""); var button = new Gtk.ModelButton (); // Add quick accelerators only for the first 3 items. string? accels = null; if (i < 3) { switch (i) { case 0: accels = Akira.Services.ActionManager.ACTION_PREFIX + Akira.Services.ActionManager.ACTION_LOAD_FIRST; break; case 1: accels = Akira.Services.ActionManager.ACTION_PREFIX + Akira.Services.ActionManager.ACTION_LOAD_SECOND; break; case 2: accels = Akira.Services.ActionManager.ACTION_PREFIX + Akira.Services.ActionManager.ACTION_LOAD_THIRD; break; } button.get_child ().destroy (); var label = new Granite.AccelLabel.from_action_name (file_name, accels); button.add (label); button.action_name = accels; } else { button.text = file_name; // Define the open action on click only for those files that don't // have an accelerator to prevent double calls. button.clicked.connect (() => { var file = File.new_for_path (full_path); if (!file.query_exists ()) { window.event_bus.canvas_notification ( _("Unable to open file at '%s'").printf (full_path) ); return; } File[] files = {}; files += file; window.app.open (files, ""); }); } button.tooltip_text = all_files[i]; recent_files_grid.add (button); } recent_files_grid.show_all (); } private void on_file_edited () { if (title.has_suffix ("*")) { return; } title = ("%s*").printf (title); } private void on_file_saved (string? file_name) { if (file_name == null) { title = title.has_suffix ("*") ? title.slice (0, title.length - 1) : title; return; } title = file_name.has_suffix (".akira") ? file_name.replace (".akira", "") : file_name; } private void on_selected_items_changed (List selected_items) { if (selected_items.length () == 0) { selected_item = null; update_button_sensitivity (); return; } if (selected_item == null || selected_item != selected_items.nth_data (0)) { selected_item = selected_items.nth_data (0); update_button_sensitivity (); } } private void update_button_sensitivity () { var z_buttons_sensitive = selected_item != null && !(selected_item is Lib.Items.CanvasArtboard); move_up.sensitive = z_buttons_sensitive; move_down.sensitive = z_buttons_sensitive; move_top.sensitive = z_buttons_sensitive; move_bottom.sensitive = z_buttons_sensitive; if (!z_buttons_sensitive || selected_item.get_canvas () == null) { return; } var item_position = window.items_manager.get_item_z_index (selected_item); if (item_position == 0) { move_down.sensitive = false; move_bottom.sensitive = false; } // Account for nobs and select effect. if (item_position == window.items_manager.get_item_top_position (selected_item)) { move_up.sensitive = false; move_top.sensitive = false; } } private Gtk.ModelButton create_model_button (string text, string? icon, string? accels = null) { var button = new Gtk.ModelButton (); button.get_child ().destroy (); var label = new Granite.AccelLabel.from_action_name (text, accels); if (icon != null) { var image = new Gtk.Image.from_icon_name (icon, Gtk.IconSize.MENU); image.margin_end = 6; label.attach_next_to ( image, label.get_child_at (0, 0), Gtk.PositionType.LEFT ); } button.add (label); button.action_name = accels; return button; } } Akira-0.0.16/src/Layouts/LeftSideBar.vala000066400000000000000000000054461410625726100200620ustar00rootroot00000000000000/* * Copyright (c) 2019 Alecaddd (http://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Alessandro "Alecaddd" Castellani */ public class Akira.Layouts.LeftSideBar : Gtk.Grid { public weak Akira.Window window { get; construct; } public Akira.Layouts.Partials.TransformPanel transform_panel; public Akira.Layouts.Partials.FillsPanel fills_panel; public Akira.Layouts.Partials.BordersPanel borders_panel; public bool toggled { get { return visible; } set { visible = value; no_show_all = !value; } } public LeftSideBar (Akira.Window window) { Object ( window: window, orientation: Gtk.Orientation.HORIZONTAL, toggled: true ); } construct { window.event_bus.toggle_presentation_mode.connect (toggle); window.event_bus.request_widget_redraw.connect (on_widget_redraw_request); get_style_context ().add_class ("sidebar-l"); var align_items_panel = new Akira.Layouts.Partials.AlignItemsPanel (window); transform_panel = new Akira.Layouts.Partials.TransformPanel (window); var border_radius_panel = new Akira.Layouts.Partials.BorderRadiusPanel (window); fills_panel = new Akira.Layouts.Partials.FillsPanel (window); borders_panel = new Akira.Layouts.Partials.BordersPanel (window); var scrolled_window = new Gtk.ScrolledWindow (null, null); scrolled_window.hscrollbar_policy = Gtk.PolicyType.NEVER; scrolled_window.expand = true; var scrolled_grid = new Gtk.Grid (); scrolled_grid.expand = true; scrolled_grid.attach (transform_panel, 0, 0, 1, 1); scrolled_grid.attach (border_radius_panel, 0, 1, 1, 1); scrolled_grid.attach (fills_panel, 0, 2, 1, 1); scrolled_grid.attach (borders_panel, 0, 3, 1, 1); scrolled_window.add (scrolled_grid); attach (align_items_panel, 0, 0, 1, 1); attach (scrolled_window, 0, 1, 1, 1); show_all (); } private void toggle () { toggled = !toggled; } private void on_widget_redraw_request () { queue_resize (); } } Akira-0.0.16/src/Layouts/MainCanvas.vala000066400000000000000000000200531410625726100177450ustar00rootroot00000000000000/* * Copyright (c) 2019-2020 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Alessandro "Alecaddd" Castellani * Authored by: Giacomo "giacomoalbe" Alberini */ public class Akira.Layouts.MainCanvas : Gtk.Grid { public const int CANVAS_SIZE = 100000; public const double SCROLL_DISTANCE = 0; public Gtk.ScrolledWindow main_scroll; public Akira.Lib.Canvas canvas; public weak Akira.Window window { get; construct; } private Gtk.Overlay main_overlay; private Granite.Widgets.OverlayBar overlaybar; private Granite.Widgets.Toast notification; private double scroll_origin_x = 0; private double scroll_origin_y = 0; public MainCanvas (Akira.Window window) { Object (window: window, orientation: Gtk.Orientation.VERTICAL); } construct { get_style_context ().add_class ("main-canvas"); main_overlay = new Gtk.Overlay (); notification = new Granite.Widgets.Toast (_("")); main_scroll = new Gtk.ScrolledWindow (null, null); main_scroll.expand = true; // Overlay the scrollbars only if mouse pointer is inside canvas main_scroll.overlay_scrolling = false; // Change visibility of canvas scrollbars main_scroll.set_policy (Gtk.PolicyType.NEVER, Gtk.PolicyType.NEVER); canvas = new Akira.Lib.Canvas (window); canvas.set_bounds (0, 0, CANVAS_SIZE, CANVAS_SIZE); canvas.set_scale (1.0); canvas.canvas_moved.connect ((event_x, event_y) => { // Move scroll window according to normalized mouse delta // relative to the scroll window, so with Canvas' pixel // coordinates translated into ScrolledWindow's one. double event_x_pixel_space = event_x; double event_y_pixel_space = event_y; // Convert coordinates to pixel space, which does account for // canvas scale and canvas translation. // Otherwise, delta can start to "diverge" due to the // translation of starting point happening during canvas translation canvas.convert_to_pixels (ref event_x_pixel_space, ref event_y_pixel_space); var delta_x = event_x_pixel_space - scroll_origin_x; var delta_y = event_y_pixel_space - scroll_origin_y; main_scroll.hadjustment.value -= delta_x; main_scroll.vadjustment.value -= delta_y; }); canvas.canvas_scroll_set_origin.connect ((origin_x, origin_y) => { // Update scroll origin on Canvas' button_press_event scroll_origin_x = origin_x; scroll_origin_y = origin_y; canvas.convert_to_pixels (ref scroll_origin_x, ref scroll_origin_y); }); canvas.scroll_event.connect (on_scroll); main_scroll.add (canvas); main_overlay.add (main_scroll); main_overlay.add_overlay (notification); add (main_overlay); // Set up event listeners. window.event_bus.exporting.connect (on_exporting); window.event_bus.export_completed.connect (on_export_completed); window.event_bus.canvas_notification.connect (trigger_notification); } public bool on_scroll (Gdk.EventScroll event) { bool is_shift = (event.state & Gdk.ModifierType.SHIFT_MASK) > 0; bool is_ctrl = (event.state & Gdk.ModifierType.CONTROL_MASK) > 0; double delta_x, delta_y; event.get_scroll_deltas (out delta_x, out delta_y); if (delta_y < -SCROLL_DISTANCE) { // Scroll UP. if (is_ctrl) { // Divide the delta if it's too high. This fixes the zoom with // the mouse wheel. if (delta_y <= -1) { delta_y /= 10; } // Get the current zoom before zooming. double old_zoom = canvas.get_scale (); // Zoom in. window.event_bus.update_scale (delta_y * -1); // Adjust zoom based on cursor position. zoom_on_cursor (event, old_zoom); } else if (is_shift) { main_scroll.hadjustment.value += delta_y * 10; } else { main_scroll.vadjustment.value += delta_y * 10; } } else if (delta_y > SCROLL_DISTANCE) { // Scroll DOWN. if (is_ctrl) { // Divide the delta if it's too high. This fixes the zoom with // the mouse wheel. if (delta_y >= 1) { delta_y /= 10; } // Get the current zoom before zooming. double old_zoom = canvas.get_scale (); // Zoom out. window.event_bus.update_scale (-delta_y); // Adjust zoom based on cursor position. zoom_on_cursor (event, old_zoom); } else if (is_shift) { main_scroll.hadjustment.value += delta_y * 10; } else { main_scroll.vadjustment.value += delta_y * 10; } } if (delta_x < -SCROLL_DISTANCE) { main_scroll.hadjustment.value += delta_x * 10; } else if (delta_x > SCROLL_DISTANCE) { main_scroll.hadjustment.value += delta_x * 10; } return true; } private void zoom_on_cursor (Gdk.EventScroll event, double old_zoom) { // The regular zoom mode shifts the visible viewing area // to center itself (it already has one translation applied) // so you cannot just move the viewing area by the distance // of the current mouse location and the new mouse location. // If you want to zoom to your mouse you need to find the // difference between the distances of the current mouse location // in the current view scale to the left view border and the new // mouse location that has the new canvas scale applied to the // new left view border and shift the view by that difference. int width = main_scroll.get_allocated_width (); int height = main_scroll.get_allocated_height (); var center_x = main_scroll.hadjustment.value + (width / 2); var center_y = main_scroll.vadjustment.value + (height / 2); var old_center_x = (center_x / canvas.get_scale ()) * old_zoom; var old_center_y = (center_y / canvas.get_scale ()) * old_zoom; var new_event_x = (event.x / old_zoom) * canvas.get_scale (); var new_event_y = (event.y / old_zoom) * canvas.get_scale (); var old_hadjustment = old_center_x - (width / 2); var old_vadjustment = old_center_y - (height / 2); main_scroll.hadjustment.value += (new_event_x - main_scroll.hadjustment.value) - (event.x - old_hadjustment); main_scroll.vadjustment.value += (new_event_y - main_scroll.vadjustment.value) - (event.y - old_vadjustment); } private async void on_exporting (string message) { overlaybar = new Granite.Widgets.OverlayBar (main_overlay); overlaybar.label = message; overlaybar.active = true; show_all (); } private async void on_export_completed () { main_overlay.remove (overlaybar); overlaybar = null; yield trigger_notification (_("Export completed!")); } private async void trigger_notification (string message) { notification.title = message; notification.send_notification (); } } Akira-0.0.16/src/Layouts/MainWindow.vala000066400000000000000000000036311410625726100200040ustar00rootroot00000000000000/* * Copyright (c) 2019 Alecaddd (http://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Alessandro "Alecaddd" Castellani */ public class Akira.Layouts.MainWindow : Gtk.Grid { public weak Akira.Window window { get; construct; } public Akira.Layouts.MainCanvas main_canvas; public Akira.Layouts.LeftSideBar left_sidebar; public Akira.Layouts.RightSideBar right_sidebar; public Gtk.Paned pane; public Gtk.Paned pane2; public MainWindow (Akira.Window window) { Object (window: window); } construct { left_sidebar = new Akira.Layouts.LeftSideBar (window); right_sidebar = new Akira.Layouts.RightSideBar (window); main_canvas = new Akira.Layouts.MainCanvas (window); pane = new Gtk.Paned (Gtk.Orientation.HORIZONTAL); pane2 = new Gtk.Paned (Gtk.Orientation.HORIZONTAL); pane.pack2 (pane2, true, false); pane2.pack1 (main_canvas, true, false); if (!settings.get_boolean ("invert-sidebar")) { pane.pack1 (left_sidebar, false, false); pane2.pack2 (right_sidebar, false, false); } else { pane.pack1 (right_sidebar, false, false); pane2.pack2 (left_sidebar, false, false); } attach (pane, 0, 0, 1, 1); } } Akira-0.0.16/src/Layouts/Partials/000077500000000000000000000000001410625726100166375ustar00rootroot00000000000000Akira-0.0.16/src/Layouts/Partials/AlignItemsPanel.vala000066400000000000000000000074671410625726100225360ustar00rootroot00000000000000/* * Copyright (c) 2019 Alecaddd (http://alecaddd.com) * * 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 * * Authored by: Giacomo "giacomoalbe" Alberini */ public class Akira.Layouts.Partials.AlignItemsPanel : Gtk.Grid { public weak Akira.Window window { get; construct; } public int current_button_column { get; set; default = 0; } private struct AlignBoxItem { public string type; public string? action_name; public string? icon_name; public string? tooltip_text; public string[]? accels; public AlignBoxItem ( string type, string? action_name = null, string? icon_name = null, string? tooltip_text = null, string[]? accels = null) { this.type = type; this.action_name = action_name; this.icon_name = icon_name; this.tooltip_text = tooltip_text; this.accels = accels; } } private AlignBoxItem[] align_items_panel_buttons = { AlignBoxItem ("btn", "even-h", "distribute-horizontal-center", _("Distribute Horizontally"), {"1"}), AlignBoxItem ("btn", "even-v", "distribute-vertical-center", _("Distribute Vertically"), {"2"}), AlignBoxItem ("sep"), AlignBoxItem ("btn", "alig-h-l", "align-horizontal-left", _("Align Left"), {"3"}), AlignBoxItem ("btn", "alig-h-c", "align-horizontal-center", _("Align Center"), {"4"}), AlignBoxItem ("btn", "alig-h-r", "align-horizontal-right", _("Align Right"), {"5"}), AlignBoxItem ("sep"), AlignBoxItem ("btn", "alig-v-t", "align-vertical-top", _("Align Top"), {"6"}), AlignBoxItem ("btn", "alig-v-c", "align-vertical-center", _("Align Middle"), {"7"}), AlignBoxItem ("btn", "alig-v-b", "align-vertical-bottom", _("Align Bottom"), {"8"}) }; public AlignItemsPanel (Akira.Window window) { Object ( window: window, orientation: Gtk.Orientation.VERTICAL ); } construct { get_style_context ().add_class ("alignment-box"); column_homogeneous = true; hexpand = true; foreach (var item in align_items_panel_buttons) { switch (item.type) { case "sep": var separator = new Gtk.Separator (Gtk.Orientation.VERTICAL); separator.halign = Gtk.Align.CENTER; separator.margin_top = separator.margin_bottom = 4; attach (separator, current_button_column++, 0, 1, 1); break; case "btn": var tmp_align_box_button = new Widgets.AlignBoxButton ( window, item.action_name, item.icon_name, item.tooltip_text, item.accels); attach (tmp_align_box_button, current_button_column++, 0, 1, 1); break; } } } } Akira-0.0.16/src/Layouts/Partials/Artboard.vala000066400000000000000000000511471410625726100212520ustar00rootroot00000000000000/* * Copyright (c) 2019-2020 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Alessandro "Alecaddd" Castellani * Authored by: Giacomo Alberini */ public class Akira.Layouts.Partials.Artboard : Gtk.ListBoxRow { public weak Akira.Window window { get; construct; } private Gtk.TargetList drop_targets { get; set; default = null; } private const Gtk.TargetEntry ARTBOARD_ENTRY[] = { { "ARTBOARD", Gtk.TargetFlags.SAME_APP, 0 } }; private const Gtk.TargetEntry TARGET_ENTRIES[] = { { "ARTBOARD", Gtk.TargetFlags.SAME_APP, 0 }, { "LAYER", Gtk.TargetFlags.SAME_APP, 0 } }; private Gtk.Grid artboard_handle; public Gtk.Label label; public Gtk.Entry entry; public Gtk.EventBox handle; public Gtk.Image icon_locked; public Gtk.Image icon_unlocked; public Gtk.Image icon_hidden; public Gtk.Image icon_visible; public Gtk.ToggleButton button_locked; public Gtk.ToggleButton button_hidden; public Gtk.ToggleButton button; public Gtk.Image button_icon; public Gtk.Revealer revealer; public Gtk.ListBox container; public Akira.Lib.Items.CanvasArtboard model { get; construct; } // Drag and Drop properties. private Gtk.Revealer motion_revealer; public Gtk.Revealer motion_artboard_revealer; private bool _editing; public bool editing { get { return _editing; } set { _editing = value; } } public Artboard (Akira.Window window, Akira.Lib.Items.CanvasArtboard model) { Object ( window: window, model: model ); } construct { get_style_context ().add_class ("artboard"); drop_targets = new Gtk.TargetList (TARGET_ENTRIES); label = new Gtk.Label (""); label.get_style_context ().add_class ("artboard-name"); label.halign = Gtk.Align.FILL; label.xalign = 0; label.hexpand = true; label.set_ellipsize (Pango.EllipsizeMode.END); model.name.bind_property ("name", label, "label", BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL); entry = new Gtk.Entry (); entry.margin_top = entry.margin_bottom = 2; entry.margin_start = 6; entry.expand = true; entry.visible = false; entry.no_show_all = true; // NOTE: We can't bind the entry to the model.name otherwise we won't be // able to handle the ESC key to restore the previous entry. entry.text = model.name.name; entry.activate.connect (update_on_enter); entry.key_release_event.connect (update_on_escape); entry.focus_in_event.connect (handle_focus_in); entry.focus_out_event.connect (update_on_leave); var label_grid = new Gtk.Grid (); label_grid.expand = true; label_grid.attach (label, 0, 0, 1, 1); label_grid.attach (entry, 1, 0, 1, 1); revealer = new Gtk.Revealer (); revealer.hexpand = true; revealer.reveal_child = true; container = new Gtk.ListBox (); container.get_style_context ().add_class ("artboard-container"); container.activate_on_single_click = false; container.selection_mode = Gtk.SelectionMode.SINGLE; // Block all the events from bubbling up and triggering the Artboard's events. container.event.connect (() => { return true; }); revealer.add (container); var motion_grid = new Gtk.Grid (); motion_grid.get_style_context ().add_class ("grid-motion"); motion_grid.height_request = 2; motion_revealer = new Gtk.Revealer (); motion_revealer.transition_type = Gtk.RevealerTransitionType.SLIDE_DOWN; motion_revealer.reveal_child = false; motion_revealer.add (motion_grid); var motion_artboard_grid = new Gtk.Grid (); motion_artboard_grid.get_style_context ().add_class ("grid-motion"); motion_artboard_grid.height_request = 2; motion_artboard_revealer = new Gtk.Revealer (); motion_artboard_revealer.transition_type = Gtk.RevealerTransitionType.SLIDE_DOWN; motion_artboard_revealer.reveal_child = false; motion_artboard_revealer.add (motion_artboard_grid); handle = new Gtk.EventBox (); handle.hexpand = true; handle.add (label_grid); handle.button_press_event.connect (on_click_event); button_locked = new Gtk.ToggleButton (); button_locked.tooltip_text = _("Lock Layer"); button_locked.get_style_context ().remove_class ("button"); button_locked.get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT); button_locked.get_style_context ().add_class ("layer-action"); button_locked.valign = Gtk.Align.CENTER; icon_locked = new Gtk.Image.from_icon_name ("changes-allow-symbolic", Gtk.IconSize.MENU); icon_unlocked = new Gtk.Image.from_icon_name ("changes-prevent-symbolic", Gtk.IconSize.MENU); icon_unlocked.visible = false; icon_unlocked.no_show_all = true; button_hidden = new Gtk.ToggleButton (); button_hidden.tooltip_text = _("Hide Layer"); button_hidden.get_style_context ().remove_class ("button"); button_hidden.get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT); button_hidden.get_style_context ().add_class ("layer-action"); button_hidden.valign = Gtk.Align.CENTER; icon_hidden = new Gtk.Image.from_icon_name ("layer-visible-symbolic", Gtk.IconSize.MENU); icon_visible = new Gtk.Image.from_icon_name ("layer-hidden-symbolic", Gtk.IconSize.MENU); icon_visible.visible = false; icon_visible.no_show_all = true; var button_locked_grid = new Gtk.Grid (); button_locked_grid.margin_end = 6; button_locked_grid.attach (icon_locked, 0, 0, 1, 1); button_locked_grid.attach (icon_unlocked, 1, 0, 1, 1); var button_hidden_grid = new Gtk.Grid (); button_hidden_grid.margin_end = 14; button_hidden_grid.attach (icon_hidden, 0, 0, 1, 1); button_hidden_grid.attach (icon_visible, 1, 0, 1, 1); button_hidden.add (button_hidden_grid); button_locked.add (button_locked_grid); button = new Gtk.ToggleButton (); button.active = true; button.get_style_context ().remove_class ("button"); button.get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT); button.get_style_context ().add_class ("revealer-button"); button_icon = new Gtk.Image.from_icon_name ("pan-down-symbolic", Gtk.IconSize.MENU); button.add (button_icon); artboard_handle = new Gtk.Grid (); artboard_handle.get_style_context ().add_class ("artboard-handle"); artboard_handle.attach (handle, 0, 0, 1, 1); artboard_handle.attach (button_locked, 1, 0, 1, 1); artboard_handle.attach (button_hidden, 2, 0, 1, 1); artboard_handle.attach (button, 3, 0, 1, 1); var grid = new Gtk.Grid (); grid.attach (artboard_handle, 0, 0, 1, 1); grid.attach (motion_revealer, 0, 1, 1, 1); grid.attach (revealer, 0, 2, 1, 1); grid.attach (motion_artboard_revealer, 0, 3, 1, 1); add (grid); get_style_context ().add_class ("artboard"); build_drag_and_drop (); button.toggled.connect (() => { revealer.reveal_child = ! revealer.get_reveal_child (); if (revealer.get_reveal_child ()) { button.get_style_context ().remove_class ("closed"); } else { button.get_style_context ().add_class ("closed"); } }); model.layer.notify["selected"].connect (() => { if (model.layer.selected) { activate (); return; } ((Gtk.ListBox) parent).unselect_row (this); }); handle.enter_notify_event.connect (event => { if (model.layer.locked) { return true; } get_style_context ().add_class ("hover"); window.event_bus.hover_over_layer (model); return false; }); handle.leave_notify_event.connect (event => { get_style_context ().remove_class ("hover"); window.event_bus.hover_over_layer (null); return false; }); container.bind_model (model.items, item => { return new Layouts.Partials.Layer (window, ((Lib.Items.CanvasItem) item), container); }); lock_actions (); hide_actions (); window.event_bus.hover_over_item.connect (on_hover_over_item); } private void on_hover_over_item (Lib.Items.CanvasItem? item) { if (item == model) { get_style_context ().add_class ("hovered"); return; } get_style_context ().remove_class ("hovered"); } private void build_drag_and_drop () { // Make the artboard layer a draggable widget. Gtk.drag_source_set (this, Gdk.ModifierType.BUTTON1_MASK, ARTBOARD_ENTRY, Gdk.DragAction.MOVE); drag_begin.connect (on_drag_begin); drag_data_get.connect (on_drag_data_get); // Make the artboard handle widget a DnD destination. Gtk.drag_dest_set (artboard_handle, Gtk.DestDefaults.MOTION, TARGET_ENTRIES, Gdk.DragAction.MOVE); artboard_handle.drag_motion.connect (on_drag_motion); artboard_handle.drag_leave.connect (on_drag_leave); artboard_handle.drag_drop.connect (on_drag_drop); artboard_handle.drag_data_received.connect (on_drag_data_received); } private void on_drag_begin (Gtk.Widget widget, Gdk.DragContext context) { // Close the layers container. button.active = false; var row = (widget as Akira.Layouts.Partials.Artboard); Gtk.Allocation alloc; row.artboard_handle.get_allocation (out alloc); var surface = new Cairo.ImageSurface (Cairo.Format.ARGB32, alloc.width, alloc.height); var cr = new Cairo.Context (surface); cr.set_source_rgba (0, 0, 0, 0.3); cr.set_line_width (1); cr.move_to (0, 0); cr.line_to (alloc.width, 0); cr.line_to (alloc.width, alloc.height); cr.line_to (0, alloc.height); cr.line_to (0, 0); cr.stroke (); cr.set_source_rgba (255, 255, 255, 0.5); cr.rectangle (0, 0, alloc.width, alloc.height); cr.fill (); row.artboard_handle.draw (cr); Gtk.drag_set_icon_surface (context, surface); } private void on_drag_data_get (Gtk.Widget widget, Gdk.DragContext context, Gtk.SelectionData selection_data, uint target_type, uint time) { uchar[] data = new uchar[(sizeof (Akira.Layouts.Partials.Artboard))]; ((Gtk.Widget[])data)[0] = widget; selection_data.set ( Gdk.Atom.intern_static_string ("ARTBOARD"), 32, data ); } public bool on_drag_motion (Gdk.DragContext context, int x, int y, uint time) { var target = Gtk.drag_dest_find_target (this, context, drop_targets); if (target == Gdk.Atom.intern_static_string ("ARTBOARD")) { motion_artboard_revealer.reveal_child = true; } else { motion_revealer.reveal_child = true; } return true; } public void on_drag_leave (Gdk.DragContext context, uint time) { var target = Gtk.drag_dest_find_target (this, context, drop_targets); if (target == Gdk.Atom.intern_static_string ("ARTBOARD")) { motion_artboard_revealer.reveal_child = false; } else { motion_revealer.reveal_child = false; } } /** * Receive the signal when an item is dropped on top of the layer. * If it's a valid layer, get the correct target type and trigger on_drag_data_received (). */ private bool on_drag_drop (Gtk.Widget widget, Gdk.DragContext context, int x, int y, uint time) { if (context.list_targets () != null) { var target_type = (Gdk.Atom) context.list_targets ().nth_data (0); Gtk.drag_get_data (widget, context, target_type, time); } return false; } /** * Handle the received layer, find the position of the targeted layer and trigger * a z-index update. */ private void on_drag_data_received ( Gdk.DragContext context, int x, int y, Gtk.SelectionData selection_data, uint target_type, uint time ) { int items_count, pos_source, pos_target, source, target; var type = Gtk.drag_dest_find_target (this, context, drop_targets); // Used to adjust the position of swappable items if the source item // is dragged from the bottom up. int position_adjustment = 0; if (type == Gdk.Atom.intern_static_string ("ARTBOARD")) { var artboard = (Layouts.Partials.Artboard) ( (Gtk.Widget[]) selection_data.get_data () )[0]; items_count = (int) window.items_manager.artboards.get_n_items (); pos_target = items_count - 1 - window.items_manager.artboards.index (model); pos_source = items_count - 1 - window.items_manager.artboards.index (artboard.model); // Interrupt if item position doesn't exist. if (pos_source == -1) { return; } // z-index is the exact opposite of items placement as the last item // is the topmost element. Because of this, we need some trickery to // properly handle the list's order. source = items_count - 1 - pos_source; target = items_count - 1 - pos_target; // Interrupt if the item was dropped in the same position. if (source == target) { debug ("same position"); return; } // If the initial position is higher than the targeted dropped layer, it // means the layer was dragged from the bottom up, therefore we need to // increase the dropped target by 1 since we don't deal with location 0. if (source > target) { position_adjustment--; target++; } // Swap the position inside the List Model. window.items_manager.artboards.swap_items (source, target); // The actual items in the canvas might not match the items in the List Model // due to Artboards labels, grids, and other pseudo elements. Therefore we need // to get the real position of the child and swap them. var root = artboard.model.parent; root.move_child (root.find_child (artboard.model), root.find_child (model) + position_adjustment); window.event_bus.z_selected_changed (); return; } var layer = (Layer) ((Gtk.Widget[]) selection_data.get_data ())[0]; // Change artboard if necessary. window.items_manager.change_artboard.begin (layer.model, model); // Use the existing action to push an item all the way to the top. window.event_bus.change_z_selected (true, true); model.changed (true); } private bool on_click_event (Gdk.EventButton event) { if (model.layer.locked) { return true; } switch (event.type) { case Gdk.EventType.@2BUTTON_PRESS: entry.text = label.label; entry.visible = true; entry.no_show_all = false; label.visible = false; label.no_show_all = true; button_locked.visible = false; button_locked.no_show_all = true; button_hidden.visible = false; button_hidden.no_show_all = true; editing = true; Timeout.add (200, () => { entry.grab_focus (); return false; }); return true; case Gdk.EventType.BUTTON_PRESS: window.event_bus.request_add_item_to_selection (model); // Selected layers can't show hover a effect. get_style_context ().remove_class ("hovered"); // Always move the focus back to the canvas. window.event_bus.set_focus_on_canvas (); window.event_bus.hover_over_layer (null); return true; } return false; } public void update_on_enter () { update_label (); } public bool update_on_leave () { update_label (); window.event_bus.connect_typing_accel (); return false; } public bool update_on_escape (Gdk.EventKey key) { if (key.keyval == Gdk.Key.Escape) { entry.text = label.label; update_label (); window.event_bus.request_escape (); } return false; } private void update_label () { entry.visible = false; entry.no_show_all = true; label.visible = true; label.no_show_all = false; editing = false; var new_label = entry.get_text (); window.event_bus.set_focus_on_canvas (); if (label.label == new_label) { return; } label.label = new_label; } private bool handle_focus_in (Gdk.EventFocus event) { window.event_bus.disconnect_typing_accel (); return false; } private void lock_actions () { button_locked.bind_property ("active", model.layer, "locked", BindingFlags.BIDIRECTIONAL | BindingFlags.SYNC_CREATE); button_locked.toggled.connect (() => { var active = button_locked.get_active (); button_locked.tooltip_text = active ? _("Unlock Layer") : _("Lock Layer"); if (active) { button_locked.get_style_context ().add_class ("show"); // Disable any pointer events for a locked item. model.pointer_events = Goo.CanvasPointerEvents.NONE; // Let the UI know that this item was locked. window.event_bus.item_locked (model); ((Gtk.ListBox) parent).unselect_row (this); model.layer.selected = false; } else { button_locked.get_style_context ().remove_class ("show"); // Re-enable pointer events. model.pointer_events = Goo.CanvasPointerEvents.ALL; } icon_unlocked.visible = active; icon_unlocked.no_show_all = !active; icon_locked.visible = !active; icon_locked.no_show_all = active; window.event_bus.set_focus_on_canvas (); window.event_bus.file_edited (); }); } private void hide_actions () { button_hidden.bind_property ("active", model, "visibility", BindingFlags.BIDIRECTIONAL | BindingFlags.SYNC_CREATE, (binding, srcval, ref targetval) => { Goo.CanvasItemVisibility status = (bool) srcval.get_boolean () ? Goo.CanvasItemVisibility.INVISIBLE : Goo.CanvasItemVisibility.VISIBLE; targetval.set_enum (status); return true; }, (binding, srcval, ref targetval) => { var status = ((Goo.CanvasItemVisibility) srcval.get_enum ()) == Goo.CanvasItemVisibility.INVISIBLE; targetval.set_boolean (status); return true; }); button_hidden.toggled.connect (() => { var active = button_hidden.get_active (); button_hidden.tooltip_text = active ? _("Show Layer") : _("Hide Layer"); if (active) { button_hidden.get_style_context ().add_class ("show"); } else { button_hidden.get_style_context ().remove_class ("show"); } icon_visible.visible = active; icon_visible.no_show_all = ! active; icon_hidden.visible = ! active; icon_hidden.no_show_all = active; window.event_bus.set_focus_on_canvas (); window.event_bus.file_edited (); }); } } Akira-0.0.16/src/Layouts/Partials/BlendingModeItem.vala000066400000000000000000000022421410625726100226520ustar00rootroot00000000000000/* * Copyright (c) 2019 Alecaddd (http://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Giacomo "giacomoalbe" Alberini */ public class Akira.Layouts.Partials.BlendingModeItem : Gtk.Label { public Akira.Utils.BlendingMode mode { get; construct; } public BlendingModeItem (Akira.Utils.BlendingMode mode) { Object ( mode: mode ); } construct { label = mode.get_name (); halign = Gtk.Align.START; get_style_context ().add_class (Gtk.STYLE_CLASS_MENUITEM); } } Akira-0.0.16/src/Layouts/Partials/BorderItem.vala000066400000000000000000000075741410625726100215550ustar00rootroot00000000000000/** * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Alessandro "alecaddd" Castellani * Authored by: Ivan "isneezy" Vilanculo */ public class Akira.Layouts.Partials.BorderItem : Gtk.Grid { private unowned Akira.Window window; private unowned Lib.Components.Border border; private Gtk.Button hidden_button; private Gtk.Button delete_button; private Gtk.Image hidden_button_icon; private bool hidden { owned get { return border.hidden; } set { border.hidden = value; set_hidden_button (); toggle_ui_visibility (); } } public signal void border_deleted (); public BorderItem (Akira.Window window, Lib.Components.Border border) { this.window = window; this.border = border; create_ui (); hidden = border.hidden; create_event_bindings (); show_all (); } private void create_ui () { margin_top = margin_bottom = 5; var fill_chooser = new Gtk.Grid (); fill_chooser.hexpand = true; fill_chooser.margin_end = 5; fill_chooser.add (new Widgets.ColorRow (window, new Models.ColorModel (null, border))); hidden_button = new Gtk.Button (); hidden_button.get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT); hidden_button.get_style_context ().add_class ("button-rounded"); hidden_button.can_focus = false; hidden_button.valign = Gtk.Align.CENTER; delete_button = new Gtk.Button (); delete_button.get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT); delete_button.get_style_context ().add_class ("button-rounded"); delete_button.can_focus = false; delete_button.valign = Gtk.Align.CENTER; delete_button.set_tooltip_text (_("Remove border color")); delete_button.add (new Gtk.Image.from_icon_name ("user-trash-symbolic", Gtk.IconSize.SMALL_TOOLBAR)); attach (fill_chooser, 0, 0, 1, 1); attach (hidden_button, 1, 0, 1, 1); attach (delete_button, 2, 0, 1, 1); } private void create_event_bindings () { delete_button.clicked.connect (on_delete_item); hidden_button.clicked.connect (toggle_visibility); } private void on_delete_item () { border.remove (); border_deleted (); } private void set_hidden_button () { if (hidden_button_icon != null) { hidden_button.remove (hidden_button_icon); } hidden_button_icon = new Gtk.Image.from_icon_name ( "layer-%s-symbolic".printf (hidden ? "hidden" : "visible"), Gtk.IconSize.SMALL_TOOLBAR); hidden_button.add (hidden_button_icon); hidden_button_icon.show_all (); } private void toggle_visibility () { hidden = !hidden; toggle_ui_visibility (); } private void toggle_ui_visibility () { if (hidden) { get_style_context ().add_class ("disabled"); hidden_button.set_tooltip_text (_("Show border")); return; } hidden_button.set_tooltip_text (_("Hide border")); get_style_context ().remove_class ("disabled"); } } Akira-0.0.16/src/Layouts/Partials/BorderRadiusPanel.vala000066400000000000000000000354311410625726100230570ustar00rootroot00000000000000/* * Copyright (c) 2019 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Bilal Elmoussaoui * Authored by: Alessandro "Alecaddd" Castellani */ public class Akira.Layouts.Partials.BorderRadiusPanel : Gtk.Grid { public weak Akira.Window window { get; construct; } public Gtk.Label label; private Gtk.Revealer options_revealer; private Gtk.Grid options_grid; private Gtk.Adjustment radius_adj; private Gtk.Scale border_radius_scale; private Widgets.InputField border_radius_entry; private Gtk.ToggleButton options_button; private Widgets.InputField border_radius_bottom_left_entry; private Widgets.InputField border_radius_bottom_right_entry; private Widgets.InputField border_radius_top_left_entry; private Widgets.InputField border_radius_top_right_entry; private Gtk.Switch autoscale_switch; private Gtk.Switch uniform_switch; private Binding radius_binding; private Binding uniform_binding; private Binding autoscale_binding; private double max_value; private Akira.Lib.Items.CanvasRect _selected_item; private Akira.Lib.Items.CanvasRect selected_item { get { return _selected_item; } set { // If the same item is already selected, or the value is still null // we don't do anything to prevent redraw and calculations. if (_selected_item == value) { return; } disconnect_previous_item (); _selected_item = value; if (_selected_item == null || _selected_item.border_radius == null) { disable (); return; } enable (); } } public bool toggled { get { return visible; } set { visible = value; no_show_all = !value; } } public BorderRadiusPanel (Akira.Window window) { Object ( window: window, orientation: Gtk.Orientation.VERTICAL ); } construct { var title_cont = new Gtk.Grid (); title_cont.get_style_context ().add_class ("option-panel"); label = new Gtk.Label (_("Style")); label.halign = Gtk.Align.FILL; label.xalign = 0; label.hexpand = true; label.set_ellipsize (Pango.EllipsizeMode.END); title_cont.attach (label, 0, 0, 1, 1); attach (title_cont, 0, 0, 1, 1); var panel_grid = new Gtk.Grid (); get_style_context ().add_class ("style-panel"); panel_grid.row_spacing = 6; panel_grid.border_width = 12; panel_grid.column_spacing = 6; panel_grid.hexpand = true; attach (panel_grid, 0, 1, 1, 1); var border_radius_label = new Gtk.Label (_("Border Radius")); border_radius_label.get_style_context ().add_class ("group-title"); border_radius_label.halign = Gtk.Align.START; border_radius_label.hexpand = true; border_radius_label.margin_bottom = 2; panel_grid.attach (border_radius_label, 0, 1, 3, 1); radius_adj = new Gtk.Adjustment (0, 0, 1.0, 10.0, 0, 0); border_radius_scale = new Gtk.Scale (Gtk.Orientation.HORIZONTAL, radius_adj); border_radius_scale.digits = 0; border_radius_scale.draw_value = false; border_radius_scale.valign = Gtk.Align.CENTER; border_radius_scale.halign = Gtk.Align.FILL; border_radius_scale.hexpand = true; panel_grid.attach (border_radius_scale, 0, 2, 1, 1); border_radius_entry = new Widgets.InputField ( Widgets.InputField.Unit.PIXEL, 7, true, true); border_radius_entry.entry.hexpand = false; border_radius_entry.entry.width_request = 64; border_radius_entry.valign = Gtk.Align.CENTER; panel_grid.attach (border_radius_entry, 1, 2, 1, 1); border_radius_entry.entry.bind_property ( "value", radius_adj, "value", BindingFlags.BIDIRECTIONAL | BindingFlags.SYNC_CREATE); var options_image = new Gtk.Image.from_icon_name ("open-menu-symbolic", Gtk.IconSize.BUTTON); options_button = new Gtk.ToggleButton (); options_button.valign = Gtk.Align.CENTER; options_button.halign = Gtk.Align.END; options_button.get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT); options_button.add (options_image); options_button.can_focus = false; options_button.set_tooltip_text (_("Border radius options")); panel_grid.attach (options_button, 2, 2, 1, 1); options_revealer = new Gtk.Revealer (); options_revealer.transition_type = Gtk.RevealerTransitionType.NONE; panel_grid.attach (options_revealer, 0, 3, 3, 1); options_grid = new Gtk.Grid (); options_grid.border_width = 12; options_grid.hexpand = true; var border_entries_grid = new Gtk.Grid (); border_entries_grid.row_spacing = 12; border_entries_grid.border_width = 12; border_entries_grid.column_spacing = 12; border_entries_grid.hexpand = true; border_radius_top_left_entry = new Widgets.InputField ( Widgets.InputField.Unit.PIXEL, 7, true, true); border_radius_top_left_entry.entry.hexpand = false; border_radius_top_left_entry.entry.width_request = 64; border_radius_top_left_entry.valign = Gtk.Align.CENTER; border_radius_top_left_entry.halign = Gtk.Align.START; border_entries_grid.attach (border_radius_top_left_entry, 0, 0, 1, 1); border_radius_top_right_entry = new Widgets.InputField ( Widgets.InputField.Unit.PIXEL, 7, true, true); border_radius_top_right_entry.entry.hexpand = false; border_radius_top_right_entry.entry.width_request = 64; border_radius_top_right_entry.valign = Gtk.Align.CENTER; border_radius_top_right_entry.halign = Gtk.Align.END; border_entries_grid.attach (border_radius_top_right_entry, 1, 0, 1, 1); border_radius_bottom_left_entry = new Widgets.InputField ( Widgets.InputField.Unit.PIXEL, 7, true, true); border_radius_bottom_left_entry.entry.hexpand = false; border_radius_bottom_left_entry.entry.width_request = 64; border_radius_bottom_left_entry.valign = Gtk.Align.CENTER; border_radius_bottom_left_entry.halign = Gtk.Align.START; border_entries_grid.attach (border_radius_bottom_left_entry, 0, 1, 1, 1); border_radius_bottom_right_entry = new Widgets.InputField ( Widgets.InputField.Unit.PIXEL, 7, true, true); border_radius_bottom_right_entry.entry.hexpand = false; border_radius_bottom_right_entry.entry.width_request = 64; border_radius_bottom_right_entry.valign = Gtk.Align.CENTER; border_radius_bottom_right_entry.halign = Gtk.Align.END; border_entries_grid.attach (border_radius_bottom_right_entry, 1, 1, 1, 1); options_grid.attach (border_entries_grid, 0, 0, 1, 1); options_revealer.add (options_grid); var border_options_grid = new Gtk.Grid (); border_options_grid.row_spacing = 6; border_options_grid.border_width = 12; border_options_grid.column_spacing = 6; border_options_grid.hexpand = true; autoscale_switch = new Gtk.Switch (); autoscale_switch.valign = Gtk.Align.CENTER; autoscale_switch.halign = Gtk.Align.START; border_options_grid.attach (autoscale_switch, 0, 0, 1, 1); var autoscale_label = new Gtk.Label (_("Autoscale Corners")); autoscale_label.valign = Gtk.Align.CENTER; autoscale_label.halign = Gtk.Align.START; border_options_grid.attach (autoscale_label, 1, 0, 1, 1); uniform_switch = new Gtk.Switch (); uniform_switch.valign = Gtk.Align.CENTER; uniform_switch.halign = Gtk.Align.START; border_options_grid.attach (uniform_switch, 0, 1, 1, 1); var uniform_label = new Gtk.Label (_("Uniform Corners")); uniform_label.valign = Gtk.Align.CENTER; uniform_label.halign = Gtk.Align.START; border_options_grid.attach (uniform_label, 1, 1, 1, 1); options_grid.attach (border_options_grid, 0, 1, 1, 1); show_all (); bind_signals (); } private void bind_signals () { toggled = false; window.event_bus.selected_items_list_changed.connect (on_selected_items_list_changed); options_button.toggled.connect (() => { options_revealer.reveal_child = !options_revealer.child_revealed; window.event_bus.request_widget_redraw (); }); uniform_switch.notify["active"].connect (() => { update_all_borders (uniform_switch.active); }); // border_radius_top_left_entry.entry.changed.connect (on_radius_change); // border_radius_top_right_entry.entry.changed.connect (on_radius_change); // border_radius_bottom_right_entry.entry.changed.connect (on_radius_change); // border_radius_bottom_left_entry.entry.changed.connect (on_radius_change); } private void on_selected_items_list_changed (List selected_items) { // Interrupt if we don't have an item selected or if more than 1 is selected // since we can't handle the border radius of multiple items at once. if (selected_items.length () == 0 || selected_items.length () > 1) { selected_item = null; toggled = false; return; } if (!(selected_items.nth_data (0) is Akira.Lib.Items.CanvasRect)) { selected_item = null; toggled = false; return; } if (selected_item == null || selected_item != selected_items.nth_data (0)) { toggled = true; selected_item = (Akira.Lib.Items.CanvasRect) selected_items.nth_data (0); } } private void on_size_change () { var max_size = double.min (selected_item.width, selected_item.height); max_value = Math.round (max_size / 2); radius_adj.upper = max_value; border_radius_entry.set_range (0, max_value); if (!selected_item.border_radius.autoscale) { return; } // Calculate the radius percentage and update the value on shape resize. var percentage = Math.round (border_radius_scale.get_value () / max_size * 100); border_radius_scale.set_value (Math.round (percentage * max_size / 100)); } private void enable () { on_size_change (); uniform_switch.active = selected_item.border_radius.uniform; autoscale_switch.active = selected_item.border_radius.autoscale; // Uniform radius if (selected_item.border_radius.uniform) { radius_adj.value = selected_item.border_radius.x; } update_all_borders (selected_item.border_radius.uniform); // Non-Uniform radius // if (!selected_item.border_radius.uniform) { // border_radius_top_left_entry.entry.text = selected_item.radius_tl; // border_radius_top_right_entry.entry.text = selected_item.radius_tr; // border_radius_bottom_right_entry.entry.text = selected_item.radius_br; // border_radius_bottom_left_entry.entry.text = selected_item.radius_bl; // } radius_binding = radius_adj.bind_property ( "value", selected_item.border_radius, "x", BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL); uniform_binding = uniform_switch.bind_property ( "active", selected_item.border_radius, "uniform"); autoscale_binding = autoscale_switch.bind_property ( "active", selected_item.border_radius, "autoscale"); selected_item.notify["width"].connect (on_size_change); selected_item.notify["height"].connect (on_size_change); } private void disconnect_previous_item () { // Disconnect the model binding if an item was previously stored. // This is necessary to prevent GObject Critical errors. if (selected_item != null) { selected_item.notify["width"].disconnect (on_size_change); selected_item.notify["height"].disconnect (on_size_change); } } private void update_all_borders (bool switch_active) { border_radius_scale.sensitive = switch_active; border_radius_entry.entry.sensitive = switch_active; border_radius_bottom_left_entry.entry.sensitive = !switch_active; border_radius_bottom_right_entry.entry.sensitive = !switch_active; border_radius_top_left_entry.entry.sensitive = !switch_active; border_radius_top_right_entry.entry.sensitive = !switch_active; string border_value = !switch_active ? ((int)border_radius_scale.get_value ()).to_string () : ""; border_radius_bottom_left_entry.entry.text = border_value; border_radius_bottom_right_entry.entry.text = border_value; border_radius_top_left_entry.entry.text = border_value; border_radius_top_right_entry.entry.text = border_value; } private void disable () { // border_radius_top_left_entry.entry.changed.disconnect (on_radius_change); // border_radius_top_right_entry.entry.changed.disconnect (on_radius_change); // border_radius_bottom_right_entry.entry.changed.disconnect (on_radius_change); // border_radius_bottom_left_entry.entry.changed.disconnect (on_radius_change); radius_binding.unbind (); uniform_binding.unbind (); autoscale_binding.unbind (); autoscale_switch.active = false; uniform_switch.active = false; border_radius_scale.set_value (0); border_radius_entry.entry.text = ""; border_radius_entry.entry.sensitive = false; border_radius_top_left_entry.entry.text = ""; border_radius_top_left_entry.entry.sensitive = false; border_radius_top_right_entry.entry.text = ""; border_radius_top_right_entry.entry.sensitive = false; border_radius_bottom_left_entry.entry.text = ""; border_radius_bottom_left_entry.entry.sensitive = false; border_radius_bottom_right_entry.entry.text = ""; border_radius_bottom_right_entry.entry.sensitive = false; } } Akira-0.0.16/src/Layouts/Partials/BordersPanel.vala000066400000000000000000000114041410625726100220640ustar00rootroot00000000000000/** * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Alessandro "alecaddd" Castellani */ public class Akira.Layouts.Partials.BordersPanel : Gtk.Grid { private unowned Akira.Window window; public Gtk.Button add_btn; public Gtk.ListBox borders_list_container; private GLib.ListStore list; private unowned List? items; public bool toggled { get { return visible; } set { visible = value; no_show_all = !value; } } public BordersPanel (Akira.Window window) { this.window = window; var title_cont = new Gtk.Grid (); title_cont.orientation = Gtk.Orientation.HORIZONTAL; title_cont.hexpand = true; title_cont.get_style_context ().add_class ("option-panel"); var label = new Gtk.Label (_("Borders")); label.halign = Gtk.Align.FILL; label.xalign = 0; label.hexpand = true; label.set_ellipsize (Pango.EllipsizeMode.END); add_btn = new Gtk.Button (); add_btn.get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT); add_btn.can_focus = false; add_btn.valign = Gtk.Align.CENTER; add_btn.halign = Gtk.Align.CENTER; add_btn.set_tooltip_text (_("Add border")); add_btn.add (new Gtk.Image.from_icon_name ("list-add-symbolic", Gtk.IconSize.SMALL_TOOLBAR)); title_cont.attach (label, 0, 0, 1, 1); title_cont.attach (add_btn, 1, 0, 1, 1); list = new GLib.ListStore (typeof (Lib.Components.Border)); borders_list_container = new Gtk.ListBox (); borders_list_container.margin_top = 5; borders_list_container.margin_bottom = 15; borders_list_container.margin_start = 10; borders_list_container.margin_end = 5; borders_list_container.selection_mode = Gtk.SelectionMode.NONE; borders_list_container.get_style_context ().add_class ("fills-list"); borders_list_container.bind_model (list, item => { var border_items = new Layouts.Partials.BorderItem (window, (Lib.Components.Border) item); border_items.border_deleted.connect (() => { reload_list (items); }); return border_items; }); attach (title_cont, 0, 0, 1, 1); attach (borders_list_container, 0, 1, 1, 1); show_all (); create_event_bindings (); } private void create_event_bindings () { toggled = false; window.event_bus.selected_items_list_changed.connect (reload_list); add_btn.clicked.connect (() => { var border_color = Gdk.RGBA (); border_color.parse (settings.border_color); foreach (Lib.Items.CanvasItem item in items) { list.insert (0, item.borders.add_border_color (border_color, (int) settings.border_size)); } }); // Listen to the model changes when adding/removing items. list.items_changed.connect ((position, removed, added) => { window.main_window.left_sidebar.queue_resize (); }); } private void reload_list (List selected_items) { // Always clear the list model when a selection changes. list.remove_all (); if (selected_items.length () == 0) { items = null; toggled = false; return; } items = selected_items; bool show = false; foreach (Lib.Items.CanvasItem item in selected_items) { // Skip items that don't have a border item since there will be nothing to show. if (item.borders == null) { continue; } // At least an item has the borders component, so we can show the show = true; // Loops through all the available borders and add them tot he list model. // TODO: handle duplicate identical colors. foreach (Lib.Components.Border border in item.borders.borders) { list.insert (0, border); } } toggled = show; } } Akira-0.0.16/src/Layouts/Partials/FillItem.vala000066400000000000000000000076441410625726100212240ustar00rootroot00000000000000/* * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Giacomo "giacomoalbe" Alberini * Authored by: Alessandro "alecaddd" Castellani * Authored by: Ivan "isneezy" Vilanculo */ public class Akira.Layouts.Partials.FillItem : Gtk.Grid { private unowned Akira.Window window; private unowned Lib.Components.Fill fill; private Gtk.Button hidden_button; private Gtk.Button delete_button; private Gtk.Image hidden_button_icon; private bool hidden { owned get { return fill.hidden; } set { fill.hidden = value; set_hidden_button (); toggle_ui_visibility (); } } public signal void fill_deleted (); public FillItem (Akira.Window window, Lib.Components.Fill fill) { this.window = window; this.fill = fill; create_ui (); hidden = fill.hidden; create_event_bindings (); show_all (); } private void create_ui () { margin_top = margin_bottom = 5; var fill_chooser = new Gtk.Grid (); fill_chooser.hexpand = true; fill_chooser.margin_end = 5; fill_chooser.add (new Widgets.ColorRow (window, new Models.ColorModel (fill))); hidden_button = new Gtk.Button (); hidden_button.get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT); hidden_button.get_style_context ().add_class ("button-rounded"); hidden_button.can_focus = false; hidden_button.valign = Gtk.Align.CENTER; delete_button = new Gtk.Button (); delete_button.get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT); delete_button.get_style_context ().add_class ("button-rounded"); delete_button.can_focus = false; delete_button.valign = Gtk.Align.CENTER; delete_button.set_tooltip_text (_("Remove fill color")); delete_button.add (new Gtk.Image.from_icon_name ("user-trash-symbolic", Gtk.IconSize.SMALL_TOOLBAR)); attach (fill_chooser, 0, 0, 1, 1); attach (hidden_button, 1, 0, 1, 1); attach (delete_button, 2, 0, 1, 1); } private void create_event_bindings () { delete_button.clicked.connect (on_delete_item); hidden_button.clicked.connect (toggle_visibility); } private void on_delete_item () { fill.remove (); fill_deleted (); } private void set_hidden_button () { if (hidden_button_icon != null) { hidden_button.remove (hidden_button_icon); } hidden_button_icon = new Gtk.Image.from_icon_name ( "layer-%s-symbolic".printf (hidden ? "hidden" : "visible"), Gtk.IconSize.SMALL_TOOLBAR); hidden_button.add (hidden_button_icon); hidden_button_icon.show_all (); } private void toggle_visibility () { hidden = !hidden; toggle_ui_visibility (); } private void toggle_ui_visibility () { if (hidden) { get_style_context ().add_class ("disabled"); hidden_button.set_tooltip_text (_("Show fill color")); return; } hidden_button.set_tooltip_text (_("Hide fill color")); get_style_context ().remove_class ("disabled"); } } Akira-0.0.16/src/Layouts/Partials/FillsPanel.vala000066400000000000000000000113551410625726100215420ustar00rootroot00000000000000/** * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Giacomo "giacomoalbe" Alberini * Authored by: Alessandro "alecaddd" Castellani */ public class Akira.Layouts.Partials.FillsPanel : Gtk.Grid { private unowned Akira.Window window; private Gtk.Button add_btn; private Gtk.ListBox fills_list_container; private GLib.ListStore list; private unowned List? items; public bool toggled { get { return visible; } set { visible = value; no_show_all = !value; } } public FillsPanel (Akira.Window window) { this.window = window; var title_cont = new Gtk.Grid (); title_cont.orientation = Gtk.Orientation.HORIZONTAL; title_cont.hexpand = true; title_cont.get_style_context ().add_class ("option-panel"); var label = new Gtk.Label (_("Fills")); label.halign = Gtk.Align.FILL; label.xalign = 0; label.hexpand = true; label.set_ellipsize (Pango.EllipsizeMode.END); add_btn = new Gtk.Button (); add_btn.get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT); add_btn.can_focus = false; add_btn.valign = Gtk.Align.CENTER; add_btn.halign = Gtk.Align.CENTER; add_btn.set_tooltip_text (_("Add fill color")); add_btn.add (new Gtk.Image.from_icon_name ("list-add-symbolic", Gtk.IconSize.SMALL_TOOLBAR)); title_cont.attach (label, 0, 0, 1, 1); title_cont.attach (add_btn, 1, 0, 1, 1); list = new GLib.ListStore (typeof (Lib.Components.Fill)); fills_list_container = new Gtk.ListBox (); fills_list_container.margin_top = 5; fills_list_container.margin_bottom = 15; fills_list_container.margin_start = 10; fills_list_container.margin_end = 5; fills_list_container.selection_mode = Gtk.SelectionMode.NONE; fills_list_container.get_style_context ().add_class ("fills-list"); fills_list_container.bind_model (list, item => { var fill_item = new Layouts.Partials.FillItem (window, (Lib.Components.Fill) item); fill_item.fill_deleted.connect (() => { reload_list (items); }); return fill_item; }); attach (title_cont, 0, 0, 1, 1); attach (fills_list_container, 0, 1, 1, 1); show_all (); create_event_bindings (); } private void create_event_bindings () { toggled = false; window.event_bus.selected_items_list_changed.connect (reload_list); add_btn.clicked.connect (() => { var fill_color = Gdk.RGBA (); fill_color.parse (settings.fill_color); foreach (Lib.Items.CanvasItem item in items) { list.insert (0, item.fills.add_fill_color (fill_color)); } }); // Listen to the model changes when adding or removing items. list.items_changed.connect ((position, removed, added) => { window.main_window.left_sidebar.queue_resize (); }); } private void reload_list (List selected_items) { // Always clear the list model when a selection changes. list.remove_all (); if (selected_items.length () == 0) { items = null; toggled = false; return; } items = selected_items; bool show = false; foreach (Lib.Items.CanvasItem item in selected_items) { // Skip items that don't have a fill item since there will be nothing to show. if (item.fills == null) { continue; } // At least an item has the fills component, so we can show the show = true; // Loops through all the available fills and add them tot he list model. // TODO: handle duplicate identical colors. foreach (Lib.Components.Fill fill in item.fills.fills) { list.insert (0, fill); } } toggled = show; } } Akira-0.0.16/src/Layouts/Partials/Layer.vala000066400000000000000000000573671410625726100206020ustar00rootroot00000000000000/* * Copyright (c) 2019-2020 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Alessandro "Alecaddd" Castellani * Authored by: Giacomo Alberini */ public class Akira.Layouts.Partials.Layer : Gtk.ListBoxRow { public weak Akira.Window window { get; construct; } // public Akira.Layouts.Partials.Artboard? artboard { get; construct set; } public Akira.Layouts.Partials.Layer? layer_group { get; construct set; } public string icon_name { get; construct; } public Akira.Lib.Items.CanvasItem model { get; construct; } private bool scroll_up = false; private bool scrolling = false; private bool should_scroll = false; public Gtk.Adjustment vadjustment; private const int SCROLL_STEP_SIZE = 5; private const int SCROLL_DISTANCE = 30; private const int SCROLL_DELAY = 50; private const Gtk.TargetEntry TARGET_ENTRIES[] = { { "LAYER", Gtk.TargetFlags.SAME_APP, 0 } }; // Drag and Drop properties. private Gtk.Revealer motion_revealer; private bool dragged = false; public Gtk.Image icon; public Gtk.Image icon_folder_open; public Gtk.Image icon_locked; public Gtk.Image icon_unlocked; public Gtk.Image icon_hidden; public Gtk.Image icon_visible; public Gtk.ToggleButton button_locked; public Gtk.ToggleButton button_hidden; public Gtk.Label label; public Gtk.Entry entry; public Gtk.EventBox handle; private Gtk.Grid handle_grid; private Gtk.Grid label_grid; // Group related properties public Gtk.ToggleButton button; public Gtk.Image button_icon; public Gtk.Revealer revealer; public Gtk.ListBox container; private bool _editing; public bool editing { get { return _editing; } set { _editing = value; } } private bool _grouped; public bool grouped { get { return _grouped; } set construct { _grouped = value; } } public Layer ( Akira.Window window, Akira.Lib.Items.CanvasItem model, Gtk.ListBox? list = null ) { Object ( window: window, model: model ); if (model.layer.selected && list != null) { list.select_row (this); } } construct { can_focus = true; get_style_context ().add_class ("layer"); label = new Gtk.Label (""); label.halign = Gtk.Align.FILL; label.xalign = 0; label.expand = true; label.set_ellipsize (Pango.EllipsizeMode.END); model.name.bind_property ("name", label, "label", BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL); entry = new Gtk.Entry (); entry.margin_top = entry.margin_bottom = 4; entry.margin_end = 10; entry.expand = true; entry.visible = false; entry.no_show_all = true; // NOTE: We can't bind the entry to the model.name otherwise we won't be // able to handle the ESC key to restore the previous entry. entry.text = model.name.name; entry.activate.connect (update_on_enter); entry.key_release_event.connect (update_on_escape); entry.focus_in_event.connect (handle_focus_in); entry.focus_out_event.connect (update_on_leave); icon = new Gtk.Image.from_icon_name (model.name.icon, Gtk.IconSize.MENU); icon.margin_start = icon_name != "folder-symbolic" ? 16 : 0; icon.margin_end = 10; icon.vexpand = true; icon.valign = Gtk.Align.CENTER; icon.get_style_context ().add_class (Gtk.STYLE_CLASS_DIM_LABEL); icon_folder_open = new Gtk.Image.from_icon_name ("folder-open-symbolic", Gtk.IconSize.MENU); icon_folder_open.margin_end = 10; icon_folder_open.vexpand = true; icon_folder_open.visible = false; icon_folder_open.no_show_all = true; icon_folder_open.get_style_context ().add_class (Gtk.STYLE_CLASS_DIM_LABEL); var icon_layer_grid = new Gtk.Grid (); icon_layer_grid.attach (icon, 0, 0, 1, 1); icon_layer_grid.attach (icon_folder_open, 1, 0, 1, 1); button_locked = new Gtk.ToggleButton (); button_locked.tooltip_text = _("Lock Layer"); button_locked.get_style_context ().remove_class ("button"); button_locked.get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT); button_locked.get_style_context ().add_class ("layer-action"); button_locked.valign = Gtk.Align.CENTER; icon_locked = new Gtk.Image.from_icon_name ("changes-allow-symbolic", Gtk.IconSize.MENU); icon_unlocked = new Gtk.Image.from_icon_name ("changes-prevent-symbolic", Gtk.IconSize.MENU); icon_unlocked.visible = false; icon_unlocked.no_show_all = true; var button_locked_grid = new Gtk.Grid (); button_locked_grid.margin_end = 6; button_locked_grid.attach (icon_locked, 0, 0, 1, 1); button_locked_grid.attach (icon_unlocked, 1, 0, 1, 1); button_locked.add (button_locked_grid); button_hidden = new Gtk.ToggleButton (); button_hidden.tooltip_text = _("Hide Layer"); button_hidden.get_style_context ().remove_class ("button"); button_hidden.get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT); button_hidden.get_style_context ().add_class ("layer-action"); button_hidden.valign = Gtk.Align.CENTER; icon_hidden = new Gtk.Image.from_icon_name ("layer-visible-symbolic", Gtk.IconSize.MENU); icon_visible = new Gtk.Image.from_icon_name ("layer-hidden-symbolic", Gtk.IconSize.MENU); icon_visible.visible = false; icon_visible.no_show_all = true; var button_hidden_grid = new Gtk.Grid (); button_hidden_grid.margin_end = 14; button_hidden_grid.attach (icon_hidden, 0, 0, 1, 1); button_hidden_grid.attach (icon_visible, 1, 0, 1, 1); button_hidden.add (button_hidden_grid); var motion_grid = new Gtk.Grid (); motion_grid.get_style_context ().add_class ("grid-motion"); motion_grid.height_request = 2; motion_revealer = new Gtk.Revealer (); motion_revealer.transition_type = Gtk.RevealerTransitionType.SLIDE_DOWN; motion_revealer.reveal_child = false; motion_revealer.add (motion_grid); handle_grid = new Gtk.Grid (); handle_grid.expand = true; handle_grid.attach (icon_layer_grid, 0, 0, 1, 1); handle_grid.attach (label, 1, 0, 1, 1); handle_grid.attach (entry, 2, 0, 1, 1); handle = new Gtk.EventBox (); handle.expand = true; handle.can_focus = true; handle.above_child = false; handle.add (handle_grid); label_grid = new Gtk.Grid (); label_grid.expand = true; label_grid.attach (handle, 0, 0, 1, 1); label_grid.attach (button_locked, 1, 0, 1, 1); label_grid.attach (button_hidden, 2, 0, 1, 1); label_grid.attach (motion_revealer, 0, 1, 3, 1); is_group (); build_drag_and_drop (); handle.button_press_event.connect (on_click_event); handle.enter_notify_event.connect (event => { if (model.layer.locked) { return true; } get_style_context ().add_class ("hover"); window.event_bus.hover_over_layer (model); return false; }); handle.leave_notify_event.connect (event => { get_style_context ().remove_class ("hover"); window.event_bus.hover_over_layer (null); return false; }); model.layer.notify["selected"].connect (() => { if (model.layer.selected) { get_style_context ().remove_class ("hovered"); activate (); return; } ((Gtk.ListBox) parent).unselect_row (this); }); lock_actions (); hide_actions (); reveal_actions (); window.event_bus.hover_over_item.connect (on_hover_over_item); } private void on_hover_over_item (Lib.Items.CanvasItem? item) { if (item == model) { get_style_context ().add_class ("hovered"); return; } get_style_context ().remove_class ("hovered"); } private void is_group () { if (!grouped) { add (label_grid); return; } get_style_context ().add_class ("layer-group"); button = new Gtk.ToggleButton (); button.active = true; button.get_style_context ().remove_class ("button"); button.get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT); button.get_style_context ().add_class ("revealer-button"); button_icon = new Gtk.Image.from_icon_name ("pan-down-symbolic", Gtk.IconSize.MENU); button.add (button_icon); label_grid.attach (button, 0, 0, 1, 1); revealer = new Gtk.Revealer (); revealer.hexpand = true; revealer.reveal_child = true; container = new Gtk.ListBox (); container.get_style_context ().add_class ("group-container"); container.activate_on_single_click = true; container.selection_mode = Gtk.SelectionMode.SINGLE; // Block all the events from bubbling up and triggering the Artboard's events. container.event.connect (() => { return true; }); revealer.add (container); if (revealer.get_reveal_child ()) { icon_folder_open.visible = true; icon_folder_open.no_show_all = false; icon.visible = false; icon.no_show_all = true; } var group_grid = new Gtk.Grid (); group_grid.attach (label_grid, 0, 0, 1, 1); group_grid.attach (revealer, 0, 1, 1, 1); add (group_grid); } private void reveal_actions () { if (!grouped) { return; } button.toggled.connect (() => { revealer.reveal_child = ! revealer.get_reveal_child (); if (revealer.get_reveal_child ()) { button.get_style_context ().remove_class ("closed"); icon_folder_open.visible = true; icon_folder_open.no_show_all = false; icon.visible = false; icon.no_show_all = true; } else { button.get_style_context ().add_class ("closed"); icon_folder_open.visible = false; icon_folder_open.no_show_all = true; icon.visible = true; icon.no_show_all = false; } window.main_window.right_sidebar.layers_panel.reload_zebra (); }); } private void build_drag_and_drop () { // Make this a draggable widget. Gtk.drag_source_set (this, Gdk.ModifierType.BUTTON1_MASK, TARGET_ENTRIES, Gdk.DragAction.MOVE); drag_begin.connect (on_drag_begin); drag_data_get.connect (on_drag_data_get); // Make this widget a DnD destination. Gtk.drag_dest_set (this, Gtk.DestDefaults.MOTION, TARGET_ENTRIES, Gdk.DragAction.MOVE); drag_motion.connect (on_drag_motion); drag_leave.connect (on_drag_leave); drag_drop.connect (on_drag_drop); drag_data_received.connect (on_drag_data_received); drag_end.connect (on_drag_end); } private void on_drag_begin (Gtk.Widget widget, Gdk.DragContext context) { var row = (widget as Akira.Layouts.Partials.Layer); Gtk.Allocation alloc; row.get_allocation (out alloc); var surface = new Cairo.ImageSurface (Cairo.Format.ARGB32, alloc.width, alloc.height); var cr = new Cairo.Context (surface); cr.set_source_rgba (0, 0, 0, 0.3); cr.set_line_width (1); cr.move_to (0, 0); cr.line_to (alloc.width, 0); cr.line_to (alloc.width, alloc.height); cr.line_to (0, alloc.height); cr.line_to (0, 0); cr.stroke (); cr.set_source_rgba (255, 255, 255, 0.5); cr.rectangle (0, 0, alloc.width, alloc.height); cr.fill (); row.handle_grid.draw (cr); Gtk.drag_set_icon_surface (context, surface); get_style_context ().add_class ("transparent"); dragged = true; } private void on_drag_data_get ( Gtk.Widget widget, Gdk.DragContext context, Gtk.SelectionData selection_data, uint target_type, uint time ) { uchar[] data = new uchar[(sizeof (Akira.Layouts.Partials.Layer))]; ((Gtk.Widget[])data)[0] = widget; selection_data.set ( Gdk.Atom.intern_static_string ("LAYER"), 32, data ); } /** * Handle the received layer, find the position of the targeted layer and trigger * a z-index update. */ private void on_drag_data_received ( Gdk.DragContext context, int x, int y, Gtk.SelectionData selection_data, uint target_type, uint time ) { var layer = (Layer) ((Gtk.Widget[]) selection_data.get_data ())[0]; // Used to adjust the position of swappable items if the source item // is dragged from the bottom up. int position_adjustment = 0; // Change artboard if necessary. window.items_manager.change_artboard.begin (layer.model, model.artboard); // Store the source of our items. var items_source = model.artboard == null ? window.items_manager.free_items : model.artboard.items; var items_count = (int) items_source.get_n_items (); var pos_target = items_count - 1 - items_source.index (model); var pos_source = items_count - 1 - items_source.index (layer.model); // Interrupt if item position doesn't exist. if (pos_source == -1) { return; } // z-index is the exact opposite of items placement as the last item // is the topmost element. Because of this, we need some trickery to // properly handle the list's order. var source = items_count - 1 - pos_source; var target = items_count - 1 - pos_target; // Interrupt if the item was dropped in the same position. if (source - 1 == target) { return; } // If the initial position is higher than the targeted dropped layer, it // means the layer was dragged from the bottom up, therefore we need to // increase the dropped target by 1 since we don't deal with location 0. if (source > target) { position_adjustment--; target++; } debug ("%i - %i", source, target); // Swap the location of the items in the List Model. items_source.swap_items (source, target); // The actual items in the canvas might not match the items in the List Model // due to Artboards labels, grids, and other pseudo elements. Therefore we need // to get the real position of the child and swap them. var root = layer.model.parent; root.move_child (root.find_child (layer.model), root.find_child (model) + position_adjustment); window.event_bus.z_selected_changed (); } /** * Receive the signal when an item is dropped on top of the layer. * If it's a valid layer, get the correct target type and trigger on_drag_data_received (). */ private bool on_drag_drop (Gtk.Widget widget, Gdk.DragContext context, int x, int y, uint time) { if (context.list_targets () != null) { var target_type = (Gdk.Atom) context.list_targets ().nth_data (0); Gtk.drag_get_data (widget, context, target_type, time); } return false; } private bool on_drag_motion (Gdk.DragContext context, int x, int y, uint time) { int row_index = get_index (); var row = (Akira.Layouts.Partials.Layer) ((Gtk.ListBox) parent).get_row_at_index (row_index); if (!dragged) { motion_revealer.reveal_child = true; } Gtk.Allocation alloc; get_allocation (out alloc); Gtk.Allocation row_alloc; row.get_allocation (out row_alloc); int real_y = (row_index * alloc.height) + y; check_scroll (real_y); if (should_scroll && !scrolling) { scrolling = true; Timeout.add (SCROLL_DELAY, scroll); } return true; } private void on_drag_leave (Gdk.DragContext context, uint time) { motion_revealer.reveal_child = false; should_scroll = false; } private void on_drag_end (Gdk.DragContext context) { get_style_context ().remove_class ("transparent"); dragged = false; } /** * Handle the click event for the EventBox to manage item selection and name editing. * * @param {Gdk.Event} event - The button click event. * @return {bool} True to stop propagation, False to let other events run. */ public bool on_click_event (Gdk.EventButton event) { if (model.layer.locked) { return true; } switch (event.type) { case Gdk.EventType.@2BUTTON_PRESS: entry.text = label.label; entry.visible = true; entry.no_show_all = false; label.visible = false; label.no_show_all = true; button_locked.visible = false; button_locked.no_show_all = true; button_hidden.visible = false; button_hidden.no_show_all = true; editing = true; Timeout.add (200, () => { entry.grab_focus (); return false; }); return true; case Gdk.EventType.BUTTON_PRESS: // Selected layers can't show hover effect. // We need to reflect the status of the canvas item. get_style_context ().remove_class ("hovered"); window.event_bus.request_add_item_to_selection (model); window.event_bus.hover_over_layer (null); // We need this in case the user clicks on the layer right after being unlocked. if (!is_selected ()) { ((Gtk.ListBox) parent).select_row (this); } // We're returning false to not interrupt the natural bubbling of the click event. return false; } return false; } public void update_on_enter () { update_label (); } public bool update_on_leave () { update_label (); window.event_bus.connect_typing_accel (); return false; } public bool update_on_escape (Gdk.EventKey key) { if (key.keyval == Gdk.Key.Escape) { entry.text = label.label; update_label (); window.event_bus.request_escape (); } return false; } private void update_label () { entry.visible = false; entry.no_show_all = true; label.visible = true; label.no_show_all = false; button_locked.visible = true; button_locked.no_show_all = false; button_hidden.visible = true; button_hidden.no_show_all = false; editing = false; var new_label = entry.get_text (); window.event_bus.set_focus_on_canvas (); if (label.label == new_label) { return; } label.label = new_label; } private void lock_actions () { button_locked.bind_property ("active", model.layer, "locked", BindingFlags.BIDIRECTIONAL | BindingFlags.SYNC_CREATE); button_locked.toggled.connect (() => { var active = button_locked.get_active (); button_locked.tooltip_text = active ? _("Unlock Layer") : _("Lock Layer"); if (active) { button_locked.get_style_context ().add_class ("show"); // Disable any pointer events for a locked item. model.pointer_events = Goo.CanvasPointerEvents.NONE; // Let the UI know that this item was locked. window.event_bus.item_locked (model); ((Gtk.ListBox) parent).unselect_row (this); model.layer.selected = false; } else { button_locked.get_style_context ().remove_class ("show"); // Re-enable pointer events. model.pointer_events = Goo.CanvasPointerEvents.ALL; } icon_unlocked.visible = active; icon_unlocked.no_show_all = !active; icon_locked.visible = !active; icon_locked.no_show_all = active; window.event_bus.set_focus_on_canvas (); window.event_bus.file_edited (); }); } private void hide_actions () { button_hidden.bind_property ("active", model, "visibility", BindingFlags.BIDIRECTIONAL | BindingFlags.SYNC_CREATE, (binding, srcval, ref targetval) => { Goo.CanvasItemVisibility status = (bool) srcval.get_boolean () ? Goo.CanvasItemVisibility.INVISIBLE : Goo.CanvasItemVisibility.VISIBLE; targetval.set_enum (status); return true; }, (binding, srcval, ref targetval) => { var status = ((Goo.CanvasItemVisibility) srcval.get_enum ()) == Goo.CanvasItemVisibility.INVISIBLE; targetval.set_boolean (status); return true; }); button_hidden.toggled.connect (() => { var active = button_hidden.get_active (); button_hidden.tooltip_text = active ? _("Show Layer") : _("Hide Layer"); if (active) { button_hidden.get_style_context ().add_class ("show"); } else { button_hidden.get_style_context ().remove_class ("show"); } icon_visible.visible = active; icon_visible.no_show_all = ! active; icon_hidden.visible = ! active; icon_hidden.no_show_all = active; window.event_bus.set_focus_on_canvas (); window.event_bus.file_edited (); }); } private void check_scroll (int y) { vadjustment = window.main_window.right_sidebar.layers_scroll.vadjustment; if (vadjustment == null) { return; } double vadjustment_min = vadjustment.value; double vadjustment_max = vadjustment.page_size + vadjustment_min; double show_min = double.max (0, y - SCROLL_DISTANCE); double show_max = double.min (vadjustment.upper, y + SCROLL_DISTANCE); if (vadjustment_min > show_min) { should_scroll = true; scroll_up = true; } else if (vadjustment_max < show_max) { should_scroll = true; scroll_up = false; } else { should_scroll = false; } } private bool scroll () { if (should_scroll) { if (scroll_up) { vadjustment.value -= SCROLL_STEP_SIZE; } else { vadjustment.value += SCROLL_STEP_SIZE; } } else { scrolling = false; } return should_scroll; } private bool handle_focus_in (Gdk.EventFocus event) { window.event_bus.disconnect_typing_accel (); return false; } } Akira-0.0.16/src/Layouts/Partials/LayersPanel.vala000066400000000000000000000245621410625726100217340ustar00rootroot00000000000000/* * Copyright (c) 2019-2020 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Alessandro "Alecaddd" Castellani * Authored by: Giacomo Alberini */ public class Akira.Layouts.Partials.LayersPanel : Gtk.Grid { public weak Akira.Window window { get; construct; } private int loop; private bool scroll_up = false; private bool scrolling = false; private bool should_scroll = false; public Gtk.Adjustment vadjustment; private Gtk.ListBox items_list; private Gtk.ListBox artboards_list; private Gtk.Grid empty_area; private const int SCROLL_STEP_SIZE = 5; private const int SCROLL_DISTANCE = 30; private const int SCROLL_DELAY = 50; // Drag and Drop properties. private Gtk.Revealer motion_layer_revealer; private Gtk.Revealer motion_artboard_revealer; private Gtk.TargetList drop_targets { get; set; default = null; } private const Gtk.TargetEntry TARGET_ENTRIES[] = { { "ARTBOARD", Gtk.TargetFlags.SAME_APP, 0 }, { "LAYER", Gtk.TargetFlags.SAME_APP, 0 } }; public LayersPanel (Akira.Window window) { Object ( window: window, vexpand: true, orientation: Gtk.Orientation.VERTICAL ); } construct { expand = true; drop_targets = new Gtk.TargetList (TARGET_ENTRIES); items_list = new Gtk.ListBox (); artboards_list = new Gtk.ListBox (); items_list.activate_on_single_click = false; items_list.selection_mode = Gtk.SelectionMode.SINGLE; artboards_list.activate_on_single_click = false; artboards_list.selection_mode = Gtk.SelectionMode.SINGLE; items_list.bind_model (window.items_manager.free_items, item => { return new Layouts.Partials.Layer (window, ((Lib.Items.CanvasItem) item), items_list); }); artboards_list.bind_model (window.items_manager.artboards, item => { return new Layouts.Partials.Artboard (window, ((Lib.Items.CanvasArtboard) item)); }); get_style_context ().add_class ("layers-panel"); // Motion revealer for layers Drag and Drop on the empty area. var motion_grid = new Gtk.Grid (); motion_grid.get_style_context ().add_class ("grid-motion"); motion_grid.height_request = 2; motion_layer_revealer = new Gtk.Revealer (); motion_layer_revealer.transition_type = Gtk.RevealerTransitionType.SLIDE_DOWN; motion_layer_revealer.add (motion_grid); // Motion revealer for layers Drag and Drop on the empty area. var motion_artboard_grid = new Gtk.Grid (); motion_artboard_grid.get_style_context ().add_class ("grid-motion"); motion_artboard_grid.height_request = 2; motion_artboard_revealer = new Gtk.Revealer (); motion_artboard_revealer.transition_type = Gtk.RevealerTransitionType.SLIDE_DOWN; motion_artboard_revealer.add (motion_artboard_grid); empty_area = new Gtk.Grid (); empty_area.expand = true; attach (items_list, 0, 1); attach (motion_layer_revealer, 0, 2); attach (artboards_list, 0, 3); attach (motion_artboard_revealer, 0, 4); attach (empty_area, 0, 5); build_drag_and_drop (); redraw_list (); window.event_bus.item_inserted.connect (redraw_list); window.event_bus.item_deleted.connect (redraw_list); window.event_bus.z_selected_changed.connect (redraw_list); } private void redraw_list () { reload_zebra (); show_all (); } private void build_drag_and_drop () { // Make the empty area of the panel a drop area for scroll motion and items sorting. Gtk.drag_dest_set (empty_area, Gtk.DestDefaults.ALL, TARGET_ENTRIES, Gdk.DragAction.MOVE); empty_area.drag_motion.connect (on_drag_motion); empty_area.drag_leave.connect (on_drag_leave); empty_area.drag_data_received.connect (on_drag_data_received); } private bool on_drag_motion (Gdk.DragContext context, int x, int y, uint time) { var type = Gtk.drag_dest_find_target (this, context, drop_targets); if (type == Gdk.Atom.intern_static_string ("ARTBOARD")) { motion_artboard_revealer.reveal_child = true; } else { motion_layer_revealer.reveal_child = true; } check_scroll (y); if (should_scroll && !scrolling) { scrolling = true; Timeout.add (SCROLL_DELAY, scroll); } return true; } private void on_drag_leave (Gdk.DragContext context, uint time) { var type = Gtk.drag_dest_find_target (this, context, drop_targets); if (type == Gdk.Atom.intern_static_string ("ARTBOARD")) { motion_artboard_revealer.reveal_child = false; } else { motion_layer_revealer.reveal_child = false; } should_scroll = false; } /** * Handle the received layer, find the position of the targeted layer and trigger * a z-index update. */ private void on_drag_data_received ( Gdk.DragContext context, int x, int y, Gtk.SelectionData selection_data, uint target_type, uint time ) { int items_count, pos_source, source; var type = Gtk.drag_dest_find_target (this, context, drop_targets); if (type == Gdk.Atom.intern_static_string ("ARTBOARD")) { var artboard = (Layouts.Partials.Artboard) ( (Gtk.Widget[]) selection_data.get_data () )[0]; items_count = (int) window.items_manager.artboards.get_n_items (); pos_source = items_count - 1 - window.items_manager.artboards.index (artboard.model); // Interrupt if item position doesn't exist. if (pos_source == -1) { return; } // z-index is the exact opposite of items placement as the last item // is the topmost element. Because of this, we need some trickery to // properly handle the list's order. source = items_count - 1 - pos_source; // Interrupt if the item was dropped in the same position. if (source == items_count - 1) { debug ("same position"); return; } // Swap the position inside the List Model. window.items_manager.artboards.swap_items (source, items_count - 1); // The actual items in the canvas might not match the items in the List Model // due to Artboards labels, grids, and other pseudo elements. Therefore we need // to get the real position of the child and swap them. var root = artboard.model.parent; root.move_child (root.find_child (artboard.model), 0); window.event_bus.z_selected_changed (); return; } var layer = (Layouts.Partials.Layer) ((Gtk.Widget[]) selection_data.get_data ())[0]; var layer_artboard = layer.model.artboard; // Change artboard if necessary. window.items_manager.change_artboard.begin (layer.model, null); // If the moved layer had an artboard, no need to do anything else. if (layer_artboard != null) { return; } // Use the existing action to push an item all the way to the bottom. window.event_bus.change_z_selected (false, true); } private void check_scroll (int y) { vadjustment = window.main_window.right_sidebar.layers_scroll.vadjustment; if (vadjustment == null) { return; } double vadjustment_min = vadjustment.value; double vadjustment_max = vadjustment.page_size + vadjustment_min; double show_min = double.max (0, y - SCROLL_DISTANCE); double show_max = double.min (vadjustment.upper, y + SCROLL_DISTANCE); if (vadjustment_min > show_min) { should_scroll = true; scroll_up = true; } else if (vadjustment_max < show_max) { should_scroll = true; scroll_up = false; } else { should_scroll = false; } } private bool scroll () { if (should_scroll) { if (scroll_up) { vadjustment.value -= SCROLL_STEP_SIZE; } else { vadjustment.value += SCROLL_STEP_SIZE; } } else { scrolling = false; } return should_scroll; } public void reload_zebra () { loop = 0; items_list.@foreach (row => { zebra_layer ((Akira.Layouts.Partials.Layer) row); }); artboards_list.@foreach (row => { zebra_artboard ((Akira.Layouts.Partials.Artboard) row); }); } private void zebra_artboard (Akira.Layouts.Partials.Artboard artboard) { // Handle zebra striped separately for each artboard loop = 0; artboard.container.foreach (row => { if (!(row is Akira.Layouts.Partials.Layer)) { return; } zebra_layer ((Akira.Layouts.Partials.Layer) row); }); } private void zebra_layer (Akira.Layouts.Partials.Layer layer) { loop++; layer.get_style_context ().remove_class ("even"); if (loop % 2 == 0) { layer.get_style_context ().add_class ("even"); } if (layer.grouped) { zebra_layer_group (layer); } } private void zebra_layer_group (Akira.Layouts.Partials.Layer layer) { bool open = layer.revealer.get_reveal_child (); layer.container.foreach (row => { if (!(row is Akira.Layouts.Partials.Layer) || !open) { return; } zebra_layer ((Akira.Layouts.Partials.Layer) row); }); } } Akira-0.0.16/src/Layouts/Partials/PagesPanel.vala000066400000000000000000000030431410625726100215230ustar00rootroot00000000000000/* * Copyright (c) 2019 Alecaddd (http://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Alessandro "Alecaddd" Castellani */ public class Akira.Layouts.Partials.PagesPanel : Gtk.ListBox { public weak Akira.Window window { get; construct; } // private bool scroll_up = false; // private bool scrolling = false; // private bool should_scroll = false; // public Gtk.Adjustment vadjustment; // private const int SCROLL_STEP_SIZE = 5; // private const int SCROLL_DISTANCE = 30; // private const int SCROLL_DELAY = 50; private const Gtk.TargetEntry TARGET_ENTRIES[] = { { "PAGES", Gtk.TargetFlags.SAME_APP, 0 } }; public PagesPanel (Akira.Window window) { Object ( window: window, activate_on_single_click: false, selection_mode: Gtk.SelectionMode.SINGLE ); } construct { expand = true; } } Akira-0.0.16/src/Layouts/Partials/TransformPanel.vala000066400000000000000000000257111410625726100224450ustar00rootroot00000000000000/* * Copyright (c) 2020 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Ana Gelez * Authored by: Alessandro "Alecaddd" Castellani */ public class Akira.Layouts.Partials.TransformPanel : Gtk.Grid { public weak Akira.Window window { get; construct; } public weak Akira.Lib.Canvas canvas; private Widgets.LinkedInput x; private Widgets.LinkedInput y; private Widgets.LinkedInput width; private Widgets.LinkedInput height; private Widgets.LinkedInput rotation; private Gtk.ToggleButton lock_changes; private Gtk.ToggleButton hflip_button; private Gtk.ToggleButton vflip_button; private Gtk.Adjustment opacity_adj; private Widgets.InputField opacity_entry; private Gtk.Scale scale; // Bindings. private Binding x_bind; private Binding y_bind; private Binding ratio_bind; private Binding width_bind; private Binding height_bind; private Binding rotation_bind; private Binding opacity_bind; private Binding hflip_bind; private Binding vflip_bind; public TransformPanel (Akira.Window main_window) { Object ( window: main_window, orientation: Gtk.Orientation.HORIZONTAL ); } private Lib.Items.CanvasItem? _selected_item; public Lib.Items.CanvasItem? selected_item { get { return _selected_item; } set { // If the same item is already selected, or the value is still null // we don't do anything to prevent redraw and calculations. if (_selected_item == value) { return; } disconnect_previous_item (); disable (); _selected_item = value; bool has_item = _selected_item != null; if (has_item) { enable (); } x.enabled = has_item; y.enabled = has_item; height.enabled = has_item; width.enabled = has_item; rotation.enabled = has_item && !(_selected_item is Lib.Items.CanvasArtboard); hflip_button.sensitive = has_item && !(_selected_item is Lib.Items.CanvasArtboard); vflip_button.sensitive = has_item && !(_selected_item is Lib.Items.CanvasArtboard); opacity_entry.entry.sensitive = has_item && !(_selected_item is Lib.Items.CanvasArtboard); scale.sensitive = has_item && !(_selected_item is Lib.Items.CanvasArtboard); lock_changes.sensitive = has_item; } } construct { border_width = 12; row_spacing = 6; column_spacing = 6; hexpand = true; x = new Widgets.LinkedInput (_("X"), _("Horizontal position")); x.input_field.set_range (-Akira.Layouts.MainCanvas.CANVAS_SIZE, Akira.Layouts.MainCanvas.CANVAS_SIZE); y = new Widgets.LinkedInput (_("Y"), _("Vertical position")); y.input_field.set_range (-Akira.Layouts.MainCanvas.CANVAS_SIZE, Akira.Layouts.MainCanvas.CANVAS_SIZE); width = new Widgets.LinkedInput (_("W"), _("Width")); width.input_field.set_range (0, Akira.Layouts.MainCanvas.CANVAS_SIZE); height = new Widgets.LinkedInput (_("H"), _("Height")); height.input_field.set_range (0, Akira.Layouts.MainCanvas.CANVAS_SIZE); var lock_image = new Gtk.Image.from_icon_name ("changes-allow-symbolic", Gtk.IconSize.BUTTON); lock_changes = new Gtk.ToggleButton (); lock_changes.tooltip_text = _("Lock Ratio"); lock_changes.get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT); lock_changes.get_style_context ().add_class ("label-colors"); lock_changes.image = lock_image; lock_changes.can_focus = false; lock_changes.sensitive = false; lock_changes.toggled.connect (() => { var icon = lock_changes.active ? "changes-prevent-symbolic" : "changes-allow-symbolic"; lock_changes.image = new Gtk.Image.from_icon_name (icon, Gtk.IconSize.BUTTON); }); rotation = new Widgets.LinkedInput (_("R"), _("Rotation degrees"), "°"); rotation.input_field.set_range (-360, 360); hflip_button = new Gtk.ToggleButton (); hflip_button.add (new Widgets.ButtonImage ("object-flip-horizontal")); hflip_button.get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT); hflip_button.hexpand = false; hflip_button.can_focus = false; hflip_button.sensitive = false; hflip_button.halign = Gtk.Align.CENTER; hflip_button.valign = Gtk.Align.CENTER; hflip_button.tooltip_markup = Granite.markup_accel_tooltip ({"bracketleft"}, _("Flip Horizontally")); vflip_button = new Gtk.ToggleButton (); vflip_button.add (new Widgets.ButtonImage ("object-flip-vertical")); vflip_button.get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT); vflip_button.hexpand = false; vflip_button.can_focus = false; vflip_button.sensitive = false; vflip_button.halign = Gtk.Align.CENTER; vflip_button.valign = Gtk.Align.CENTER; vflip_button.tooltip_markup = Granite.markup_accel_tooltip ({"bracketright"}, _("Flip Vertically")); var align_grid = new Gtk.Grid (); align_grid.hexpand = true; align_grid.column_homogeneous = true; align_grid.attach (hflip_button, 0, 0, 1, 1); align_grid.attach (vflip_button, 1, 0, 1, 1); opacity_adj = new Gtk.Adjustment (100.0, 0, 100.0, 0, 0, 0); scale = new Gtk.Scale (Gtk.Orientation.HORIZONTAL, opacity_adj); scale.hexpand = true; scale.sensitive = false; scale.draw_value = false; scale.digits = 0; scale.margin_end = 20; opacity_entry = new Widgets.InputField ( Widgets.InputField.Unit.PERCENTAGE, 7, true, true); opacity_entry.entry.bind_property ( "value", opacity_adj, "value", BindingFlags.BIDIRECTIONAL | BindingFlags.SYNC_CREATE); opacity_entry.entry.hexpand = false; opacity_entry.entry.width_request = 64; var opacity_grid = new Gtk.Grid (); opacity_grid.hexpand = true; opacity_grid.attach (scale, 0, 0, 1); opacity_grid.attach (opacity_entry, 1, 0, 1); attach (group_title (_("Position")), 0, 0, 3); attach (x, 0, 1, 1); attach (y, 2, 1, 1); attach (new Widgets.PanelSeparator (), 0, 2, 3); attach (group_title (_("Size")), 0, 3, 3); attach (width, 0, 4, 1); attach (lock_changes, 1, 4, 1); attach (height, 2, 4, 1); attach (new Widgets.PanelSeparator (), 0, 5, 3); attach (group_title (_("Transform")), 0, 6, 3); attach (rotation, 0, 7, 1); attach (align_grid, 2, 7, 1); attach (new Widgets.PanelSeparator (), 0, 8, 3); attach (group_title (_("Opacity")), 0, 9, 3); attach (opacity_grid, 0, 10, 3); window.event_bus.selected_items_list_changed.connect (on_selected_items_list_changed); } private void on_selected_items_list_changed (List selected_items) { if (selected_items.length () == 0) { selected_item = null; return; } selected_item = selected_items.nth_data (0); } private void disconnect_previous_item () { if (selected_item == null) { return; } // Clear the bindings. x_bind.unbind (); y_bind.unbind (); ratio_bind.unbind (); width_bind.unbind (); height_bind.unbind (); // Unbind only those defined. if (rotation_bind != null) { rotation_bind.unbind (); } if (opacity_bind != null) { opacity_bind.unbind (); } if (hflip_bind != null) { hflip_bind.unbind (); vflip_bind.unbind (); } } private void disable () { // Reset all the values. x.value = 0.0; y.value = 0.0; width.value = 0.0; height.value = 0.0; opacity_adj.value = 100.0; rotation.value = 0.0; lock_changes.active = false; hflip_button.active = false; vflip_button.active = false; } private void enable () { canvas = selected_item.canvas as Akira.Lib.Canvas; x_bind = window.coords_middleware.bind_property ( "x", x, "value", BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL ); y_bind = window.coords_middleware.bind_property ( "y", y, "value", BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL ); ratio_bind = selected_item.size.bind_property ( "locked", lock_changes, "active", BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL); width_bind = window.size_middleware.bind_property ( "width", width, "value", BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL); height_bind = window.size_middleware.bind_property ( "height", height, "value", BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL); // Some items like Artboards don't implement every component. if (selected_item.rotation != null) { rotation_bind = selected_item.rotation.bind_property ( "rotation", rotation, "value", BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL); } if (selected_item.opacity != null) { opacity_bind = selected_item.opacity.bind_property ( "opacity", opacity_adj, "value", BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL); } if (selected_item.flipped != null) { hflip_bind = selected_item.flipped.bind_property ( "horizontal", hflip_button, "active", BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL); vflip_bind = selected_item.flipped.bind_property ( "vertical", vflip_button, "active", BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL); } } private Gtk.Label group_title (string title) { var title_label = new Gtk.Label (title); title_label.get_style_context ().add_class ("group-title"); title_label.halign = Gtk.Align.START; title_label.hexpand = true; title_label.margin_bottom = 2; return title_label; } } Akira-0.0.16/src/Layouts/RightSideBar.vala000066400000000000000000000200421410625726100202320ustar00rootroot00000000000000/* * Copyright (c) 2019-2020 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Alessandro "Alecaddd" Castellani */ public class Akira.Layouts.RightSideBar : Gtk.Grid { public weak Akira.Window window { get; construct; } public Akira.Layouts.Partials.LayersPanel layers_panel; public Akira.Layouts.Partials.PagesPanel pages_panel; public Gtk.ScrolledWindow layers_scroll; public Gtk.ScrolledWindow pages_scroll; public bool toggled { get { return visible; } set { visible = value; no_show_all = !value; } } // Drag and Drop properties. private Gtk.Revealer motion_revealer; private Gtk.TargetList drop_targets { get; set; default = null; } private const Gtk.TargetEntry TARGET_ENTRIES[] = { { "ARTBOARD", Gtk.TargetFlags.SAME_APP, 0 }, { "LAYER", Gtk.TargetFlags.SAME_APP, 0 } }; public RightSideBar (Akira.Window window) { Object ( orientation: Gtk.Orientation.VERTICAL, column_homogeneous: true, toggled: true, window: window ); } construct { get_style_context ().add_class ("sidebar-r"); width_request = 220; drop_targets = new Gtk.TargetList (TARGET_ENTRIES); var pane = new Gtk.Paned (Gtk.Orientation.VERTICAL); pane.expand = true; pane.wide_handle = false; pane.position = 600; layers_panel = new Akira.Layouts.Partials.LayersPanel (window); var layers_grid = new Gtk.Grid (); layers_grid.vexpand = true; layers_grid.add (layers_panel); layers_scroll = new Gtk.ScrolledWindow (null, null); layers_scroll.expand = true; layers_scroll.add (layers_grid); var scrolled_child = layers_scroll.get_child (); if (scrolled_child is Gtk.Container) { ((Gtk.Container) scrolled_child).set_focus_vadjustment (new Gtk.Adjustment (0, 0, 0, 0, 0, 0)); } // Motion revealer for Drag and Drop on the top search bar. var motion_grid = new Gtk.Grid (); motion_grid.get_style_context ().add_class ("grid-motion"); motion_grid.height_request = 2; motion_revealer = new Gtk.Revealer (); motion_revealer.transition_type = Gtk.RevealerTransitionType.SLIDE_DOWN; motion_revealer.add (motion_grid); var top_panel = new Gtk.Grid (); top_panel.attach (build_search_bar (), 0, 0, 1, 1); top_panel.attach (motion_revealer, 0, 1, 1, 1); top_panel.attach (layers_scroll, 0, 2, 1, 1); pane.pack1 (top_panel, false, false); pages_panel = new Akira.Layouts.Partials.PagesPanel (window); pages_scroll = new Gtk.ScrolledWindow (null, null); pages_scroll.expand = true; pages_scroll.add (pages_panel); attach (pane, 0 , 0 , 1, 1); window.event_bus.toggle_presentation_mode.connect (toggle); } private Gtk.Grid build_search_bar () { var search = new Gtk.SearchEntry (); search.hexpand = true; search.margin = 5; search.placeholder_text = _("Search Layer"); search.focus_in_event.connect (handle_focus_in); search.focus_out_event.connect (handle_focus_out); search.activate.connect (() => { warning ("search"); }); var search_grid = new Gtk.Grid (); search_grid.get_style_context ().add_class ("border-bottom"); search_grid.add (search); // Build Drag and Drop for items moving atop the search entry. Gtk.drag_dest_set (search, Gtk.DestDefaults.ALL, TARGET_ENTRIES, Gdk.DragAction.MOVE); search.drag_motion.connect (on_drag_motion); search.drag_leave.connect (on_drag_leave); search.drag_data_received.connect (on_drag_data_received); // Build Drag and Drop for items moving atop the search grid. Gtk.drag_dest_set (search_grid, Gtk.DestDefaults.ALL, TARGET_ENTRIES, Gdk.DragAction.MOVE); search_grid.drag_motion.connect (on_drag_motion); search_grid.drag_leave.connect (on_drag_leave); search_grid.drag_data_received.connect (on_drag_data_received); return search_grid; } private bool on_drag_motion (Gdk.DragContext context, int x, int y, uint time) { motion_revealer.reveal_child = true; return true; } private void on_drag_leave (Gdk.DragContext context, uint time) { motion_revealer.reveal_child = false; } /** * Handle the received layer, find the position of the targeted layer and trigger * a z-index update. */ private void on_drag_data_received ( Gdk.DragContext context, int x, int y, Gtk.SelectionData selection_data, uint target_type, uint time ) { int items_count, pos_source, source; var type = Gtk.drag_dest_find_target (this, context, drop_targets); if (type == Gdk.Atom.intern_static_string ("ARTBOARD")) { var artboard = (Layouts.Partials.Artboard) ( (Gtk.Widget[]) selection_data.get_data () )[0]; items_count = (int) window.items_manager.artboards.get_n_items (); pos_source = items_count - 1 - window.items_manager.artboards.index (artboard.model); // Interrupt if item position doesn't exist. if (pos_source == -1) { return; } // z-index is the exact opposite of items placement as the last item // is the topmost element. Because of this, we need some trickery to // properly handle the list's order. source = items_count - 1 - pos_source; // Interrupt if the item was dropped in the same position. if (source == 0) { debug ("same position"); return; } // Swap the position inside the List Model. window.items_manager.artboards.swap_items (source, 0); // The actual items in the canvas might not match the items in the List Model // due to Artboards labels, grids, and other pseudo elements. Therefore we need // to get the real position of the child and swap them. var root = artboard.model.parent; root.move_child (root.find_child (artboard.model), root.get_n_children ()); window.event_bus.z_selected_changed (); return; } var layer = (Akira.Layouts.Partials.Layer) ((Gtk.Widget[]) selection_data.get_data ())[0]; var layer_artboard = layer.model.artboard; // Change artboard if necessary. window.items_manager.change_artboard.begin (layer.model, null); // If the moved layer had an artboard, no need to do anything else. if (layer_artboard != null) { return; } // Use the existing action to push an item all the way to the top. window.event_bus.change_z_selected (true, true); } private bool handle_focus_in (Gdk.EventFocus event) { if (!(window is Akira.Window)) { return true; } window.event_bus.disconnect_typing_accel (); return false; } private bool handle_focus_out (Gdk.EventFocus event) { if (!(window is Akira.Window)) { return true; } window.event_bus.connect_typing_accel (); return false; } private void toggle () { toggled = !toggled; } } Akira-0.0.16/src/Lib/000077500000000000000000000000001410625726100141265ustar00rootroot00000000000000Akira-0.0.16/src/Lib/Canvas.vala000066400000000000000000000362731410625726100162210ustar00rootroot00000000000000/* * Copyright (c) 2019-2020 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Felipe Escoto * Authored by: Alberto Fanjul * Authored by: Giacomo Alberini * Authored by: Alessandro "Alecaddd" Castellani */ public class Akira.Lib.Canvas : Goo.Canvas { public weak Akira.Window window { get; construct; } // List of accepted dragged targets. private const Gtk.TargetEntry[] TARGETS = { {"text/uri-list", 0, 0} }; public signal void canvas_moved (double delta_x, double delta_y); public signal void canvas_scroll_set_origin (double origin_x, double origin_y); public Managers.ExportManager export_manager; public Managers.SelectedBoundManager selected_bound_manager; public Managers.NobManager nob_manager; private Managers.GridManager grid_manager; private Managers.HoverManager hover_manager; private Managers.ModeManager mode_manager; private Managers.SnapManager snap_manager; public bool ctrl_is_pressed = false; public bool shift_is_pressed = false; public bool holding; public double current_scale = 1.0; private Gdk.CursorType current_cursor = Gdk.CursorType.ARROW; // Used to show the canvas bounds of selected items. private Goo.CanvasRect ghost; public Canvas (Akira.Window window) { Object (window: window); } construct { events |= Gdk.EventMask.KEY_PRESS_MASK; events |= Gdk.EventMask.BUTTON_PRESS_MASK; events |= Gdk.EventMask.BUTTON_RELEASE_MASK; events |= Gdk.EventMask.POINTER_MOTION_MASK; events |= Gdk.EventMask.SCROLL_MASK; events |= Gdk.EventMask.SMOOTH_SCROLL_MASK; events |= Gdk.EventMask.TOUCHPAD_GESTURE_MASK; events |= Gdk.EventMask.TOUCH_MASK; export_manager = new Managers.ExportManager (this); selected_bound_manager = new Managers.SelectedBoundManager (this); nob_manager = new Managers.NobManager (this); grid_manager = new Managers.GridManager (this); hover_manager = new Managers.HoverManager (this); mode_manager = new Managers.ModeManager (this); snap_manager = new Managers.SnapManager (this); // Make the canvas a destination for drag actions. Gtk.drag_dest_set (this, Gtk.DestDefaults.ALL, TARGETS, Gdk.DragAction.COPY); drag_data_received.connect (on_drag_data_received); window.event_bus.update_scale.connect (on_update_scale); window.event_bus.set_scale.connect (on_set_scale); window.event_bus.set_focus_on_canvas.connect (on_set_focus_on_canvas); window.event_bus.request_escape.connect (on_escape_key); window.event_bus.insert_item.connect (on_insert_item); window.event_bus.update_snap_decorators.connect (on_update_snap_decorators); } /** * Handle the data received after a drag and drop action. */ private void on_drag_data_received ( Gdk.DragContext drag_context, int x, int y, Gtk.SelectionData data, uint info, uint time ) { // Make the app aware that we're adding images to the canvas. window.event_bus.insert_item ("image"); // Loop through the list of the dragged files. int index = 0; foreach (string link in data.get_uris ()) { var file_link = link.replace ("file://", "").replace ("file:/", ""); file_link = Uri.unescape_string (file_link); var image = File.new_for_path (file_link); if (!Utils.Image.is_valid_image (image)) { continue; } // Create the image manager. var manager = new Lib.Managers.ImageManager (image, index); // Create the item. var item = window.items_manager.insert_item (x, y, manager); // Force the resize of the item to its original size. ((Lib.Items.CanvasImage)item).resize_pixbuf (-1, -1, true); index++; } Gtk.drag_finish (drag_context, true, false, time); // Reset the mode manager to the default "selection mode". mode_manager.deregister_active_mode (); update_canvas (); } public void interaction_mode_changed () { set_cursor_by_interaction_mode (); } public void set_cursor_by_interaction_mode () { hover_manager.remove_hover_effect (); Gdk.CursorType? new_cursor = mode_manager.active_cursor_type (); if (new_cursor == null) { var hover_cursor = Akira.Lib.Managers.NobManager.cursor_from_nob (nob_manager.hovered_nob); new_cursor = (hover_cursor == null) ? Gdk.CursorType.ARROW : hover_cursor; } if (current_cursor != new_cursor) { // debug (@"Changing cursor. $new_cursor"); set_cursor (new_cursor); } } public override bool key_press_event (Gdk.EventKey event) { uint uppercase_keyval = Gdk.keyval_to_upper (event.keyval); switch (uppercase_keyval) { case Gdk.Key.Control_L: case Gdk.Key.Control_R: ctrl_is_pressed = true; toggle_item_ghost (false); break; case Gdk.Key.Shift_L: case Gdk.Key.Shift_R: shift_is_pressed = true; break; case Gdk.Key.Alt_L: case Gdk.Key.Alt_R: // Show the ghost item only if the CTRL button is not pressed. toggle_item_ghost (!ctrl_is_pressed); break; } if (mode_manager.key_press_event (event)) { return true; } switch (uppercase_keyval) { case Gdk.Key.space: mode_manager.start_panning_mode (); if (mode_manager.key_press_event (event)) { return true; } break; case Gdk.Key.Up: case Gdk.Key.Down: case Gdk.Key.Right: case Gdk.Key.Left: window.event_bus.move_item_from_canvas (event); window.event_bus.detect_artboard_change (); return true; default: break; } return false; } public override bool key_release_event (Gdk.EventKey event) { uint uppercase_keyval = Gdk.keyval_to_upper (event.keyval); switch (uppercase_keyval) { case Gdk.Key.Control_L: case Gdk.Key.Control_R: ctrl_is_pressed = false; break; case Gdk.Key.Shift_L: case Gdk.Key.Shift_R: shift_is_pressed = false; break; case Gdk.Key.Alt_L: case Gdk.Key.Alt_R: toggle_item_ghost (false); break; } if (mode_manager.key_release_event (event)) { return true; } return false; } public override bool button_press_event (Gdk.EventButton event) { focus_canvas (); holding = true; event.x = event.x / current_scale; event.y = event.y / current_scale; hover_manager.remove_hover_effect (); if (mode_manager.button_press_event (event)) { return true; } if (event.button == Gdk.BUTTON_MIDDLE) { mode_manager.start_panning_mode (); if (mode_manager.button_press_event (event)) { return true; } } return press_event_on_selection (event); } public override bool button_release_event (Gdk.EventButton event) { if (mode_manager.button_release_event (event)) { return true; } return false; } public override bool motion_notify_event (Gdk.EventMotion event) { event.x = event.x / current_scale; event.y = event.y / current_scale; window.event_bus.coordinate_change (event.x, event.y); if (mode_manager.motion_notify_event (event)) { return true; } var nob_hovered = nob_manager.hit_test (event.x, event.y); if (nob_hovered != nob_manager.hovered_nob) { nob_manager.hovered_nob = nob_hovered; set_cursor_by_interaction_mode (); } hover_manager.on_mouse_over (event.x, event.y, nob_hovered); return false; } public void start_export_area_selection () { var new_mode = new Akira.Lib.Modes.ExportMode (this, mode_manager); mode_manager.register_mode (new_mode); } public void on_insert_item () { var new_mode = new Akira.Lib.Modes.ItemInsertMode (this, mode_manager); mode_manager.register_mode (new_mode); } /* * Perform a series of updates after an item is created. */ public void update_canvas () { // Synchronous update to make sure item is initialized before any other event. update (); grid_manager.on_canvas_update (); } /* * Handle escape key. */ public void on_escape_key () { mode_manager.deregister_active_mode (); // Clear the selected export area to be sure to not leave anything behind. export_manager.clear (); // Clear the image manager in case the user was adding an image. window.items_manager.image_manager = null; on_set_focus_on_canvas (); } public void on_set_focus_on_canvas () { ctrl_is_pressed = false; focus_canvas (); // Clear the selected export area to be sure to not leave anything behind. export_manager.clear (); } public void focus_canvas () { grab_focus (get_root_item ()); } private bool press_event_on_selection (Gdk.EventButton event) { var nob_clicked = nob_manager.hit_test (event.x, event.y); nob_manager.set_selected_by_name (nob_clicked); if (nob_clicked == Akira.Lib.Managers.NobManager.Nob.NONE) { var clicked_item = get_item_at (event.x, event.y, true); // Deselect if no item was clicked, or a non selected artboard was clicked. // We do this to allow users to clear the selection when clicking on the // empty artboard space, which is a white GooCanvasRect item. if ( clicked_item == null || ( clicked_item is Goo.CanvasRect && !(clicked_item is Items.CanvasItem) && !(clicked_item is Selection.Nob) && !((Items.CanvasItem) clicked_item.parent).layer.selected ) ) { selected_bound_manager.reset_selection (); // TODO: allow for multi select with click & drag on canvas // Workaround: when no item is clicked, there's no point in keeping holding active holding = false; return true; } // If we're clicking on the Artboard's label, change the target to the Artboard. if ( clicked_item is Goo.CanvasText && clicked_item.parent is Items.CanvasArtboard && !(clicked_item is Items.CanvasItem) ) { clicked_item = clicked_item.parent as Items.CanvasItem; } if (clicked_item is Items.CanvasItem) { var item = clicked_item as Items.CanvasItem; // Item has been selected. selected_bound_manager.add_item_to_selection (item); } } if (selected_bound_manager.selected_items.length () > 0) { var new_mode = new Akira.Lib.Modes.TransformMode (this, mode_manager); mode_manager.register_mode (new_mode); if (mode_manager.button_press_event (event)) { return true; } } else { nob_manager.set_selected_by_name (Akira.Lib.Managers.NobManager.Nob.NONE); } return false; } private void on_update_scale (double zoom) { // Force the zoom value to 8% if we're currently at a 2% scale in order // to go back to 10% and increase from there. if (current_scale == 0.02 && zoom == 0.1) { zoom = 0.08; } current_scale += zoom; // Prevent the canvas from shrinking below 2%; if (current_scale < 0.02) { current_scale = 0.02; } // Prevent the canvas from growing above 5000%; if (current_scale > 50) { current_scale = 50; } window.event_bus.set_scale (current_scale); } private void on_set_scale (double scale) { current_scale = scale; set_scale (scale); window.event_bus.zoom (); window.event_bus.update_snap_decorators (); } private void set_cursor (Gdk.CursorType? cursor_type) { // debug (@"Setting cursor: $cursor_type"); current_cursor = cursor_type; var cursor = new Gdk.Cursor.for_display (Gdk.Display.get_default (), cursor_type); get_window ().set_cursor (cursor); } /* * Show or hide the ghost bounding box of the selected items. */ public void toggle_item_ghost (bool show) { // If no items is selected we can't show anything. if (selected_bound_manager.selected_items.length () == 0) { return; } // Temporarily get the first item until multi select is implemented. var item = selected_bound_manager.selected_items.nth_data (0); if (show) { ghost = new Goo.CanvasRect ( null, item.coordinates.x1, item.coordinates.y1, item.coordinates.x2 - item.coordinates.x1, item.coordinates.y2 - item.coordinates.y1, "line-width", 1.0 / current_scale, "stroke-color", "#41c9fd", null ); ghost.set ("parent", get_root_item ()); ghost.can_focus = false; ghost.pointer_events = Goo.CanvasPointerEvents.NONE; return; } if (ghost != null) { ghost.remove (); } } /* * Will update snap decorators if necessary. */ private void on_update_snap_decorators () { var extra_context = mode_manager.active_mode_extra_context (); if (extra_context is Akira.Lib.Modes.TransformMode.TransformExtraContext) { snap_manager.generate_decorators ( ((Lib.Modes.TransformMode.TransformExtraContext) extra_context).snap_guide_data); } else if (snap_manager.is_active ()) { snap_manager.reset_decorators (); } } } Akira-0.0.16/src/Lib/Components/000077500000000000000000000000001410625726100162535ustar00rootroot00000000000000Akira-0.0.16/src/Lib/Components/Border.vala000066400000000000000000000042541410625726100203420ustar00rootroot00000000000000/** * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Alessandro "Alecaddd" Castellani */ /** * Border component to keep track of a single border, which includes different attributes. */ public class Akira.Lib.Components.Border : Component { public unowned Borders borders { get; set; } // Since items can have multiple border colors, we need to keep track of each // with a unique identifier in order to properly update them. public int id { get; set; } public Gdk.RGBA color { get; set; } // Store the hexadecimal string version of the color (E.g.: #FF00CC) public string hex { get; set; } public int size { get; set; } public int alpha { get; set; } public bool hidden { get; set; } public Border (Borders _borders, Items.CanvasItem _item, Gdk.RGBA init_color, int init_size, int border_id) { borders = _borders; item = _item; id = border_id; color = init_color; size = init_size; alpha = 255; // Listen for changed to the border attributes to properly trigger the color generation. this.notify["color"].connect (() => { hex = Utils.Color.rgba_to_hex (color.to_string ()); borders.reload (); }); this.notify["size"].connect (() => { borders.reload (); }); this.notify["hidden"].connect (() => { borders.reload (); }); } public void remove () { borders.remove_border (this); } } Akira-0.0.16/src/Lib/Components/BorderRadius.vala000066400000000000000000000030231410625726100215030ustar00rootroot00000000000000/** * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Alessandro "Alecaddd" Castellani */ /** * BorderRadius component to handle the border radius of an item. */ public class Akira.Lib.Components.BorderRadius : Component { public double x { get; set; } public double y { get; set; } public bool uniform { get; set; } public bool autoscale { get; set; } public BorderRadius (Items.CanvasItem _item) { item = _item; x = y = 0.0; uniform = true; autoscale = false; this.notify["x"].connect (update); this.notify["y"].connect (update); } public void update () { // We use the X value for both radii in case the radius is set to uniform. if (uniform) { item.set ("radius-x", x); item.set ("radius-y", x); } } } Akira-0.0.16/src/Lib/Components/Borders.vala000066400000000000000000000111121410625726100205140ustar00rootroot00000000000000/** * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Alessandro "Alecaddd" Castellani */ /** * Borders component to keep track of the item's border colors, which have to account * for the global opacity as well when rendering the item. */ public class Akira.Lib.Components.Borders : Component { // A list of all the borders the item might have. public Gee.ArrayList borders { get; set; } // Keep track of the newly created Fill child components. private int id { get; set; default = 0; } public Borders (Items.CanvasItem _item, Gdk.RGBA init_color, int init_size) { item = _item; borders = new Gee.ArrayList (); // Only add the initial border if the user configured it in the Settings. if (settings.set_border) { add_border_color (init_color, init_size); } else { reload (); } } /** * Create a new border color component. * * @param {Gdk.RGBA} color - The initial color of the border. * @return Fill - The newly created border component. */ public Border add_border_color (Gdk.RGBA init_color, int init_size) { var new_border = new Border (this, item, init_color, init_size, id); borders.add (new_border); // Increase the ID to keep an incremental unique identifier. id++; // Trigger the generation of the border color. reload (); return new_border; } public int count () { return borders.size; } public void reload () { // If we don't have any border associated with this item, remove the border color. if (count () == 0) { item.set ("stroke-color-rgba", null); item.set ("line-width", 0.0); return; } bool has_colors = false; // Set an initial arbitrary color with full transparency. var rgba_border = Gdk.RGBA (); rgba_border.alpha = 0; // Set an initial border size, we currently support one size // even for multiple borders. int size = 0; // Loop through all the configured borders and reload the color. foreach (Border border in borders) { // Skip if the border is hidden as we don't need to blend colors. if (border.hidden) { continue; } // Set the new blended color. rgba_border = Utils.Color.blend_colors (rgba_border, border.color); size = int.max (size, border.size); has_colors = true; } // Apply the mixed RGBA value only if we had one. if (has_colors) { // Keep in consideration the global opacity to properly update the border color. rgba_border.alpha = rgba_border.alpha * item.opacity.opacity / 100; uint stroke_color_rgba = Utils.Color.rgba_to_uint (rgba_border); item.set ("stroke-color-rgba", stroke_color_rgba); // The "line-width" property expects a DOUBLE type, but we don't support subpixels // so we always handle the border size as INT, therefore we need to type cast it here. item.set ("line-width", (double) size); } else { item.set ("stroke-color-rgba", null); item.set ("line-width", 0.0); } } public void remove_border (Border border) { borders.remove (border); reload (); } /** * Helper method to allow the global shortcut action to update the border color. */ public void update_color_from_action (Gdk.RGBA color) { // If no border color is available, create a new one. if (count () == 0) { add_border_color (color, 1); return; } // Get the first border color since the user is using the global color picker. Border first = borders.get (0); first.color = color; reload (); } } Akira-0.0.16/src/Lib/Components/Component.vala000066400000000000000000000022001410625726100210540ustar00rootroot00000000000000/** * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Alessandro "Alecaddd" Castellani */ public class Akira.Lib.Components.Component : Object { /** * This is the base Component class other components will extend. * It doesn't do anything other than setting the CanvasItem during construct. * It might be removed in the future if deemed unnecessary. */ public unowned Lib.Items.CanvasItem item { get; set; } } Akira-0.0.16/src/Lib/Components/Coordinates.vala000066400000000000000000000125401410625726100213740ustar00rootroot00000000000000/** * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Alessandro "Alecaddd" Castellani */ /** * Coordinates component to keep track of the item's initial coordinates. */ public class Akira.Lib.Components.Coordinates : Component { // LEFT item position, converted to artboard's coordinates if the item is inside an artboard. public double x { get { // If the item is an artboard we need to get the bounds of the background since // the artboard group will have its bounds changing based on the location of the // child items. if (item is Items.CanvasArtboard) { return ((Items.CanvasArtboard) item).background.bounds.x1; } double item_x = item.bounds.x1 + get_border (); if (item.artboard != null) { double temp_y = 0.0; item.canvas.convert_to_item_space (item.artboard, ref item_x, ref temp_y); } return item_x; } } // Global LEFT item position relative to the Canvas, ignoring potential parent's artboard. public double x1 { get { // If the item is an artboard we need to get the bounds of the background since // the artboard group will have its bounds changing based on the location of the // child items. if (item is Items.CanvasArtboard) { return ((Items.CanvasArtboard) item).background.bounds.x1; } return item.bounds.x1 + get_border (); } } // Global RIGHT (LEFT + WIDTH) item position relative to the Canvas, // ignoring potential parent's artboard. public double x2 { get { // If the item is an artboard we need to get the bounds of the background since // the artboard group will have its bounds changing based on the location of the // child items. if (item is Items.CanvasArtboard) { return ((Items.CanvasArtboard) item).background.bounds.x2; } return item.bounds.x2 - get_border (); } } // TOP item position, converted to artboard's coordinates if the item is inside an artboard. public double y { get { // If the item is an artboard we need to get the bounds of the background since // the artboard group will have its bounds changing based on the location of the // child items. if (item is Items.CanvasArtboard) { return ((Items.CanvasArtboard) item).background.bounds.y1; } double item_y = item.bounds.y1 + get_border (); if (item.artboard != null) { double temp_x = 0.0; item.canvas.convert_to_item_space (item.artboard, ref temp_x, ref item_y); } return item_y; } } // Global TOP item position relative to the Canvas, ignoring potential parent's artboard. public double y1 { get { // If the item is an artboard we need to get the bounds of the background since // the artboard group will have its bounds changing based on the location of the // child items. if (item is Items.CanvasArtboard) { return ((Items.CanvasArtboard) item).background.bounds.y1; } return item.bounds.y1 + get_border (); } } // Global BOTTOM (TOP + HEIGHT) item position relative to the Canvas, // ignoring potential parent's artboard. public double y2 { get { // If the item is an artboard we need to get the bounds of the background since // the artboard group will have its bounds changing based on the location of the // child items. if (item is Items.CanvasArtboard) { return ((Items.CanvasArtboard) item).background.bounds.y2; } return item.bounds.y2 - get_border (); } } public Coordinates (Items.CanvasItem _item) { item = _item; } /** * The item's bounds account also for the border width, but we shouldn't, * so we need to account for half the border width since we're only dealing * with a centered border. In the future, once borders can be inside or outside, * we will need to update this condition. */ private double get_border () { if (item.borders == null) { return 0; } // Temporarily return the current line_width of the item // since we only support 1 border at the time. double stroke; item.get ("line-width", out stroke); return stroke > 0 ? stroke / 2 : 0; } } Akira-0.0.16/src/Lib/Components/Fill.vala000066400000000000000000000043201410625726100200050ustar00rootroot00000000000000/** * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Alessandro "Alecaddd" Castellani */ /** * Fill component to keep track of a single filling, which includes different attributes. */ public class Akira.Lib.Components.Fill : Component { public unowned Fills fills { get; set; } // Since items can have multiple filling colors, we need to keep track of each // with a unique identifier in order to properly update them. public int id { get; set; } public Gdk.RGBA color { get; set; } // Store the hexadecimal string version of the color (E.g.: #FF00CC) public string hex { get; set; } public int alpha { get; set; } public bool hidden { get; set; } public Fill (Fills _fills, Items.CanvasItem _item, Gdk.RGBA init_color, int fill_id) { fills = _fills; item = _item; id = fill_id; color = init_color; hex = color.to_string (); alpha = 255; // Listen for changed to the fill attributes to properly trigger the color generation. this.notify["color"].connect (() => { hex = Utils.Color.rgba_to_hex (color.to_string ()); fills.reload (); }); this.notify["hidden"].connect (() => { fills.reload (); }); this.notify["alpha"].connect (() => { var rgba = Gdk.RGBA (); rgba = color; rgba.alpha = ((double) alpha) / 255; color = rgba; }); } public void remove () { fills.remove_fill (this); } } Akira-0.0.16/src/Lib/Components/Fills.vala000066400000000000000000000105121410625726100201700ustar00rootroot00000000000000/** * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Alessandro "Alecaddd" Castellani */ /** * Fills component to keep track of the item's filling colors, which have to account * for the global opacity as well when rendering the item. */ public class Akira.Lib.Components.Fills : Component { // A list of all the fills the item might have. public Gee.ArrayList fills { get; set; } // Keep track of the newly created Fill child components. private int id { get; set; default = 0; } public Fills (Items.CanvasItem _item, Gdk.RGBA color) { item = _item; fills = new Gee.ArrayList (); add_fill_color (color); } /** * Create a new fill color component. * * @param {Gdk.RGBA} color - The initial color of the fill. * @return Fill - The newly created fill component. */ public Fill add_fill_color (Gdk.RGBA color) { var new_fill = new Fill (this, item, color, id); fills.add (new_fill); // Increase the ID to keep an incremental unique identifier. id++; // Trigger the generation of the fill color. reload (); return new_fill; } public int count () { return fills.size; } /** * Loop through all the fill colors and create a final blend. */ public void reload () { // If we don't have any fill associated with this item, remove the background color. if (count () == 0) { if (item is Items.CanvasArtboard) { ((Items.CanvasArtboard) item).background.set ("fill-color-rgba", null); } else { item.set ("fill-color-rgba", null); } return; } bool has_colors = false; // Set an initial arbitrary color with full transparency. var rgba_fill = Gdk.RGBA (); rgba_fill.alpha = 0; // Loop through all the configured fills. foreach (Fill fill in fills) { // Skip if the fill is hidden as we don't need to blend colors. if (fill.hidden) { continue; } // Set the new blended color. rgba_fill = Utils.Color.blend_colors (rgba_fill, fill.color); has_colors = true; } // Apply the mixed RGBA value only if we had one. if (has_colors) { // Keep in consideration the global opacity to properly update the fill color. rgba_fill.alpha = rgba_fill.alpha * item.opacity.opacity / 100; uint fill_color_rgba = Utils.Color.rgba_to_uint (rgba_fill); if (item is Items.CanvasArtboard) { ((Items.CanvasArtboard) item).background.set ("fill-color-rgba", fill_color_rgba); } else { item.set ("fill-color-rgba", fill_color_rgba); } } else { if (item is Items.CanvasArtboard) { ((Items.CanvasArtboard) item).background.set ("fill-color-rgba", null); } else { item.set ("fill-color-rgba", null); } } } public void remove_fill (Fill fill) { fills.remove (fill); reload (); } /** * Helper method to allow the global shortcut action to update the fill color. */ public void update_color_from_action (Gdk.RGBA color) { // If no fill color is available, create a new one. if (count () == 0) { add_fill_color (color); return; } // Get the first fill color since the user is using the global color picker. Fill first = fills.get (0); first.color = color; reload (); } } Akira-0.0.16/src/Lib/Components/Flipped.vala000066400000000000000000000041241410625726100205040ustar00rootroot00000000000000/** * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Alessandro "Alecaddd" Castellani */ /** * Flipped component to handle the flipped (mirrored) state of an item. */ public class Akira.Lib.Components.Flipped : Component { public bool horizontal { get; set; } public bool vertical { get; set; } public Flipped (Items.CanvasItem _item) { item = _item; horizontal = false; vertical = false; this.notify["horizontal"].connect (() => { flip_item (-1, 1); }); this.notify["vertical"].connect (() => { flip_item (1, -1); }); } /** * GooCanvas doesn't come with a mirror or flip method out of the box, * therefore we need to use Cairo and do it manually. */ private void flip_item (double sx, double sy) { double center_x = item.size.width / 2; double center_y = item.size.height / 2; Cairo.Matrix transform; item.get_transform (out transform); double radians = Utils.AffineTransform.deg_to_rad (item.rotation.rotation); transform.translate (center_x, center_y); transform.rotate (-radians); transform.scale (sx, sy); transform.rotate (radians); transform.translate (-center_x, -center_y); item.set_transform (transform); ((Lib.Canvas) item.canvas).window.event_bus.item_value_changed (); } } Akira-0.0.16/src/Lib/Components/Layer.vala000066400000000000000000000021171410625726100201750ustar00rootroot00000000000000/** * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Alessandro "Alecaddd" Castellani */ /** * Layer component to keep track of the item's attributes for the layers panel. */ public class Akira.Lib.Components.Layer : Component { public bool selected { get; set; } public bool locked { get; set; } public Layer () { selected = false; locked = false; } } Akira-0.0.16/src/Lib/Components/Name.vala000066400000000000000000000053071410625726100200050ustar00rootroot00000000000000/** * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Alessandro "Alecaddd" Castellani */ /** * Name component to handle generating an ID and a unique name on creation. */ public class Akira.Lib.Components.Name : Component { public string id { get; set; } public string name { get; set; } public string icon { get; set; } public Name (Lib.Items.CanvasItem _item) { item = _item; set_properties (); update_name (); } private void set_properties () { // Assign the proper icon for the layers panel. // We can't use a switch () method here because the typeof () method is not supported. if (item is Items.CanvasArtboard) { icon = null; name = _("Artboard"); } if (item is Items.CanvasRect) { icon = "shape-rectangle-symbolic"; name = _("Rectangle"); } if (item is Items.CanvasEllipse) { icon = "shape-circle-symbolic"; name = _("Ellipse"); } if (item is Items.CanvasText) { icon = "shape-text-symbolic"; name = _("Text"); } if (item is Items.CanvasImage) { icon = "shape-image-symbolic"; name = _("Image"); } } private void update_name () { var type = item.get_type (); // Make sure the initial ID includes the current count of the total amount // of items with the same item type in the same artboard. int count = 0; var items = ((Lib.Canvas) item.canvas).window.items_manager.free_items; if (item.artboard != null) { items = item.artboard.items; } if (item is Lib.Items.CanvasArtboard) { items = ((Lib.Canvas) item.canvas).window.items_manager.artboards; } foreach (var _item in items) { if (_item.get_type () == type) { count++; } } id = name + " " + count.to_string (); name = id; } } Akira-0.0.16/src/Lib/Components/Opacity.vala000066400000000000000000000027721410625726100205400ustar00rootroot00000000000000/** * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Alessandro "Alecaddd" Castellani */ /** * Opacity component to keep track of the item global opacity, which has to account * for all fills and borders colors. */ public class Akira.Lib.Components.Opacity : Component { public double opacity { get; set; } public Opacity (Items.CanvasItem _item) { item = _item; // Set opacity to 100% (fully visible) when the item is first created. opacity = 100.0; this.notify["opacity"].connect (() => { // Reload the item's colors only if it uses those components. if (item.fills != null) { item.fills.reload (); } if (item.borders != null) { item.borders.reload (); } }); } } Akira-0.0.16/src/Lib/Components/Rotation.vala000066400000000000000000000032261410625726100207220ustar00rootroot00000000000000/** * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Alessandro "Alecaddd" Castellani */ /** * Rotation component to keep track of the item's rotation. */ public class Akira.Lib.Components.Rotation : Component { private double _rotation; public double rotation { get { return _rotation; } set { // Interrupt if nothing changed. if (_rotation == value) { return; } var center_x = item.size.width / 2; var center_y = item.size.height / 2; var new_rotation = value - _rotation; item.rotate (new_rotation, center_x, center_y); _rotation += new_rotation; ((Lib.Canvas) item.canvas).window.event_bus.item_value_changed (); } } public Rotation (Items.CanvasItem _item) { item = _item; // Set rotation to 0 when the item is first created. _rotation = 0.0; } } Akira-0.0.16/src/Lib/Components/Size.vala000066400000000000000000000070321410625726100200340ustar00rootroot00000000000000/** * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Alessandro "Alecaddd" Castellani */ /** * Size component to keep track of the item's size ratio attributes. */ public class Akira.Lib.Components.Size : Component { // Keep track of the size changed internally based on the size ratio. private bool auto_resize = false; public bool locked { get; set; } public double ratio { get; set; } public double width { get { double w = 0.0; item.get ("width", out w); return w; } set { item.set ("width", value); if (locked && !auto_resize) { auto_resize = true; var locked_height = Utils.AffineTransform.fix_size (value / ratio); height = item is Items.CanvasImage && locked_height < 1 ? 1 : locked_height; auto_resize = false; } if (!auto_resize) { Lib.Canvas canvas = item.canvas as Lib.Canvas; canvas.window.event_bus.item_value_changed (); // If the value wasn't changed automatically by the auto resize, // and the image is selected, recalculate the pixbuf quality. if (item is Items.CanvasImage && item.layer.selected && !canvas.holding) { canvas.window.event_bus.detect_image_size_change (); } } } } public double height { get { double h = 0.0; item.get ("height", out h); return h; } set { item.set ("height", value); if (locked && !auto_resize) { auto_resize = true; var locked_width = Utils.AffineTransform.fix_size (value / ratio); height = item is Items.CanvasImage && locked_width < 1 ? 1 : locked_width; auto_resize = false; } if (!auto_resize) { Lib.Canvas canvas = item.canvas as Lib.Canvas; canvas.window.event_bus.item_value_changed (); // If the value wasn't changed automatically by the auto resize, // and the image is selected, recalculate the pixbuf quality. if (item is Items.CanvasImage && item.layer.selected && !canvas.holding) { canvas.window.event_bus.detect_image_size_change (); } } } } public Size (Items.CanvasItem _item) { item = _item; locked = false; ratio = 1.0; this.notify["locked"].connect (update_ratio); } /** * Helper method to update the size ratio of an item. */ public void update_ratio () { // Avoid divding by 0. if (width == 0 || height == 0) { return; } ratio = width / height; } } Akira-0.0.16/src/Lib/Items/000077500000000000000000000000001410625726100152075ustar00rootroot00000000000000Akira-0.0.16/src/Lib/Items/CanvasArtboard.vala000066400000000000000000000156671410625726100207650ustar00rootroot00000000000000/** * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Alessandro "Alecaddd" Castellani */ using Akira.Lib.Components; /** * Generate the Artboard, based on the CanvasGroup item, which is basically a rectangle. */ public class Akira.Lib.Items.CanvasArtboard : Goo.CanvasGroup, Akira.Lib.Items.CanvasItem { public Gee.ArrayList components { get; set; } public Items.CanvasArtboard? artboard { get; set; } // Override the list type of the Goo.CanvasGroup. public new Akira.Models.ListModel items; // Unique attributes of the Artboard. public Goo.CanvasRect background; public Goo.CanvasText label; private const int FONT_SIZE = 10; private uint light_color; private uint dark_color; public CanvasArtboard (double _x, double _y, Goo.CanvasItem? _parent) { parent = _parent; // Artboards can't be nested. artboard = null; // Create the Artboard. x = y = 0; width = height = 1; init_position (this, _x, _y); // Add the newly created item to the Canvas. parent.add_child (this, -1); // Force the generation of the item bounds on creation. Goo.CanvasBounds bounds; this.get_bounds (out bounds); // Add all the components that this item uses. components = new Gee.ArrayList (); components.add (new Name (this)); components.add (new Coordinates (this)); components.add (new Opacity (this)); components.add (new Size (this)); // Create the background element before adding the Fills component. create_background (); // Artboards have fills that can be edited, but they always start // with a full white background. var fill_color = Gdk.RGBA (); fill_color.parse ("#fff"); components.add (new Fills (this, fill_color)); components.add (new Layer ()); // Init the items list. items = new Models.ListModel (); create_label (); } private void create_background () { background = new Goo.CanvasRect (this, 0, 0, 1, 1, "line-width", 0.0, null); background.translate (0, 0); background.can_focus = false; // Even if this item doesn't receive any pointer events we can't set NONE // since users should be able to click on the artboard's background to drag // the artboard around when the artboard is selected. this.size.bind_property ("width", background, "width", BindingFlags.SYNC_CREATE); this.size.bind_property ("height", background, "height", BindingFlags.SYNC_CREATE); } private void create_label () { // Define the label colors for dark/light theme variation. light_color = Utils.Color.color_string_to_uint ("rgba(255, 255, 255, 0.75)"); dark_color = Utils.Color.color_string_to_uint ("rgba(0, 0, 0, 0.75)"); // Type cast the akira canvas to gain access to its attributes. var akira_canvas = canvas as Lib.Canvas; // Create the text with the base Canvas as initial parent. label = new Goo.CanvasText ( parent, name.name, x, y, 1.0, Goo.CanvasAnchorType.SW, "font", "Open Sans " + (FONT_SIZE / akira_canvas.current_scale).to_string (), "ellipsize", Pango.EllipsizeMode.END, "fill-color-rgba", settings.dark_theme ? light_color : dark_color, null); label.can_focus = false; // Change the parent to allow mouse pointer selection. label.parent = this; this.bind_property ("visibility", label, "visibility", BindingFlags.SYNC_CREATE); this.bind_property ("pointer_events", label, "pointer_events", BindingFlags.SYNC_CREATE); this.name.bind_property ("name", label, "text", BindingFlags.SYNC_CREATE); this.size.bind_property ("width", label, "width", BindingFlags.SYNC_CREATE); // Listen to the theme changing event to update the label color. akira_canvas.window.event_bus.change_theme.connect (on_theme_changed); // Update the label font size when the canvas zoom changes. akira_canvas.window.event_bus.set_scale.connect (on_canvas_scaled); } /* * Update the color of the artboard label based on the light/dark theme. */ private void on_theme_changed () { label.set ("fill-color-rgba", settings.dark_theme ? light_color : dark_color); } /* * Update the artboard label font size based on the current scale. */ private void on_canvas_scaled (double scale) { label.set ("font", "Open Sans " + (FONT_SIZE / scale).to_string ()); } /** * Helper method to determine if a click event happened inside an artboard. */ public bool is_inside (double x, double y) { return x <= background.bounds.x2 && x >= background.bounds.x1 && y >= background.bounds.y1 && y <= background.bounds.y2; } /** * Detect if an item was moved outside the artboard's sizing limits. * We use the background bounds because the artboard bounds grow based * on the location of the child items. So if an item is outside the * artboard's background, the artboard bounds will reflect the new group bounds. */ public bool is_outside (Items.CanvasItem item) { return item.coordinates.x1 > background.bounds.x2 || item.coordinates.y1 > background.bounds.y2 || item.coordinates.x2 < background.bounds.x1 || item.coordinates.y2 < background.bounds.y1; } public uint get_items_length () { return items.get_n_items (); } public void remove_item (Items.CanvasItem item) { // Remove the child from the GooCanvasItem parent. remove_child (find_child (item)); // Remove the item from the ListModel. items.remove_item.begin (item); // Unset the artboard attribute. item.artboard = null; } public void delete () { background.remove (); // Type cast the akira canvas to gain access to its attributes. var akira_canvas = canvas as Lib.Canvas; // Disconnect previously set events. akira_canvas.window.event_bus.change_theme.disconnect (on_theme_changed); akira_canvas.window.event_bus.set_scale.disconnect (on_canvas_scaled); // Reassign the Canvas as parent to the label in order to remove it. label.parent = parent; label.remove (); } } Akira-0.0.16/src/Lib/Items/CanvasEllipse.vala000066400000000000000000000046521410625726100206140ustar00rootroot00000000000000/** * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Alessandro "Alecaddd" Castellani */ using Akira.Lib.Components; /** * Generate a simple Ellipse. */ public class Akira.Lib.Items.CanvasEllipse : Goo.CanvasEllipse, Akira.Lib.Items.CanvasItem { public Gee.ArrayList components { get; set; } public Items.CanvasArtboard? artboard { get; set; } public CanvasEllipse ( double _x, double _y, int border_size, Gdk.RGBA border_color, Gdk.RGBA fill_color, Goo.CanvasItem? _parent, Items.CanvasArtboard? _artboard ) { parent = _artboard != null ? _artboard : _parent; artboard = _artboard; // Create the ellipse. x = y = 0; width = height = 1; // The CanvasEllipse needs a starting radius at least half of the initial width. radius_x = radius_y = 0.5; init_position (this, _x, _y); // Add the newly created item to the Canvas or Artboard. parent.add_child (this, -1); // Force the generation of the item bounds on creation. Goo.CanvasBounds bounds; this.get_bounds (out bounds); // Add all the components that this item uses. components = new Gee.ArrayList (); components.add (new Name (this)); components.add (new Coordinates (this)); components.add (new Opacity (this)); components.add (new Rotation (this)); components.add (new Fills (this, fill_color)); components.add (new Borders (this, border_color, border_size)); components.add (new Size (this)); components.add (new Flipped (this)); components.add (new Layer ()); check_add_to_artboard (this); } } Akira-0.0.16/src/Lib/Items/CanvasImage.vala000066400000000000000000000120401410625726100202270ustar00rootroot00000000000000/** * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Alessandro "Alecaddd" Castellani */ using Akira.Lib.Components; /** * Generate a simple Image item. */ public class Akira.Lib.Items.CanvasImage : Goo.CanvasImage, Akira.Lib.Items.CanvasItem { public Gee.ArrayList components { get; set; } public Items.CanvasArtboard? artboard { get; set; } // CanvasImage unique attributes. public Lib.Managers.ImageManager manager { get; set; } private Gdk.Pixbuf original_pixbuf; public CanvasImage ( double _x, double _y, Lib.Managers.ImageManager _manager, Goo.CanvasItem? _parent, Items.CanvasArtboard? _artboard ) { parent = _artboard != null ? _artboard : _parent; artboard = _artboard; // Set the ImageManager. manager = _manager; // Create the image item. x = y = 0; width = height = 1; scale_to_fit = true; init_position (this, _x, _y); // Add the newly created item to the Canvas or Artboard. parent.add_child (this, -1); // Initialize the imported image. init_pixbuf (); // Force the generation of the item bounds on creation. Goo.CanvasBounds bounds; this.get_bounds (out bounds); // Add all the components that this item uses. components = new Gee.ArrayList (); components.add (new Name (this)); components.add (new Coordinates (this)); components.add (new Opacity (this)); components.add (new Rotation (this)); components.add (new Size (this)); components.add (new Flipped (this)); components.add (new Layer ()); check_add_to_artboard (this); ((Lib.Canvas) canvas).window.event_bus.detect_image_size_change.connect (check_resize_pixbuf); } private void init_pixbuf () { // Load the pixbuf at full resolution to properly define the size ratio of the item. manager.get_pixbuf.begin (-1, -1, (obj, res) => { try { original_pixbuf = manager.get_pixbuf.end (res); pixbuf = original_pixbuf; // Define the item's size based on the images size. size.width = original_pixbuf.width; size.height = original_pixbuf.height; // Imported images should have their size ratio locked by default. // Change the locked attribute after the size has been defined to let // the Size component properly calculate the correct size ratio. size.locked = true; // Reset the size to a 2px initial value after the size ratio was properly defined // in order to allow the user to decide the initial image size. We use 2px in order // to avoid issues when dividing by the ratio in case of narrow images. size.width = 2; } catch (Error e) { warning (e.message); ((Lib.Canvas) canvas).window.event_bus.canvas_notification (e.message); } }); } /** * Trigger the pixbuf resampling. */ public void check_resize_pixbuf () { // Interrupt if this image isn't part of the selection. if (!layer.selected) { return; } // Interrupt if the size of the image didn't change. if (size.width == manager.pixbuf.get_width () && size.height == manager.pixbuf.get_height ()) { return; } resize_pixbuf ((int) size.width, (int) size.height); } /** * Resample the pixbuf size. * * @param {int} w - The new width. * @param {int} h - The new height. * @param {bool} update - If the updated pixbuf size should be applied to the CanvasItem. */ public void resize_pixbuf (int w, int h, bool update = false) { manager.get_pixbuf.begin (w, h, (obj, res) => { try { var _pixbuf = manager.get_pixbuf.end (res); pixbuf = _pixbuf; if (update) { width = _pixbuf.get_width (); height = _pixbuf.get_height (); } } catch (Error e) { warning (e.message); ((Lib.Canvas) canvas).window.event_bus.canvas_notification (e.message); } }); } } Akira-0.0.16/src/Lib/Items/CanvasItem.vala000066400000000000000000000120771410625726100201150ustar00rootroot00000000000000/** * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Alessandro "Alecaddd" Castellani */ using Akira.Lib.Components; /** * This is the base interface other items will need to extend in order to be created. * This interface shouldn't have any abstract attributes other than the components. * We use components instead of inheritance to keep our items modular and avoid useless * attributes repetitions. */ public interface Akira.Lib.Items.CanvasItem : Goo.CanvasItemSimple, Goo.CanvasItem { public abstract Gee.ArrayList components { get; set; } // Keep track of the parent artboard if the item belongs to one. public abstract Items.CanvasArtboard? artboard { get; set; } /** * Find the component attached to the item by its GLib.Type. */ private Component? get_component (GLib.Type type) { foreach (Component comp in components) { if (comp.get_type () == type) { return comp; } } return null; } /** * The X & Y initial coordinates of an item need to be set to 0 and then * the item needs to be translated to the proper position in order to ensure * the generation of the item's Cairo.Matrix which is used across the app. */ public void init_position (Items.CanvasItem item, double x, double y) { if (item.artboard != null) { item.canvas.convert_to_item_space (item.artboard, ref x, ref y); } item.translate (x, y); } /** * Check if the item belongs to an artboard, and if so add it to the * list of items inside the artboard. We do this separately after all * the components have been initialized to avoid issues in retrieving * attributes not yet defined when the list model is updated. */ public void check_add_to_artboard (Items.CanvasItem item) { if (item.artboard != null) { item.artboard.items.add_item.begin (item); } } public Components.Name? name { get { Component? component = this.get_component (typeof (Components.Name)); return (Components.Name) component; } } public Components.Coordinates? coordinates { get { Component? component = this.get_component (typeof (Components.Coordinates)); return (Components.Coordinates) component; } } public Components.Opacity? opacity { get { Component? component = this.get_component (typeof (Components.Opacity)); return (Components.Opacity) component; } } public Components.Rotation? rotation { get { Component? component = this.get_component (typeof (Components.Rotation)); return (Components.Rotation) component; } } public Components.Fills? fills { get { Component? component = this.get_component (typeof (Components.Fills)); return (Components.Fills) component; } } public Components.Borders? borders { get { Component? component = this.get_component (typeof (Components.Borders)); return (Components.Borders) component; } } public Components.Size? size { get { Component? component = this.get_component (typeof (Components.Size)); return (Components.Size) component; } } public Components.Flipped? flipped { get { Component? component = this.get_component (typeof (Components.Flipped)); return (Components.Flipped) component; } } public Components.BorderRadius? border_radius { get { Component? component = this.get_component (typeof (Components.BorderRadius)); return (Components.BorderRadius) component; } } public Components.Layer? layer { get { Component? component = this.get_component (typeof (Components.Layer)); return (Components.Layer) component; } } public void delete () { // If we're deleting an Artboard, deal with it inside its class. if (this is CanvasArtboard) { ((CanvasArtboard) this).delete (); } // Remove the item from the artboard before deleting it // if it belongs to one. if (artboard != null) { artboard.remove_item (this); } remove (); } } Akira-0.0.16/src/Lib/Items/CanvasRect.vala000066400000000000000000000046001410625726100201050ustar00rootroot00000000000000/** * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Alessandro "Alecaddd" Castellani */ using Akira.Lib.Components; /** * Generate a simple Rectangle. */ public class Akira.Lib.Items.CanvasRect : Goo.CanvasRect, Akira.Lib.Items.CanvasItem { public Gee.ArrayList components { get; set; } public Items.CanvasArtboard? artboard { get; set; } public CanvasRect ( double _x, double _y, int border_size, Gdk.RGBA border_color, Gdk.RGBA fill_color, Goo.CanvasItem? _parent, Items.CanvasArtboard? _artboard ) { parent = _artboard != null ? _artboard : _parent; artboard = _artboard; // Create the rectangle. x = y = 0.0; width = height = 1; radius_x = radius_y = 0.0; init_position (this, _x, _y); // Add the newly created item to the Canvas or Artboard. parent.add_child (this, -1); // Force the generation of the item bounds on creation. Goo.CanvasBounds bounds; this.get_bounds (out bounds); // Add all the components that this item uses. components = new Gee.ArrayList (); components.add (new Name (this)); components.add (new Coordinates (this)); components.add (new Opacity (this)); components.add (new Rotation (this)); components.add (new Fills (this, fill_color)); components.add (new Borders (this, border_color, border_size)); components.add (new Size (this)); components.add (new Flipped (this)); components.add (new BorderRadius (this)); components.add (new Layer ()); check_add_to_artboard (this); } } Akira-0.0.16/src/Lib/Items/CanvasText.vala000066400000000000000000000045071410625726100201420ustar00rootroot00000000000000/** * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Alessandro "Alecaddd" Castellani */ using Akira.Lib.Components; /** * Generate a simple Text item. */ public class Akira.Lib.Items.CanvasText : Goo.CanvasText, Akira.Lib.Items.CanvasItem { public Gee.ArrayList components { get; set; } public Items.CanvasArtboard? artboard { get; set; } public CanvasText ( string _text, double _x, double _y, double _width, double _height, Goo.CanvasAnchorType _anchor = Goo.CanvasAnchorType.NW, string _font = "Open Sans 16", Goo.CanvasItem? _parent, Items.CanvasArtboard? _artboard ) { parent = _artboard != null ? _artboard : _parent; artboard = _artboard; // Create the text item. x = y = 0; width = height = 1; text = _text; anchor = _anchor; font = _font; init_position (this, _x, _y); // Add the newly created item to the Canvas or Artboard. parent.add_child (this, -1); // Force the generation of the item bounds on creation. Goo.CanvasBounds bounds; this.get_bounds (out bounds); // Add all the components that this item uses. components = new Gee.ArrayList (); components.add (new Name (this)); components.add (new Coordinates (this)); components.add (new Opacity (this)); components.add (new Rotation (this)); components.add (new Size (this)); components.add (new Flipped (this)); components.add (new Layer ()); check_add_to_artboard (this); } } Akira-0.0.16/src/Lib/Managers/000077500000000000000000000000001410625726100156635ustar00rootroot00000000000000Akira-0.0.16/src/Lib/Managers/ExportManager.vala000066400000000000000000000437171410625726100213200ustar00rootroot00000000000000/* * Copyright (c) 2020 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Alessandro "Alecaddd" Castellani */ public class Akira.Lib.Managers.ExportManager : Object { private const string COLOR = "#41c9fd"; private const double LINE_WIDTH = 2.0; private const double MIN_SIZE = 1.0; public enum Type { AREA, SELECTION, ARTBOARD } public weak Akira.Lib.Canvas canvas { get; construct; } public Akira.Dialogs.ExportDialog export_dialog; private double initial_x; private double initial_y; private double initial_width; private double initial_height; public Goo.CanvasRect area; public Cairo.Format format; public Cairo.Surface surface; public Cairo.Context context; public Gdk.PixbufLoader loader; public Gee.HashMap pixbufs { get; set construct; } public ExportManager (Akira.Lib.Canvas canvas) { Object ( canvas: canvas ); pixbufs = new Gee.HashMap (); } public Goo.CanvasRect create_area (Gdk.EventButton event) { var dash = new Goo.CanvasLineDash (2, 5.0, 5.0); var rgba_fill = Gdk.RGBA (); rgba_fill.parse (COLOR); rgba_fill.alpha = 0.1; uint fill_color_rgba = Utils.Color.rgba_to_uint (rgba_fill); area = new Goo.CanvasRect ( null, Utils.AffineTransform.fix_size (event.x), Utils.AffineTransform.fix_size (event.y), 2.0, 2.0, "line-width", LINE_WIDTH / canvas.current_scale, "stroke-color", COLOR, "line-dash", dash, "fill-color-rgba", fill_color_rgba, null ); initial_x = event.x; initial_y = event.y; initial_width = 1.0; initial_height = 1.0; area.set ("parent", canvas.get_root_item ()); area.can_focus = false; area.pointer_events = Goo.CanvasPointerEvents.NONE; return area; } public void resize_area (double x, double y) { double area_width = area.width; double area_height = area.height; double area_x = area.x; double area_y = area.y; double delta_x = x - initial_x; double delta_y = y - initial_y; double new_width = delta_x; double new_height = delta_y; // Width size constraints. if (Utils.AffineTransform.fix_size (x) < area_x && area_width != 1) { // If the mouse event goes beyond the available width of the area // super quickly, collapse the size to 1 and maintain the position. new_width = -area_width + 1; } else if (Utils.AffineTransform.fix_size (x) < area_x) { // If the user keeps moving the mouse beyond the available width of the area // prevent any size changes. new_width = 0; } else if (area_width == 1 && delta_x <= 0) { // Don't update the size or position if the delta keeps increasing, // meaning the user is still moving left. new_width = 0; } // Height size constraints. if (Utils.AffineTransform.fix_size (y) < area_y && area_height != 1) { // If the mouse event goes beyond the available height of the area // super quickly, collapse the size to 1 and maintain the position. new_height = -area_height + 1; } else if (Utils.AffineTransform.fix_size (y) < area_y) { // If the user keeps moving the mouse beyond the available height of the area // prevent any size changes. new_height = 0; } else if (area_height == 1 && delta_y <= 0) { // Don't update the size or position if the delta keeps increasing, // meaning the user is still moving down. new_height = 0; } if (canvas.ctrl_is_pressed) { new_height = new_width; if (area_width != area_height) { new_height = area_width - area_height; } } area.set ("width", new_width + area.width); area.set ("height", new_height + area.height); // Update the initial coordinates to keep getting the correct delta. initial_x = x; initial_y = y; } public void clear () { if (area == null) { return; } area.remove (); } /** * Trigger the creation of the pixbuf for the export_area action. */ public void create_area_snapshot () { // Hide the area before rendering. area.visibility = Goo.CanvasItemVisibility.INVISIBLE; // Open Export Dialog before we have the preview. trigger_export_dialog (Type.AREA); // Generate the image to export. init_generate_area_pixbuf.begin (); } /** * Trigger the creation of the pixbuf for the export_selection action. */ public void create_selection_snapshot () { canvas.window.event_bus.hide_select_effect (); // Open Export Dialog before we have the preview. trigger_export_dialog (Type.SELECTION); // Generate the image to export. init_generate_selection_pixbuf.begin (); } public void regenerate_pixbuf (Type type) { switch (type) { case AREA: init_generate_area_pixbuf.begin (); break; case SELECTION: canvas.window.event_bus.hide_select_effect (); init_generate_selection_pixbuf.begin (); break; } } /** * Use multithreading to handle async pixbuf loading without freezing the UI. */ public async void init_generate_area_pixbuf () throws ThreadError { if (Thread.supported () == false) { error ("Threads are not supported!"); } canvas.window.event_bus.export_preview (_("Generating preview, please wait…")); SourceFunc callback = init_generate_area_pixbuf.callback; new Thread (null, () => { try { generate_area_pixbuf (); } catch (Error e) { error ("Could not generate export preview: %s", e.message); } Idle.add ((owned) callback); Thread.exit (null); return null; }); yield; yield export_dialog.generate_export_preview (); canvas.window.event_bus.preview_completed (); } public async void init_generate_selection_pixbuf () throws ThreadError { if (Thread.supported () == false) { error ("Threads are not supported!"); } canvas.window.event_bus.export_preview (_("Generating preview, please wait…")); SourceFunc callback = init_generate_selection_pixbuf.callback; new Thread (null, () => { try { generate_selection_pixbuf (); } catch (Error e) { error ("Could not generate export preview: %s", e.message); } Idle.add ((owned) callback); Thread.exit (null); return null; }); yield; yield export_dialog.generate_export_preview (); canvas.window.event_bus.preview_completed (); canvas.window.event_bus.show_select_effect (); } public void generate_area_pixbuf () throws Error { // Clear pixbuf array from previously stored values. pixbufs.clear (); if (settings.export_format == "png") { format = Cairo.Format.ARGB32; } else if (settings.export_format == "jpg") { format = Cairo.Format.RGB24; } // Create the rendered image with Cairo. surface = new Cairo.ImageSurface ( format, (int) Math.round (area.width), (int) Math.round (area.height) ); context = new Cairo.Context (surface); // Draw a white background if JPG export. if (settings.export_format == "jpg" || !settings.export_alpha) { context.set_source_rgba (1, 1, 1, 1); context.rectangle (0, 0, (int) Math.round (area.width), (int) Math.round (area.height)); context.fill (); } // Move to the currently selected area. context.translate (-area.bounds.x1, -area.bounds.y1); // Render the selected area. canvas.render (context, null, canvas.current_scale); // Create pixbuf from stream. try { loader = new Gdk.PixbufLoader.with_mime_type ("image/png"); } catch (Error e) { throw (e); } surface.write_to_png_stream ((data) => { try { loader.write ((uint8 []) data); } catch (Error e) { return Cairo.Status.DEVICE_ERROR; } return Cairo.Status.SUCCESS; }); var scaled = rescale_image (loader.get_pixbuf ()); try { loader.close (); } catch (Error e) { throw (e); } pixbufs.set (_("Untitled"), scaled); } public void generate_selection_pixbuf () throws Error { // Clear pixbuf array from previously stored values. pixbufs.clear (); if (settings.export_format == "png") { format = Cairo.Format.ARGB32; } else if (settings.export_format == "jpg") { format = Cairo.Format.RGB24; } // Loop through all the currently selected elements. for (var i = 0; i < canvas.selected_bound_manager.selected_items.length (); i++) { var item = canvas.selected_bound_manager.selected_items.nth_data (i); var name = _("Untitled %i").printf (i); // Weird goocanvas issue which sets the border to 0.**** instead of 0 // which causes a half pixel white border on export. if (item.line_width < 1) { var fill_color = item.fill_color_rgba; item.set ("stroke-color-rgba", fill_color); item.set ("line-width", 0.0); } // If the item is an artboard, account for the label's height. if (item is Akira.Lib.Items.CanvasArtboard) { var artboard = item as Akira.Lib.Items.CanvasArtboard; name = artboard.name.name; } // Hide the ghost item. ((Lib.Canvas) item.canvas).toggle_item_ghost (false); // Always use the item's bounds so we can include borders. double x1 = item.bounds.x1; double x2 = item.bounds.x2; double y1 = item.bounds.y1; double y2 = item.bounds.y2; // If the item is an artboard, use the bounds of the background item // since the CanvasGroup bounds will grow based on the position of its children. if (item is Items.CanvasArtboard) { var item_artboard = item as Items.CanvasArtboard; x1 = item_artboard.background.bounds.x1; x2 = item_artboard.background.bounds.x2; y1 = item_artboard.background.bounds.y1; y2 = item_artboard.background.bounds.y2; } // Create the rendered image with Cairo. surface = new Cairo.ImageSurface ( format, (int) Math.round (x2 - x1), (int) Math.round (y2 - y1) ); context = new Cairo.Context (surface); // Draw a white background if JPG export. if (settings.export_format == "jpg" || !settings.export_alpha) { context.set_source_rgba (1, 1, 1, 1); context.rectangle ( 0, 0, (int) Math.round (x2 - x1), (int) Math.round (y2 - y1) ); context.fill (); } // Move to the currently selected item. context.translate (-x1, -y1); // Render the selected item. canvas.render (context, null, canvas.current_scale); // Create pixbuf from stream. try { loader = new Gdk.PixbufLoader.with_mime_type ("image/png"); } catch (Error e) { throw (e); } surface.write_to_png_stream ((data) => { try { loader.write ((uint8 []) data); } catch (Error e) { return Cairo.Status.DEVICE_ERROR; } return Cairo.Status.SUCCESS; }); var scaled = rescale_image (loader.get_pixbuf (), item); try { loader.close (); } catch (Error e) { throw (e); } pixbufs.set (name, scaled); } } public Gdk.Pixbuf rescale_image (Gdk.Pixbuf pixbuf, Lib.Items.CanvasItem? item = null) { Gdk.Pixbuf scaled_image; double width, height; // If the item is null it means we're dealing with a custom area and we // don't have the bounds manager. if (item != null) { // Use the item's bounds to include the border. double x1 = item.bounds.x1; double x2 = item.bounds.x2; double y1 = item.bounds.y1; double y2 = item.bounds.y2; // If the item is an artboard, use the bounds of the background item // since the CanvasGroup bounds will grow based on the position of its children. if (item is Items.CanvasArtboard) { var item_artboard = item as Items.CanvasArtboard; x1 = item_artboard.background.bounds.x1; x2 = item_artboard.background.bounds.x2; y1 = item_artboard.background.bounds.y1; y2 = item_artboard.background.bounds.y2; } width = x2 - x1; height = y2 - y1; } else { width = area.width; height = area.height; } switch (settings.export_scale) { case 0: scaled_image = pixbuf.scale_simple ( (int) width / 2, (int) height / 2, Gdk.InterpType.BILINEAR ); break; case 2: scaled_image = pixbuf.scale_simple ( (int) width * 2, (int) height * 2, Gdk.InterpType.BILINEAR ); break; case 3: scaled_image = pixbuf.scale_simple ( (int) width * 4, (int) height * 4, Gdk.InterpType.BILINEAR ); break; default: scaled_image = pixbuf.scale_simple ( (int) width * 1, (int) height * 1, Gdk.InterpType.BILINEAR ); break; } return scaled_image; } public void trigger_export_dialog (Type type) { // Disable all those accels interfering with regular typing. canvas.window.event_bus.disconnect_typing_accel (); export_dialog = new Akira.Dialogs.ExportDialog (canvas.window, this, type); export_dialog.show_all (); export_dialog.present (); // Update the dialog UI based on the stored gsettings options. export_dialog.update_format_ui (); // Store the dialog size into gsettings users don't get upset. export_dialog.close.connect (() => { int width, height; export_dialog.get_size (out width, out height); settings.export_width = width; settings.export_height = height; canvas.window.event_bus.connect_typing_accel (); canvas.window.event_bus.set_focus_on_canvas (); // Clean up the Manager. context = null; surface = null; clear (); }); } public async void export_images () { canvas.window.event_bus.exporting (_("Exporting images…")); SourceFunc callback = export_images.callback; new Thread (null, () => { for (int i = 0; i < export_dialog.list_store.get_n_items (); i++) { var model = (Akira.Models.ExportModel) export_dialog.list_store.get_object (i); try { if (settings.export_format == "png") { model.pixbuf.save ( settings.export_folder + "/" + model.filename + ".png", "png", "compression", settings.export_compression.to_string (), null); } else if (settings.export_format == "jpg") { model.pixbuf.save ( settings.export_folder + "/" + model.filename + ".jpg", "jpeg", "quality", settings.export_quality.to_string (), null); } } catch (Error e) { error ("Unable to export images: %s", e.message); } } Idle.add ((owned) callback); Thread.exit (null); return null; }); yield; canvas.window.event_bus.export_completed (); } } Akira-0.0.16/src/Lib/Managers/GridManager.vala000066400000000000000000000143321410625726100207130ustar00rootroot00000000000000/* * Copyright (c) 2021 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Alessandro "Alecaddd" Castellani */ /** * Manages the Canvas Pixel grid. This class takes care of generating and updating * the global pixel grid whenever the user requires it. It also listens to the scale * variation of the main Canvas in order to return a properly usable grid with decently * spaced columns and rows, and a decently rendered grid thickness. */ public class Akira.Lib.Managers.GridManager : Object { public weak Lib.Canvas canvas { get; set construct; } private Goo.CanvasGrid pixel_grid; private bool is_grid_visible; public GridManager (Lib.Canvas canvas) { this.canvas = canvas; create_pixel_grid (); canvas.window.event_bus.toggle_pixel_grid.connect (on_toggle_pixel_grid); canvas.window.event_bus.update_pixel_grid.connect (on_update_pixel_grid); canvas.window.event_bus.zoom.connect (on_canvas_zoom); } /* * Generate the default pixel grid. */ private void create_pixel_grid () { pixel_grid = new Goo.CanvasGrid ( null, 0, 0, Layouts.MainCanvas.CANVAS_SIZE, Layouts.MainCanvas.CANVAS_SIZE, 1, 1, 0, 0); var grid_rgba = Gdk.RGBA (); grid_rgba.parse (settings.grid_color); pixel_grid.horz_grid_line_width = pixel_grid.vert_grid_line_width = 0.02; pixel_grid.horz_grid_line_color_gdk_rgba = pixel_grid.vert_grid_line_color_gdk_rgba = grid_rgba; pixel_grid.visibility = Goo.CanvasItemVisibility.HIDDEN; pixel_grid.set ("parent", canvas.get_root_item ()); pixel_grid.can_focus = false; pixel_grid.pointer_events = Goo.CanvasPointerEvents.NONE; is_grid_visible = false; } /* * Trigger the update of the pixel grid after the settings color have been changed. */ private void on_update_pixel_grid () { var grid_rgba = Gdk.RGBA (); grid_rgba.parse (settings.grid_color); pixel_grid.horz_grid_line_color_gdk_rgba = pixel_grid.vert_grid_line_color_gdk_rgba = grid_rgba; } /* * Show or hide the pixel grid based on its state. */ private void on_toggle_pixel_grid () { if (!is_grid_visible) { is_grid_visible = true; raise (); recalculate (); return; } pixel_grid.visibility = Goo.CanvasItemVisibility.HIDDEN; is_grid_visible = false; } private void on_canvas_zoom () { // Check if the user requested the pixel grid and if is not already visible. if (!is_grid_visible) { return; } recalculate (); } /* * Update the pixel grid to always show the most optimal line thickness, * as well as number of columns and rows based on the canvas current scale. */ private void recalculate () { double thickness = 0.04; double steps = 1; var scale = canvas.current_scale; // Hide the pixel grid if the zoom is below or equal to 20%. if (scale < 0.2) { pixel_grid.visibility = Goo.CanvasItemVisibility.HIDDEN; return; } if (pixel_grid.visibility == Goo.CanvasItemVisibility.HIDDEN) { pixel_grid.visibility = Goo.CanvasItemVisibility.VISIBLE; } // -50% if (scale < 0.5) { thickness = 1; steps = 40; } // 50% - 150% if (scale >= 0.5 && scale < 1.5) { thickness = 0.5; steps = 20; } // 150% - 250% if (scale >= 1.5 && scale < 2.5) { thickness = 0.25; steps = 10; } // 250% - 350% if (scale >= 2.5 && scale < 3.5) { thickness = 0.125; steps = 5; } // 350% - 450% if (scale >= 3.5 && scale < 4.5) { thickness = 0.1; steps = 3; } // 450% - 600% if (scale >= 4.5 && scale < 6) { thickness = 0.08; steps = 2; } if (scale > 14) { thickness = 0.02; } // Update the grid offset to always be half of the line thickness // in order to guarantee a sharp line rendering. pixel_grid.x_offset = pixel_grid.y_offset = thickness / 2; // Update the line thickness. pixel_grid.horz_grid_line_width = pixel_grid.vert_grid_line_width = thickness; // Update the steps between columns and rows. pixel_grid.x_step = pixel_grid.y_step = steps; } /* * Called when the canvas is updated after the creation of a new item. */ public void on_canvas_update () { if (is_grid_visible) { raise (); } } /* * Move the pixel grid to the top of the stack. */ private void raise () { // Update the pixel grid if it's visible in order to move it to the foreground. var root = canvas.get_root_item (); var current_position = root.find_child (pixel_grid); var top_position = root.get_n_children (); // The grid should always be below the select effect and nobs, // so we decrease the count to account for that, otherwise we // decrease by 1 to ignore the grid current position. top_position -= canvas.selected_bound_manager.selected_items.length () > 0 ? 11 : 1; // Always move the grid to the top of the stack if necessary. if (current_position < top_position) { root.move_child (current_position, top_position); } } } Akira-0.0.16/src/Lib/Managers/HoverManager.vala000066400000000000000000000111221410625726100211030ustar00rootroot00000000000000/* * Copyright (c) 2019 Alecaddd (http://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Giacomo Alberini */ public class Akira.Lib.Managers.HoverManager : Object { private const string STROKE_COLOR = "#41c9fd"; private const double LINE_WIDTH = 2.0; public weak Akira.Lib.Canvas canvas { get; construct; } private Goo.CanvasItem hover_effect; private Lib.Items.CanvasItem current_hover_item; public HoverManager (Akira.Lib.Canvas canvas) { Object ( canvas: canvas ); } construct { canvas.window.event_bus.zoom.connect (on_canvas_zoom); canvas.window.event_bus.hover_over_layer.connect (on_layer_hovered); } public void on_mouse_over (double event_x, double event_y, Akira.Lib.Managers.NobManager.Nob nob) { if (nob != Akira.Lib.Managers.NobManager.Nob.NONE) { current_hover_item = null; remove_hover_effect (); return; } var target = canvas.get_item_at (event_x, event_y, true); // Remove the hover effect is no item is hovered, or the item is the // white background of the CanvasArtboard, which is a GooCanvasRect item. if (target == null || (target is Goo.CanvasRect && !(target is Items.CanvasItem))) { current_hover_item = null; remove_hover_effect (); return; } // If we're hovering over the Artboard's label, change the target to the Artboard. if ( target is Goo.CanvasText && target.parent is Items.CanvasArtboard && !(target is Items.CanvasItem) ) { target = target.parent as Items.CanvasItem; } if (!(target is Items.CanvasItem)) { return; } var item = target as Items.CanvasItem; if (current_hover_item != null && item.name.id == current_hover_item.name.id) { // We already have the hover effect rendered correctly. return; } // We need to recreate it. remove_hover_effect (); current_hover_item = item; create_hover_effect (item); if (!item.layer.selected) { canvas.window.event_bus.hover_over_item (item); } return; } private void on_layer_hovered (Items.CanvasItem? item) { if (item == null) { remove_hover_effect (); return; } remove_hover_effect (); create_hover_effect (item); } private void create_hover_effect (Items.CanvasItem item) { if (item.layer.selected) { return; } hover_effect = new Goo.CanvasRect ( null, 0, 0, item.size.width, item.size.height, "line-width", LINE_WIDTH / canvas.current_scale, "stroke-color", STROKE_COLOR, null ); Cairo.Matrix matrix; item.get_transform (out matrix); // If the item is inside an artboard, we need to convert // its coordinates from the artboard space. if (item.artboard != null) { item.canvas.convert_from_item_space (item.artboard, ref matrix.x0, ref matrix.y0); } hover_effect.set_transform (matrix); hover_effect.set ("parent", canvas.get_root_item ()); hover_effect.can_focus = false; hover_effect.pointer_events = Goo.CanvasPointerEvents.NONE; } public void remove_hover_effect () { if (hover_effect == null) { return; } hover_effect.remove (); hover_effect = null; canvas.window.event_bus.hover_over_item (null); } private void on_canvas_zoom () { // Interrupt if we don't have any hover effect currently visible. if (hover_effect == null) { return; } // Update the line width of the hover effect based on the canvas scale. hover_effect.set ("line-width", LINE_WIDTH / canvas.current_scale); } } Akira-0.0.16/src/Lib/Managers/ImageManager.vala000066400000000000000000000060721410625726100210520ustar00rootroot00000000000000/* * Copyright (c) 2020 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Adam Bieńkowski * Authored by: Alessandro "Alecaddd" Castellani */ public class Akira.Lib.Managers.ImageManager : Object { public GLib.File file { get; set; } // Save the generated Pixbuf for later reference. public Gdk.Pixbuf pixbuf; // The unique name of the loaded image, including the current timestamp. public string filename; private const string[] ACCEPTED_TYPES = { "image/jpeg", "image/png", "image/tiff", "image/svg+xml", "image/gif" }; public ImageManager (GLib.File _file, int id) { file = _file; var timestamp = new GLib.DateTime.now_utc (); filename = ("akira-img-%i-%s.%s").printf ( id, timestamp.to_unix ().to_string (), Utils.Image.get_extension (file) ); } /** * Initialize a new ImageManager from a previously saved file. * We use this to avoid changing the filename which should be unique. * * @param {GLib.File} _file - The file loaded from the saved archive. * @param {string} _filename - The original filename of the saved file. */ public ImageManager.from_archive (GLib.File _file, string _filename) { file = _file; filename = _filename; } /** * Generate the Pixbuf from the given file. This method is also called to * resample the quality of the pixbuf when the image is resized. * * @param {int} width - The requested width for the resample. * @param {int} height - The requested height for the resample. * @return Gdk.Pixbuf */ public async Gdk.Pixbuf get_pixbuf (int width = -1, int height = -1) throws Error { FileInputStream stream; try { stream = yield file.read_async (); } catch (Error e) { throw e; } if (width != -1 && height != -1) { try { pixbuf = yield new Gdk.Pixbuf.from_stream_at_scale_async (stream, width, height, false); return pixbuf; } catch (Error e) { throw e; } } else { try { pixbuf = yield new Gdk.Pixbuf.from_stream_async (stream); return pixbuf; } catch (Error e) { throw e; } } } } Akira-0.0.16/src/Lib/Managers/ItemsManager.vala000066400000000000000000000611571410625726100211160ustar00rootroot00000000000000/** * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Giacomo Alberini * Authored by: Alessandro "Alecaddd" Castellani */ public class Akira.Lib.Managers.ItemsManager : Object { public weak Akira.Window window { get; construct; } public Akira.Models.ListModel free_items; public Akira.Models.ListModel artboards; public Akira.Models.ListModel images; private GLib.Type item_type { get; set; } private Goo.CanvasItem root; private int border_size; private Gdk.RGBA border_color; private Gdk.RGBA fill_color; // Keep track of the expensive Artboard change method. private bool is_changing = false; // Keep track of newly imported images before creation. public Lib.Managers.ImageManager? image_manager; public ItemsManager (Akira.Window window) { Object ( window: window ); } construct { free_items = new Akira.Models.ListModel (); artboards = new Akira.Models.ListModel (); images = new Akira.Models.ListModel (); border_color = Gdk.RGBA (); fill_color = Gdk.RGBA (); window.event_bus.insert_item.connect (set_item_to_insert); window.event_bus.request_delete_item.connect (on_request_delete_item); window.event_bus.detect_artboard_change.connect (on_detect_artboard_change); } public void insert_image (Lib.Managers.ImageManager manager) { image_manager = manager; window.event_bus.insert_item ("image"); } public Items.CanvasItem? insert_item ( double x, double y, Lib.Managers.ImageManager? manager = null, Items.CanvasArtboard? artboard = null ) { update_default_values (); Items.CanvasItem? new_item = null; // Populate root item here and not in the construct @since // there the canvas is not yet defined, so we need to wait for // the first item to be created to fill this variable if (root == null) { root = window.main_window.main_canvas.canvas.get_root_item (); } if (artboard == null) { foreach (Items.CanvasArtboard _artboard in artboards) { if (_artboard.is_inside (x, y)) { artboard = _artboard; break; } } } // We can't use a switch () method here because the typeof () method is not supported. if (item_type == typeof (Items.CanvasArtboard)) { new_item = add_artboard (x, y); } if (item_type == typeof (Items.CanvasRect)) { new_item = add_rect (x, y, root, artboard); } if (item_type == typeof (Items.CanvasEllipse)) { new_item = add_ellipse (x, y, root, artboard); } if (item_type == typeof (Items.CanvasText)) { new_item = add_text (x, y, root, artboard); } if (item_type == typeof (Items.CanvasImage)) { // If we don't have a manager passed to this method but a general image manager // is available in the class, it means the user is importing a new image. if (manager == null && image_manager != null) { manager = image_manager; } new_item = add_image (x, y, manager, root, artboard); // Empty the image manager since we used it. image_manager = null; } if (new_item == null) { return null; } if (new_item is Items.CanvasArtboard) { artboards.add_item.begin ((Items.CanvasArtboard) new_item); } else { // Add it to "free items" if it doesn't belong to an artboard. if (new_item.artboard == null) { free_items.add_item.begin ((Items.CanvasItem) new_item); } // We need to additionally store images in a dedicated list in order // to easily access them when saving the .akira/Pictures folder. // If we don't curate this dedicated list, it would be a nightamer to // loop through all the free items and artboard items to check for images. if (new_item is Items.CanvasImage) { images.add_item.begin ((new_item as Akira.Lib.Items.CanvasImage)); } } window.event_bus.item_inserted (); window.event_bus.file_edited (); return new_item; } /** * Helper method to add an item to the canvas, used when dragging an item * outside an artboard where a reset of the parent root is necessary. */ public void add_item_to_canvas (Lib.Items.CanvasItem item) { item.set_parent (root); item.parent.add_child (item, -1); free_items.add_item.begin (item); window.event_bus.file_edited (); ((Lib.Canvas) item.canvas).update_canvas (); } /** * Helper method to add an item to an artboard, used when dragging an item * from the canvas or another artboard where a reset of the parent root is necessary. */ public void add_item_to_artboard (Lib.Items.CanvasItem item, Lib.Items.CanvasArtboard artboard) { item.set_parent (artboard); item.artboard = artboard; item.parent.add_child (item, -1); item.check_add_to_artboard (item); window.event_bus.file_edited (); } public void on_request_delete_item (Lib.Items.CanvasItem item) { // Remove the layer from the Artboards list if it's an artboard. if (item is Items.CanvasArtboard) { artboards.remove_item.begin (item as Items.CanvasArtboard); } // Remove the image from the list so we don't keep it in the saved file. if (item is Items.CanvasImage) { images.remove_item.begin ((item as Akira.Lib.Items.CanvasImage)); // Mark it for removal if we have a saved file. if (window.akira_file != null) { window.akira_file.remove_image.begin ( ((Akira.Lib.Items.CanvasImage) item).manager.filename ); } } // Remove the layer from the Free Items list only if the item doesn't // belong to an artboard, and it's not an artboard itself. if (item.artboard == null && !(item is Items.CanvasArtboard)) { free_items.remove_item.begin (item); } // Let the app know we're deleting an item. window.event_bus.item_deleted (item); item.delete (); window.event_bus.file_edited (); } public Items.CanvasItem add_artboard (double x, double y) { var artboard = new Items.CanvasArtboard ( Utils.AffineTransform.fix_size (x), Utils.AffineTransform.fix_size (y), root ); return artboard as Items.CanvasItem; } public Items.CanvasItem add_rect ( double x, double y, Goo.CanvasItem parent, Items.CanvasArtboard? artboard ) { return new Items.CanvasRect ( Utils.AffineTransform.fix_size (x), Utils.AffineTransform.fix_size (y), border_size, border_color, fill_color, parent, artboard ); } public Items.CanvasEllipse add_ellipse ( double x, double y, Goo.CanvasItem parent, Items.CanvasArtboard? artboard ) { return new Items.CanvasEllipse ( Utils.AffineTransform.fix_size (x), Utils.AffineTransform.fix_size (y), border_size, border_color, fill_color, parent, artboard ); } public Items.CanvasText add_text ( double x, double y, Goo.CanvasItem parent, Items.CanvasArtboard? artboard ) { return new Items.CanvasText ( "Akira is awesome :)", Utils.AffineTransform.fix_size (x), Utils.AffineTransform.fix_size (y), 200, 25f, Goo.CanvasAnchorType.NW, "Open Sans 18", parent, artboard ); } public Items.CanvasImage add_image ( double x, double y, Lib.Managers.ImageManager manager, Goo.CanvasItem parent, Items.CanvasArtboard? artboard ) { return new Items.CanvasImage ( Utils.AffineTransform.fix_size (x), Utils.AffineTransform.fix_size (y), manager, parent, artboard ); } public int get_item_z_index (Items.CanvasItem item) { if (item.artboard != null) { var items_count = (int) item.artboard.items.get_n_items (); return items_count - 1 - item.artboard.items.index (item); } return (int) free_items.get_n_items () - 1 - free_items.index (item); } public int get_item_top_position (Items.CanvasItem item) { if (item.artboard != null) { return (int) item.artboard.items.get_n_items () - 1; } return (int) free_items.get_n_items () - 1; } public void set_item_to_insert (string insert_type) { switch (insert_type) { case "rectangle": item_type = typeof (Items.CanvasRect); break; case "ellipse": item_type = typeof (Items.CanvasEllipse); break; case "text": item_type = typeof (Items.CanvasText); break; case "artboard": item_type = typeof (Items.CanvasArtboard); break; case "image": item_type = typeof (Items.CanvasImage); break; } } public void swap_items (int source_z_index, int target_z_index) { // z-index is the exact opposite of items placement // inside the free_items list // last in is the topmost element var free_items_length = (int) free_items.get_n_items (); var source = free_items_length - 1 - source_z_index; var target = free_items_length - 1 - target_z_index; // Remove item at source position var item_to_swap = free_items.remove_at (source); // Insert item at target position free_items.insert_at (target, item_to_swap); } private void update_default_values () { fill_color.parse (settings.fill_color); // Do not set the border if the user disabled it. if (settings.set_border) { border_size = (int) settings.border_size; border_color.parse (settings.border_color); } } /* * Create an item loaded from an opened file. * * @param Json.Object obj - The json object containing the item to load. */ public void load_item (Json.Object obj) { Items.CanvasItem? item = null; Items.CanvasArtboard? artboard = null; var components = obj.get_member ("Components").get_object (); var coordinates = components.get_member ("Coordinates").get_object (); var pos_x = coordinates.get_double_member ("x"); var pos_y = coordinates.get_double_member ("y"); // If item is inside an artboard update the coordinates accordingly. if (obj.has_member ("artboard")) { foreach (var _artboard in artboards) { if (_artboard.name.id == obj.get_string_member ("artboard")) { window.main_window.main_canvas.canvas.convert_from_item_space ( _artboard, ref pos_x, ref pos_y ); artboard = _artboard; break; } } } switch (obj.get_string_member ("type")) { case "rectangle": item_type = typeof (Items.CanvasRect); item = insert_item (pos_x, pos_y, null, artboard); break; case "ellipse": item_type = typeof (Items.CanvasEllipse); item = insert_item (pos_x, pos_y, null, artboard); break; case "text": item_type = typeof (Items.CanvasText); item = insert_item (pos_x, pos_y, null, artboard); break; case "artboard": item_type = typeof (Items.CanvasArtboard); item = insert_item (pos_x, pos_y, null, artboard); break; case "image": item_type = typeof (Items.CanvasImage); var filename = obj.get_string_member ("image_id"); var file = File.new_for_path ( Path.build_filename ( window.akira_file.pictures_folder.get_path (), filename ) ); var manager = new Lib.Managers.ImageManager.from_archive (file, filename); item = insert_item (pos_x, pos_y, manager, artboard); break; } var selected_bound_manager = window.main_window.main_canvas.canvas.selected_bound_manager; selected_bound_manager.add_item_to_selection (item); restore_attributes (item, artboard, components); // Restore the matrix transform to properly reset position and rotation. var matrix = obj.get_member ("matrix").get_object (); var new_matrix = Cairo.Matrix ( matrix.get_double_member ("xx"), matrix.get_double_member ("yx"), matrix.get_double_member ("xy"), matrix.get_double_member ("yy"), matrix.get_double_member ("x0"), matrix.get_double_member ("y0") ); item.set_transform (new_matrix); selected_bound_manager.reset_selection (); } /* * Restore the saved attributes of a loaded object. * * @param Items.CanvasItem item - The newly created item. * @param Json.Object obj - The json object containing the item's attributes. */ private void restore_attributes (Items.CanvasItem item, Items.CanvasArtboard? artboard, Json.Object components) { // Restore identifiers. if (components.has_member ("Name")) { var name = components.get_member ("Name").get_object (); item.name.id = name.get_string_member ("id"); item.name.name = name.get_string_member ("name"); item.name.icon = name.get_string_member ("icon"); } // Restore opacity. if (components.has_member ("Opacity")) { var opacity = components.get_member ("Opacity").get_object (); item.opacity.opacity = opacity.get_double_member ("opacity"); } // Restore rotation. if (components.has_member ("Rotation")) { var rotation = components.get_member ("Rotation").get_object (); item.rotation.rotation = rotation.get_double_member ("rotation"); } // Restore size. if (components.has_member ("Size")) { var size = components.get_member ("Size").get_object (); item.size.locked = size.get_boolean_member ("locked"); item.size.ratio = size.get_double_member ("ratio"); item.size.width = size.get_double_member ("width"); item.size.height = size.get_double_member ("height"); } // Restore flipped. if (components.has_member ("Flipped")) { var flipped = components.get_member ("Flipped").get_object (); item.flipped.horizontal = flipped.get_boolean_member ("horizontal"); item.flipped.vertical = flipped.get_boolean_member ("vertical"); } // Restore border radius. if (components.has_member ("BorderRadius")) { var border_radius = components.get_member ("BorderRadius").get_object (); item.border_radius.x = border_radius.get_double_member ("x"); item.border_radius.y = border_radius.get_double_member ("y"); item.border_radius.uniform = border_radius.get_boolean_member ("uniform"); item.border_radius.autoscale = border_radius.get_boolean_member ("autoscale"); } // Restore layer. if (components.has_member ("Layer")) { var layer = components.get_member ("Layer").get_object (); item.layer.locked = layer.get_boolean_member ("locked"); } // Restore fills. if (components.has_member ("Fills")) { // Delete all pre-existing fills to be sure we're starting with a clean slate. foreach (Lib.Components.Fill fill in item.fills.fills) { item.fills.fills.remove (fill); } var fills = components.get_member ("Fills").get_object (); fills.foreach_member ((i, name, node) => { var obj = node.get_object (); var color = Gdk.RGBA (); color.parse (obj.get_string_member ("color")); var fill = item.fills.add_fill_color (color); fill.alpha = (int) obj.get_int_member ("alpha"); fill.hidden = obj.get_boolean_member ("hidden"); }); item.fills.reload (); } // Restore borders. if (components.has_member ("Borders")) { // Delete all pre-existing borders to be sure we're starting with a clean slate. foreach (Lib.Components.Border border in item.borders.borders) { item.borders.borders.remove (border); } var borders = components.get_member ("Borders").get_object (); borders.foreach_member ((i, name, node) => { var obj = node.get_object (); var color = Gdk.RGBA (); color.parse (obj.get_string_member ("color")); var border = item.borders.add_border_color (color, (int) obj.get_int_member ("size")); border.alpha = (int) obj.get_int_member ("alpha"); border.hidden = obj.get_boolean_member ("hidden"); }); item.borders.reload (); } // Restore image size. if (item is Items.CanvasImage) { ((Items.CanvasImage) item).resize_pixbuf ( (int) item.size.width, (int) item.size.height, true ); } } /** * Handle the aftermath of an item transformation, like size changes or movement * to see if we need to add or remove an item to an Artboard. */ private async void on_detect_artboard_change () { // Interrupt if no artboard is currently present. if (artboards.get_n_items () == 0) { return; } // Interrupt if this is already running. if (is_changing) { return; } // Interrupt if no item is selected. if (window.main_window.main_canvas.canvas.selected_bound_manager.selected_items.length () == 0) { return; } is_changing = true; // We need to copy the array of selected items as we need to remove and add items once // moved to force the natural redraw of the canvas. var items = window.main_window.main_canvas.canvas.selected_bound_manager.selected_items.copy (); // Update the size ratio to always be faithful to the updated size. foreach (var item in items) { if (item is Items.CanvasArtboard) { continue; } item.size.update_ratio (); } // Check if any of the currently moved items was dropped inside or outside any artboard. foreach (var item in items) { if (item is Items.CanvasArtboard) { continue; } // Interrupt if the item is already inside an artboard and was only moved within it. if (item.artboard != null && !item.artboard.is_outside (item)) { continue; } Items.CanvasArtboard? new_artboard = null; foreach (Items.CanvasArtboard artboard in artboards) { // Interrupt the loop if we find an artboard that matches the dropped coordinate. if (!artboard.is_outside (item)) { new_artboard = artboard; break; } } yield change_artboard (item, new_artboard); } is_changing = false; } /** * Add or remove an item from an artboard. */ public async void change_artboard (Items.CanvasItem item, Items.CanvasArtboard? new_artboard) { // Interrupt if the item was moved within its original artboard. if (item.artboard == new_artboard) { debug ("Same parent"); return; } // Save the coordinates before removing the item. Cairo.Matrix matrix; item.get_transform (out matrix); // If the item was moved from inside an Artboard to the empty Canvas. if (item.artboard != null && new_artboard == null) { debug ("Artboard => Free Item"); // Convert the matrix transform before removing the item from the artboard. item.canvas.convert_from_item_space (item.artboard, ref matrix.x0, ref matrix.y0); // Remove the item from the Artboard. item.artboard.remove_item (item); // Remove the item from the selection and redraw the layers panel. window.event_bus.item_deleted (item); // Attach the item to the Canvas. add_item_to_canvas (item); // Apply the updated coordinates. item.set_transform (matrix); window.event_bus.item_inserted (); window.event_bus.request_add_item_to_selection (item); return; } // If the item was moved from the empty Canvas to an Artboard. if (item.artboard == null && new_artboard != null) { debug ("Free Item => Artboard"); // Convert the matrix transform to the new artboard. item.canvas.convert_to_item_space (new_artboard, ref matrix.x0, ref matrix.y0); // Remove the child from the GooCanvasItem parent. item.parent.remove_child (item.parent.find_child (item)); // Remove the item from the free items list. free_items.remove_item.begin (item); // Remove the item from the selection and redraw the layers panel. window.event_bus.item_deleted (item); // Attach the item to the Artboard. add_item_to_artboard (item, new_artboard); // Apply the updated coordinates. item.set_transform (matrix); window.event_bus.item_inserted (); window.event_bus.request_add_item_to_selection (item); return; } // If the item was moved from inside an Artboard to another Artboard. if (item.artboard != null && new_artboard != null) { debug ("Artboard => Artboard"); // Passing from an artboard to another we need to first convert the coordinates // from the old artboard to the global canvas, and then convert them again // to the new artboard. item.canvas.convert_from_item_space (item.artboard, ref matrix.x0, ref matrix.y0); item.canvas.convert_to_item_space (new_artboard, ref matrix.x0, ref matrix.y0); // Remove the item from the Artboard. item.artboard.remove_item (item); // Remove the item from the selection and redraw the layers panel. window.event_bus.item_deleted (item); // Attach the item to the Artboard. add_item_to_artboard (item, new_artboard); // Apply the updated coordinates. item.set_transform (matrix); // Trigger the canvas repaint after the item was added back. window.event_bus.item_inserted (); window.event_bus.request_add_item_to_selection (item); return; } } } Akira-0.0.16/src/Lib/Managers/ModeManager.vala000066400000000000000000000135131410625726100207120ustar00rootroot00000000000000/** * Copyright (c) 2021 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Martin "mbfraga" Fraga */ /** * Manages InteractionMode's via registration. This class can be plugged into the event methods of a Canvas * in order to allow these modes to affect items in the canvas as well as allowing them to absorb said * events. * * Only one InteractionMode is guaranteed to exist at a time, and this manager will correctly alert the * beginning and end of a registered mode. * * The exception to the above rule is pan_mode, which can be running on top of another mode in certain cases and * masks events appropriately. * * See InteractionMode.vala for more details on how to create modes. */ public class Akira.Lib.Managers.ModeManager : Object { public weak Akira.Lib.Canvas canvas { get; construct; } private Akira.Lib.Modes.PanMode pan_mode; private Akira.Lib.Modes.InteractionMode active_mode; public ModeManager (Akira.Lib.Canvas canvas) { Object ( canvas: canvas ); } /* * Register a new mode as the active mode. Any prior mode will be deregistered. */ public void register_mode (Akira.Lib.Modes.InteractionMode new_mode) { if (active_mode != null) { inner_deregister_active_mode (false); } active_mode = new_mode; active_mode.mode_begin (); canvas.interaction_mode_changed (); } /* * Deregister active mode or pan mode if it matches the mode_type. * This should generally be used for safety since a new mode may already have been * registered by the time this method is called. */ public void deregister_mode (Akira.Lib.Modes.InteractionMode.ModeType mode_type) { if (active_mode != null && active_mode.mode_type () == mode_type) { inner_deregister_active_mode (true); } else if (pan_mode != null && pan_mode.mode_type () == mode_type) { stop_panning_mode (); } } /* * Deregister the currently active mode. */ public void deregister_active_mode () { if (active_mode != null) { inner_deregister_active_mode (true); } } /* * Start panning mode that will mask any existing mode. Also, other modes may be started * during panning mode in certain conditions. */ public void start_panning_mode () { if (pan_mode != null) { return; } pan_mode = new Akira.Lib.Modes.PanMode (canvas, this); pan_mode.mode_begin (); canvas.interaction_mode_changed (); } /* * Stops panning mode. */ public void stop_panning_mode () { if (pan_mode != null) { inner_stop_panning_mode (true); } } /* * Inner panning mode stop method with optional notification to canvas. */ private void inner_stop_panning_mode (bool notify) { pan_mode.mode_end (); pan_mode = null; if (notify) { canvas.interaction_mode_changed (); } } /* * Inner mode deregistration method with optional notification to canvas. */ private void inner_deregister_active_mode (bool notify) { active_mode.mode_end (); active_mode = null; if (notify) { canvas.interaction_mode_changed (); } } /* * Returns optional extra context. See InteractionMode for more details. */ public Object? active_mode_extra_context () { if (pan_mode != null) { return pan_mode.extra_context (); } return active_mode != null ? active_mode.extra_context () : null; } /* * Returns cursor that should be used based on active modes. */ public Gdk.CursorType? active_cursor_type () { if (pan_mode != null) { return pan_mode.cursor_type (); } return active_mode != null ? active_mode.cursor_type () : null; } public bool key_press_event (Gdk.EventKey event) { if (pan_mode != null && pan_mode.key_press_event (event)) { return false; } return (active_mode != null) ? active_mode.key_press_event (event) : false; } public bool key_release_event (Gdk.EventKey event) { if (pan_mode != null && pan_mode.key_release_event (event)) { return true; } return (active_mode != null) ? active_mode.key_release_event (event) : false; } public bool button_press_event (Gdk.EventButton event) { if (pan_mode != null && pan_mode.button_press_event (event)) { return true; } return (active_mode != null) ? active_mode.button_press_event (event) : false; } public bool button_release_event (Gdk.EventButton event) { if (pan_mode != null && pan_mode.button_release_event (event)) { return true; } return (active_mode != null) ? active_mode.button_release_event (event) : false; } public bool motion_notify_event (Gdk.EventMotion event) { if (pan_mode != null && pan_mode.motion_notify_event (event)) { return true; } return (active_mode != null) ? active_mode.motion_notify_event (event) : false; } } Akira-0.0.16/src/Lib/Managers/NobManager.vala000066400000000000000000000512311410625726100205430ustar00rootroot00000000000000/** * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Giacomo Alberini * Authored by: Alessandro "Alecaddd" Castellani */ public class Akira.Lib.Managers.NobManager : Object { private const string STROKE_COLOR = "#666"; private const double LINE_WIDTH = 1.0; private const double LINE_HEIGHT = 40.0; /* Grabber Pos: 8 | 0 1 2 7 3 6 5 4 // -1 if no nob is grabbed. */ public enum Nob { NONE=-1, TOP_LEFT, TOP_CENTER, TOP_RIGHT, RIGHT_CENTER, BOTTOM_RIGHT, BOTTOM_CENTER, BOTTOM_LEFT, LEFT_CENTER, ROTATE } /* * Nob data associated with an item selection. */ public class ItemNobData : Object { construct { bb_matrix = Cairo.Matrix.identity (); } // Values in canvas coordinates. public double top_left_x = 0.0; public double top_left_y = 0.0; public double width_offset_x = 0.0; public double width_offset_y = 0.0; public double height_offset_x = 0.0; public double height_offset_y = 0.0; // bb_width and bb_height are also used by the SizeMiddleware to represent // the width and height of selected items in the Transform Panel. public double bb_width = 0.0; public double bb_height = 0.0; public Cairo.Matrix bb_matrix; // Values for the Transform Panel fields. public double selected_x = 0.0; public double selected_y = 0.0; } public weak Akira.Lib.Canvas canvas { get; construct; } public Nob selected_nob; public Nob hovered_nob; private Goo.CanvasItem root; private Goo.CanvasRect? select_effect; private Akira.Lib.Selection.Nob[] nobs = new Akira.Lib.Selection.Nob[9]; private Goo.CanvasPolyline? rotation_line; // Active nob data associated with current selection. // private ItemNobData active_nob_data; // Tracks if an artboard is part of the current selection. private bool is_artboard; private bool nobs_constructed = false; // If the effect needs to be created or it's only a value update. private bool create { get; set; default = true; } public NobManager (Akira.Lib.Canvas canvas) { Object ( canvas: canvas ); } construct { canvas.window.event_bus.selected_items_list_changed.connect (on_add_select_effect); canvas.window.event_bus.selected_items_changed.connect (on_add_select_effect); canvas.window.event_bus.zoom.connect (on_canvas_zoom); canvas.window.event_bus.hide_select_effect.connect (on_hide_select_effect); canvas.window.event_bus.show_select_effect.connect (on_show_select_effect); } /** * Set which nob is selected by its Nob name. */ public void set_selected_by_name (Nob selected_nob) { this.selected_nob = selected_nob; } public Nob hit_test (double x, double y) { double scale = canvas.current_scale; foreach (var ui_nob in nobs) { if (ui_nob != null && ui_nob.is_visible ()) { if (ui_nob.hit_test (x, y, scale)) { return ui_nob.handle_id; } } } return Nob.NONE; } public static bool is_top_nob (Nob nob) { return nob == Nob.TOP_LEFT || nob == Nob.TOP_CENTER || nob == Nob.TOP_RIGHT; } public static bool is_bot_nob (Nob nob) { return nob == Nob.BOTTOM_LEFT || nob == Nob.BOTTOM_CENTER || nob == Nob.BOTTOM_RIGHT; } public static bool is_left_nob (Nob nob) { return nob == Nob.TOP_LEFT || nob == Nob.LEFT_CENTER || nob == Nob.BOTTOM_LEFT; } public static bool is_right_nob (Nob nob) { return nob == Nob.TOP_RIGHT || nob == Nob.RIGHT_CENTER || nob == Nob.BOTTOM_RIGHT; } public static bool is_corner_nob (Nob nob) { return nob == Nob.TOP_RIGHT || nob == Nob.TOP_LEFT || nob == Nob.BOTTOM_RIGHT || nob == Nob.BOTTOM_LEFT; } /* * Return a cursor type based of the type of nob. */ public static Gdk.CursorType? cursor_from_nob (Nob nob_id) { Gdk.CursorType? result = null; switch (nob_id) { case Managers.NobManager.Nob.NONE: result = null; break; case Managers.NobManager.Nob.TOP_LEFT: result = Gdk.CursorType.TOP_LEFT_CORNER; break; case Managers.NobManager.Nob.TOP_CENTER: result = Gdk.CursorType.TOP_SIDE; break; case Managers.NobManager.Nob.TOP_RIGHT: result = Gdk.CursorType.TOP_RIGHT_CORNER; break; case Managers.NobManager.Nob.RIGHT_CENTER: result = Gdk.CursorType.RIGHT_SIDE; break; case Managers.NobManager.Nob.BOTTOM_RIGHT: result = Gdk.CursorType.BOTTOM_RIGHT_CORNER; break; case Managers.NobManager.Nob.BOTTOM_CENTER: result = Gdk.CursorType.BOTTOM_SIDE; break; case Managers.NobManager.Nob.BOTTOM_LEFT: result = Gdk.CursorType.BOTTOM_LEFT_CORNER; break; case Managers.NobManager.Nob.LEFT_CENTER: result = Gdk.CursorType.LEFT_SIDE; break; case Managers.NobManager.Nob.ROTATE: result = Gdk.CursorType.EXCHANGE; break; } return result; } /** * Takes a set of items and populates information needed to determine * the selection box and nob positions. If the number of items is one, * the selection box may be rotated, otherwise it is never rotated. */ public static void populate_nob_bounds_from_items (List items, ref ItemNobData nob_data) { nob_data.top_left_x = 0; nob_data.top_left_y = 0; // Check if we only have one item currently selected. if (items.length () == 1) { var item = items.first ().data; item.get_transform (out nob_data.bb_matrix); // Set the coordinates for the transform panel. // Use x and y coordinates to account for the item being inside artboard. nob_data.selected_x = item.coordinates.x; nob_data.selected_y = item.coordinates.y; Cairo.Matrix nob_matrix = nob_data.bb_matrix; if (item.artboard != null) { Cairo.Matrix artboard_matrix; item.artboard.get_transform (out artboard_matrix); nob_matrix.multiply (nob_data.bb_matrix, artboard_matrix); } nob_data.bb_width = item.size.width; nob_data.bb_height = item.size.height; double width_offset_x = nob_data.bb_width; double width_offset_y = 0; double height_offset_x = 0; double height_offset_y = nob_data.bb_height; nob_matrix.transform_distance (ref width_offset_x, ref width_offset_y); nob_matrix.transform_distance (ref height_offset_x, ref height_offset_y); nob_matrix.transform_point (ref nob_data.top_left_x, ref nob_data.top_left_y); nob_data.width_offset_x = width_offset_x; nob_data.width_offset_y = width_offset_y; nob_data.height_offset_x = height_offset_x; nob_data.height_offset_y = height_offset_y; return; } nob_data.bb_matrix = Cairo.Matrix.identity (); bool first = true; double x = 0; double y = 0; double x1 = 0; double y1 = 0; double x2 = 0; double y2 = 0; foreach (var item in items) { // Store the coordinates accounting for items inside artboards. x = first ? item.coordinates.x : double.min (x, item.coordinates.x); y = first ? item.coordinates.y : double.min (y, item.coordinates.y); x1 = first ? item.coordinates.x1 : double.min (x1, item.coordinates.x1); x2 = double.max (x2, item.coordinates.x2); y1 = first ? item.coordinates.y1 : double.min (y1, item.coordinates.y1); y2 = double.max (y2, item.coordinates.y2); first = false; } // Set the coordinates for the transform panel. nob_data.selected_x = x; nob_data.selected_y = y; nob_data.bb_width = x2 - x1; nob_data.bb_height = y2 - y1; nob_data.top_left_x = x1; nob_data.top_left_y = y1; nob_data.width_offset_x = nob_data.bb_width; nob_data.width_offset_y = 0; nob_data.height_offset_x = 0; nob_data.height_offset_y = nob_data.bb_height; } /** * Calculates the position of a nob based on values * calculated using `populate_nob_bounds_from_items`. */ private static void calculate_nob_position ( Nob nob_name, ItemNobData nob_data, ref double pos_x, ref double pos_y ) { double top_left_x = nob_data.top_left_x; double top_left_y = nob_data.top_left_y; double width_offset_x = nob_data.width_offset_x; double width_offset_y = nob_data.width_offset_y; double height_offset_x = nob_data.height_offset_x; double height_offset_y = nob_data.height_offset_y; switch (nob_name) { case Nob.TOP_LEFT: pos_x = top_left_x; pos_y = top_left_y; break; case Nob.TOP_CENTER: pos_x = top_left_x + width_offset_x / 2.0; pos_y = top_left_y + width_offset_y / 2.0; break; case Nob.TOP_RIGHT: pos_x = top_left_x + width_offset_x; pos_y = top_left_y + width_offset_y; break; case Nob.RIGHT_CENTER: pos_x = top_left_x + width_offset_x + height_offset_x / 2.0; pos_y = top_left_y + width_offset_y + height_offset_y / 2.0; break; case Nob.BOTTOM_RIGHT: pos_x = top_left_x + width_offset_x + height_offset_x; pos_y = top_left_y + width_offset_y + height_offset_y; break; case Nob.BOTTOM_CENTER: pos_x = top_left_x + width_offset_x / 2.0 + height_offset_x; pos_y = top_left_y + width_offset_y / 2.0 + height_offset_y; break; case Nob.BOTTOM_LEFT: pos_x = top_left_x + height_offset_x; pos_y = top_left_y + height_offset_y; break; case Nob.LEFT_CENTER: pos_x = top_left_x + height_offset_x / 2.0; pos_y = top_left_y + height_offset_y / 2.0; break; case Nob.NONE: default: break; } } /** * Calculates the position of a nob based on a selection of items and the nob id. */ public static void nob_position_from_items ( List items, Nob nob_name, ref double pos_x, ref double pos_y ) { var nob_data = new ItemNobData (); populate_nob_bounds_from_items (items, ref nob_data); calculate_nob_position (nob_name, nob_data, ref pos_x, ref pos_y); } /** * What happens when the canvas is zoomed in. */ private void on_canvas_zoom () { on_add_select_effect (canvas.selected_bound_manager.selected_items); } /** * Adds selection effects if applicable to selected items, * and repositions the selection and nobs. */ private void on_add_select_effect (List selected_items) { if (selected_items.length () == 0) { remove_select_effect (); return; } populate_nobs (); var active_nob_data = new ItemNobData (); populate_nob_bounds_from_items (selected_items, ref active_nob_data); update_select_effect (selected_items, active_nob_data); update_nob_position (selected_items, active_nob_data); } /** * Resets all selection and nob items. */ private void remove_select_effect (bool keep_selection = false) { if (select_effect == null) { return; } select_effect.remove (); select_effect = null; rotation_line.set ("visibility", Goo.CanvasItemVisibility.HIDDEN); foreach (var nob in nobs) { nob.set ("visibility", Goo.CanvasItemVisibility.HIDDEN); } } /** * Updates selection items, constructing them if necessary. */ private void update_select_effect (List selected_items, ItemNobData nob_data) { if (select_effect == null) { select_effect = new Goo.CanvasRect ( null, 0, 0, nob_data.bb_width, nob_data.bb_height, "line-width", LINE_WIDTH / canvas.current_scale, "stroke-color", STROKE_COLOR, null ); select_effect.set ("parent", root); select_effect.pointer_events = Goo.CanvasPointerEvents.NONE; } // If only one item is selected and it's inside an artboard, // we need to convert its coordinates from the artboard space. Cairo.Matrix tmp_matrix = nob_data.bb_matrix; var item = selected_items.first ().data; if (selected_items.length () == 1 && item.artboard != null) { item.canvas.convert_from_item_space (item.artboard, ref tmp_matrix.x0, ref tmp_matrix.y0); } select_effect.set_transform (tmp_matrix); select_effect.set ("width", nob_data.bb_width); select_effect.set ("height", nob_data.bb_height); select_effect.set ("line-width", LINE_WIDTH / canvas.current_scale); } /** * Update the position of all nobs of selected items. It will show or hide them based on * the properties of the selection. */ private void update_nob_position (List selected_items, ItemNobData nob_data) { is_artboard = false; foreach (var item in selected_items) { if (item is Items.CanvasArtboard) { is_artboard = true; break; } } var nob_size = Selection.Nob.NOB_SIZE / canvas.current_scale; bool print_middle_width_nobs = nob_data.bb_width > nob_size * 3; bool print_middle_height_nobs = nob_data.bb_height > nob_size * 3; foreach (var nob in nobs) { bool set_visible = true; double center_x = 0; double center_y = 0; var nob_name = nob.handle_id; calculate_nob_position (nob_name, nob_data, ref center_x, ref center_y); // Unique calculation for the rotation nob. if (nob.handle_id == Nob.ROTATE) { double line_offset_x = 0; double line_offset_y = - (LINE_HEIGHT / canvas.current_scale); nob_data.bb_matrix.transform_distance (ref line_offset_x, ref line_offset_y); // If only one item is selected and it's inside an artboard, // we need to convert its coordinates from the artboard space. Cairo.Matrix tmp_matrix = nob_data.bb_matrix; var item = selected_items.first ().data; if (selected_items.length () == 1 && item.artboard != null) { item.canvas.convert_from_item_space (item.artboard, ref tmp_matrix.x0, ref tmp_matrix.y0); } center_x = nob_data.top_left_x + nob_data.width_offset_x / 2.0 + line_offset_x; center_y = nob_data.top_left_y + nob_data.width_offset_y / 2.0 + line_offset_y; set_visible = !is_artboard; if (set_visible) { rotation_line.set_transform (tmp_matrix); rotation_line.translate (nob_data.bb_width / 2.0, - LINE_HEIGHT / canvas.current_scale); rotation_line.set ("line-width", LINE_WIDTH / canvas.current_scale); rotation_line.set ("height", LINE_HEIGHT / canvas.current_scale); rotation_line.set ("visibility", Goo.CanvasItemVisibility.VISIBLE); rotation_line.raise (select_effect); } else { rotation_line.set ("visibility", Goo.CanvasItemVisibility.HIDDEN); } // Raise to the rotation_line, so the line is under the rotation nob. nob.update_state (nob_data.bb_matrix, center_x, center_y, set_visible); nob.raise (rotation_line); continue; } // Check if we need to hide the vertically centered nobs. if (!print_middle_height_nobs && (nob_name == Nob.RIGHT_CENTER || nob_name == Nob.LEFT_CENTER)) { set_visible = false; } // Check if we need to hide the horizontally centere nobs. if (!print_middle_width_nobs && (nob_name == Nob.TOP_CENTER || nob_name == Nob.BOTTOM_CENTER)) { set_visible = false; } nob.update_state (nob_data.bb_matrix, center_x, center_y, set_visible); nob.raise (select_effect); // If we're hiding all centered nobs, we need to shift the position // of the corner nobs to improve the grabbing area. if (!print_middle_width_nobs && !print_middle_height_nobs) { var half = nob_size / 2; // Use Cairo.translate to automatically account for the item's rotation. if (nob_name == Nob.TOP_LEFT) { nob.translate (-half, -half); } else if (nob_name == Nob.TOP_RIGHT) { nob.translate (half, -half); } else if (nob_name == Nob.BOTTOM_RIGHT) { nob.translate (half, half); } else if (nob_name == Nob.BOTTOM_LEFT) { nob.translate (-half, half); } } } } /** * Constructs all nobs and the rotation line if they haven't been constructed already. * Nobs don't take mouse events, instead hit_test () is used to interact with nobs. */ private void populate_nobs () { if (nobs_constructed) { return; } root = canvas.get_root_item (); for (int i = 0; i < 9; i++) { var nob = new Selection.Nob (root, (Managers.NobManager.Nob) i); nob.set ("visibility", Goo.CanvasItemVisibility.HIDDEN); nob.pointer_events = Goo.CanvasPointerEvents.NONE; nobs[i] = nob; } // Create the line to visually connect the rotation nob to the item. rotation_line = new Goo.CanvasPolyline.line ( null, 0, 0, 0, LINE_HEIGHT, "line-width", LINE_WIDTH / canvas.current_scale, "stroke-color", STROKE_COLOR, null); rotation_line.set ("parent", root); rotation_line.pointer_events = Goo.CanvasPointerEvents.NONE; nobs_constructed = true; } /** * Asynchronous call to hide selection and nobs. */ private async void on_hide_select_effect () { foreach (var nob in nobs) { nob.set ("visibility", Goo.CanvasItemVisibility.HIDDEN); } select_effect.set ("visibility", Goo.CanvasItemVisibility.HIDDEN); rotation_line.set ("visibility", Goo.CanvasItemVisibility.HIDDEN); } /** * Asynchronous call to show selection and nobs. */ private async void on_show_select_effect () { for (int i = 0; i < 9; i++) { // If an artboard is part of the current selection, don't show the rotation nob. if (is_artboard && i == 8) { continue; } nobs[i].set ("visibility", Goo.CanvasItemVisibility.VISIBLE); } select_effect.set ("visibility", Goo.CanvasItemVisibility.VISIBLE); if (!is_artboard) { rotation_line.set ("visibility", Goo.CanvasItemVisibility.VISIBLE); } } } Akira-0.0.16/src/Lib/Managers/SelectedBoundManager.vala000066400000000000000000000176771410625726100225650ustar00rootroot00000000000000/** * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Giacomo Alberini * Authored by: Alessandro "Alecaddd" Castellani */ public class Akira.Lib.Managers.SelectedBoundManager : Object { public weak Akira.Lib.Canvas canvas { get; construct; } public weak Akira.Window window { get; construct; } private unowned List _selected_items; public unowned List selected_items { get { return _selected_items; } set { _selected_items = value; canvas.window.event_bus.selected_items_list_changed (value); } } public SelectedBoundManager (Akira.Lib.Canvas canvas) { Object ( canvas: canvas, window: canvas.window ); canvas.window.event_bus.change_z_selected.connect (change_z_selected); canvas.window.event_bus.item_value_changed.connect (update_selected_items); canvas.window.event_bus.flip_item.connect (on_flip_item); canvas.window.event_bus.move_item_from_canvas.connect (on_move_item_from_canvas); canvas.window.event_bus.item_deleted.connect (remove_item_from_selection); canvas.window.event_bus.request_add_item_to_selection.connect (add_item_to_selection); canvas.window.event_bus.item_locked.connect (remove_item_from_selection); } construct { reset_selection (); } public void add_item_to_selection (Items.CanvasItem item) { // Don't clear and reselect the same element if it's already selected. if (selected_items.index (item) != -1) { return; } // Just 1 selected element at the same time // TODO: allow for multi selection with shift pressed reset_selection (); item.layer.selected = true; item.size.update_ratio (); selected_items.append (item); // Initialize the state manager coordinates. canvas.window.event_bus.init_state_coords (); // Move focus back to the canvas. canvas.window.event_bus.set_focus_on_canvas (); } public void delete_selection () { if (selected_items.length () == 0) { return; } for (var i = 0; i < selected_items.length (); i++) { var item = selected_items.nth_data (i); canvas.window.event_bus.request_delete_item (item); } // By emptying the selected_items list, the select_effect gets dropped selected_items = new List (); } public void reset_selection () { if (selected_items.length () == 0) { return; } foreach (var item in selected_items) { item.layer.selected = false; } selected_items = new List (); } private void update_selected_items () { canvas.window.event_bus.selected_items_changed (selected_items); foreach (var item in selected_items) { if (!(item is Items.CanvasArtboard)) { continue; } Cairo.Matrix matrix; item.get_transform (out matrix); ((Items.CanvasArtboard) item).label.set_transform (matrix); } } private void change_z_selected (bool raise, bool total) { if (selected_items.length () == 0) { return; } Items.CanvasItem selected_item = selected_items.nth_data (0); // Cannot move artboard z-index wise. if (selected_item is Items.CanvasArtboard) { return; } int items_count = 0; int pos_selected = -1; if (selected_item.artboard != null) { // Inside an artboard. items_count = (int) selected_item.artboard.items.get_n_items (); pos_selected = items_count - 1 - selected_item.artboard.items.index (selected_item); } else { items_count = (int) window.items_manager.free_items.get_n_items (); pos_selected = items_count - 1 - window.items_manager.free_items.index (selected_item); } // Interrupt if item position doesn't exist. if (pos_selected == -1) { warning ("item position doesn't exist"); return; } int target_position = -1; if (raise) { if (pos_selected < (items_count - 1)) { target_position = pos_selected + 1; } if (total) { target_position = items_count - 1; } } else { if (pos_selected > 0) { target_position = pos_selected - 1; } if (total) { target_position = 0; } } // Interrupt if the target position is invalid. if (target_position == -1) { debug ("Target position invalid"); return; } Items.CanvasItem target_item = null; // z-index is the exact opposite of items placement inside the items list model // as the last item is actually the topmost element. var source = items_count - 1 - pos_selected; var target = items_count - 1 - target_position; if (selected_item.artboard != null) { target_item = selected_item.artboard.items.get_item (target) as Lib.Items.CanvasItem; selected_item.artboard.items.swap_items (source, target); } else { target_item = window.items_manager.free_items.get_item (target) as Lib.Items.CanvasItem; window.items_manager.free_items.swap_items (source, target); } if (raise) { selected_item.raise (target_item); } else { selected_item.lower (target_item); } canvas.window.event_bus.z_selected_changed (); } private void on_flip_item (bool vertical) { if (selected_items.length () == 0) { return; } // Loop through all the currently selected items. foreach (Items.CanvasItem item in selected_items) { // Skip if the item is an Artboard. if (item is Items.CanvasArtboard) { continue; } if (vertical) { item.flipped.vertical = !item.flipped.vertical; continue; } item.flipped.horizontal = !item.flipped.horizontal; } } private void on_move_item_from_canvas (Gdk.EventKey event) { if (selected_items.length () == 0 || !canvas.has_focus) { return; } var amount = (event.state & Gdk.ModifierType.SHIFT_MASK) > 0 ? 10 : 1; double x = 0.0, y = 0.0; switch (event.keyval) { case Gdk.Key.Up: y -= amount; break; case Gdk.Key.Down: y += amount; break; case Gdk.Key.Right: x += amount; break; case Gdk.Key.Left: x -= amount; break; } window.event_bus.update_state_coords (x, y); } private void remove_item_from_selection (Lib.Items.CanvasItem item) { if (selected_items.index (item) > -1) { selected_items.remove (item); } canvas.window.event_bus.set_focus_on_canvas (); } } Akira-0.0.16/src/Lib/Managers/SnapManager.vala000066400000000000000000000222371410625726100207320ustar00rootroot00000000000000/** * Copyright (c) 2021 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Martin "mbfraga" Fraga */ /** * Manages Goo.CanvasItem decorators used to display snap lines and dots. */ public class Akira.Lib.Managers.SnapManager : Object { private const double LINE_WIDTH = 0.5; private const double DOT_RADIUS = 2.0; public weak Akira.Lib.Canvas canvas { get; construct; } // Decorator items to be drawn in the Canvas. private Goo.CanvasItem root; private Gee.ArrayList v_decorator_lines; private Gee.ArrayList h_decorator_lines; private Gee.ArrayList decorator_dots; /* * Type of snap guides to show (could be a selection or just a point). */ public enum SnapGuideType { NONE, SELECTION, POINT } /* * Data that can be used to tell the SnapManager details on how to show snap guides. */ public class SnapGuideData { public SnapGuideType type = SnapGuideType.NONE; public double x = 0.0; public double y = 0.0; } private bool any_decorators_visible = false; public SnapManager (Akira.Lib.Canvas canvas) { Object ( canvas: canvas ); } construct { v_decorator_lines = new Gee.ArrayList (); h_decorator_lines = new Gee.ArrayList (); decorator_dots = new Gee.ArrayList (); canvas.window.event_bus.update_snaps_color.connect (on_update_snaps_color); } /* * Generate guides as indicated by the data. */ public void generate_decorators (SnapGuideData new_data) { switch (new_data.type) { case SnapGuideType.NONE: reset_decorators (); break; case SnapGuideType.SELECTION: unowned var selected_items = canvas.selected_bound_manager.selected_items; var sensitivity = Utils.Snapping.adjusted_sensitivity (canvas.current_scale); var snap_grid = Utils.Snapping.generate_best_snap_grid (canvas, selected_items, sensitivity); var matches = Utils.Snapping.generate_snap_matches (snap_grid, selected_items, sensitivity); populate_decorators_from_data (matches, snap_grid); break; case SnapGuideType.POINT: // TODO break; } } /* * Returns true if the manager has active decorators */ public bool is_active () { return any_decorators_visible; } /* * Makes all decorators invisible, and ready to be reused */ public void reset_decorators () { foreach (var decorator in v_decorator_lines) { decorator.set ("visibility", Goo.CanvasItemVisibility.HIDDEN); } foreach (var decorator in h_decorator_lines) { decorator.set ("visibility", Goo.CanvasItemVisibility.HIDDEN); } foreach (var decorator in decorator_dots) { decorator.set ("visibility", Goo.CanvasItemVisibility.HIDDEN); } any_decorators_visible = false; } /* * Populates decorators (if applicable) based on match data and the snap grid. * Reuses decorator Goo.CanvasItems if possible, otherwise constructs new ones. */ public void populate_decorators_from_data (Utils.Snapping.SnapMatchData data, Utils.Snapping.SnapGrid grid) { if (root == null) { root = canvas.get_root_item (); } reset_decorators (); if (data.v_data.snap_found ()) { foreach (var snap_position in data.v_data.exact_matches) { any_decorators_visible = true; add_vertical_decorator_line (snap_position.key, snap_position.value, grid); } } if (data.h_data.snap_found ()) { foreach (var snap_position in data.h_data.exact_matches) { any_decorators_visible = true; add_horizontal_decorator_line (snap_position.key, snap_position.value, grid); } } } private void add_vertical_decorator_line (int pos, int polarity_offset, Utils.Snapping.SnapGrid grid) { double lw = LINE_WIDTH / canvas.current_scale; var snap_value = grid.v_snaps.get (pos); if (snap_value != null) { // To actually show decorators in their exact position, we offset by 0.5. double actual_pos = (double) (pos + polarity_offset); // Add dots. foreach (var normal in snap_value.normals) { add_decorator_dot (normal, actual_pos); } // Add lines (reuse if possible). foreach (var line in v_decorator_lines) { if (line.visibility == Goo.CanvasItemVisibility.HIDDEN) { line.set ("visibility", Goo.CanvasItemVisibility.VISIBLE); line.set ("y", actual_pos); line.set ("line-width", lw); line.raise (null); return; } } var tmp = new Goo.CanvasPolyline.line ( null, canvas.x1, actual_pos, canvas.x2, actual_pos, "line-width", lw, "stroke-color", settings.snaps_color, null ); tmp.can_focus = false; tmp.pointer_events = Goo.CanvasPointerEvents.NONE; tmp.set ("parent", root); tmp.raise (null); v_decorator_lines.add (tmp); } } private void add_horizontal_decorator_line (int pos, int polarity_offset, Utils.Snapping.SnapGrid grid) { double lw = LINE_WIDTH / canvas.current_scale; var snap_value = grid.h_snaps.get (pos); if (snap_value != null) { double actual_pos = (double) (pos + polarity_offset); // Add dots. foreach (var normal in snap_value.normals) { add_decorator_dot (actual_pos, normal); } // Add lines (reuse if possible). foreach (var line in h_decorator_lines) { if (line.visibility == Goo.CanvasItemVisibility.HIDDEN) { line.set ("visibility", Goo.CanvasItemVisibility.VISIBLE); line.set ("x", actual_pos); line.set ("line-width", lw); line.raise (null); return; } } var tmp = new Goo.CanvasPolyline.line ( null, actual_pos, canvas.y1, actual_pos, canvas.y2, "line-width", lw, "stroke-color", settings.snaps_color, null ); tmp.can_focus = false; tmp.pointer_events = Goo.CanvasPointerEvents.NONE; tmp.set ("parent", root); tmp.raise (null); h_decorator_lines.add (tmp); } } private void add_decorator_dot (double x, double y) { double dot_radius = DOT_RADIUS / canvas.current_scale; // Add dot. foreach (var line in decorator_dots) { if (line.visibility == Goo.CanvasItemVisibility.HIDDEN) { line.set ("visibility", Goo.CanvasItemVisibility.VISIBLE); line.set ("center_x", x); line.set ("center_y", y); line.set ("radius_x", dot_radius); line.set ("radius_y", dot_radius); line.raise (null); return; } } var tmp = new Goo.CanvasEllipse ( null, x, y, dot_radius, dot_radius, "line-width", 0.0, "fill-color", settings.snaps_color, null ); tmp.can_focus = false; tmp.pointer_events = Goo.CanvasPointerEvents.NONE; tmp.set ("parent", root); tmp.raise (null); decorator_dots.add (tmp); } /** * Loop through all the existing guides and update the color. */ private void on_update_snaps_color () { // Points. foreach (var dot in decorator_dots) { dot.set ("fill-color", settings.snaps_color); } // Horizontal lines. foreach (var line in h_decorator_lines) { line.set ("stroke-color", settings.snaps_color); } // Vertical lines. foreach (var line in v_decorator_lines) { line.set ("stroke-color", settings.snaps_color); } } } Akira-0.0.16/src/Lib/Modes/000077500000000000000000000000001410625726100151755ustar00rootroot00000000000000Akira-0.0.16/src/Lib/Modes/ExportMode.vala000066400000000000000000000042031410625726100201270ustar00rootroot00000000000000/** * Copyright (c) 2021 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Martin "mbfraga" Fraga */ /* * ExportMode handles selecting an area for exporting. */ public class Akira.Lib.Modes.ExportMode : InteractionMode { public weak Akira.Lib.Canvas canvas { get; construct; } public weak Akira.Lib.Managers.ModeManager mode_manager { get; construct; } private bool resizing = false; public ExportMode (Akira.Lib.Canvas canvas, Akira.Lib.Managers.ModeManager mode_manager) { Object ( canvas: canvas, mode_manager : mode_manager ); } public override InteractionMode.ModeType mode_type () { return InteractionMode.ModeType.EXPORT; } public override Gdk.CursorType? cursor_type () { return Gdk.CursorType.CROSSHAIR; } public override bool button_press_event (Gdk.EventButton event) { canvas.selected_bound_manager.reset_selection (); canvas.export_manager.create_area (event); resizing = true; return true; } public override bool button_release_event (Gdk.EventButton event) { if (resizing) { canvas.export_manager.create_area_snapshot (); mode_manager.deregister_mode (mode_type ()); } return true; } public override bool motion_notify_event (Gdk.EventMotion event) { if (resizing) { canvas.export_manager.resize_area (event.x, event.y); } return true; } } Akira-0.0.16/src/Lib/Modes/InteractionMode.vala000066400000000000000000000076421410625726100211370ustar00rootroot00000000000000/** * Copyright (c) 2021 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Martin "mbfraga" Fraga */ /* * InteractionMode is an abstract definition. It abstracts a canvas interaction mode that can absorb mouse and key * events, as well as having a well defined beginning and end. How these things are defined is up to a higher * class such as the ModeManager. * * In general only one InteractionMode will be active at a time. There are some exceptions where a mode may * be masked by another, but this should be handled with a Manager with strong invariant management. * * To create a new mode: * 1. Add a new ModeType * 2. Create a new class that inherits from Object and InteractionMode * 3. Implement all abstract methods, and return the correct mode_type * 4. Create the new mode with the right trigger in Canvas, and ModeManager will automatically handle it * based on the abstract methods below. Sometimes the same event that creates the mode should be passed * to the mode_manager after the creation of the mode in order to guarantee correct behavior. * 5. For now, modes should take mode_manager on construction in order to be able to stop themselves. In * the future this should be built into the api in a more abstract way. */ public abstract class Akira.Lib.Modes.InteractionMode : Object { /* * Mode type that is used for introspection. */ public enum ModeType { RESIZE, ITEM_INSERT, EXPORT, PAN } /* * Override to define ModeType associated to mode. */ public abstract ModeType mode_type (); /* * Override to add startup behavior to the mode. */ public virtual void mode_begin () {} /* * Override to add shutdown behavior to mode. */ public virtual void mode_end () {} /* * Override to define cursor associated to mode. */ public virtual Gdk.CursorType? cursor_type () { return Gdk.CursorType.ARROW; } /* * Override to define key press event. Return true to absorb. */ public virtual bool key_press_event (Gdk.EventKey event) { return false; } /* * Override to define key release event. Return true to absorb. */ public virtual bool key_release_event (Gdk.EventKey event) { return false; } /* * Override to define button press event. Return true to absorb. */ public virtual bool button_press_event (Gdk.EventButton event) { return false; } /* * Override to define button release event. Return true to absorb. */ public virtual bool button_release_event (Gdk.EventButton event) { return false; } /* * Override to define mouse motion event. Return true to absorb. */ public virtual bool motion_notify_event (Gdk.EventMotion event) { return false; } /* * Optionally override to provide some extra context that may be used * further up to know how to update other managers based on this mode. * * This context should not be relied upon for vital operations or anything * that requires a specific order of operations. It is generally meant for * more cosmetic features. */ public virtual Object? extra_context () { return null; } } Akira-0.0.16/src/Lib/Modes/ItemInsertMode.vala000066400000000000000000000075201410625726100207360ustar00rootroot00000000000000/** * Copyright (c) 2021 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Martin "mbfraga" Fraga */ /* * ItemInsertMode handles item insertion. After the first click, this mode will use static methods * in the TransformMode to transform the inserted items. * * In the future, this mode can be kept alive during multiple clicks when inserting items like polylines. */ public class Akira.Lib.Modes.ItemInsertMode : InteractionMode { public weak Akira.Lib.Canvas canvas { get; construct; } public weak Akira.Lib.Managers.ModeManager mode_manager { get; construct; } private Akira.Lib.Modes.TransformMode transform_mode; public ItemInsertMode (Akira.Lib.Canvas canvas, Akira.Lib.Managers.ModeManager mode_manager) { Object ( canvas: canvas, mode_manager : mode_manager ); } construct { transform_mode = null; } public override InteractionMode.ModeType mode_type () { return InteractionMode.ModeType.ITEM_INSERT; } public override void mode_end () { if (transform_mode != null) { transform_mode.mode_end (); } } public override Gdk.CursorType? cursor_type () { if (transform_mode != null) { return transform_mode.cursor_type (); } return Gdk.CursorType.CROSSHAIR; } public override bool key_press_event (Gdk.EventKey event) { if (transform_mode != null) { return transform_mode.key_press_event (event); } return false; } public override bool key_release_event (Gdk.EventKey event) { if (transform_mode != null) { return transform_mode.key_press_event (event); } return false; } public override bool button_press_event (Gdk.EventButton event) { if (transform_mode != null) { return transform_mode.button_press_event (event); } if (event.button == Gdk.BUTTON_PRIMARY) { var sel_manager = canvas.selected_bound_manager; sel_manager.reset_selection (); var new_item = canvas.window.items_manager.insert_item (event.x, event.y); sel_manager.add_item_to_selection (new_item); canvas.nob_manager.selected_nob = Managers.NobManager.Nob.BOTTOM_RIGHT; canvas.update_canvas (); transform_mode = new Akira.Lib.Modes.TransformMode (canvas, null); transform_mode.mode_begin (); transform_mode.button_press_event (event); return true; } return false; } public override bool button_release_event (Gdk.EventButton event) { if (transform_mode != null) { transform_mode.button_release_event (event); mode_manager.deregister_mode (mode_type ()); } return true; } public override bool motion_notify_event (Gdk.EventMotion event) { if (transform_mode != null) { return transform_mode.motion_notify_event (event); } return true; } public override Object? extra_context () { if (transform_mode != null) { return transform_mode.extra_context (); } return null; } } Akira-0.0.16/src/Lib/Modes/PanMode.vala000066400000000000000000000063221410625726100173700ustar00rootroot00000000000000/** * Copyright (c) 2021 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Martin "mbfraga" Fraga */ /* * PanMode handles panning. This will handle space or middle click panning. This mode should * be used as a secondary mode that overrides masks other modes. See ModeManager. */ public class Akira.Lib.Modes.PanMode : InteractionMode { public weak Akira.Lib.Canvas canvas { get; construct; } public weak Akira.Lib.Managers.ModeManager mode_manager { get; construct; } private bool space_held = false; private bool panning = false; private double origin_x = 0; private double origin_y = 0; public PanMode (Akira.Lib.Canvas canvas, Akira.Lib.Managers.ModeManager mode_manager) { Object ( canvas: canvas, mode_manager : mode_manager ); } public override InteractionMode.ModeType mode_type () { return InteractionMode.ModeType.PAN; } public override Gdk.CursorType? cursor_type () { return panning ? Gdk.CursorType.HAND2 : Gdk.CursorType.HAND1; } public override bool key_press_event (Gdk.EventKey event) { uint uppercase_keyval = Gdk.keyval_to_upper (event.keyval); if (uppercase_keyval == Gdk.Key.space) { space_held = true; } return true; } public override bool key_release_event (Gdk.EventKey event) { uint uppercase_keyval = Gdk.keyval_to_upper (event.keyval); if (uppercase_keyval == Gdk.Key.space) { space_held = false; if (!panning) { mode_manager.deregister_mode (mode_type ()); } } return true; } public override bool button_press_event (Gdk.EventButton event) { if (!panning && (space_held || event.button == Gdk.BUTTON_MIDDLE)) { origin_x = event.x; origin_y = event.y; canvas.canvas_scroll_set_origin (origin_x, origin_y); toggle_panning (true); } return true; } public override bool button_release_event (Gdk.EventButton event) { toggle_panning (false); if (!space_held) { mode_manager.deregister_mode (mode_type ()); } return true; } public override bool motion_notify_event (Gdk.EventMotion event) { if (panning) { canvas.canvas_moved (event.x, event.y); } return true; } private void toggle_panning (bool new_state) { if (panning != new_state) { panning = new_state; canvas.interaction_mode_changed (); } } } Akira-0.0.16/src/Lib/Modes/TransformMode.vala000066400000000000000000000341771410625726100206360ustar00rootroot00000000000000/** * Copyright (c) 2021 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Martin "mbfraga" Fraga */ /* * TransformMode handles mouse-activated transformations. Static methods can * be used to apply the underlying code on top of other modes that may need to * use the functionality. */ public class Akira.Lib.Modes.TransformMode : InteractionMode { private const double ROTATION_FIXED_STEP = 15.0; public weak Akira.Lib.Canvas canvas { get; construct; } public weak Akira.Lib.Managers.ModeManager mode_manager { get; construct; } public class InitialDragState { public double press_x = 0.0; public double press_y = 0.0; public double nob_x = 0.0; public double nob_y = 0.0; public double item_x = 0.0; public double item_y = 0.0; public double item_width = 0.0; public double item_height = 0.0; public Cairo.Matrix item_transform; public double item_scale_x_adj = 0.0; public double item_scale_y_adj = 0.0; public double rotation_center_x = 0.0; public double rotation_center_y = 0.0; public bool wants_snapping = true; } public class TransformExtraContext : Object { public Akira.Lib.Managers.SnapManager.SnapGuideData snap_guide_data; } public InitialDragState initial_drag_state; public TransformExtraContext transform_extra_context; public TransformMode (Akira.Lib.Canvas canvas, Akira.Lib.Managers.ModeManager? mode_manager) { Object ( canvas: canvas, mode_manager : mode_manager ); } construct { initial_drag_state = new InitialDragState (); transform_extra_context = new TransformExtraContext (); transform_extra_context.snap_guide_data = new Akira.Lib.Managers.SnapManager.SnapGuideData (); } public override void mode_begin () { unowned var selected_items = canvas.selected_bound_manager.selected_items; var success = initialize_items_drag_state (selected_items, ref initial_drag_state); if (!success && mode_manager != null) { mode_manager.deregister_mode (mode_type ()); return; } } public override void mode_end () { transform_extra_context = null; canvas.nob_manager.set_selected_by_name (Akira.Lib.Managers.NobManager.Nob.NONE); canvas.window.event_bus.detect_artboard_change (); canvas.window.event_bus.update_snap_decorators (); } public override InteractionMode.ModeType mode_type () { return InteractionMode.ModeType.RESIZE; } public override Gdk.CursorType? cursor_type () { var selected_nob = canvas.nob_manager.selected_nob; return Managers.NobManager.cursor_from_nob (selected_nob); } public override bool key_press_event (Gdk.EventKey event) { return true; } public override bool key_release_event (Gdk.EventKey event) { return false; } public override bool button_press_event (Gdk.EventButton event) { initial_drag_state.press_x = event.x; initial_drag_state.press_y = event.y; Akira.Lib.Managers.NobManager.nob_position_from_items ( canvas.selected_bound_manager.selected_items, canvas.nob_manager.selected_nob, ref initial_drag_state.nob_x, ref initial_drag_state.nob_y ); return true; } public override bool button_release_event (Gdk.EventButton event) { if (mode_manager != null) { mode_manager.deregister_mode (mode_type ()); } return true; } public override bool motion_notify_event (Gdk.EventMotion event) { var selected_nob = canvas.nob_manager.selected_nob; unowned var selected_items = canvas.selected_bound_manager.selected_items; if (selected_items.length () != 1) { return false; } switch (selected_nob) { case Managers.NobManager.Nob.NONE: move_from_event ( canvas, selected_items, initial_drag_state, event.x, event.y, ref transform_extra_context.snap_guide_data ); break; case Managers.NobManager.Nob.ROTATE: rotate_from_event ( canvas, selected_items, initial_drag_state, event.x, event.y, ref transform_extra_context.snap_guide_data ); break; default: scale_from_event ( canvas, selected_items, initial_drag_state, selected_nob, event.x, event.y, ref transform_extra_context.snap_guide_data ); break; } // Notify the X & Y values in the state manager. canvas.window.event_bus.reset_state_coords (); return true; } public override Object? extra_context () { return transform_extra_context; } /* * Initialize the initial drag state of an item. Return true on success. */ public static bool initialize_items_drag_state ( GLib.List selected_items, ref InitialDragState drag_state ) { if (selected_items.length () != 1) { return false; } var item = selected_items.nth_data (0); drag_state.item_x = item.coordinates.x; drag_state.item_y = item.coordinates.y; item.get_transform (out drag_state.item_transform); if (selected_items.length () == 1) { drag_state.item_width = item.size.width; drag_state.item_height = item.size.height; } else { // TODO there should probably be a nice method to get a bounding box from a list of items. } drag_state.item_scale_x_adj = 0; drag_state.item_scale_y_adj = 0; // If rotation is multiple of 90, then snap to pixel grid before scale. if (item.rotation != null && GLib.Math.fmod (item.rotation.rotation, 90) == 0) { drag_state.item_scale_x_adj = Utils.AffineTransform.fix_size (drag_state.item_x) - drag_state.item_x; drag_state.item_scale_y_adj = Utils.AffineTransform.fix_size (drag_state.item_y) - drag_state.item_y; drag_state.item_width = Utils.AffineTransform.fix_size (drag_state.item_width); drag_state.item_height = Utils.AffineTransform.fix_size (drag_state.item_height); } drag_state.rotation_center_x = (item.coordinates.x1 + item.coordinates.x2) / 2.0; drag_state.rotation_center_y = (item.coordinates.y1 + item.coordinates.y2) / 2.0; return true; } public static void move_from_event ( Akira.Lib.Canvas canvas, GLib.List selected_items, InitialDragState initial_drag_state, double event_x, double event_y, ref Akira.Lib.Managers.SnapManager.SnapGuideData guide_data ) { if (selected_items.length () != 1) { return; } // for now we only transform one item Akira.Lib.Items.CanvasItem item = selected_items.nth_data (0); // Keep reset and delta values for future adjustments. // Calculate values needed to reset to the original position. var reset_x = item.coordinates.x - initial_drag_state.item_x; var reset_y = item.coordinates.y - initial_drag_state.item_y; // Calculate the change based on the event. var delta_x = event_x - initial_drag_state.press_x; var delta_y = event_y - initial_drag_state.press_y; // Keep reset and delta values for future adjustments. // fix_size should be called right before a transform. var first_move_x = Utils.AffineTransform.fix_size (delta_x - reset_x); var first_move_y = Utils.AffineTransform.fix_size (delta_y - reset_y); Cairo.Matrix matrix; item.get_transform (out matrix); // Increment the cairo matrix coordinates so we can ignore the item's rotation. matrix.x0 += first_move_x; matrix.y0 += first_move_y; item.set_transform (matrix); // Interrupt if the user disabled the snapping or we don't have any // adjacent item to snap to. if (!settings.enable_snaps) { return; } // Make adjustment basted on snaps. // Double the sensitivity to allow for reuse of grid after snap. var sensitivity = Utils.Snapping.adjusted_sensitivity (canvas.current_scale); var snap_grid = Utils.Snapping.generate_best_snap_grid (canvas, selected_items, sensitivity); // Interrupt if we don't have any snap to use. if (snap_grid.is_empty ()) { return; } int snap_offset_x = 0; int snap_offset_y = 0; var matches = Utils.Snapping.generate_snap_matches (snap_grid, selected_items, sensitivity); // Don't force the offset translation on items. This is mostly // used when moving items from the Transform Panel where we want to show // the snapping guides but ignore the magnetic effect. if (initial_drag_state.wants_snapping) { if (matches.h_data.snap_found ()) { snap_offset_x = matches.h_data.snap_offset (); matrix.x0 += snap_offset_x; } if (matches.v_data.snap_found ()) { snap_offset_y = matches.v_data.snap_offset (); matrix.y0 += snap_offset_y; } item.set_transform (matrix); } guide_data.type = Akira.Lib.Managers.SnapManager.SnapGuideType.SELECTION; canvas.window.event_bus.update_snap_decorators (); } private static void scale_from_event ( Akira.Lib.Canvas canvas, GLib.List selected_items, InitialDragState initial_drag_state, Akira.Lib.Managers.NobManager.Nob selected_nob, double event_x, double event_y, ref Akira.Lib.Managers.SnapManager.SnapGuideData guide_data ) { if (selected_items.length () != 1) { return; } // for now we only transform one item Akira.Lib.Items.CanvasItem item = selected_items.nth_data (0); event_x = Akira.Utils.AffineTransform.fix_size (event_x); event_y = Akira.Utils.AffineTransform.fix_size (event_y); double rel_event_x = event_x; double rel_event_y = event_y; double rel_press_x = initial_drag_state.nob_x; double rel_press_y = initial_drag_state.nob_y; // Convert the coordinates from the canvas to the item so we know the real // values even if the item is rotated. canvas.convert_to_item_space (item, ref rel_event_x, ref rel_event_y); canvas.convert_to_item_space (item, ref rel_press_x, ref rel_press_y); // Calculate the change based on the event. var delta_x = rel_event_x - rel_press_x; var delta_y = rel_event_y - rel_press_y; bool ratio_locked = canvas.ctrl_is_pressed || item.size.locked; // These values will be populated. double inc_width = 0; double inc_height = 0; double inc_x = 0; double inc_y = 0; Utils.AffineTransform.calculate_size_adjustments ( selected_nob, initial_drag_state.item_width, initial_drag_state.item_height, delta_x, delta_y, initial_drag_state.item_width / initial_drag_state.item_height, ratio_locked, canvas.shift_is_pressed, initial_drag_state.item_transform, ref inc_x, ref inc_y, ref inc_width, ref inc_height ); var reset_width = item.size.width - initial_drag_state.item_width; var reset_height = item.size.height - initial_drag_state.item_height; Cairo.Matrix new_matrix; item.get_transform (out new_matrix); new_matrix.x0 = initial_drag_state.item_transform.x0 + inc_x + initial_drag_state.item_scale_x_adj; new_matrix.y0 = initial_drag_state.item_transform.y0 + inc_y + initial_drag_state.item_scale_y_adj; item.set_transform (new_matrix); Utils.AffineTransform.adjust_size (item, inc_width - reset_width, inc_height - reset_height); } private static void rotate_from_event ( Akira.Lib.Canvas canvas, GLib.List selected_items, InitialDragState initial_drag_state, double event_x, double event_y, ref Akira.Lib.Managers.SnapManager.SnapGuideData guide_data ) { if (selected_items.length () != 1) { return; } var radians = GLib.Math.atan2 ( event_x - initial_drag_state.rotation_center_x, initial_drag_state.rotation_center_y - event_y ); var new_rotation = radians * (180 / Math.PI) + 360; if (canvas.ctrl_is_pressed) { var step_num = GLib.Math.round (new_rotation / 15.0); new_rotation = 15.0 * step_num; } Akira.Lib.Items.CanvasItem item = selected_items.nth_data (0); // Cap new_rotation to the [0, 360] range. new_rotation = GLib.Math.fmod (new_rotation + 360, 360); item.rotation.rotation = Akira.Utils.AffineTransform.fix_size (new_rotation); } } Akira-0.0.16/src/Lib/Selection/000077500000000000000000000000001410625726100160535ustar00rootroot00000000000000Akira-0.0.16/src/Lib/Selection/Nob.vala000066400000000000000000000052311410625726100174370ustar00rootroot00000000000000/** * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Alessandro "Alecaddd" Castellani */ public class Akira.Lib.Selection.Nob : Goo.CanvasRect { public const double NOB_SIZE = 10; public const double LINE_WIDTH = 1; public Managers.NobManager.Nob handle_id; private double nob_size; public double center_x; public double center_y; public Nob (Goo.CanvasItem? root, Managers.NobManager.Nob _handle_id) { Object ( parent: root ); handle_id = _handle_id; can_focus = false; set_rectangle (); } /* * Returns true if position is within a circular area around center. */ public bool hit_test (double x, double y, double scale) { double xd = center_x - x; double yd = center_y - y; double dist = GLib.Math.sqrt (xd * xd + yd * yd); return (dist <= (NOB_SIZE / scale)); } public void update_state (Cairo.Matrix matrix, double new_x, double new_y, bool visible) { matrix.x0 = new_x; matrix.y0 = new_y; set_transform (matrix); center_x = new_x; center_y = new_y; var canvas = canvas as Akira.Lib.Canvas; line_width = LINE_WIDTH / canvas.current_scale; nob_size = NOB_SIZE / canvas.current_scale; set ("line-width", line_width); set ("x", - nob_size / 2.0); set ("y", - nob_size / 2.0); set ("height", nob_size); set ("width", nob_size); this.set ( "visibility", visible ? Goo.CanvasItemVisibility.VISIBLE: Goo.CanvasItemVisibility.HIDDEN ); } public void set_rectangle () { x = 0; y = 0; update_state (Cairo.Matrix.identity (), 0, 0, false); if (handle_id == Managers.NobManager.Nob.ROTATE) { set ("radius-x", nob_size); set ("radius-y", nob_size); } set ("fill-color", "#fff"); set ("stroke-color", "#41c9fd"); } } Akira-0.0.16/src/Main.vala000066400000000000000000000020751410625726100151550ustar00rootroot00000000000000/* * Copyright (c) 2019 Alecaddd (http://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Alessandro "Alecaddd" Castellani */ public static bool verbose = false; public static int main (string[] args) { verbose = "-d" in args; Environment.set_application_name (Constants.APP_NAME); Environment.set_prgname (Constants.APP_NAME); var application = new Akira.Application (); return application.run (args); } Akira-0.0.16/src/Middlewares/000077500000000000000000000000001410625726100156605ustar00rootroot00000000000000Akira-0.0.16/src/Middlewares/CoordinatesMiddleware.vala000066400000000000000000000140141410625726100227750ustar00rootroot00000000000000/** * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Alessandro "Alecaddd" Castellani */ /** * Middleware handling the currently selected objects coordinates with the Transform Panel. * This is used to guarantee correct values in the Transform Panel no matter if one or * multiple items are selected, and to always return the true items' coordinates which * are held by the GooCanvasItem. */ public class Akira.StateManagers.CoordinatesMiddleware : Object { public weak Akira.Window window { get; construct; } private weak Akira.Lib.Canvas canvas; // Store the initial coordinates of the item before the values are edited by // the user interacting with the Transform Panel fields. private double initial_x; private double initial_y; // These attributes represent only the primary X & Y coordinates of the selected shapes. // These are not the origin points of each selected shape, but only the TOP-LEFT values // of the bounding box selection. private double? _x = null; public double x { get { return _x != null ? _x : 0; } set { if (value == _x) { return; } _x = Utils.AffineTransform.fix_size (value); move_from_panel (); } } private double? _y = null; public double y { get { return _y != null ? _y : 0; } set { if (value == _y) { return; } _y = Utils.AffineTransform.fix_size (value); move_from_panel (); } } // Allow or deny updating the items position. private bool do_update = true; public CoordinatesMiddleware (Akira.Window window) { Object ( window: window ); } construct { // Get the canvas on construct as we will need to use its methods. canvas = window.main_window.main_canvas.canvas; // Initialize event listeners. window.event_bus.init_state_coords.connect (on_init_state_coords); window.event_bus.reset_state_coords.connect (on_reset_state_coords); window.event_bus.update_state_coords.connect (on_update_state_coords); } private void get_coordinates_from_items () { // Reset the selected coordinates to always get correct values. initial_x = 0; initial_y = 0; var nob_data = new Akira.Lib.Managers.NobManager.ItemNobData (); Lib.Managers.NobManager.populate_nob_bounds_from_items ( canvas.selected_bound_manager.selected_items, ref nob_data ); initial_x = nob_data.selected_x; initial_y = nob_data.selected_y; } /** * Initialize the manager coordinates with the selected items coordinates. * The coordinates change comes from a canvas action that already moved the items, * therefore we set the do_update to false to prevent updating the selected * items' Cairo Matrix. */ private void on_init_state_coords () { do_update = false; // Get the items X & Y coordinates. get_coordinates_from_items (); x = initial_x; y = initial_y; do_update = true; } /** * Update the coordinates to trigger the shapes transformation. * This action comes from an arrow keypress event from the Canvas. */ private void on_update_state_coords (double moved_x, double moved_y) { x += moved_x; y += moved_y; window.event_bus.file_edited (); } /** * Reset the coordinates to get the newly updated coordinates from the selected items. * This method is called when items are moved from the canvas, so we only need to update * the X and Y values for the Transform Panel without triggering the update_items_*(). */ private void on_reset_state_coords () { on_init_state_coords (); window.event_bus.item_value_changed (); window.event_bus.file_edited (); } /** * Update the position of all selected items. */ private void move_from_panel () { if (_x == null || _y == null || !do_update) { return; } // Get the current item X & Y coordinates before translating. get_coordinates_from_items (); // Loop through all the selected items to update their position. foreach (Lib.Items.CanvasItem item in canvas.selected_bound_manager.selected_items) { // Set the ignore_offset attribute to true to avoid the forced // respositioning of the item (magnetic offset snapping). var drag_state = new Akira.Lib.Modes.TransformMode.InitialDragState (); var tmp = new GLib.List (); tmp.append (item); if (Akira.Lib.Modes.TransformMode.initialize_items_drag_state (tmp, ref drag_state)) { drag_state.wants_snapping = false; drag_state.press_x = initial_x; drag_state.press_y = initial_y; drag_state.nob_x = initial_x; drag_state.nob_y = initial_y; var guide_data = new Akira.Lib.Managers.SnapManager.SnapGuideData (); Akira.Lib.Modes.TransformMode.move_from_event (canvas, tmp, drag_state, x, y, ref guide_data); } } window.event_bus.item_value_changed (); } } Akira-0.0.16/src/Middlewares/SizeMiddleware.vala000066400000000000000000000121231410625726100214340ustar00rootroot00000000000000/** * Copyright (c) 2021 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Alessandro "Alecaddd" Castellani */ /** * Middleware handling the currently selected objects sizes with the Transform Panel. * This is used to guarantee correct values in the Transform Panel no matter if one or * multiple items are selected, and to always return the true items' sizes which * are held by the GooCanvasItem. */ public class Akira.StateManagers.SizeMiddleware : Object { public weak Akira.Window window { get; construct; } private weak Akira.Lib.Canvas canvas; // Store the initial size of the item before the values are edited by // the user interacting with the Transform Panel fields. private double initial_width; private double initial_height; // Allow or deny updating the items size. private bool do_update = true; // These attributes represent only the primary WIDTH & HEIGHT coordinates of the selected shapes. // These are not the original sizes of each selected shape, but only the BOTTOM-RIGHT values // of the bounding box selection. private double? _width = null; public double width { get { return _width != null ? _width : 0; } set { if (value == _width) { return; } _width = Utils.AffineTransform.fix_size (value); scale_from_panel (); } } private double? _height = null; public double height { get { return _height != null ? _height : 0; } set { if (value == _height) { return; } _height = Utils.AffineTransform.fix_size (value); scale_from_panel (); } } public SizeMiddleware (Akira.Window window) { Object ( window: window ); } construct { // Get the canvas on construct as we will need to use its methods. canvas = window.main_window.main_canvas.canvas; // Initialize event listeners. window.event_bus.init_state_coords.connect (on_init_state_coords); window.event_bus.reset_state_coords.connect (on_reset_state_coords); } private void get_size_from_items () { // Reset the selected coordinates to always get correct values. initial_width = 0; initial_height = 0; var nob_data = new Akira.Lib.Managers.NobManager.ItemNobData (); Lib.Managers.NobManager.populate_nob_bounds_from_items ( canvas.selected_bound_manager.selected_items, ref nob_data ); initial_width = nob_data.bb_width; initial_height = nob_data.bb_height; } /** * Initialize the manager sizes with the selected items sizes. * The sizes change comes from a canvas action that already moved the items, * therefore we set the do_update to false to prevent updating the selected * items' Cairo Matrix. */ private void on_init_state_coords () { do_update = false; // Get the items WIDTH & HEIGHT. get_size_from_items (); width = initial_width; height = initial_height; do_update = true; } /** * Reset the sizes to get the newly updated sizes from the selected items. * This method is called when items are resized from the canvas, so we only need to update * the WIDTH & HEIGHT values for the Transform Panel without triggering the update_items_size(). */ private void on_reset_state_coords () { on_init_state_coords (); window.event_bus.item_value_changed (); window.event_bus.file_edited (); } /** * Update the size of all selected items. */ private void scale_from_panel () { if (_width == null || _height == null || !do_update) { return; } // Loop through all the selected items to update their size. foreach (Lib.Items.CanvasItem item in canvas.selected_bound_manager.selected_items) { // TODO: We're temporarily applying the exact same size to all selected items. // This will change once we implement the multi select and the ability to resize // and translate multiple items relative to their position. var delta_h = height - item.size.height; var delta_w = width - item.size.width; item.size.width += delta_w; item.size.height += delta_h; } } } Akira-0.0.16/src/Models/000077500000000000000000000000001410625726100146435ustar00rootroot00000000000000Akira-0.0.16/src/Models/ColorModel.vala000066400000000000000000000050341410625726100175510ustar00rootroot00000000000000/* * Copyright (c) 2021 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * * Akira 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 Akira. If not, see . * * Authored by: Alessandro "Alecaddd" Castellani */ /* * Model to keep track of Fills and Borders colors of an item. We use this * model to easily bind the GtkListBox UI to the Fills and Borders Components. */ public class Akira.Models.ColorModel : GLib.Object { private unowned Lib.Components.Fill? fill; private unowned Lib.Components.Border? border; public Type type; public enum Type { FILL, BORDER } public string color { owned get { return type == Type.FILL ? fill.color.to_string () : border.color.to_string (); } set { var new_rgba = Gdk.RGBA (); new_rgba.parse (value); new_rgba.alpha = (double) alpha / 255; if (type == Type.FILL) { fill.color = new_rgba; return; } border.color = new_rgba; } } public int alpha { get { return type == Type.FILL ? fill.alpha : border.alpha; } set { if (type == Type.FILL) { fill.alpha = value; return; } border.alpha = value; } } public bool hidden { get { return type == Type.FILL ? fill.hidden : border.hidden; } set { if (type == Type.FILL) { fill.hidden = value; return; } border.hidden = value; } } public int size { get { return border.size; } set { border.size = value; } } public ColorModel (Lib.Components.Fill? fill, Lib.Components.Border? border = null) { type = fill != null ? Type.FILL : Type.BORDER; this.fill = fill; this.border = border; } } Akira-0.0.16/src/Models/ExportModel.vala000066400000000000000000000022421410625726100177520ustar00rootroot00000000000000/* * Copyright (c) 2020 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Alessandro "alecaddd" Castellani */ public class Akira.Models.ExportModel : GLib.Object { public Gdk.Pixbuf pixbuf { get; set construct; } public string filename { get; set construct; } public ExportModel (Gdk.Pixbuf pixbuf, string filename) { Object ( pixbuf: pixbuf, filename: filename ); } public string to_string () { return "Filename: %s".printf (filename); } } Akira-0.0.16/src/Models/ListModel.vala000066400000000000000000000065761410625726100174220ustar00rootroot00000000000000/* * Copyright (c) 2019 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Giacomo "giacomoalbe" Alberini * Authored by: Alessandro "alecaddd" Castellani */ public class Akira.Models.ListModel : GLib.Object, GLib.ListModel { private GLib.List list; construct { list = new GLib.List (); } public uint get_n_items () { return (uint) list.length (); } public Object? get_item (uint position) { return list.nth_data (position) as Object; } public new Model get (uint index) { return list.nth_data (index); } public Type get_item_type () { return typeof (Model); } public Model? find_item (Model item) { for (var i = 0; i < list.length (); i++) { if (list.nth_data (i) == item) { return get_item (i); } } return null; } public int index (Model item) { return (int) list.index (find_item (item)); } public async void add_item (Model model_item) { list.prepend (model_item); items_changed (0, 0, 1); } public async void remove_item (Model? model) { if (model == null) { return; } var position = list.index (model); list.remove (model); items_changed (position, 1, 0); } public void swap_items (int source_index, int target_index) { // Remove item at source position var item_to_swap = remove_at (source_index); // Insert item at target position insert_at (target_index, item_to_swap); } public void insert_at (int position, Model item) { list.insert (item, position); items_changed (position, 0, 1); } public Model? remove_at (int position) { var item = list.nth_data (position); list.remove (item); items_changed (position, 1, 0); return item; } public async void clear () { list.foreach ((item) => { remove_item.begin (item); }); } public void sort (CompareFunc sort_fn) { list.sort (sort_fn); items_changed (0, list.length (), list.length ()); } public Iterator iterator () { return new Iterator (this); } public class Iterator { private int index; private int length; private ListModel model; public Iterator (ListModel model) { this.model = model; this.length = (int) model.list.length (); } public bool next () { return index < length; } public Model get () { return model.list.nth_data (this.index++); } } } Akira-0.0.16/src/Services/000077500000000000000000000000001410625726100152035ustar00rootroot00000000000000Akira-0.0.16/src/Services/ActionManager.vala000066400000000000000000000460721410625726100205710ustar00rootroot00000000000000/* * Copyright (c) 2019-2020 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Alessandro "Alecaddd" Castellani * Authored by: Ivan "isneezy" Vilanculo */ public class Akira.Services.ActionManager : Object { public weak Akira.Application app { get; construct; } public weak Akira.Window window { get; construct; } private const int PREVIEW_SIZE = 300; private const int PREVIEW_PADDING = 3; private Gtk.FileChooserNative dialog; private Gtk.Image preview_image; public SimpleActionGroup actions { get; construct; } public const string ACTION_PREFIX = "win."; public const string ACTION_NEW_WINDOW = "action_new_window"; public const string ACTION_OPEN = "action_open"; public const string ACTION_SAVE = "action_save"; public const string ACTION_SAVE_AS = "action_save_as"; public const string ACTION_LOAD_FIRST = "action_load_first"; public const string ACTION_LOAD_SECOND = "action_load_second"; public const string ACTION_LOAD_THIRD = "action_load_third"; public const string ACTION_TOGGLE_PIXEL_GRID = "action-show-pixel-grid"; public const string ACTION_PRESENTATION = "action_presentation"; public const string ACTION_PREFERENCES = "action_preferences"; public const string ACTION_EXPORT_SELECTION = "action_export_selection"; public const string ACTION_EXPORT_ARTBOARDS = "action_export_artboards"; public const string ACTION_EXPORT_GRAB = "action_export_grab"; public const string ACTION_QUIT = "action_quit"; public const string ACTION_ZOOM_IN = "action_zoom_in"; public const string ACTION_ZOOM_IN_2 = "action_zoom_in_2"; public const string ACTION_ZOOM_OUT = "action_zoom_out"; public const string ACTION_ZOOM_RESET = "action_zoom_reset"; public const string ACTION_MOVE_UP = "action_move_up"; public const string ACTION_MOVE_DOWN = "action_move_down"; public const string ACTION_MOVE_TOP = "action_move_top"; public const string ACTION_MOVE_BOTTOM = "action_move_bottom"; public const string ACTION_ARTBOARD_TOOL = "action_artboard_tool"; public const string ACTION_RECT_TOOL = "action_rect_tool"; public const string ACTION_ELLIPSE_TOOL = "action_ellipse_tool"; public const string ACTION_TEXT_TOOL = "action_text_tool"; public const string ACTION_IMAGE_TOOL = "action_image_tool"; public const string ACTION_DELETE = "action_delete"; public const string ACTION_FLIP_H = "action_flip_h"; public const string ACTION_FLIP_V = "action_flip_v"; public const string ACTION_ESCAPE = "action_escape"; public const string ACTION_SHORTCUTS = "action_shortcuts"; public const string ACTION_PICK_COLOR = "action_pick_color"; public static Gee.MultiMap action_accelerators = new Gee.HashMultiMap (); public static Gee.MultiMap typing_accelerators = new Gee.HashMultiMap (); private const ActionEntry[] ACTION_ENTRIES = { { ACTION_NEW_WINDOW, action_new_window }, { ACTION_OPEN, action_open }, { ACTION_SAVE, action_save }, { ACTION_SAVE_AS, action_save_as }, { ACTION_LOAD_FIRST, action_load_first }, { ACTION_LOAD_SECOND, action_load_second }, { ACTION_LOAD_THIRD, action_load_third }, { ACTION_TOGGLE_PIXEL_GRID, action_toggle_pixel_grid }, { ACTION_PRESENTATION, action_presentation }, { ACTION_PREFERENCES, action_preferences }, { ACTION_EXPORT_SELECTION, action_export_selection }, { ACTION_EXPORT_ARTBOARDS, action_export_artboards }, { ACTION_EXPORT_GRAB, action_export_grab }, { ACTION_QUIT, action_quit }, { ACTION_ZOOM_IN, action_zoom_in }, { ACTION_ZOOM_IN_2, action_zoom_in_2 }, { ACTION_ZOOM_OUT, action_zoom_out }, { ACTION_MOVE_UP, action_move_up }, { ACTION_MOVE_DOWN, action_move_down }, { ACTION_MOVE_TOP, action_move_top }, { ACTION_MOVE_BOTTOM, action_move_bottom }, { ACTION_ZOOM_RESET, action_zoom_reset }, { ACTION_ARTBOARD_TOOL, action_artboard_tool }, { ACTION_RECT_TOOL, action_rect_tool }, { ACTION_ELLIPSE_TOOL, action_ellipse_tool }, { ACTION_TEXT_TOOL, action_text_tool }, { ACTION_IMAGE_TOOL, action_image_tool }, { ACTION_DELETE, action_delete }, { ACTION_FLIP_H, action_flip_h }, { ACTION_FLIP_V, action_flip_v }, { ACTION_ESCAPE, action_escape }, { ACTION_SHORTCUTS, action_shortcuts }, { ACTION_PICK_COLOR, action_pick_color }, }; public ActionManager (Akira.Application akira_app, Akira.Window window) { Object ( app: akira_app, window: window ); } static construct { action_accelerators.set (ACTION_NEW_WINDOW, "n"); action_accelerators.set (ACTION_OPEN, "o"); action_accelerators.set (ACTION_SAVE, "s"); action_accelerators.set (ACTION_SAVE_AS, "s"); action_accelerators.set (ACTION_LOAD_FIRST, "1"); action_accelerators.set (ACTION_LOAD_SECOND, "2"); action_accelerators.set (ACTION_LOAD_THIRD, "3"); action_accelerators.set (ACTION_PRESENTATION, "period"); action_accelerators.set (ACTION_PREFERENCES, "comma"); action_accelerators.set (ACTION_EXPORT_SELECTION, "e"); action_accelerators.set (ACTION_EXPORT_ARTBOARDS, "a"); action_accelerators.set (ACTION_EXPORT_GRAB, "g"); action_accelerators.set (ACTION_QUIT, "q"); action_accelerators.set (ACTION_ZOOM_IN_2, "equal"); action_accelerators.set (ACTION_ZOOM_IN, "plus"); action_accelerators.set (ACTION_ZOOM_OUT, "minus"); action_accelerators.set (ACTION_ZOOM_RESET, "0"); action_accelerators.set (ACTION_MOVE_UP, "Up"); action_accelerators.set (ACTION_MOVE_DOWN, "Down"); action_accelerators.set (ACTION_MOVE_TOP, "Up"); action_accelerators.set (ACTION_MOVE_BOTTOM, "Down"); action_accelerators.set (ACTION_FLIP_H, "bracketleft"); action_accelerators.set (ACTION_FLIP_V, "bracketright"); action_accelerators.set (ACTION_SHORTCUTS, "F1"); action_accelerators.set (ACTION_PICK_COLOR, "c"); typing_accelerators.set (ACTION_ESCAPE, "Escape"); typing_accelerators.set (ACTION_ARTBOARD_TOOL, "a"); typing_accelerators.set (ACTION_RECT_TOOL, "r"); typing_accelerators.set (ACTION_ELLIPSE_TOOL, "e"); typing_accelerators.set (ACTION_TEXT_TOOL, "t"); typing_accelerators.set (ACTION_IMAGE_TOOL, "i"); typing_accelerators.set (ACTION_DELETE, "Delete"); typing_accelerators.set (ACTION_DELETE, "BackSpace"); typing_accelerators.set (ACTION_TOGGLE_PIXEL_GRID, "Tab"); } construct { actions = new SimpleActionGroup (); actions.add_action_entries (ACTION_ENTRIES, this); window.insert_action_group ("win", actions); var iter = action_accelerators.map_iterator (); while (iter.next ()) { app.set_accels_for_action (ACTION_PREFIX + iter.get_key (), { iter.get_value () }); } enable_typing_accels (); window.event_bus.disconnect_typing_accel.connect (disable_typing_accels); window.event_bus.connect_typing_accel.connect (enable_typing_accels); } // Temporarily disable all the accelerators that might interfere with input fields. private void disable_typing_accels () { var iter = typing_accelerators.map_iterator (); while (iter.next ()) { app.set_accels_for_action (ACTION_PREFIX + iter.get_key (), {}); } } // Enable all the accelerators that might interfere with input fields. private void enable_typing_accels () { var iter = typing_accelerators.map_iterator (); while (iter.next ()) { app.set_accels_for_action (ACTION_PREFIX + iter.get_key (), { iter.get_value () }); } } private void action_quit () { window.before_destroy (); } private void action_presentation () { window.event_bus.toggle_presentation_mode (); } private void action_new_window () { app.new_window (); } private void action_open () { window.file_manager.open_file (); } private void action_save () { window.file_manager.save_file (); } private void action_save_as () { window.file_manager.save_file_as (); } public void action_load_first () { if (settings.recently_opened.length == 0 || settings.recently_opened[0] == null) { window.event_bus.canvas_notification (_("No recently opened file available!")); return; } var file = File.new_for_path (settings.recently_opened[0]); if (!file.query_exists ()) { window.event_bus.canvas_notification ( _("Unable to open file at '%s'").printf (settings.recently_opened[0]) ); return; } File[] files = {}; files += file; window.app.open (files, ""); } private void action_load_second () { if (settings.recently_opened.length < 1 || settings.recently_opened[1] == null) { window.event_bus.canvas_notification (_("No second most recently opened file available!")); return; } var file = File.new_for_path (settings.recently_opened[1]); if (!file.query_exists ()) { window.event_bus.canvas_notification ( _("Unable to open file at '%s'").printf (settings.recently_opened[1]) ); return; } File[] files = {}; files += file; window.app.open (files, ""); } private void action_load_third () { if (settings.recently_opened.length < 2 || settings.recently_opened[2] == null) { window.event_bus.canvas_notification (_("No third most recently opened file available!")); return; } var file = File.new_for_path (settings.recently_opened[2]); if (!file.query_exists ()) { window.event_bus.canvas_notification ( _("Unable to open file at '%s'").printf (settings.recently_opened[2]) ); return; } File[] files = {}; files += file; window.app.open (files, ""); } private void action_toggle_pixel_grid () { window.event_bus.toggle_pixel_grid (); } private void action_preferences () { var settings_dialog = new Akira.Dialogs.SettingsDialog (window); settings_dialog.show_all (); settings_dialog.present (); settings_dialog.close.connect (() => { window.event_bus.set_focus_on_canvas (); }); } private void action_export_selection () { weak Akira.Lib.Canvas canvas = window.main_window.main_canvas.canvas; if (canvas.selected_bound_manager.selected_items.length () == 0) { // Check if an element is currently selected. window.event_bus.canvas_notification (_("Nothing selected to export!")); return; } canvas.export_manager.create_selection_snapshot (); } private void action_export_artboards () { // Check if at least an artboard is present. window.event_bus.canvas_notification (_("Export of Artboards currently unavailable…sorry 😑️")); // TODO: Trigger artboards pixbuf generation. } private void action_export_grab () { weak Akira.Lib.Canvas canvas = window.main_window.main_canvas.canvas; canvas.start_export_area_selection (); } private void action_zoom_in () { window.event_bus.update_scale (0.1); } private void action_zoom_in_2 () { action_zoom_in (); } private void action_zoom_out () { window.event_bus.update_scale (-0.1); } private void action_zoom_reset () { window.event_bus.set_scale (1); } private void action_move_up () { window.event_bus.change_z_selected (true, false); } private void action_move_down () { window.event_bus.change_z_selected (false, false); } private void action_move_top () { window.event_bus.change_z_selected (true, true); } private void action_move_bottom () { window.event_bus.change_z_selected (false, true); } private void action_artboard_tool () { window.event_bus.insert_item ("artboard"); } private void action_rect_tool () { window.event_bus.insert_item ("rectangle"); } // Delete the currently selected items. private void action_delete () { window.main_window.main_canvas.canvas.selected_bound_manager.delete_selection (); } private void action_flip_h () { window.event_bus.flip_item (); } private void action_flip_v () { window.event_bus.flip_item (true); } private void action_ellipse_tool () { window.event_bus.insert_item ("ellipse"); } private void action_text_tool () { window.event_bus.insert_item ("text"); } private void action_image_tool () { dialog = new Gtk.FileChooserNative ( _("Choose image file"), window, Gtk.FileChooserAction.OPEN, _("Select"), _("Close")); preview_image = new Gtk.Image (); dialog.preview_widget = preview_image; dialog.update_preview.connect (on_update_preview); dialog.select_multiple = true; dialog.response.connect ((response_id) => on_choose_image_response (dialog, response_id)); dialog.show (); } private void on_update_preview () { string? filename = dialog.get_preview_filename (); if (filename == null) { dialog.set_preview_widget_active (false); return; } // Read the image format data first. int width = 0; int height = 0; Gdk.PixbufFormat? format = Gdk.Pixbuf.get_file_info (filename, out width, out height); if (format == null) { dialog.set_preview_widget_active (false); return; } // If the image is too big, resize it. Gdk.Pixbuf pixbuf; try { pixbuf = new Gdk.Pixbuf.from_file_at_scale (filename, PREVIEW_SIZE, PREVIEW_SIZE, true); } catch (Error e) { dialog.set_preview_widget_active (false); return; } if (pixbuf == null) { dialog.set_preview_widget_active (false); return; } pixbuf = pixbuf.apply_embedded_orientation (); // Distribute the extra space around the image. int extra_space = PREVIEW_SIZE - pixbuf.width; int smaller_half = extra_space / 2; int larger_half = extra_space - smaller_half; // Pad the image manually and avoids rounding errors. preview_image.set_margin_start (PREVIEW_PADDING + smaller_half); preview_image.set_margin_end (PREVIEW_PADDING + larger_half); // Show the preview. preview_image.set_from_pixbuf (pixbuf); dialog.set_preview_widget_active (true); } private void on_choose_image_response (Gtk.FileChooserNative dialog, int response_id) { switch (response_id) { case Gtk.ResponseType.ACCEPT: case Gtk.ResponseType.OK: SList files = dialog.get_files (); files.@foreach ((file) => { if (!Akira.Utils.Image.is_valid_image (file)) { window.event_bus.canvas_notification ( _("Error! .%s files are not supported!" ).printf (Akira.Utils.Image.get_extension (file))); return; } var manager = new Akira.Lib.Managers.ImageManager (file, files.index (file)); window.items_manager.insert_image (manager); }); break; } dialog.destroy (); } private void action_escape () { window.event_bus.request_escape (); // If the layout is hidden, allow users to easily get out of presentation mode // when they press Escape. if (!window.headerbar.toggled) { action_presentation (); } } private void action_shortcuts () { var dialog = new Akira.Dialogs.ShortcutsDialog (window); dialog.show_all (); dialog.present (); } private void action_pick_color () { weak Akira.Lib.Canvas canvas = window.main_window.main_canvas.canvas; // Interrupt if no item is selected. if (canvas.selected_bound_manager.selected_items.length () == 0) { return; } // Hide the ghost bound manager. canvas.toggle_item_ghost (false); bool is_holding_shift = false; var color_picker = new Akira.Utils.ColorPicker (); color_picker.show_all (); color_picker.key_pressed.connect (e => { is_holding_shift = e.keyval == Gdk.Key.Shift_L; }); color_picker.key_released.connect (e => { is_holding_shift = e.keyval == Gdk.Key.Shift_L; }); color_picker.cancelled.connect (() => { color_picker.close (); }); color_picker.picked.connect (color => { foreach (var item in canvas.selected_bound_manager.selected_items) { // Ignore the item if it doesn't have a fills or border component // based on the shift key pressed by the user. if ((item.fills == null && !is_holding_shift) || (item.borders == null && is_holding_shift)) { continue; } if (is_holding_shift) { item.borders.update_color_from_action (color); continue; } item.fills.update_color_from_action (color); } color_picker.close (); // Force a UI reload of the fills and borders panel since some items // had their properties changed. canvas.window.event_bus.selected_items_list_changed (canvas.selected_bound_manager.selected_items); }); } public static void action_from_group (string action_name, ActionGroup? action_group) { action_group.activate_action (action_name, null); } } Akira-0.0.16/src/Services/EventBus.vala000066400000000000000000000073261410625726100176130ustar00rootroot00000000000000/* * Copyright (c) 2019-2020 Alecaddd (https://alecaddd.com) * * 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 * * Authored by: Giacomo "giacomoalbe" Alberini * Authored by: Alessandro "alecaddd" Castellani */ public class Akira.Services.EventBus : Object { // File signals. public signal void file_edited (); public signal void file_saved (string? file_name); public signal void update_recent_files_list (); // Layout signals. public signal void change_sensitivity (string type); public signal void request_widget_redraw (); public signal void change_theme (); public signal void toggle_presentation_mode (); // Canvas signals. public signal void coordinate_change (double x, double y); public signal void insert_item (string type); public signal void item_inserted (); public signal void move_item_from_canvas (Gdk.EventKey event); public signal void request_escape (); public signal void set_focus_on_canvas (); public signal void update_nob_size (); public signal void update_scale (double scale); public signal void set_scale (double scale); public signal void zoom (); public signal void canvas_notification (string message); public signal void hide_select_effect (); public signal void show_select_effect (); public signal void toggle_pixel_grid (); public signal void update_pixel_grid (); public signal void update_snaps_color (); public signal void update_snap_decorators (); // Options panel signals. public signal void align_items (string align_action); public signal void init_state_coords (); public signal void reset_state_coords (); public signal void update_state_coords (double moved_x, double moved_y); public signal void item_value_changed (); // Item signals. public signal void change_z_selected (bool raise, bool total); public signal void flip_item (bool vertical = false); public signal void request_add_item_to_selection (Lib.Items.CanvasItem item); public signal void request_delete_item (Lib.Items.CanvasItem item); public signal void selected_items_changed (List selected_items); public signal void selected_items_list_changed (List selected_items); public signal void z_selected_changed (); public signal void detect_artboard_change (); public signal void detect_image_size_change (); // Layers panel signals. public signal void hover_over_item (Lib.Items.CanvasItem? item); public signal void hover_over_layer (Lib.Items.CanvasItem? item); public signal void item_deleted (Lib.Items.CanvasItem item); public signal void item_locked (Lib.Items.CanvasItem item); // Others. public signal void disconnect_typing_accel (); public signal void connect_typing_accel (); // Export signals. public signal void export_preview (string message); public signal void preview_completed (); public signal void exporting (string message); public signal void export_completed (); } Akira-0.0.16/src/Services/Settings.vala000066400000000000000000000123351410625726100176540ustar00rootroot00000000000000/* * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Alessandro "Alecaddd" Castellani * Bilal Elmoussaoui */ public class Akira.Services.Settings : GLib.Settings { // Main window settings. public string version { owned get { return get_string ("version"); } set { set_string ("version", value); } } public int pos_x { get { return get_int ("pos-x"); } set { set_int ("pos-x", value); } } public int pos_y { get { return get_int ("pos-y"); } set { set_int ("pos-y", value); } } public int window_width { get { return get_int ("window-width"); } set { set_int ("window-width", value); } } public int window_height { get { return get_int ("window-height"); } set { set_int ("window-height", value); } } public int right_paned { get { return get_int ("right-paned"); } set { set_int ("right-paned", value); } } public int left_paned { get { return get_int ("left-paned"); } set { set_int ("left-paned", value); } } // Theme settings. public bool dark_theme { get { return get_boolean ("dark-theme"); } set { set_boolean ("dark-theme", value); } } public bool show_label { get { return get_boolean ("show-label"); } set { set_boolean ("show-label", value); } } public bool use_symbolic { get { return get_boolean ("use-symbolic"); } set { set_boolean ("use-symbolic", value); } } // Default canvas settings. public string grid_color { owned get { return get_string ("grid-color"); } set { set_string ("grid-color", value); } } public bool enable_snaps { get { return get_boolean ("enable-snaps"); } set { set_boolean ("enable-snaps", value); } } public string snaps_color { owned get { return get_string ("snaps-color"); } set { set_string ("snaps-color", value); } } public int snaps_sensitivity { get { return get_int ("snaps-sensitivity"); } set { set_int ("snaps-sensitivity", value); } } // Default shape settings. public string fill_color { owned get { return get_string ("fill-color"); } set { set_string ("fill-color", value); } } public bool set_border { get { return get_boolean ("set-border"); } set { set_boolean ("set-border", value); } } public int border_size { get { return get_int ("border-size"); } set { set_int ("border-size", value); } } public string border_color { owned get { return get_string ("border-color"); } set { set_string ("border-color", value); } } // File settings. public bool open_quick { get { return get_boolean ("open-quick"); } set { set_boolean ("open-quick", value); } } public string[] recently_opened { owned get { return get_strv ("recently-opened"); } set { set_strv ("recently-opened", value); } } // Export Settings. public string export_folder { owned get { return get_string ("export-folder"); } set { set_string ("export-folder", value); } } public int export_width { get { return get_int ("export-width"); } set { set_int ("export-width", value); } } public int export_height { get { return get_int ("export-height"); } set { set_int ("export-height", value); } } public int export_paned { get { return get_int ("export-paned"); } set { set_int ("export-paned", value); } } public int export_quality { get { return get_int ("export-quality"); } set { set_int ("export-quality", value); } } public int export_compression { get { return get_int ("export-compression"); } set { set_int ("export-compression", value); } } public string export_format { owned get { return get_string ("export-format"); } set { set_string ("export-format", value); } } public int export_scale { get { return get_int ("export-scale"); } set { set_int ("export-scale", value); } } public bool export_alpha { get { return get_boolean ("export-alpha"); } set { set_boolean ("export-alpha", value); } } // Colors library. public string[] global_colors { owned get { return get_strv ("global-colors"); } set { set_strv ("global-colors", value); } } public Settings () { Object (schema_id: Constants.APP_ID); } } Akira-0.0.16/src/Utils/000077500000000000000000000000001410625726100145205ustar00rootroot00000000000000Akira-0.0.16/src/Utils/AffineTransform.vala000066400000000000000000000237561410625726100204660ustar00rootroot00000000000000/** * Copyright (c) 2020-2021 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Giacomo "giacomoalbe" Alberini * Authored by: Alessandro "Alecaddd" Castellani */ using Akira.Lib.Items; using Akira.Lib.Managers; public class Akira.Utils.AffineTransform : Object { private const int MIN_SIZE = 1; private const int MIN_POS = 10; /** * Calculate adjustments necessary for a nob resize operation. All inputs * should have already been transformed to the correct space. */ public static void calculate_size_adjustments ( NobManager.Nob nob, double item_width, double item_height, double delta_x, double delta_y, double size_ratio, bool ratio_locked, bool symmetric, Cairo.Matrix transform, ref double inc_x, ref double inc_y, ref double inc_width, ref double inc_height ) { double local_x_adj = 0.0; double local_y_adj = 0.0; double perm_x_adj = 0.0; double perm_y_adj = 0.0; double perm_w_adj = 0; double perm_h_adj = 0; nob = correct_nob ( nob, item_width, item_height, symmetric, ref delta_x, ref delta_y, ref perm_x_adj, ref perm_y_adj, ref perm_w_adj, ref perm_h_adj ); double symmetry_offset_x = 0; double symmetry_offset_y = 0; // Handle vertical adjustment. if (NobManager.is_top_nob (nob)) { inc_height = fix_size (-delta_y); local_y_adj = -inc_height; if (symmetric) { inc_height *= 2; } } else if (NobManager.is_bot_nob (nob)) { inc_height = fix_size (inc_height + delta_y); if (symmetric) { symmetry_offset_y = -delta_y; local_y_adj = symmetry_offset_y; inc_height += delta_y; } } // Handle horizontal adjustment. if (NobManager.is_left_nob (nob)) { inc_width = fix_size (inc_width - delta_x); local_x_adj = -inc_width; if (symmetric) { inc_width *= 2; } } else if (NobManager.is_right_nob (nob)) { inc_width = fix_size (delta_x); if (symmetric) { symmetry_offset_x = -delta_x; local_x_adj = symmetry_offset_x; inc_width += delta_x; } } if (ratio_locked) { item_width += perm_w_adj; item_height += perm_h_adj; bool pure_v = (nob == NobManager.Nob.TOP_CENTER || nob == NobManager.Nob.BOTTOM_CENTER); bool pure_h = (nob == NobManager.Nob.RIGHT_CENTER || nob == NobManager.Nob.LEFT_CENTER); if (pure_v || (!pure_h && (item_width + inc_width) / (item_height + inc_height) < size_ratio)) { inc_width = fix_size ((inc_height + perm_h_adj) * size_ratio - perm_w_adj); if (symmetric) { local_x_adj = -fix_size (inc_width / 2.0); } else if (nob == NobManager.Nob.TOP_LEFT || nob == NobManager.Nob.BOTTOM_LEFT) { local_x_adj = -inc_width; } else if (pure_v) { local_x_adj = - fix_size (inc_width / 2.0); } } else if (!pure_v) { inc_height = fix_size ((inc_width + perm_w_adj) / size_ratio - perm_h_adj); if (symmetric) { local_y_adj = -fix_size (inc_height / 2.0); } else if (nob == NobManager.Nob.TOP_LEFT || nob == NobManager.Nob.TOP_RIGHT) { local_y_adj = -inc_height; } else if (pure_h) { local_y_adj = - fix_size (inc_height / 2.0); } } } apply_transform_to_adjustment ( transform, local_x_adj + perm_x_adj, local_y_adj - perm_y_adj, ref inc_x, ref inc_y ); inc_width += perm_w_adj; inc_height += perm_h_adj; } /** * Corrects which nob should be used for scaling depending on the delta change of the drag. * The nob will be flipped in the vertical and horizontal directions if needed, and * the necessary adjustments to delta_x, delta_y and other adjustments will be populated. * * h_flip will be true if a horizontal flip is required. * v_flip will be true if a vertical flip is required. * delta_x and delta_y are the delta positions from the start of the drag to the current position. * perm_{x,y}_adj are permanent translation adjustments required on the bounding box. * perm_{h,w}_adj are permanent scaling adjustments required on the bounding box. * both _adj adjustments are in the items' local coordinates. */ private static NobManager.Nob correct_nob ( NobManager.Nob nob, double item_width, double item_height, bool symmetric, ref double delta_x, ref double delta_y, ref double perm_x_adj, ref double perm_y_adj, ref double perm_w_adj, ref double perm_h_adj ) { var height_to_check = symmetric ? item_height / 2.0 : item_height; var width_to_check = symmetric ? item_width / 2.0 : item_width; if (NobManager.is_top_nob (nob)) { if (fix_size (height_to_check - delta_y) == 0) { delta_y -= 1; } else if (height_to_check - delta_y < 0) { delta_y -= height_to_check; perm_y_adj = -item_height + (item_height - height_to_check); perm_h_adj = -item_height; if (nob == NobManager.Nob.TOP_LEFT) { nob = NobManager.Nob.BOTTOM_LEFT; } else if (nob == NobManager.Nob.TOP_CENTER) { // Nothing more to do. return NobManager.Nob.BOTTOM_CENTER; } else if (nob == NobManager.Nob.TOP_RIGHT) { nob = NobManager.Nob.BOTTOM_RIGHT; } } } else if (NobManager.is_bot_nob (nob)) { if (fix_size (height_to_check + delta_y) == 0) { delta_y += 1; } else if (height_to_check + delta_y < 0) { delta_y += height_to_check; perm_y_adj = - (item_height - height_to_check); perm_h_adj = -item_height; if (nob == NobManager.Nob.BOTTOM_LEFT) { nob = NobManager.Nob.TOP_LEFT; } else if (nob == NobManager.Nob.BOTTOM_CENTER) { // Nothing more to do. return NobManager.Nob.TOP_CENTER; } else if (nob == NobManager.Nob.BOTTOM_RIGHT) { nob = NobManager.Nob.TOP_RIGHT; } } } if (NobManager.is_left_nob (nob)) { if (fix_size (width_to_check - delta_x) == 0) { delta_x -= 1; } else if (width_to_check - delta_x < 0) { delta_x -= width_to_check; perm_x_adj = item_width - (item_width - width_to_check); perm_w_adj = -item_width; if (nob == NobManager.Nob.TOP_LEFT) { nob = NobManager.Nob.TOP_RIGHT; } else if (nob == NobManager.Nob.LEFT_CENTER) { nob = NobManager.Nob.RIGHT_CENTER; } else if (nob == NobManager.Nob.BOTTOM_LEFT) { nob = NobManager.Nob.BOTTOM_RIGHT; } } } else if (NobManager.is_right_nob (nob)) { if (fix_size (width_to_check + delta_x) == 0) { delta_x += 1; } else if (width_to_check + delta_x < 0) { delta_x += width_to_check; perm_x_adj = (item_width - width_to_check); perm_w_adj = -item_width; if (nob == NobManager.Nob.TOP_RIGHT) { nob = NobManager.Nob.TOP_LEFT; } else if (nob == NobManager.Nob.RIGHT_CENTER) { nob = NobManager.Nob.LEFT_CENTER; } else if (nob == NobManager.Nob.BOTTOM_RIGHT) { nob = NobManager.Nob.BOTTOM_LEFT; } } } return nob; } /** * Apply transform to a translation adjustment, and adjust the increment with it. */ private static void apply_transform_to_adjustment ( Cairo.Matrix transform, double adj_x, double adj_y, ref double inc_x, ref double inc_y ) { transform.transform_distance (ref adj_x, ref adj_y); inc_x += adj_x; inc_y += adj_y; } public static void adjust_size (Lib.Items.CanvasItem item, double adj_x, double adj_y) { var new_width = item.size.width + adj_x; var new_height = item.size.height + adj_y; // Prevent accidental negative values. if (new_width > 0) { item.size.width = new_width; } if (new_height > 0) { item.size.height = new_height; } } public static double fix_size (double size) { return GLib.Math.round (size); } public static double deg_to_rad (double deg) { return deg * Math.PI / 180.0; } } Akira-0.0.16/src/Utils/BlendingMode.vala000066400000000000000000000034501410625726100177160ustar00rootroot00000000000000/* * Copyright (c) 2019 Alecaddd (http://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Giacomo "giacomoalbe" Alberini */ public enum Akira.Utils.BlendingMode { NORMAL, MULTIPLY, OVERLAY, SOFT_LIGHT, HARD_LIGHT, LIGHTEN, DARKEN, SCREEN, DIFFERENCE, LUMINOSITY, HUE; public static BlendingMode[] all () { return { NORMAL, MULTIPLY, OVERLAY, SOFT_LIGHT, HARD_LIGHT, LIGHTEN, DARKEN, SCREEN, DIFFERENCE, LUMINOSITY, HUE }; } public string get_name () { var blending_mode_tokens = this .to_string () .split ("_"); // Get everything but BLENDING_MODE blending_mode_tokens = blending_mode_tokens[4:blending_mode_tokens.length]; var formatted_blending_mode = ""; foreach (var elem in blending_mode_tokens) { elem = elem[0].toupper ().to_string () + elem[1:elem.length].down (); formatted_blending_mode += elem; } return formatted_blending_mode; } } Akira-0.0.16/src/Utils/Color.vala000066400000000000000000000076321410625726100164530ustar00rootroot00000000000000/** * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Giacomo "giacomoalbe" Alberini */ /** * Helper object class containing all static methods for RGBA manipulation. */ public class Akira.Utils.Color : Object { public static string rgba_to_hex (string rgba_string) { var rgba = Gdk.RGBA (); rgba.parse (rgba_string); return rgba_to_hex_string (rgba); } public static string rgba_to_hex_string (Gdk.RGBA rgba) { return "#%02x%02x%02x".printf ( (int) (rgba.red * 255), (int) (rgba.green * 255), (int) (rgba.blue * 255) ); } public static Gdk.RGBA hex_to_rgba (string hex) { var rgba = Gdk.RGBA (); rgba.parse (hex); return rgba; } public static bool is_valid_hex (string hex) { if (hex == "") { return false; } // Interrupt if there is no '#' in the hex value. This prevents the app // from crashing when the user deletes the '#' already present in a // valid hex value. if (!hex.contains ("#")) { return false; } var hex_values = hex.split ("#") [1]; if (hex_values.length != 3 && hex_values.length != 6) { return false; } // Since validation is done inside the insert-text // we can assume that, if it's arrived here // the content is only 0-9A-F return true; } public static uint rgba_to_uint (Gdk.RGBA rgba) { uint uint_rgba = 0; uint_rgba |= ((uint) (rgba.red * 255)) << 24; uint_rgba |= ((uint) (rgba.green * 255)) << 16; uint_rgba |= ((uint) (rgba.blue * 255)) << 8; uint_rgba |= ((uint) (rgba.alpha * 255)); return uint_rgba; } public static Gdk.RGBA blend_colors (Gdk.RGBA base_color, Gdk.RGBA added_color) { // If the newly added color alpha is 0 we don't need to do any color mixing // as the added color won't alter the base color. if (added_color.alpha == 0.0) { return base_color; } // If the newly added color alpha is 1 or the base color alpha is 0 // we don't need to do any color mixing, as the added color will be // the only one visible. if (added_color.alpha == 1.0 || base_color.alpha == 0) { return added_color; } // Simple blend using Alpha channels. In the future we will support // different blending modes. double alpha = 1 - (1 - added_color.alpha) * (1 - base_color.alpha); double ar1 = added_color.alpha / alpha; double ar2 = (1 - added_color.alpha) / alpha; double red = added_color.red * ar1 + base_color.red * base_color.alpha * ar2; double green = added_color.green * ar1 + base_color.green * base_color.alpha * ar2; double blue = added_color.blue * ar1 + base_color.blue * base_color.alpha * ar2; var rgba = Gdk.RGBA (); rgba.alpha = alpha; rgba.red = red; rgba.green = green; rgba.blue = blue; return rgba; } public static uint color_string_to_uint (string color) { var rgba = Gdk.RGBA (); rgba.parse (color); return rgba_to_uint (rgba); } } Akira-0.0.16/src/Utils/ColorPicker.vala000066400000000000000000000271731410625726100176130ustar00rootroot00000000000000/* * Copyright (c) 2020 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Ivan "isneezy" Vilanculo * Ported from: https://github.com/ColorPicker/RonnyDo */ public class Akira.Utils.ColorPicker : Gtk.Window { public signal void picked (Gdk.RGBA color); public signal void cancelled (); public signal void moved (Gdk.RGBA color); public signal void key_pressed (Gdk.EventKey e); public signal void key_released (Gdk.EventKey e); const string DARK_BORDER_COLOR_STRING = "#333333"; private Gdk.RGBA dark_border_color = Gdk.RGBA (); const string BRIGHT_BORDER_COLOR_STRING = "#FFFFFF"; private Gdk.RGBA bright_border_color = Gdk.RGBA (); // 1. Snapsize is the amount of pixel going to be magnified by the zoomlevel. // 2. The snapsize must be odd to have a 1px magnifier center. // 3. Asure that snapsize*max_zoomlevel+shadow_width*2 is smaller than 2 * get_screen ().get_display ().get_maximal_cursor_size() // Valid: snapsize = 31, max_zoomlevel = 7, shadow_width = 15 --> 247px // get_maximal_cursor_size = 128 --> 256px // Otherwise the cursor starts to flicker. See https://github.com/stuartlangridge/ColourPicker/issues/6#issuecomment-277972290 // and https://github.com/RonnyDo/ColorPicker/issues/19 int snapsize = 31; int min_zoomlevel = 2; int max_zoomlevel = 7; int zoomlevel = 6; int shadow_width = 15; private Gdk.Cursor magnifier = null; construct { app_paintable = true; decorated = false; resizable = false; set_visual (get_screen ().get_rgba_visual ()); type = Gtk.WindowType.POPUP; } public ColorPicker () { stick (); set_resizable (true); set_deletable (false); set_skip_taskbar_hint (true); set_skip_pager_hint (true); set_keep_above (true); dark_border_color.parse (DARK_BORDER_COLOR_STRING); bright_border_color.parse (BRIGHT_BORDER_COLOR_STRING); // TODO remove the zoom level restauration if we do not need it // restore zoomlevel // if (settings.zoomlevel >= min_zoomlevel && settings.zoomlevel <= max_zoomlevel) { // zoomlevel = settings.zoomlevel; // } var display = Gdk.Display.get_default (); Gdk.Monitor monitor = display.get_primary_monitor (); Gdk.Rectangle geom = monitor.get_geometry (); set_default_size (geom.width, geom.height); } public override bool button_release_event (Gdk.EventButton e) { // button_1 is left mouse button if (e.button == 1) { Gdk.RGBA color = get_color_at ((int) e.x_root, (int) e.y_root); picked (color); // button_3 is right mouse button } else if (e.button == 3) { cancelled (); } return true; } public override bool draw (Cairo.Context cr) { return false; } public override bool motion_notify_event (Gdk.EventMotion e) { Gdk.RGBA color = get_color_at ((int) e.x_root, (int) e.y_root); moved (color); set_magnifier_cursor (); return true; } public override bool scroll_event (Gdk.EventScroll e) { switch (e.direction) { case Gdk.ScrollDirection.UP: if (zoomlevel < max_zoomlevel) { zoomlevel++; } set_magnifier_cursor (); break; case Gdk.ScrollDirection.DOWN: if (zoomlevel > min_zoomlevel) { zoomlevel--; } set_magnifier_cursor (); break; default: break; } return true; } public void set_magnifier_cursor () { var manager = Gdk.Display.get_default ().get_default_seat (); // get cursor position int px, py; get_window ().get_device_position (manager.get_pointer (), out px, out py, null); var radius = snapsize * zoomlevel / 2; // get a small area (snap) meant to be zoomed var snapped_pixbuf = snap (px - snapsize / 2, py - snapsize / 2, snapsize, snapsize); // Zoom that screenshot up, and grab a snapsize-sized piece from the middle var scaled_pb = snapped_pixbuf.scale_simple ( snapsize * zoomlevel + shadow_width * 2 , snapsize * zoomlevel + shadow_width * 2 , Gdk.InterpType.NEAREST ); // Create the base surface for our cursor var base_surface = new Cairo.ImageSurface ( Cairo.Format.ARGB32, snapsize * zoomlevel + shadow_width * 2 , snapsize * zoomlevel + shadow_width * 2 ); var base_context = new Cairo.Context (base_surface); // Create the circular path on our base surface base_context.arc (radius + shadow_width, radius + shadow_width, radius, 0, 2 * Math.PI); // Paste in the screenshot Gdk.cairo_set_source_pixbuf (base_context, scaled_pb, 0, 0); // Clip to that circular path, keeping the path around for later, and paint the pasted screenshot base_context.save (); base_context.clip_preserve (); base_context.paint (); base_context.restore (); // Draw a shadow as outside magnifier border double shadow_alpha = 0.6; base_context.set_line_width (1); for (int i = 0; i <= shadow_width; i++) { base_context.arc ( radius + shadow_width, radius + shadow_width, radius + shadow_width - i, 0, 2 * Math.PI ); Gdk.RGBA shadow_color = Gdk.RGBA (); shadow_color.parse (DARK_BORDER_COLOR_STRING); shadow_color.alpha = shadow_alpha / ((shadow_width - i + 1) * (shadow_width - i + 1)); Gdk.cairo_set_source_rgba (base_context, shadow_color); base_context.stroke (); } // Draw an outside bright magnifier border Gdk.cairo_set_source_rgba (base_context, bright_border_color); base_context.arc (radius + shadow_width, radius + shadow_width, radius - 1, 0, 2 * Math.PI); base_context.stroke (); // Draw inside square base_context.set_line_width (1); Gdk.cairo_set_source_rgba (base_context, dark_border_color); base_context.move_to (radius + shadow_width - zoomlevel, radius + shadow_width - zoomlevel); base_context.line_to (radius + shadow_width + zoomlevel, radius + shadow_width - zoomlevel); base_context.line_to (radius + shadow_width + zoomlevel, radius + shadow_width + zoomlevel); base_context.line_to (radius + shadow_width - zoomlevel, radius + shadow_width + zoomlevel); base_context.close_path (); base_context.stroke (); Gdk.cairo_set_source_rgba (base_context, bright_border_color); base_context.move_to (radius + shadow_width - zoomlevel + 1, radius + shadow_width - zoomlevel + 1); base_context.line_to (radius + shadow_width + zoomlevel - 1, radius + shadow_width - zoomlevel + 1); base_context.line_to (radius + shadow_width + zoomlevel - 1, radius + shadow_width + zoomlevel - 1); base_context.line_to (radius + shadow_width - zoomlevel + 1, radius + shadow_width + zoomlevel - 1); base_context.close_path (); base_context.stroke (); magnifier = new Gdk.Cursor.from_surface ( get_screen ().get_display (), base_surface, base_surface.get_width () / 2, base_surface.get_height () / 2); // Set the cursor manager.grab ( get_window (), Gdk.SeatCapabilities.ALL, true, magnifier, new Gdk.Event (Gdk.EventType.BUTTON_PRESS | Gdk.EventType.MOTION_NOTIFY | Gdk.EventType.SCROLL), null); } public Gdk.Pixbuf? snap (int x, int y, int w, int h) { var root = Gdk.get_default_root_window (); var screenshot = Gdk.pixbuf_get_from_window (root, x, y, w, h); return screenshot; } public override bool key_press_event (Gdk.EventKey e) { var manager = Gdk.Display.get_default ().get_default_seat (); int px, py; get_window ().get_device_position (manager.get_pointer (), out px, out py, null); switch (e.keyval) { case Gdk.Key.Escape: cancelled (); break; case Gdk.Key.Return: Gdk.RGBA color = get_color_at (px, py); picked (color); break; case Gdk.Key.Up: manager.get_pointer ().warp (get_screen (), px, py - 1); break; case Gdk.Key.Down: manager.get_pointer ().warp (get_screen (), px, py + 1); break; case Gdk.Key.Left: manager.get_pointer ().warp (get_screen (), px - 1, py); break; case Gdk.Key.Right: manager.get_pointer ().warp (get_screen (), px + 1, py); break; } key_pressed (e); return true; } public override bool key_release_event (Gdk.EventKey e) { key_released (e); return true; } public Gdk.RGBA get_color_at (int x, int y) { var root = Gdk.get_default_root_window (); Gdk.Pixbuf? pixbuf = Gdk.pixbuf_get_from_window (root, x, y, 1, 1); if (pixbuf != null) { // see https://hackage.haskell.org/package/gtk3-0.14.6/docs/Graphics-UI-Gtk-Gdk-Pixbuf.html uint8 red = pixbuf.get_pixels ()[0]; uint8 green = pixbuf.get_pixels ()[1]; uint8 blue = pixbuf.get_pixels ()[2]; Gdk.RGBA color = Gdk.RGBA (); string spec = "rgb(" + red.to_string () + "," + green.to_string () + "," + blue.to_string () + ")"; if (color.parse (spec)) { return color; } else { stdout.printf ("ERROR: Parse pixel rgb values failed."); } } // fallback: default RGBA color stdout.printf ("ERROR: Gdk.pixbuf_get_from_window failed"); return Gdk.RGBA (); } public override void show_all () { base.show_all (); var manager = Gdk.Display.get_default ().get_default_seat (); var window = get_window (); var status = manager.grab ( window, Gdk.SeatCapabilities.ALL, false, new Gdk.Cursor.for_display (window.get_display (), Gdk.CursorType.CROSSHAIR), new Gdk.Event (Gdk.EventType.BUTTON_PRESS | Gdk.EventType.BUTTON_RELEASE | Gdk.EventType.MOTION_NOTIFY), null); if (status != Gdk.GrabStatus.SUCCESS) { manager.ungrab (); } // show magnifier set_magnifier_cursor (); } public new void close () { // TODO remove the zoom level saving if we do not need it // save zoomlevel // settings.zoomlevel = zoomlevel; get_window ().set_cursor (null); base.close (); } } Akira-0.0.16/src/Utils/Dialogs.vala000066400000000000000000000035241410625726100167530ustar00rootroot00000000000000/* * Copyright (c) 2019 Alecaddd (http://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Alessandro "Alecaddd" Castellani */ public class Akira.Utils.Dialogs : Object { public weak Akira.Window window { get; construct; } public Dialogs (Akira.Window window) { Object ( window: window ); } public Granite.MessageDialog message_dialog ( string title, string description, string icon, string primary_button, string? secondary_button = null ) { var dialog = new Granite.MessageDialog.with_image_from_icon_name ( title, description, icon, Gtk.ButtonsType.CANCEL); dialog.transient_for = window; if (secondary_button != null) { var button2 = new Gtk.Button.with_label (secondary_button); button2.get_style_context ().add_class (Gtk.STYLE_CLASS_SUGGESTED_ACTION); dialog.add_action_widget (button2, 2); } var button = new Gtk.Button.with_label (primary_button); button.get_style_context ().add_class (Gtk.STYLE_CLASS_DESTRUCTIVE_ACTION); dialog.add_action_widget (button, Gtk.ResponseType.ACCEPT); return dialog; } } Akira-0.0.16/src/Utils/Image.vala000066400000000000000000000045151410625726100164140ustar00rootroot00000000000000/* * Copyright (c) 2020 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Alessandro "Alecaddd" Castellani */ public class Akira.Utils.Image : Object { private const string[] ACCEPTED_TYPES = { "image/jpeg", "image/png", "image/tiff", "image/svg+xml", "image/gif" }; /** * Check if the filename has a picture file extension. */ public static bool is_valid_image (GLib.File file) { try { var file_info = file.query_info ("standard::*", 0); // Check for correct file type, don't try to load directories. if (file_info.get_file_type () != GLib.FileType.REGULAR) { return false; } try { var pixbuf = new Gdk.Pixbuf.from_file (file.get_path ()); var width = pixbuf.get_width (); var height = pixbuf.get_height (); if (width < 1 || height < 1) return false; } catch (Error e) { warning ("Invalid image loaded: %s", e.message); return false; } foreach (var type in ACCEPTED_TYPES) { if (GLib.ContentType.equals (file_info.get_content_type (), type)) { return true; } } } catch (Error e) { warning ("Could not get file info: %s", e.message); } return false; } /** * Return only the file extension, PNG if not extension was found. */ public static string get_extension (GLib.File file) { var parts = file.get_basename ().split ("."); return parts.length > 1 ? parts[parts.length - 1] : "png"; } } Akira-0.0.16/src/Utils/Snapping.vala000066400000000000000000000335161410625726100171540ustar00rootroot00000000000000/** * Copyright (c) 2021 Alecaddd (http://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Martin "mbfraga" Fraga */ /** * Utility providing snap functionality between objects. */ public class Akira.Utils.Snapping : Object { /** * Metadata used in the cosmetic aspects of snap lines and dots. */ public class SnapMeta { public Gee.HashSet normals; public int polarity; } /** * Grid snaps found for a given selection and set of candidates. */ public struct SnapGrid { public bool is_empty () { return (v_snaps.size == 0 && h_snaps.size == 0); } public Gee.HashMap v_snaps; public Gee.HashMap h_snaps; } /** * Type of match that was found for a snap. */ public enum MatchType { NONE = -1, //< No match was found. FUZZY, //< A match was found, but requires an offset. EXACT, //< An exact match was found, no offset is necessary. } /** * Information used to define a match for a given selection. * An instance of this class corresponds to a single direction (vertical or horizontal). */ public struct SnapMatch { /** * Returns true if a match was found */ public bool snap_found () { return type != MatchType.NONE; } /** * Returns the offset necessary to bring the reference position to the selected items. */ public int snap_offset () { if (snap_found ()) { return snap_position + polarity_offset - reference_position; } return 0; } public MatchType type; public int snap_position; //< Position of matched snap. public int polarity_offset; //< Offset incurred by polarity properties. For now it is always zero. public int reference_position; //< Position relative to the selection used as a reference. public Gee.HashMap exact_matches; //< map of exact matches and their polarities. } /** * Couple of MatchData used for convenience. */ public struct SnapMatchData { public bool snap_found () { return h_data.snap_found () || v_data.snap_found (); } SnapMatch h_data; SnapMatch v_data; } /** * Returns a sensitivity adjusted to the given canvas scale. */ public static int adjusted_sensitivity (double canvas_scale) { // Limit the sensitivity. This seems like a sensible default for now. if (canvas_scale > settings.snaps_sensitivity) { return 1; } // Beyond 0.002, the snapping breaks down. Arguably, it does before. return (int) (settings.snaps_sensitivity / double.max (0.002, canvas_scale)); } /** * Generates the best snap grid from selection. */ public static SnapGrid generate_best_snap_grid ( Goo.Canvas canvas, List selection, int sensitivity ) { Lib.Items.CanvasArtboard artboard = null; bool all_in_same_artboard = false; foreach (var sel in selection) { if (artboard != null && artboard != sel.artboard) { all_in_same_artboard = false; break; } artboard = sel.artboard; all_in_same_artboard = artboard != null; } if (artboard != null && all_in_same_artboard) { return snap_grid_from_artboard (canvas, artboard, selection, sensitivity); } return snap_grid_from_canvas (canvas, selection, sensitivity); } /** * Generates a snap grid from a canvas. */ public static SnapGrid snap_grid_from_canvas ( Goo.Canvas canvas, List selection, int sensitivity ) { List vertical_candidates = null; List horizontal_candidates = null; Goo.CanvasBounds vertical_filter = {0, 0, 0, 0}; Goo.CanvasBounds horizontal_filter = {0, 0, 0, 0}; foreach (var item in selection) { horizontal_filter.x1 = item.coordinates.x1 - sensitivity; horizontal_filter.x2 = item.coordinates.x2 + sensitivity; horizontal_filter.y1 = canvas.y1; horizontal_filter.y2 = canvas.y2; vertical_filter.x1 = canvas.x1; vertical_filter.x2 = canvas.x2; vertical_filter.y1 = item.coordinates.y1 - sensitivity; vertical_filter.y2 = item.coordinates.y2 + sensitivity; vertical_candidates.concat (canvas.get_items_in_area (vertical_filter, true, true, true)); horizontal_candidates.concat (canvas.get_items_in_area (horizontal_filter, true, true, true)); } return snap_grid_from_canvas_candidates (vertical_candidates, horizontal_candidates, selection, false); } /** * Generates a snap grid from an artboard. */ public static SnapGrid snap_grid_from_artboard ( Goo.Canvas canvas, Lib.Items.CanvasArtboard artboard, List selection, int sensitivity ) { List candidates = null; foreach (var item in selection) { candidates.concat (canvas.get_items_in_area (artboard.background.bounds, true, true, true)); } return snap_grid_from_artboard_candidates (candidates, selection, artboard); } /** * Calculate snaps inside a grid that match the selection input. */ public static SnapMatchData generate_snap_matches ( SnapGrid grid, List selection, int sensitivity ) { var matches = default_match_data (); var v_sel_snaps = new Gee.HashMap (); var h_sel_snaps = new Gee.HashMap (); foreach (var item in selection) { populate_horizontal_snaps (item, ref h_sel_snaps); populate_vertical_snaps (item, ref v_sel_snaps); } populate_snap_matches_from_list (h_sel_snaps, grid.h_snaps, ref matches.h_data, sensitivity); populate_snap_matches_from_list (v_sel_snaps, grid.v_snaps, ref matches.v_data, sensitivity); return matches; } /** * Matches in one direction (vertical / horizontal). */ private static void populate_snap_matches_from_list ( Gee.HashMap target_snap_list, Gee.HashMap grid_snap_list, ref SnapMatch matches, int sensitivity ) { var sorted_target_snaps = new Gee.TreeMap (); var sorted_grid_snaps = new Gee.TreeMap (); sorted_target_snaps.set_all (target_snap_list); sorted_grid_snaps.set_all (grid_snap_list); int diff = 0; int polarity_offset = 0; var tmpdiff = sensitivity; foreach (var target_snap in sorted_target_snaps) { foreach (var cand in sorted_grid_snaps) { polarity_offset = 0; diff = (int) (cand.key - target_snap.key); diff = diff.abs (); if (diff < sensitivity) { if ((int) (cand.key + polarity_offset - target_snap.key) == 0) { matches.type = MatchType.EXACT; matches.snap_position = cand.key; matches.reference_position = target_snap.key; matches.polarity_offset = polarity_offset; matches.exact_matches[cand.key] = polarity_offset; } else if (diff < tmpdiff) { matches.type = MatchType.FUZZY; matches.snap_position = cand.key; matches.reference_position = target_snap.key; matches.polarity_offset = polarity_offset; } } tmpdiff = diff; } } } private static SnapGrid snap_grid_from_canvas_candidates ( List v_candidates, List h_candidates, List selection, bool include_artboard_contents ) { var grid = SnapGrid (); grid.v_snaps = new Gee.HashMap (); grid.h_snaps = new Gee.HashMap (); foreach (var cand in v_candidates) { var candidate_item = cand as Lib.Items.CanvasItem; if ( candidate_item != null && (include_artboard_contents || candidate_item.artboard == null) && selection.find (candidate_item) == null ) { populate_vertical_snaps (candidate_item, ref grid.v_snaps); } } foreach (var cand in h_candidates) { var candidate_item = cand as Lib.Items.CanvasItem; if ( candidate_item != null && (include_artboard_contents || candidate_item.artboard == null) && selection.find (candidate_item) == null ) { populate_horizontal_snaps (candidate_item, ref grid.h_snaps); } } return grid; } private static SnapGrid snap_grid_from_artboard_candidates ( List candidates, List selection, Lib.Items.CanvasArtboard? artboard ) { var grid = SnapGrid (); grid.v_snaps = new Gee.HashMap (); grid.h_snaps = new Gee.HashMap (); foreach (var cand in candidates) { if (cand == artboard) { populate_vertical_snaps (cand as Lib.Items.CanvasArtboard, ref grid.v_snaps); populate_horizontal_snaps (cand as Lib.Items.CanvasArtboard, ref grid.h_snaps); } var candidate_item = cand as Lib.Items.CanvasItem; if ( candidate_item != null && candidate_item.artboard == artboard && selection.find (candidate_item) == null ) { populate_vertical_snaps (candidate_item, ref grid.v_snaps); populate_horizontal_snaps (candidate_item, ref grid.h_snaps); } } return grid; } /** * Populates the horizontal snaps of an item. */ private static void populate_horizontal_snaps (Lib.Items.CanvasItem item, ref Gee.HashMap map) { int x_1 = (int) item.coordinates.x1; int x_2 = (int) item.coordinates.x2; int y_1 = (int) item.coordinates.y1; int y_2 = (int) item.coordinates.y2; int center_x = (int) (Math.ceil ((item.coordinates.x2 - item.coordinates.x1) / 2.0) + item.coordinates.x1); int center_y = (int) (Math.ceil ((item.coordinates.y2 - item.coordinates.y1) / 2.0) + item.coordinates.y1); add_to_map (x_1, y_1, y_2, center_y, -1, ref map); add_to_map (x_2, y_1, y_2, center_y, 1, ref map); add_to_map (center_x, center_y, center_y, center_y, 0, ref map); } /** * Populates the vertical snaps of an item. */ private static void populate_vertical_snaps (Lib.Items.CanvasItem item, ref Gee.HashMap map) { int x_1 = (int) item.coordinates.x1; int x_2 = (int) item.coordinates.x2; int y_1 = (int) item.coordinates.y1; int y_2 = (int) item.coordinates.y2; int center_x = (int) (Math.ceil ((item.coordinates.x2 - item.coordinates.x1) / 2.0) + item.coordinates.x1); int center_y = (int) (Math.ceil ((item.coordinates.y2 - item.coordinates.y1) / 2.0) + item.coordinates.y1); add_to_map (y_1, x_1, x_2, center_x, -1, ref map); add_to_map (y_2, x_1, x_2, center_x, 1, ref map); add_to_map (center_y, center_x, center_x, center_x, 0, ref map); } /** * Simple method to add information to a snap list. */ private static void add_to_map ( int pos, int n1, int n2, int n3, int polarity, ref Gee.HashMap map ) { if (map.has_key (pos)) { SnapMeta k = map.get (pos); k.normals.add (n1); k.normals.add (n2); k.normals.add (n3); k.polarity += polarity; return; } var v = new SnapMeta (); v.normals = new Gee.HashSet (); v.normals.add (n1); v.normals.add (n2); v.normals.add (n3); v.polarity = polarity; map.set (pos, v); } /** * Generate a default match data. */ private static SnapMatchData default_match_data () { var matches = SnapMatchData (); matches.v_data.type = MatchType.NONE; matches.v_data.snap_position = 0; matches.v_data.polarity_offset = 0; matches.v_data.reference_position = 0; matches.v_data.exact_matches = new Gee.HashMap (); matches.h_data.type = MatchType.NONE; matches.h_data.snap_position = 0; matches.h_data.polarity_offset = 0; matches.h_data.reference_position = 0; matches.h_data.exact_matches = new Gee.HashMap (); return matches; } } Akira-0.0.16/src/Widgets/000077500000000000000000000000001410625726100150265ustar00rootroot00000000000000Akira-0.0.16/src/Widgets/AddColorButton.vala000066400000000000000000000025501410625726100205600ustar00rootroot00000000000000/* * Copyright (c) 2021 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * * Akira 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 Akira. If not, see . * * Authored by: Abdallah "Abdallah-Moh" Mohammad * Authored by: Alessandro "alecaddd" Castellani */ /* * Helper class to quickly create a simple style button with a + icon. */ public class Akira.Widgets.AddColorButton : Gtk.Button { public AddColorButton () { get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT); width_request = height_request = 24; can_focus = false; valign = halign = Gtk.Align.CENTER; image = new Gtk.Image.from_icon_name ("list-add-symbolic", Gtk.IconSize.MENU); tooltip_text = _("Add the current color to the library"); } } Akira-0.0.16/src/Widgets/AlignBoxButton.vala000066400000000000000000000036451410625726100206020ustar00rootroot00000000000000/* * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * * Akira 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 Akira. If not, see . * * Authored by: Giacomo "giacomoalbe" Alberini */ public class Akira.Widgets.AlignBoxButton : Gtk.Button { public signal void triggered (AlignBoxButton emitter); public weak Akira.Window window { get; construct; } public string icon { get; construct; } public string action { get; construct; } public ButtonImage btn_image; public AlignBoxButton (Akira.Window window, string action_name, string icon_name, string tooltip, string[] accels) { Object ( window: window, icon: icon_name, action: action_name, tooltip_markup: Granite.markup_accel_tooltip (accels, tooltip) ); } construct { get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT); get_style_context ().add_class ("button-rounded"); halign = Gtk.Align.CENTER; valign = Gtk.Align.CENTER; can_focus = false; sensitive = false; btn_image = new ButtonImage (icon, Gtk.IconSize.SMALL_TOOLBAR); add (btn_image); connect_signals (); } private void connect_signals () { clicked.connect (() => { window.event_bus.align_items (action); }); } } Akira-0.0.16/src/Widgets/ButtonImage.vala000066400000000000000000000030001410625726100201020ustar00rootroot00000000000000/* * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * * Akira 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 Akira. If not, see . * * Authored by: Bilal Elmoussaoui */ public class Akira.Widgets.ButtonImage: Gtk.Image { private string icon; private Gtk.IconSize size; public ButtonImage (string icon_name, Gtk.IconSize icon_size = Gtk.IconSize.LARGE_TOOLBAR) { icon = icon_name; size = icon_size; margin = 0; settings.changed["use-symbolic"].connect (update_image); update_image (); } ~ButtonImage () { settings.changed["use-symbolic"].disconnect (update_image); } private void update_image () { if (settings.use_symbolic) { set_from_icon_name ("%s-symbolic".printf (icon), Gtk.IconSize.SMALL_TOOLBAR); return; } set_from_icon_name (icon.replace ("-symbolic", ""), size); } } Akira-0.0.16/src/Widgets/ColorField.vala000066400000000000000000000062511410625726100177210ustar00rootroot00000000000000/* * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * * Akira 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 Akira. If not, see . * * Authored by: Alessandro "Alecaddd" Castellani */ public class Akira.Widgets.ColorField : Gtk.Entry { private unowned Akira.Window window; public ColorField (Akira.Window window) { this.window = window; margin_end = margin_start = 10; width_chars = 8; max_length = 7; hexpand = true; focus_in_event.connect (handle_focus_in); focus_out_event.connect (handle_focus_out); insert_text.connect (handle_insert_text); key_press_event.connect (handle_key_press); } ~ColorField () { focus_in_event.disconnect (handle_focus_in); focus_out_event.disconnect (handle_focus_out); insert_text.disconnect (handle_insert_text); key_press_event.disconnect (handle_key_press); } private void handle_insert_text (string text, int length, ref int position) { string new_text = text.strip (); if (new_text.contains ("#")) { new_text = new_text.substring (1, new_text.length - 1); } else if (!this.text.contains ("#")) { GLib.Signal.stop_emission_by_name (this, "insert-text"); var builder = new StringBuilder (); builder.append (new_text); builder.prepend ("#"); this.text = builder.str; position = this.text.length; } bool is_valid_hex = true; bool char_is_numeric = true; bool char_is_valid_alpha = true; char keyval; for (var i = 0; i < new_text.length; i++) { keyval = new_text [i]; char_is_numeric = keyval >= Gdk.Key.@0 && keyval <= Gdk.Key.@9; char_is_valid_alpha = keyval >= Gdk.Key.A && keyval <= Gdk.Key.F; is_valid_hex &= keyval.isxdigit (); } if (!is_valid_hex) { GLib.Signal.stop_emission_by_name (this, "insert-text"); return; } } private bool handle_focus_in (Gdk.EventFocus event) { window.event_bus.disconnect_typing_accel (); return false; } private bool handle_focus_out (Gdk.EventFocus event) { window.event_bus.connect_typing_accel (); return false; } private bool handle_key_press (Gdk.EventKey event) { // Enter or Escape if (event.keyval == Gdk.Key.Return || event.keyval == Gdk.Key.Escape) { window.event_bus.set_focus_on_canvas (); return true; } return false; } } Akira-0.0.16/src/Widgets/ColorRow.vala000066400000000000000000000301651410625726100174460ustar00rootroot00000000000000/* * Copyright (c) 2021 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * * Akira 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 Akira. If not, see . * * Authored by: Alessandro "alecaddd" Castellani */ /* * Helper class to quickly create a container with a color button and a color * picker. The color button opens up the GtkColorChooser. */ public class Akira.Widgets.ColorRow : Gtk.Grid { private unowned Akira.Window window; private unowned Models.ColorModel model; private Gtk.Button color_button; private Gtk.Popover color_popover; private Gtk.ColorChooserWidget? color_chooser_widget = null; private Gtk.FlowBox global_colors_flowbox; private ColorField field; private InputField opacity_field; /* * If the color or alpha are manually set from the ColorPicker. * If true, the ColorChooserWidget doesn't need to be updated. */ private bool color_set_manually = false; /* * Keep track of the current color when the user is updating the string * and the format is not valid. */ private string old_color; /* * Type of color containers to add new colors to. We can potentially create * an API to allow adding more containers to the color picker popup. */ private enum Container { GLOBAL, DOCUMENT } public ColorRow (Akira.Window window, Models.ColorModel model) { this.window = window; this.model = model; old_color = model.color; margin_top = margin_bottom = 1; var container = new Gtk.Grid (); var context = container.get_style_context (); context.add_class ("selected-color-container"); context.add_class ("bg-pattern"); color_button = new Gtk.Button (); color_button.vexpand = true; color_button.width_request = 40; color_button.can_focus = false; color_button.get_style_context ().add_class ("selected-color"); color_button.set_tooltip_text (_("Choose color")); color_popover = new Gtk.Popover (color_button); color_popover.position = Gtk.PositionType.BOTTOM; color_button.clicked.connect (() => { init_color_chooser (); color_popover.popup (); }); container.add (color_button); set_button_color (model.color, model.alpha); // Define the eye dropper button. var eyedropper_button = new Gtk.Button (); eyedropper_button.get_style_context ().add_class ("color-picker-button"); eyedropper_button.can_focus = false; eyedropper_button.valign = Gtk.Align.CENTER; eyedropper_button.set_tooltip_text (_("Pick color")); eyedropper_button.add ( new Gtk.Image.from_icon_name ("color-select-symbolic", Gtk.IconSize.SMALL_TOOLBAR) ); eyedropper_button.clicked.connect (on_eyedropper_click); add (container); add (eyedropper_button); field = new ColorField (window); field.text = Utils.Color.rgba_to_hex (model.color); field.changed.connect (() => { // Don't do anything if the color change came from the chooser. if (color_set_manually) { return; } var field_hex = field.text; // Interrupt if what's written is not a valid color value. if (!Utils.Color.is_valid_hex (field_hex)) { return; } // Since we will update the color picker, prevent an infinite loop. color_set_manually = true; var new_rgba = Utils.Color.hex_to_rgba (field_hex); model.color = new_rgba.to_string (); set_button_color (field_hex, model.alpha); // Update the chooser widget only if it was already initialized. if (color_chooser_widget != null) { set_chooser_color (new_rgba.to_string (), model.alpha); } // Reset the bool to allow edits from the color chooser. color_set_manually = false; }); add (field); // Show the opacity field if this widget was generated from the Fills list. if (model.type == Models.ColorModel.Type.FILL) { opacity_field = new InputField (InputField.Unit.PERCENTAGE, 7, true, true); opacity_field.entry.sensitive = true; opacity_field.entry.value = Math.round ((double) model.alpha / 255 * 100); opacity_field.entry.value_changed.connect (() => { // Don't do anything if the color change came from the chooser. if (color_set_manually) { return; } // Since we will update the color picker, prevent an infinite loop. color_set_manually = true; var alpha = (int) ((double) opacity_field.entry.value / 100 * 255); model.alpha = alpha; set_button_color (model.color, alpha); // Update the chooser widget only if it was already initialized. if (color_chooser_widget != null) { set_chooser_color (model.color, alpha); } // Reset the bool to allow edits from the color chooser. color_set_manually = false; }); add (opacity_field); } // Show the border field if this widget was generated from the Borders list. if (model.type == Models.ColorModel.Type.BORDER) { var border = new InputField (InputField.Unit.PIXEL, 7, true, true); border.set_range (0, Layouts.MainCanvas.CANVAS_SIZE / 2); border.entry.sensitive = true; border.entry.value = model.size; border.entry.bind_property ("value", model, "size", BindingFlags.BIDIRECTIONAL); add (border); } } private void init_color_chooser () { if (color_chooser_widget != null) { return; } color_chooser_widget = new Gtk.ColorChooserWidget (); color_chooser_widget.hexpand = true; color_chooser_widget.show_editor = true; var color_grid = new Gtk.Grid (); color_grid.get_style_context ().add_class ("color-picker"); color_grid.row_spacing = 12; var global_colors_label = new Gtk.Label (_("Global colors")); global_colors_label.halign = Gtk.Align.START; global_colors_label.margin_start = global_colors_label.margin_end = 6; global_colors_flowbox = new Gtk.FlowBox (); global_colors_flowbox.get_style_context ().add_class ("color-grid"); global_colors_flowbox.selection_mode = Gtk.SelectionMode.NONE; global_colors_flowbox.homogeneous = false; global_colors_flowbox.column_spacing = global_colors_flowbox.row_spacing = 6; global_colors_flowbox.margin_start = global_colors_flowbox.margin_end = 6; // Large number to allow children to spread out the available space. global_colors_flowbox.max_children_per_line = 100; global_colors_flowbox.set_sort_func (sort_colors_function); var add_global_color_btn = new AddColorButton (); add_global_color_btn.clicked.connect (() => { on_save_color (Container.GLOBAL); }); global_colors_flowbox.add (add_global_color_btn); foreach (string color in settings.global_colors) { var btn = create_color_button (color); global_colors_flowbox.add (btn); } color_grid.attach (color_chooser_widget, 0, 0, 1, 1); color_grid.attach (global_colors_label, 0, 1, 1, 1); color_grid.attach (global_colors_flowbox, 0, 2, 1, 1); color_grid.show_all (); color_popover.add (color_grid); // Set the chooser color before connecting the signal. set_chooser_color (model.color, model.alpha); color_chooser_widget.notify["rgba"].connect (on_color_changed); } private int sort_colors_function (Gtk.FlowBoxChild a, Gtk.FlowBoxChild b) { return (a is AddColorButton) ? -1 : 1; } /* * Add the current color to the parent flowbox. */ private void on_save_color (Container parent) { // Store the currently active color. var color = color_chooser_widget.rgba.to_string (); // Create the new color button and connect to its signal. var btn = create_color_button (color); // Update the colors list and the schema based on the colors container. switch (parent) { case Container.GLOBAL: global_colors_flowbox.add (btn); var array = settings.global_colors; array += color; settings.global_colors = array; break; case Container.DOCUMENT: // TODO... break; } } private void set_chooser_color (string color, int alpha) { var new_rgba = Gdk.RGBA (); new_rgba.parse (color); new_rgba.alpha = (double) alpha / 255; color_chooser_widget.set_rgba (new_rgba); } private void set_button_color (string color, int alpha) { try { var provider = new Gtk.CssProvider (); var context = color_button.get_style_context (); var new_rgba = Gdk.RGBA (); new_rgba.parse (color); new_rgba.alpha = (double) alpha / 255; var new_color = new_rgba.to_string (); var css = """.selected-color { background-color: %s; border-color: shade (%s, 0.75); }""".printf (new_color, new_color); provider.load_from_data (css, css.length); context.add_provider (provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); } catch (Error e) { warning ("Style error: %s", e.message); } } private Gtk.FlowBoxChild create_color_button (string color) { var child = new Gtk.FlowBoxChild (); child.valign = child.halign = Gtk.Align.CENTER; var btn = new Widgets.RoundedColorButton (color); btn.set_color.connect ((color) => { var rgba_color = Gdk.RGBA (); rgba_color.parse (color); color_chooser_widget.set_rgba (rgba_color); }); child.add (btn); child.show_all (); return child; } private void on_color_changed () { // The color change came from the input field, prevent an infinite loop. if (color_set_manually) { return; } // Prevent visible updated fields like hex and opacity from triggering // the update of the model values. color_set_manually = true; // Update the model values. model.color = color_chooser_widget.rgba.to_string (); model.alpha = (int) (color_chooser_widget.rgba.alpha * 255); // Update the UI. set_button_color (model.color, model.alpha); field.text = Utils.Color.rgba_to_hex (model.color); if (model.type == Models.ColorModel.Type.FILL) { opacity_field.entry.value = Math.round ((double) model.alpha / 255 * 100); } // Allow manual edit from the input fields. color_set_manually = false; } private void on_eyedropper_click () { var eyedropper = new Akira.Utils.ColorPicker (); eyedropper.show_all (); eyedropper.picked.connect ((picked_color) => { init_color_chooser (); color_chooser_widget.set_rgba (picked_color); eyedropper.close (); }); eyedropper.cancelled.connect (() => { eyedropper.close (); }); } } Akira-0.0.16/src/Widgets/ExportWidget.vala000066400000000000000000000120761410625726100203260ustar00rootroot00000000000000/* * Copyright (c) 2020-2021 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * * Akira 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 Akira. If not, see . * * Authored by: Alessandro "alecaddd" Castellani */ public class Akira.Widgets.ExportWidget : Gtk.Grid { private const int MB = 1024 * 1024; private const int KB = 1024; public Akira.Models.ExportModel model { get; set construct; } private Gtk.Label info; private Gtk.Grid image_container; private Gtk.Image image; private uint8[]? imagedata; public ExportWidget (Akira.Models.ExportModel model) { Object ( orientation: Gtk.Orientation.HORIZONTAL, model: model ); } construct { halign = Gtk.Align.CENTER; valign = Gtk.Align.CENTER; column_spacing = 6; expand = true; // Label for image size info. We need to create this before calling get_image (). info = new Gtk.Label (""); info.get_style_context ().add_class ("export-info"); info.hexpand = false; info.halign = Gtk.Align.END; // Image preview container with checker. image_container = new Gtk.Grid (); image_container.halign = Gtk.Align.CENTER; image_container.get_style_context ().add_class (Granite.STYLE_CLASS_CHECKERBOARD); image_container.get_style_context ().add_class (Granite.STYLE_CLASS_CARD); image = new Gtk.Image (); image_container.add (image); get_image.begin (); model.notify["pixbuf"].connect (() => { image.clear (); get_image.begin (); }); // Filename with editable entry. var input = new Gtk.Entry (); input.get_style_context ().add_class ("export-filename"); input.width_chars = 10; input.hexpand = true; model.bind_property ("filename", input, "text", BindingFlags.BIDIRECTIONAL | BindingFlags.SYNC_CREATE); attach (input, 0, 0); attach (info, 1, 0); attach (image_container, 0, 1, 2); show_all (); settings.changed["export-quality"].connect (() => { update_file_size.begin (); }); settings.changed["export-compression"].connect (() => { update_file_size.begin (); }); } /** * Generate the image from the pixbuf model and resize it if bigger than * half of the width of the export dialog. */ public async void get_image () { var resized_image = model.pixbuf; if (resized_image.width > (settings.export_width / 2)) { // Keep the aspect ratio consistent. var w = (settings.export_width / 2); var h = (resized_image.height * w) / resized_image.width; resized_image = resized_image.scale_simple (w, h, Gdk.InterpType.BILINEAR); } image.set_from_pixbuf (resized_image); yield update_file_size (); } public async void update_file_size () { yield get_image_buffer_size (); double bytes = (double) imagedata.length; double full_bytes = imagedata.length > MB ? bytes / MB : bytes / KB; var size = imagedata.length > MB ? ("%0.1fMB").printf (full_bytes) : ("%0.1fKB").printf (full_bytes); info.label = _("%i × %i px · %s").printf ( model.pixbuf.width, model.pixbuf.height, size); } private async void get_image_buffer_size () { info.label = _("Fetching image size…"); SourceFunc callback = get_image_buffer_size.callback; new Thread (null, () => { try { if (settings.export_format == "png") { model.pixbuf.save_to_buffer ( out imagedata, "png", "compression", settings.export_compression.to_string (), null); } else if (settings.export_format == "jpg") { model.pixbuf.save_to_buffer ( out imagedata, "jpeg", "quality", settings.export_quality.to_string (), null); } } catch (Error e) { error ("Unable to create image buffer: %s", e.message); } Idle.add ((owned) callback); Thread.exit (null); return null; }); yield; } } Akira-0.0.16/src/Widgets/HeaderBarButton.vala000066400000000000000000000044321410625726100207070ustar00rootroot00000000000000/* * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * * Akira 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 Akira. If not, see . * * Authored by: Alessandro "Alecaddd" Castellani */ public class Akira.Widgets.HeaderBarButton : Gtk.Grid { public weak Akira.Window window; public Gtk.Button button; private Gtk.Label label_btn; public ButtonImage image; public string? sensitive_type; public HeaderBarButton (Akira.Window _window, string icon_name, string name, string[]? accels = null, string? type = null) { window = _window; sensitive_type = type; label_btn = new Gtk.Label (name); label_btn.get_style_context ().add_class ("headerbar-label"); button = new Gtk.Button (); button.can_focus = false; button.halign = Gtk.Align.CENTER; button.get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT); button.tooltip_markup = Granite.markup_accel_tooltip (accels, name); image = new ButtonImage (icon_name); button.add (image); attach (button, 0, 0, 1, 1); attach (label_btn, 0, 1, 1, 1); valign = Gtk.Align.CENTER; sensitive = false; update_label (); build_signals (); settings.changed["show-label"].connect ( () => { update_label (); }); } private void update_label () { label_btn.visible = settings.show_label; label_btn.no_show_all = !settings.show_label; } private void build_signals () { window.event_bus.change_sensitivity.connect ((type) => { if (type == sensitive_type) { sensitive = !sensitive; } }); } } Akira-0.0.16/src/Widgets/InputField.vala000066400000000000000000000114021410625726100177340ustar00rootroot00000000000000/* * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * * Akira 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 Akira. If not, see . * * Authored by: Alessandro "Alecaddd" Castellani */ public class Akira.Widgets.InputField : Gtk.EventBox { public Gtk.SpinButton entry { get; construct set; } public int chars { get; construct set; } public bool rtl { get; construct set; } public bool icon_right { get; construct set; } public Unit unit { get; construct set; } public string? icon { get; set; } public double step { get; set; default = 1; } public enum Unit { PIXEL, HASH, PERCENTAGE, DEGREES, NONE } public InputField ( Unit unit, int chars, bool icon_right = false, bool rtl = false) { Object ( unit: unit, chars: chars, icon_right: icon_right, rtl: rtl ); } construct { valign = Gtk.Align.CENTER; entry = new Gtk.SpinButton.with_range (0, 100, step); entry.hexpand = true; entry.width_chars = chars; entry.sensitive = false; entry.key_press_event.connect (handle_key_press); entry.scroll_event.connect (handle_scroll_event); entry.focus_in_event.connect (handle_focus_in); entry.focus_out_event.connect (handle_focus_out); switch (unit) { case Unit.HASH: icon = "input-hash-symbolic"; break; case Unit.PERCENTAGE: icon = "input-percentage-symbolic"; break; case Unit.PIXEL: icon = "input-pixel-symbolic"; break; case Unit.DEGREES: icon = "input-degrees-symbolic"; break; default: icon = null; break; } if (icon != null) { if (icon_right) { entry.get_style_context ().add_class ("input-icon-right"); entry.secondary_icon_name = icon; entry.secondary_icon_sensitive = false; entry.secondary_icon_activatable = false; } else { entry.get_style_context ().add_class ("input-icon-left"); entry.primary_icon_name = icon; entry.primary_icon_sensitive = false; entry.primary_icon_activatable = false; } } if (rtl) { entry.xalign = 1.0f; } add (entry); } public void set_range (double min_value, double max_value) { entry.set_range (min_value, max_value); } private bool handle_key_press (Gdk.EventKey event) { // Arrow UP if (event.keyval == Gdk.Key.Up && (event.state & Gdk.ModifierType.SHIFT_MASK) > 0) { entry.spin (Gtk.SpinType.STEP_FORWARD, 10); return true; } // Arrow DOWN if (event.keyval == Gdk.Key.Down && (event.state & Gdk.ModifierType.SHIFT_MASK) > 0) { entry.spin (Gtk.SpinType.STEP_BACKWARD, 10); return true; } // Enter or Escape if (event.keyval == Gdk.Key.Return || event.keyval == Gdk.Key.Escape) { Akira.Window window = get_toplevel () as Akira.Window; window.event_bus.set_focus_on_canvas (); return true; } return false; } private bool handle_scroll_event (Gdk.EventScroll event) { // If the input field is not focused, don't change the value. if (!entry.has_focus) { return true; } return false; } private bool handle_focus_in (Gdk.EventFocus event) { Akira.Window window = get_toplevel () as Akira.Window; if (!(window is Akira.Window)) { return true; } window.event_bus.disconnect_typing_accel (); return false; } private bool handle_focus_out (Gdk.EventFocus event) { Akira.Window window = get_toplevel () as Akira.Window; if (!(window is Akira.Window)) { return true; } window.event_bus.connect_typing_accel (); return false; } } Akira-0.0.16/src/Widgets/LinkedInput.vala000066400000000000000000000120431410625726100201210ustar00rootroot00000000000000/* * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * * Akira 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 Akira. If not, see . * * Authored by: Ana Gelez * Authored by: Alessandro "Alecaddd" Castellani */ /* * A digit input with a label next to it. */ public class Akira.Widgets.LinkedInput : Gtk.Grid { public string label { get; construct set; } public string tooltip { get; construct set; } public InputField input_field { get; construct set; } /** * Indicates whether the label or the entry should be first */ public bool reversed { get; construct set; } public string unit { get; construct set; } public double limit { get; set; } public double value { get; set; } public InputField.Unit icon { get; construct set;} /** * Used to avoid to infinitely updating when value is set externally. */ private bool dragging = false; private double dragging_direction = 0; public bool enabled { get { return input_field.entry.sensitive; } set { input_field.entry.sensitive = value; } } public LinkedInput (string label, string tooltip = "", string unit = "", bool reversed = false, double default_val = 0, double limit = 0.0) { Object ( label: label, tooltip: tooltip, reversed: reversed, value: default_val, limit: limit, unit: unit ); } construct { valign = Gtk.Align.CENTER; hexpand = true; get_style_context ().add_class (Gtk.STYLE_CLASS_LINKED); var event_box = new Gtk.EventBox (); event_box.event.connect (handle_event); var entry_label = new Gtk.Label (label); entry_label.get_style_context ().add_class ("entry-label"); entry_label.halign = Gtk.Align.CENTER; entry_label.width_request = 20; entry_label.hexpand = false; entry_label.tooltip_text = tooltip; switch (unit) { case "#": icon = InputField.Unit.HASH; break; case "%": icon = InputField.Unit.PERCENTAGE; break; case "px": icon = InputField.Unit.PIXEL; break; case "°": icon = InputField.Unit.DEGREES; break; default: icon = InputField.Unit.PIXEL; break; } input_field = new Widgets.InputField (icon, 7, true, false); bind_property ( "value", input_field.entry, "value", BindingFlags.BIDIRECTIONAL | BindingFlags.SYNC_CREATE); event_box.add (entry_label); if (reversed) { attach (input_field, 0, 0); attach (event_box, 1, 0); } else { attach (event_box, 0, 0); attach (input_field, 1, 0); } } public bool handle_event (Gdk.Event event) { if (!input_field.entry.sensitive) { return false; } if (event.type == Gdk.EventType.ENTER_NOTIFY) { set_cursor_from_name ("ew-resize"); } if (event.type == Gdk.EventType.LEAVE_NOTIFY) { set_cursor (Gdk.CursorType.ARROW); } if (event.type == Gdk.EventType.BUTTON_PRESS) { dragging = true; } if (event.type == Gdk.EventType.BUTTON_RELEASE) { dragging = false; dragging_direction = 0; } if (event.type == Gdk.EventType.MOTION_NOTIFY && dragging) { if (dragging_direction == 0) { dragging_direction = event.motion.x; } if (dragging_direction > event.motion.x || event.motion.x_root == 0) { input_field.entry.spin (Gtk.SpinType.STEP_BACKWARD, 1); dragging_direction = event.motion.x; } else { input_field.entry.spin (Gtk.SpinType.STEP_FORWARD, 1); dragging_direction = event.motion.x; } } return false; } private void set_cursor (Gdk.CursorType cursor_type) { var cursor = new Gdk.Cursor.for_display (Gdk.Display.get_default (), cursor_type); get_window ().set_cursor (cursor); } private void set_cursor_from_name (string name) { var cursor = new Gdk.Cursor.from_name (Gdk.Display.get_default (), name); get_window ().set_cursor (cursor); } } Akira-0.0.16/src/Widgets/MenuButton.vala000066400000000000000000000035251410625726100200000ustar00rootroot00000000000000/* * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * * Akira 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 Akira. If not, see . * * Authored by: Alessandro "Alecaddd" Castellani */ public class Akira.Widgets.MenuButton : Gtk.Grid { public Gtk.MenuButton button; private Gtk.Label label_btn; public ButtonImage image; public MenuButton (string icon_name, string name, string[]? accels = null) { label_btn = new Gtk.Label (name); label_btn.get_style_context ().add_class ("headerbar-label"); button = new Gtk.MenuButton (); button.can_focus = false; button.halign = Gtk.Align.CENTER; button.get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT); button.tooltip_markup = Granite.markup_accel_tooltip (accels, name); image = new ButtonImage (icon_name); button.add (image); attach (button, 0, 0, 1, 1); attach (label_btn, 0, 1, 1, 1); valign = Gtk.Align.CENTER; update_label (); settings.changed["show-label"].connect (() => { update_label (); }); } private void update_label () { label_btn.visible = settings.show_label; label_btn.no_show_all = !settings.show_label; } } Akira-0.0.16/src/Widgets/PanelSeparator.vala000066400000000000000000000020041410625726100206070ustar00rootroot00000000000000/* * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * * Akira 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 Akira. If not, see . * * Authored by: Alessandro "Alecaddd" Castellani */ public class Akira.Widgets.PanelSeparator : Gtk.Separator { construct { orientation = Gtk.Orientation.HORIZONTAL; get_style_context ().add_class ("panel-separator"); margin_bottom = 6; } } Akira-0.0.16/src/Widgets/RoundedColorButton.vala000066400000000000000000000041751410625726100214750ustar00rootroot00000000000000/* * Copyright (c) 2021 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * * Akira 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 Akira. If not, see . * * Authored by: Abdallah "Abdallah-Moh" Mohammad * Authored by: Alessandro "alecaddd" Castellani */ public class Akira.Widgets.RoundedColorButton : Gtk.Grid { public signal void set_color (string color); public RoundedColorButton (string color) { var context = get_style_context (); context.add_class ("saved-color-button"); context.add_class ("bg-pattern"); valign = halign = Gtk.Align.CENTER; var btn = new Gtk.Button (); var btn_context = btn.get_style_context (); btn_context.add_class ("color-item"); btn.width_request = btn.height_request = 24; btn.valign = btn.halign = Gtk.Align.CENTER; btn.can_focus = false; btn.tooltip_text = color; try { var provider = new Gtk.CssProvider (); var css = """.color-item { background-color: %s; border-color: shade (%s, 0.75); }""".printf (color, color); provider.load_from_data (css, css.length); btn_context.add_provider (provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); } catch (Error e) { warning ("Style error: %s", e.message); } // Emit the set_color signal when the button is clicked. btn.clicked.connect (() => { set_color (color); }); add (btn); } } Akira-0.0.16/src/Widgets/ZoomButton.vala000066400000000000000000000205671410625726100200250ustar00rootroot00000000000000/* * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * * Akira 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 Akira. If not, see . * * Authored by: Alessandro "Alecaddd" Castellani */ public class Akira.Widgets.ZoomButton : Gtk.Grid { public weak Akira.Window window { get; set construct; } private Gtk.Label label_btn; private Gtk.Button zoom_out_button; private Gtk.Button zoom_in_button; private Gtk.Button zoom_default_button; private Gtk.Popover zoom_popover; private Gtk.Entry zoom_input; public ZoomButton (Akira.Window window) { this.window = window; // Grid specific attributes. get_style_context ().add_class (Gtk.STYLE_CLASS_LINKED); get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT); valign = Gtk.Align.CENTER; column_homogeneous = false; width_request = 140; hexpand = false; // Zoom out button. zoom_out_button = new Gtk.Button.from_icon_name ("zoom-out-symbolic", Gtk.IconSize.MENU); zoom_out_button.get_style_context ().add_class ("button-zoom"); zoom_out_button.get_style_context ().add_class ("button-zoom-start"); zoom_out_button.can_focus = false; zoom_out_button.tooltip_markup = Granite.markup_accel_tooltip ({"minus"}, _("Zoom Out")); // Default centered zoom button. zoom_default_button = new Gtk.Button.with_label ("100%"); zoom_default_button.hexpand = true; zoom_default_button.can_focus = false; zoom_default_button.tooltip_markup = Granite.markup_accel_tooltip ( {"0"}, _("Reset Zoom. Ctrl+click to input value") ); // Zoom popover containing the input field. zoom_popover = new Gtk.Popover (zoom_default_button); zoom_popover.position = Gtk.PositionType.BOTTOM; // The zoom input field. zoom_input = new Gtk.Entry (); zoom_input.text = "100"; zoom_input.input_purpose = Gtk.InputPurpose.NUMBER; zoom_input.get_style_context ().add_class ("input-zoom"); zoom_input.get_style_context ().add_class ("input-icon-right"); zoom_input.secondary_icon_name = "input-percentage-symbolic"; zoom_input.secondary_icon_sensitive = false; zoom_input.secondary_icon_activatable = false; zoom_input.xalign = 1.0f; zoom_input.width_chars = 8; zoom_input.show_all (); zoom_popover.add (zoom_input); // Zoom in button. zoom_in_button = new Gtk.Button.from_icon_name ("zoom-in-symbolic", Gtk.IconSize.MENU); zoom_in_button.get_style_context ().add_class ("button-zoom"); zoom_in_button.get_style_context ().add_class ("button-zoom-end"); zoom_in_button.can_focus = false; zoom_in_button.tooltip_markup = Granite.markup_accel_tooltip ({"plus"}, _("Zoom In")); attach (zoom_out_button, 0, 0, 1, 1); attach (zoom_default_button, 1, 0, 1, 1); attach (zoom_in_button, 2, 0, 1, 1); // Headerbar button label. label_btn = new Gtk.Label (_("Zoom")); label_btn.get_style_context ().add_class ("headerbar-label"); label_btn.margin_top = 4; attach (label_btn, 0, 1, 3, 1); // Mouse click signals. zoom_out_button.clicked.connect (zoom_out); zoom_default_button.button_press_event.connect (zoom_reset); zoom_in_button.clicked.connect (zoom_in); // Keyboard press signals. zoom_input.key_press_event.connect (handle_key_press); zoom_input.focus_in_event.connect (handle_focus_in); zoom_input.focus_out_event.connect (handle_focus_out); // Bind the visibility of the button label to the gsetting attribute. settings.bind ("show-label", label_btn, "visible", SettingsBindFlags.DEFAULT); settings.bind ("show-label", label_btn, "no-show-all", SettingsBindFlags.INVERT_BOOLEAN); // Event listeners. window.event_bus.set_scale.connect (on_set_scale); } /* * Decrease the canvas scale by 50%. */ public void zoom_out () { window.event_bus.update_scale (-0.5); } /* * Increase the canvas scale by 50%. */ public void zoom_in () { window.event_bus.update_scale (0.5); } /* * Reset the zoom to 100%, or reveal a popover with the numberic * input field for manual inputing if the user pressed the CTRL key * while clicking on the button. */ public bool zoom_reset (Gdk.EventButton event) { // If the CTRL key was pressed, show the popover with the input field. if ((event.state & Gdk.ModifierType.CONTROL_MASK) > 0) { zoom_popover.popup (); return true; } // Otherwise reset the zoom to 100%. zoom_in_button.sensitive = true; zoom_out_button.sensitive = true; window.event_bus.set_scale (1); return true; } /* * Update the button and the input field when the canvas scale is changed. */ private void on_set_scale (double scale) { var perc_scale = scale * 100; zoom_default_button.label = "%.0f%%".printf (perc_scale); zoom_input.text = perc_scale.to_string (); } /* * Key press events on the input field. */ private bool handle_key_press (Gdk.EventKey event) { // Arrow UP pressed, increase value by 1. if (event.keyval == Gdk.Key.Up) { var text_value = double.parse (zoom_input.text) + 1; window.event_bus.set_scale (text_value / 100); return true; } // Arrow DOWN pressed, decreased value by 1. if (event.keyval == Gdk.Key.Down) { var text_value = double.parse (zoom_input.text) - 1; window.event_bus.set_scale (text_value / 100); return true; } // Enter pressed, update the scale and move the focus back to the canvas. if (event.keyval == Gdk.Key.Return) { var text_value = double.parse (zoom_input.text); // Be sure to stay within the canvas zoom in and out limits of 2% and 5000%. if (text_value < 2) { text_value = 2; } if (text_value > 5000) { text_value = 5000; } window.event_bus.set_scale (text_value / 100); window.event_bus.set_focus_on_canvas (); return true; } // Escape pressed, reset to the old value held by the zoom button. if (event.keyval == Gdk.Key.Escape) { zoom_input.text = zoom_default_button.label.replace ("%", ""); window.event_bus.set_focus_on_canvas (); return true; } // Only allow arrows, delete, and backspace keys other than numbers. if ( event.keyval == Gdk.Key.Left || event.keyval == Gdk.Key.Right || event.keyval == Gdk.Key.Delete || event.keyval == Gdk.Key.BackSpace ) { return false; } // Gtk.Entry doesn't currently support the "number only" filter, so // we need to intercept the keypress and prevent typing if the value // is not a number, or the CTRL modifier is not pressed. if ( !(event.keyval >= Gdk.Key.@0 && event.keyval <= Gdk.Key.@9) && (event.state & Gdk.ModifierType.CONTROL_MASK) == 0 ) { return true; } return false; } /* * When the input field gains focus. */ private bool handle_focus_in (Gdk.EventFocus event) { window.event_bus.disconnect_typing_accel (); return false; } /* * When the input field loses focus. */ private bool handle_focus_out (Gdk.EventFocus event) { window.event_bus.connect_typing_accel (); return false; } } Akira-0.0.16/src/Window.vala000066400000000000000000000144211410625726100155360ustar00rootroot00000000000000/* * Copyright (c) 2019-2020 Alecaddd (https://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Alessandro "Alecaddd" Castellani */ public class Akira.Window : Gtk.ApplicationWindow { public FileFormat.AkiraFile? akira_file = null; public FileFormat.FileManager file_manager; public weak Akira.Application app { get; construct; } public Akira.Services.EventBus event_bus; public Akira.Lib.Managers.ItemsManager items_manager; public Akira.Services.ActionManager action_manager; public Akira.Layouts.HeaderBar headerbar; public Akira.Layouts.MainWindow main_window; public Akira.Utils.Dialogs dialogs; public Akira.StateManagers.CoordinatesMiddleware coords_middleware; public Akira.StateManagers.SizeMiddleware size_middleware; public SimpleActionGroup actions { get; construct; } public Gtk.AccelGroup accel_group { get; construct; } public bool edited { get; set; default = false; } public Window (Akira.Application akira_app) { Object ( application: akira_app, app: akira_app, icon_name: "com.github.akiraux.akira" ); } construct { accel_group = new Gtk.AccelGroup (); add_accel_group (accel_group); event_bus = new Akira.Services.EventBus (); items_manager = new Akira.Lib.Managers.ItemsManager (this); action_manager = new Akira.Services.ActionManager (app, this); file_manager = new Akira.FileFormat.FileManager (this); headerbar = new Akira.Layouts.HeaderBar (this); main_window = new Akira.Layouts.MainWindow (this); coords_middleware = new Akira.StateManagers.CoordinatesMiddleware (this); size_middleware = new Akira.StateManagers.SizeMiddleware (this); dialogs = new Akira.Utils.Dialogs (this); build_ui (); move (settings.pos_x, settings.pos_y); show_app (); // Let the canvas grab the focus after the app is visible. main_window.main_canvas.canvas.focus_canvas (); event_bus.file_edited.connect (on_file_edited); event_bus.file_saved.connect (on_file_saved); } private void build_ui () { set_titlebar (headerbar); set_border_width (0); if (Constants.PROFILE == "development") { headerbar.get_style_context ().add_class ("devel"); } delete_event.connect ((e) => { return before_destroy (); }); add (main_window); } private void apply_user_settings () { Gtk.Settings.get_default ().gtk_application_prefer_dark_theme = settings.dark_theme; var css_provider = new Gtk.CssProvider (); css_provider.load_from_resource ("/com/github/akiraux/akira/stylesheet.css"); Gtk.StyleContext.add_provider_for_screen ( Gdk.Screen.get_default (), css_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION ); resize (settings.window_width, settings.window_height); main_window.pane.position = settings.left_paned; main_window.pane2.position = settings.right_paned; } private void on_file_edited () { edited = true; } private void on_file_saved () { edited = false; } public bool before_destroy () { update_status (); if (!edited) { close_current_file (); app.get_active_window ().destroy (); on_destroy (); } if (edited) { var dialog = dialogs.message_dialog ( _("Are you sure you want to quit?"), _("All unsaved data will be lost and impossible to recover."), "system-shutdown", _("Quit without saving!"), _("Save file") ); dialog.show_all (); dialog.response.connect ((id) => { switch (id) { case Gtk.ResponseType.ACCEPT: dialog.destroy (); close_current_file (); app.get_active_window ().destroy (); on_destroy (); break; case 2: dialog.destroy (); file_manager.save_file (); break; default: dialog.destroy (); break; } }); dialog.run (); } return true; } public void on_destroy () { uint length = app.windows.length (); if (length == 0) { app.quit (); } } private void update_status () { int width, height, x, y; get_size (out width, out height); get_position (out x, out y); settings.pos_x = x; settings.pos_y = y; settings.window_width = width; settings.window_height = height; settings.left_paned = main_window.pane.get_position (); settings.right_paned = main_window.pane2.get_position (); } public void show_app () { apply_user_settings (); show_all (); show (); present (); } public void open_file (File file) { akira_file = new FileFormat.AkiraFile (file, this); akira_file.prepare (); akira_file.load_file (); } public void save_new_file (File file, bool overwrite = false) { akira_file = new FileFormat.AkiraFile (file, this); akira_file.overwrite = overwrite; akira_file.prepare (); akira_file.save_file (); } private void close_current_file () { if (akira_file != null) { akira_file.close (); } } } Akira-0.0.16/src/config.vala.in000066400000000000000000000010221410625726100161320ustar00rootroot00000000000000namespace Constants { public const string DATADIR = "@DATADIR@"; public const string PKGDATADIR = "@PKGDATADIR@"; public const string GETTEXT_PACKAGE = "@GETTEXT_PACKAGE@"; public const string PROJECT_NAME = "@PROJECT_NAME@"; public const string VERSION = "@VERSION@"; public const string INSTALL_PREFIX = "@PREFIX@"; public const string APP_ID = "@APP_ID@"; public const string PROFILE = "@PROFILE@"; public const string APP_NAME = "Akira"; public const string TERMINAL_NAME = "akira"; } Akira-0.0.16/src/meson.build000066400000000000000000000105001410625726100155560ustar00rootroot00000000000000conf_data = configuration_data() conf_data.set('PROJECT_NAME', meson.project_name()) conf_data.set('PREFIX', akira_prefix) conf_data.set('DATADIR', akira_datadir) conf_data.set('PKGDATADIR',akira_pkgdatadir) conf_data.set('GETTEXT_PACKAGE', gettext_package) conf_data.set('VERSION', '0.0.16') conf_data.set('PROFILE', profile) conf_data.set('APP_ID', application_id) config_header = configure_file( input: 'config.vala.in', output: 'config.vala', configuration: conf_data ) sources = files( 'Application.vala', 'Window.vala', 'FileFormat/AkiraFile.vala', 'FileFormat/FileManager.vala', 'FileFormat/JsonSerializer.vala', 'FileFormat/JsonItemSerializer.vala', 'FileFormat/JsonDeserializer.vala', 'FileFormat/ZipArchiveHandler.vala', 'Services/Settings.vala', 'Services/ActionManager.vala', 'Services/EventBus.vala', 'Utils/Dialogs.vala', 'Utils/BlendingMode.vala', 'Utils/AffineTransform.vala', 'Utils/Color.vala', 'Utils/Image.vala', 'Utils/ColorPicker.vala', 'Utils/Snapping.vala', 'Layouts/HeaderBar.vala', 'Layouts/LeftSideBar.vala', 'Layouts/MainCanvas.vala', 'Layouts/MainWindow.vala', 'Layouts/RightSideBar.vala', 'Layouts/Partials/LayersPanel.vala', 'Layouts/Partials/PagesPanel.vala', 'Layouts/Partials/Artboard.vala', 'Layouts/Partials/Layer.vala', 'Layouts/Partials/BordersPanel.vala', 'Layouts/Partials/BorderItem.vala', 'Layouts/Partials/FillsPanel.vala', 'Layouts/Partials/FillItem.vala', 'Layouts/Partials/BlendingModeItem.vala', 'Layouts/Partials/TransformPanel.vala', 'Layouts/Partials/BorderRadiusPanel.vala', 'Layouts/Partials/AlignItemsPanel.vala', 'Widgets/AddColorButton.vala', 'Widgets/AlignBoxButton.vala', 'Widgets/ButtonImage.vala', 'Widgets/ColorField.vala', 'Widgets/ColorRow.vala', 'Widgets/ExportWidget.vala', 'Widgets/HeaderBarButton.vala', 'Widgets/InputField.vala', 'Widgets/LinkedInput.vala', 'Widgets/MenuButton.vala', 'Widgets/PanelSeparator.vala', 'Widgets/RoundedColorButton.vala', 'Widgets/ZoomButton.vala', 'Models/ColorModel.vala', 'Models/ExportModel.vala', 'Models/ListModel.vala', 'Dialogs/ShortcutsDialog.vala', 'Dialogs/SettingsDialog.vala', 'Dialogs/ExportDialog.vala', 'Dialogs/ReleaseDialog.vala', 'Lib/Canvas.vala', 'Lib/Components/Border.vala', 'Lib/Components/Borders.vala', 'Lib/Components/BorderRadius.vala', 'Lib/Components/Component.vala', 'Lib/Components/Coordinates.vala', 'Lib/Components/Fill.vala', 'Lib/Components/Fills.vala', 'Lib/Components/Flipped.vala', 'Lib/Components/Layer.vala', 'Lib/Components/Name.vala', 'Lib/Components/Opacity.vala', 'Lib/Components/Rotation.vala', 'Lib/Components/Size.vala', 'Lib/Items/CanvasArtboard.vala', 'Lib/Items/CanvasEllipse.vala', 'Lib/Items/CanvasImage.vala', 'Lib/Items/CanvasItem.vala', 'Lib/Items/CanvasRect.vala', 'Lib/Items/CanvasText.vala', 'Lib/Managers/ExportManager.vala', 'Lib/Managers/GridManager.vala', 'Lib/Managers/HoverManager.vala', 'Lib/Managers/ImageManager.vala', 'Lib/Managers/ItemsManager.vala', 'Lib/Managers/ModeManager.vala', 'Lib/Managers/NobManager.vala', 'Lib/Managers/SelectedBoundManager.vala', 'Lib/Managers/SnapManager.vala', 'Lib/Selection/Nob.vala', 'Middlewares/CoordinatesMiddleware.vala', 'Middlewares/SizeMiddleware.vala', 'Lib/Modes/InteractionMode.vala', 'Lib/Modes/TransformMode.vala', 'Lib/Modes/ItemInsertMode.vala', 'Lib/Modes/ExportMode.vala', 'Lib/Modes/PanMode.vala', ) deps = [ gtk_dependency, granite_dependency, gee_dependency, libxml_dependency, cairo_dependency, goocanvas_dependency, libarchive_dependency, json_glib_dependency, m_dep ] akira_library = library( 'akira-library-1.0', sources, asresources, config_header, dependencies: deps ) akira_dep = declare_dependency( dependencies: deps, link_with: akira_library, include_directories: include_directories('.') ) # Create a new executable, list the files we want to compile, list the dependencies we need, and install executable( application_id, 'Main.vala', asresources, dependencies: deps + [akira_dep], install: true ) Akira-0.0.16/tests/000077500000000000000000000000001410625726100137735ustar00rootroot00000000000000Akira-0.0.16/tests/canvas/000077500000000000000000000000001410625726100152465ustar00rootroot00000000000000Akira-0.0.16/tests/canvas/test-fills-item.vala000066400000000000000000000056541410625726100211470ustar00rootroot00000000000000/* * Copyright (c) 2019 Alecaddd (http://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Alessandro "Alecaddd" Castellani */ public class Akira.FillsItemTest : Akira.TestSuite { public FillsItemTest () { this.add_test ("loops_through_items", this.loop_through_items); } public override void setup () {} public override void teardown () {} // Unit test for Akira.Models.FillListModel.add () method. // Check whether quickly selecting and deselecting multiple items causes a segfault. public void loop_through_items () { app.activate.connect ((a) => { var window = new Akira.Window (app); app.add_window (window); var canvas = window.main_window.main_canvas.canvas; // TRUE: The canvas was properly generated. assert (canvas is Akira.Lib.Canvas); var list_model = window.main_window.left_sidebar.fills_panel.list_model; // Create 1000 Items and quickly select/deselect them to stress test the canvas. for (var i = 0; i < 10; i++) { window.items_manager.set_item_to_insert ("rectangle"); var item = window.items_manager.insert_item (10, 10); // We don't need to set any other parameter or create other widgets like the layer // panel since we're only interested in testing the selection effect and the fill model. canvas.selected_bound_manager.add_item_to_selection (item as Akira.Lib.Items.CanvasItem); // TRUE: We selected the correct item. assert (canvas.selected_bound_manager.selected_items.index (item) == 0); assert ((item as Akira.Lib.Items.CanvasItem).selected == true); // TRUE: A fill model was created and listed. assert (list_model.get_n_items () == 1); canvas.selected_bound_manager.delete_selection (); // TRUE: The previous fill model was deleted. assert (list_model.get_n_items () == 0); // TRUE: We no item is selected. assert (canvas.selected_bound_manager.selected_items.length () == 0); } // Shut down the test. app.quit (); }); app.run (); app = null; } } Akira-0.0.16/tests/canvas/test-main.vala000066400000000000000000000023251410625726100200160ustar00rootroot00000000000000/* * Copyright (c) 2019 Alecaddd (http://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Alessandro "Alecaddd" Castellani */ class Main : GLib.Object { public static int main (string[] args) { var exit_status = 0; Gtk.init (ref args); Test.init (ref args); var tests = new Akira.TestRunner (); tests.add (new Akira.FillsItemTest ()); GLib.Idle.add (() => { exit_status = tests.run (); Gtk.main_quit (); return false; }); Gtk.main (); return exit_status; } } Akira-0.0.16/tests/meson.build000066400000000000000000000016531410625726100161420ustar00rootroot00000000000000# Define environment variables to run tests. test_env = [ 'G_TEST_SRCDIR=@0@'.format(meson.current_source_dir()), 'G_TEST_BUILDDIR=@0@'.format(meson.current_build_dir()), 'GSETTINGS_BACKEND=memory', 'GSETTINGS_SCHEMA_DIR=@0@/data/schemas'.format(meson.build_root()), ] # Set necessary C flags. test_cflags = [ '-I@0@/../src'.format(meson.current_source_dir()), '-I@0@/../src'.format(meson.current_build_dir()), '-DTEST_DATA_DIR="@0@/data/schemas"'.format(meson.current_source_dir()), ] # Canvas Tests ---------------------------------------- # canvas_tests = executable ( 'canvas_tests', 'tests-model.vala', 'canvas/test-fills-item.vala', 'canvas/test-main.vala', c_args: test_cflags, dependencies: [akira_dep] ) test ('canvas_tests', canvas_tests, env: test_env) # Settings Tests ---------------------------------------- # # File Format Tests ---------------------------------------- # Akira-0.0.16/tests/tests-model.vala000066400000000000000000000153221410625726100171030ustar00rootroot00000000000000/* * Copyright (c) 2019 Alecaddd (http://alecaddd.com) * * This file is part of Akira. * * Akira 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. * Akira 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 Akira. If not, see . * * Authored by: Alessandro "Alecaddd" Castellani */ public delegate void Akira.TestCaseFunc (); public GLib.SettingsSchemaSource schema_source; private class Akira.TestSuiteAdaptor { public string name; private Akira.TestCaseFunc func; private Akira.TestSuite test_suite; public TestSuiteAdaptor (string name, owned Akira.TestCaseFunc test_case_func, Akira.TestSuite test_suite) { this.name = name; this.func = (owned) test_case_func; this.test_suite = test_suite; } public void setup (void* fixture) { this.test_suite.setup (); } public void run (void* fixture) { this.func (); } public void teardown (void* fixture) { this.test_suite.teardown (); } public GLib.TestCase get_g_test_case () { return new GLib.TestCase (this.name, this.setup, this.run, this.teardown); } } public class Akira.TestSuite : GLib.Object { private GLib.TestSuite g_test_suite; private TestSuiteAdaptor[] adaptors = new TestSuiteAdaptor[0]; public Akira.Application app; public TestSuite () { var name = this.get_name (); this.g_test_suite = new GLib.TestSuite (name); app = new Akira.Application (); } public string get_name () { return this.get_type ().name (); } public GLib.TestSuite get_g_test_suite () { return this.g_test_suite; } public void add_test (string name, owned Akira.TestCaseFunc func) { var adaptor = new TestSuiteAdaptor (name, (owned) func, this); this.adaptors += adaptor; this.g_test_suite.add (adaptor.get_g_test_case ()); } public virtual void setup () {} public virtual void teardown () {} } public class Akira.TestRunner : GLib.Object { private GLib.TestSuite root_suite; private GLib.File tmp_dir; private const string SCHEMA_FILE_NAME = "com.github.akiraux.akira.gschema.xml.in"; public TestRunner (GLib.TestSuite? root_suite = null) { if (root_suite == null) { this.root_suite = GLib.TestSuite.get_root (); } else { this.root_suite = root_suite; } } public void add (Akira.TestSuite test_suite) { this.root_suite.add_suite (test_suite.get_g_test_suite ()); } private void setup_settings () { Environment.set_variable ("GSETTINGS_BACKEND", "memory", true); Environment.set_variable ("GSETTINGS_SCHEMA_DIR", this.tmp_dir.get_path (), true); /* prepare temporary settings */ var target_schema_path = this.tmp_dir.get_path (); try { var top_builddir = TestRunner.get_top_builddir (); var source_schema_file = GLib.File.new_for_path ( Path.build_filename (top_builddir, "data/schemas", SCHEMA_FILE_NAME)); var target_schema_file = GLib.File.new_for_path ( Path.build_filename (target_schema_path, SCHEMA_FILE_NAME)); source_schema_file.copy (target_schema_file, GLib.FileCopyFlags.OVERWRITE); } catch (GLib.Error error) { GLib.error ("Error copying schema file: %s", error.message); } var compile_schemas_result = 0; try { GLib.Process.spawn_command_line_sync ( "glib-compile-schemas %s".printf (target_schema_path), null, null, out compile_schemas_result); } catch (GLib.SpawnError error) { GLib.error (error.message); } if (compile_schemas_result != 0) { GLib.error ("Could not compile schemas '%s'.", target_schema_path); } } public virtual void global_setup () { Environment.set_variable ("LANGUAGE", "C", true); try { this.tmp_dir = GLib.File.new_for_path (GLib.DirUtils.make_tmp ("gnome-Akira-test-XXXXXX")); } catch (GLib.Error error) { GLib.error ("Error creating temporary directory for test files: %s".printf (error.message)); } this.setup_settings (); } public virtual void global_teardown () { if (this.tmp_dir != null) { var tmp_dir_path = this.tmp_dir.get_path (); var delete_tmp_result = 0; try { GLib.Process.spawn_command_line_sync ( "rm -rf %s".printf (tmp_dir_path), null, null, out delete_tmp_result); } catch (GLib.SpawnError error) { GLib.warning (error.message); } if (delete_tmp_result != 0) { GLib.warning ("Could not delete temporary directory '%s'", tmp_dir_path); } } } public int run () { /* TODO: spawn a child process to tun tests, if it fails than we will be able to exit cleanly */ this.global_setup (); var exit_status = GLib.Test.run (); this.global_teardown (); return exit_status; } private static string get_top_builddir () { var builddir = Environment.get_variable ("top_builddir"); if (builddir == null) { var dir = GLib.File.new_for_path (Environment.get_current_dir ()); while (dir != null) { var schema_path = GLib.Path.build_filename (dir.get_path (), "data/schemas", SCHEMA_FILE_NAME); if (GLib.FileUtils.test (schema_path, GLib.FileTest.IS_REGULAR)) { builddir = dir.get_path (); break; } dir = dir.get_parent (); } } if (builddir == null) { /* fallback to parent dir, test should be ran from 'tests' dir */ builddir = ".."; } return builddir; } } Akira-0.0.16/uncrustify.cfg000066400000000000000000003304751410625726100155410ustar00rootroot00000000000000# Uncrustify-0.69.0_f # # General options # # The type of line endings. # # Default: auto newlines = auto # lf/crlf/cr/auto # The original size of tabs in the input. # # Default: 8 input_tab_size = 8 # unsigned number # The size of tabs in the output (only used if align_with_tabs=true). # # Default: 8 output_tab_size = 4 # unsigned number # The ASCII value of the string escape char, usually 92 (\) or (Pawn) 94 (^). # # Default: 92 string_escape_char = 92 # unsigned number # Alternate string escape char (usually only used for Pawn). # Only works right before the quote char. string_escape_char2 = 0 # unsigned number # Replace tab characters found in string literals with the escape sequence \t # instead. string_replace_tab_chars = false # true/false # Allow interpreting '>=' and '>>=' as part of a template in code like # 'void f(list>=val);'. If true, 'assert(x<0 && y>=3)' will be broken. # Improvements to template detection may make this option obsolete. tok_split_gte = false # true/false # Specify the marker used in comments to disable processing of part of the # file. # # Default: *INDENT-OFF* disable_processing_cmt = " *INDENT-OFF*" # string # Specify the marker used in comments to (re)enable processing in a file. # # Default: *INDENT-ON* enable_processing_cmt = " *INDENT-ON*" # string # Enable parsing of digraphs. enable_digraphs = false # true/false # Add or remove the UTF-8 BOM (recommend 'remove'). utf8_bom = ignore # ignore/add/remove/force # If the file contains bytes with values between 128 and 255, but is not # UTF-8, then output as UTF-8. utf8_byte = false # true/false # Force the output encoding to UTF-8. utf8_force = false # true/false # # Spacing options # # Add or remove space around non-assignment symbolic operators ('+', '/', '%', # '<<', and so forth). sp_arith = force # ignore/add/remove/force # Add or remove space around arithmetic operators '+' and '-'. # # Overrides sp_arith. sp_arith_additive = ignore # ignore/add/remove/force # Add or remove space around assignment operator '=', '+=', etc. sp_assign = force # ignore/add/remove/force # Add or remove space around '=' in C++11 lambda capture specifications. # # Overrides sp_assign. sp_cpp_lambda_assign = force # ignore/add/remove/force # Add or remove space after the capture specification in C++11 lambda. sp_cpp_lambda_paren = force # ignore/add/remove/force # Add or remove space around assignment operator '=' in a prototype. # # If set to ignore, use sp_assign. sp_assign_default = force # ignore/add/remove/force # Add or remove space before assignment operator '=', '+=', etc. # # Overrides sp_assign. sp_before_assign = force # ignore/add/remove/force # Add or remove space after assignment operator '=', '+=', etc. # # Overrides sp_assign. sp_after_assign = force # ignore/add/remove/force # Add or remove space in 'NS_ENUM ('. sp_enum_paren = ignore # ignore/add/remove/force # Add or remove space around assignment '=' in enum. sp_enum_assign = force # ignore/add/remove/force # Add or remove space before assignment '=' in enum. # # Overrides sp_enum_assign. sp_enum_before_assign = ignore # ignore/add/remove/force # Add or remove space after assignment '=' in enum. # # Overrides sp_enum_assign. sp_enum_after_assign = force # ignore/add/remove/force # Add or remove space around assignment ':' in enum. sp_enum_colon = ignore # ignore/add/remove/force # Add or remove space around preprocessor '##' concatenation operator. # # Default: add sp_pp_concat = add # ignore/add/remove/force # Add or remove space after preprocessor '#' stringify operator. # Also affects the '#@' charizing operator. sp_pp_stringify = ignore # ignore/add/remove/force # Add or remove space before preprocessor '#' stringify operator # as in '#define x(y) L#y'. sp_before_pp_stringify = ignore # ignore/add/remove/force # Add or remove space around boolean operators '&&' and '||'. sp_bool = force # ignore/add/remove/force # Add or remove space around compare operator '<', '>', '==', etc. sp_compare = force # ignore/add/remove/force # Add or remove space inside '(' and ')'. sp_inside_paren = remove # ignore/add/remove/force # Add or remove space between nested parentheses, i.e. '((' vs. ') )'. sp_paren_paren = remove # ignore/add/remove/force # Add or remove space between back-to-back parentheses, i.e. ')(' vs. ') ('. sp_cparen_oparen = remove # ignore/add/remove/force # Whether to balance spaces inside nested parentheses. sp_balance_nested_parens = false # true/false # Add or remove space between ')' and '{'. sp_paren_brace = force # ignore/add/remove/force # Add or remove space between nested braces, i.e. '{{' vs '{ {'. sp_brace_brace = ignore # ignore/add/remove/force # Add or remove space before pointer star '*'. sp_before_ptr_star = force # ignore/add/remove/force # Add or remove space before pointer star '*' that isn't followed by a # variable name. If set to 'ignore', sp_before_ptr_star is used instead. sp_before_unnamed_ptr_star = force # ignore/add/remove/force # Add or remove space between pointer stars '*'. sp_between_ptr_star = force # ignore/add/remove/force # Add or remove space after pointer star '*', if followed by a word. sp_after_ptr_star = force # ignore/add/remove/force # Add or remove space after pointer caret '^', if followed by a word. sp_after_ptr_block_caret = ignore # ignore/add/remove/force # Add or remove space after pointer star '*', if followed by a qualifier. sp_after_ptr_star_qualifier = ignore # ignore/add/remove/force # Add or remove space after a pointer star '*', if followed by a function # prototype or function definition. sp_after_ptr_star_func = force # ignore/add/remove/force # Add or remove space after a pointer star '*', if followed by an open # parenthesis, as in 'void* (*)(). sp_ptr_star_paren = force # ignore/add/remove/force # Add or remove space before a pointer star '*', if followed by a function # prototype or function definition. sp_before_ptr_star_func = force # ignore/add/remove/force # Add or remove space before a reference sign '&'. sp_before_byref = force # ignore/add/remove/force # Add or remove space before a reference sign '&' that isn't followed by a # variable name. If set to 'ignore', sp_before_byref is used instead. sp_before_unnamed_byref = ignore # ignore/add/remove/force # Add or remove space after reference sign '&', if followed by a word. sp_after_byref = ignore # ignore/add/remove/force # Add or remove space after a reference sign '&', if followed by a function # prototype or function definition. sp_after_byref_func = remove # ignore/add/remove/force # Add or remove space before a reference sign '&', if followed by a function # prototype or function definition. sp_before_byref_func = force # ignore/add/remove/force # Add or remove space between type and word. # # Default: force sp_after_type = force # ignore/add/remove/force # Add or remove space between 'decltype(...)' and word. sp_after_decltype = ignore # ignore/add/remove/force # (D) Add or remove space before the parenthesis in the D constructs # 'template Foo(' and 'class Foo('. sp_before_template_paren = ignore # ignore/add/remove/force # Add or remove space between 'template' and '<'. # If set to ignore, sp_before_angle is used. sp_template_angle = remove # ignore/add/remove/force # Add or remove space before '<'. sp_before_angle = remove # ignore/add/remove/force # Add or remove space inside '<' and '>'. sp_inside_angle = remove # ignore/add/remove/force # Add or remove space inside '<>'. sp_inside_angle_empty = ignore # ignore/add/remove/force # Add or remove space between '>' and ':'. sp_angle_colon = ignore # ignore/add/remove/force # Add or remove space after '<>'. sp_after_angle = remove # ignore/add/remove/force # Add or remove space between '>' and '(' as found in 'new List(foo);'. sp_angle_paren = force # ignore/add/remove/force # Add or remove space between '>' and '()' as found in 'new List();'. sp_angle_paren_empty = ignore # ignore/add/remove/force # Add or remove space between '>' and a word as in 'List m;' or # 'template static ...'. sp_angle_word = force # ignore/add/remove/force # Add or remove space between '>' and '>' in '>>' (template stuff). # # Default: add sp_angle_shift = add # ignore/add/remove/force # (C++11) Permit removal of the space between '>>' in 'foo >'. Note # that sp_angle_shift cannot remove the space without this option. sp_permit_cpp11_shift = false # true/false # Add or remove space before '(' of control statements ('if', 'for', 'switch', # 'while', etc.). sp_before_sparen = force # ignore/add/remove/force # Add or remove space inside '(' and ')' of control statements. sp_inside_sparen = remove # ignore/add/remove/force # Add or remove space after '(' of control statements. # # Overrides sp_inside_sparen. sp_inside_sparen_open = ignore # ignore/add/remove/force # Add or remove space before ')' of control statements. # # Overrides sp_inside_sparen. sp_inside_sparen_close = ignore # ignore/add/remove/force # Add or remove space after ')' of control statements. sp_after_sparen = remove # ignore/add/remove/force # Add or remove space between ')' and '{' of of control statements. sp_sparen_brace = force # ignore/add/remove/force # (D) Add or remove space between 'invariant' and '('. sp_invariant_paren = ignore # ignore/add/remove/force # (D) Add or remove space after the ')' in 'invariant (C) c'. sp_after_invariant_paren = ignore # ignore/add/remove/force # Add or remove space before empty statement ';' on 'if', 'for' and 'while'. sp_special_semi = remove # ignore/add/remove/force # Add or remove space before ';'. # # Default: remove sp_before_semi = remove # ignore/add/remove/force # Add or remove space before ';' in non-empty 'for' statements. sp_before_semi_for = force # ignore/add/remove/force # Add or remove space before a semicolon of an empty part of a for statement. sp_before_semi_for_empty = force # ignore/add/remove/force # Add or remove space after ';', except when followed by a comment. # # Default: add sp_after_semi = add # ignore/add/remove/force # Add or remove space after ';' in non-empty 'for' statements. # # Default: force sp_after_semi_for = force # ignore/add/remove/force # Add or remove space after the final semicolon of an empty part of a for # statement, as in 'for ( ; ; )'. sp_after_semi_for_empty = force # ignore/add/remove/force # Add or remove space before '[' (except '[]'). sp_before_square = remove # ignore/add/remove/force # Add or remove space before '[]'. sp_before_squares = remove # ignore/add/remove/force # Add or remove space before C++17 structured bindings. sp_cpp_before_struct_binding = ignore # ignore/add/remove/force # Add or remove space inside a non-empty '[' and ']'. sp_inside_square = remove # ignore/add/remove/force # (OC) Add or remove space inside a non-empty Objective-C boxed array '@[' and # ']'. If set to ignore, sp_inside_square is used. sp_inside_square_oc_array = ignore # ignore/add/remove/force # Add or remove space after ',', i.e. 'a,b' vs. 'a, b'. sp_after_comma = force # ignore/add/remove/force # Add or remove space before ','. # # Default: remove sp_before_comma = remove # ignore/add/remove/force # (C#) Add or remove space between ',' and ']' in multidimensional array type # like 'int[,,]'. sp_after_mdatype_commas = ignore # ignore/add/remove/force # (C#) Add or remove space between '[' and ',' in multidimensional array type # like 'int[,,]'. sp_before_mdatype_commas = ignore # ignore/add/remove/force # (C#) Add or remove space between ',' in multidimensional array type # like 'int[,,]'. sp_between_mdatype_commas = ignore # ignore/add/remove/force # Add or remove space between an open parenthesis and comma, # i.e. '(,' vs. '( ,'. # # Default: force sp_paren_comma = force # ignore/add/remove/force # Add or remove space before the variadic '...' when preceded by a # non-punctuator. sp_before_ellipsis = remove # ignore/add/remove/force # Add or remove space between a type and '...'. sp_type_ellipsis = ignore # ignore/add/remove/force # (D) Add or remove space between a type and '?'. sp_type_question = ignore # ignore/add/remove/force # Add or remove space between ')' and '...'. sp_paren_ellipsis = ignore # ignore/add/remove/force # Add or remove space between ')' and a qualifier such as 'const'. sp_paren_qualifier = ignore # ignore/add/remove/force # Add or remove space between ')' and 'noexcept'. sp_paren_noexcept = ignore # ignore/add/remove/force # Add or remove space after class ':'. sp_after_class_colon = force # ignore/add/remove/force # Add or remove space before class ':'. sp_before_class_colon = force # ignore/add/remove/force # Add or remove space after class constructor ':'. sp_after_constr_colon = ignore # ignore/add/remove/force # Add or remove space before class constructor ':'. sp_before_constr_colon = ignore # ignore/add/remove/force # Add or remove space before case ':'. # # Default: remove sp_before_case_colon = remove # ignore/add/remove/force # Add or remove space between 'operator' and operator sign. sp_after_operator = force # ignore/add/remove/force # Add or remove space between the operator symbol and the open parenthesis, as # in 'operator ++('. sp_after_operator_sym = ignore # ignore/add/remove/force # Overrides sp_after_operator_sym when the operator has no arguments, as in # 'operator *()'. sp_after_operator_sym_empty = ignore # ignore/add/remove/force # Add or remove space after C/D cast, i.e. 'cast(int)a' vs. 'cast(int) a' or # '(int)a' vs. '(int) a'. sp_after_cast = force # ignore/add/remove/force # Add or remove spaces inside cast parentheses. sp_inside_paren_cast = remove # ignore/add/remove/force # Add or remove space between the type and open parenthesis in a C++ cast, # i.e. 'int(exp)' vs. 'int (exp)'. sp_cpp_cast_paren = ignore # ignore/add/remove/force # Add or remove space between 'sizeof' and '('. sp_sizeof_paren = force # ignore/add/remove/force # Add or remove space between 'sizeof' and '...'. sp_sizeof_ellipsis = ignore # ignore/add/remove/force # Add or remove space between 'sizeof...' and '('. sp_sizeof_ellipsis_paren = ignore # ignore/add/remove/force # Add or remove space between 'decltype' and '('. sp_decltype_paren = ignore # ignore/add/remove/force # (Pawn) Add or remove space after the tag keyword. sp_after_tag = ignore # ignore/add/remove/force # Add or remove space inside enum '{' and '}'. sp_inside_braces_enum = force # ignore/add/remove/force # Add or remove space inside struct/union '{' and '}'. sp_inside_braces_struct = force # ignore/add/remove/force # (OC) Add or remove space inside Objective-C boxed dictionary '{' and '}' sp_inside_braces_oc_dict = ignore # ignore/add/remove/force # Add or remove space after open brace in an unnamed temporary # direct-list-initialization. sp_after_type_brace_init_lst_open = ignore # ignore/add/remove/force # Add or remove space before close brace in an unnamed temporary # direct-list-initialization. sp_before_type_brace_init_lst_close = ignore # ignore/add/remove/force # Add or remove space inside an unnamed temporary direct-list-initialization. sp_inside_type_brace_init_lst = ignore # ignore/add/remove/force # Add or remove space inside '{' and '}'. sp_inside_braces = force # ignore/add/remove/force # Add or remove space inside '{}'. sp_inside_braces_empty = remove # ignore/add/remove/force # Add or remove space between return type and function name. A minimum of 1 # is forced except for pointer return types. sp_type_func = remove # ignore/add/remove/force # Add or remove space between type and open brace of an unnamed temporary # direct-list-initialization. sp_type_brace_init_lst = ignore # ignore/add/remove/force # Add or remove space between function name and '(' on function declaration. sp_func_proto_paren = force # ignore/add/remove/force # Add or remove space between function name and '()' on function declaration # without parameters. sp_func_proto_paren_empty = ignore # ignore/add/remove/force # Add or remove space between function name and '(' on function definition. sp_func_def_paren = force # ignore/add/remove/force # Add or remove space between function name and '()' on function definition # without parameters. sp_func_def_paren_empty = ignore # ignore/add/remove/force # Add or remove space inside empty function '()'. sp_inside_fparens = remove # ignore/add/remove/force # Add or remove space inside function '(' and ')'. sp_inside_fparen = remove # ignore/add/remove/force # Add or remove space inside the first parentheses in a function type, as in # 'void (*x)(...)'. sp_inside_tparen = remove # ignore/add/remove/force # Add or remove space between the ')' and '(' in a function type, as in # 'void (*x)(...)'. sp_after_tparen_close = remove # ignore/add/remove/force # Add or remove space between ']' and '(' when part of a function call. sp_square_fparen = remove # ignore/add/remove/force # Add or remove space between ')' and '{' of function. sp_fparen_brace = force # ignore/add/remove/force # Add or remove space between ')' and '{' of s function call in object # initialization. # # Overrides sp_fparen_brace. sp_fparen_brace_initializer = ignore # ignore/add/remove/force # (Java) Add or remove space between ')' and '{{' of double brace initializer. sp_fparen_dbrace = ignore # ignore/add/remove/force # Add or remove space between function name and '(' on function calls. sp_func_call_paren = force # ignore/add/remove/force # Add or remove space between function name and '()' on function calls without # parameters. If set to 'ignore' (the default), sp_func_call_paren is used. sp_func_call_paren_empty = force # ignore/add/remove/force # Add or remove space between the user function name and '(' on function # calls. You need to set a keyword to be a user function in the config file, # like: # set func_call_user tr _ i18n sp_func_call_user_paren = ignore # ignore/add/remove/force # Add or remove space inside user function '(' and ')'. sp_func_call_user_inside_fparen = ignore # ignore/add/remove/force # Add or remove space between nested parentheses with user functions, # i.e. '((' vs. '( ('. sp_func_call_user_paren_paren = ignore # ignore/add/remove/force # Add or remove space between a constructor/destructor and the open # parenthesis. sp_func_class_paren = force # ignore/add/remove/force # Add or remove space between a constructor without parameters or destructor # and '()'. sp_func_class_paren_empty = ignore # ignore/add/remove/force # Add or remove space between 'return' and '('. sp_return_paren = force # ignore/add/remove/force # Add or remove space between 'return' and '{'. sp_return_brace = ignore # ignore/add/remove/force # Add or remove space between '__attribute__' and '('. sp_attribute_paren = remove # ignore/add/remove/force # Add or remove space between 'defined' and '(' in '#if defined (FOO)'. sp_defined_paren = force # ignore/add/remove/force # Add or remove space between 'throw' and '(' in 'throw (something)'. sp_throw_paren = force # ignore/add/remove/force # Add or remove space between 'throw' and anything other than '(' as in # '@throw [...];'. sp_after_throw = force # ignore/add/remove/force # Add or remove space between 'catch' and '(' in 'catch (something) { }'. # If set to ignore, sp_before_sparen is used. sp_catch_paren = force # ignore/add/remove/force # (OC) Add or remove space between '@catch' and '(' # in '@catch (something) { }'. If set to ignore, sp_catch_paren is used. sp_oc_catch_paren = ignore # ignore/add/remove/force # (OC) Add or remove space between class name and '(' # in '@interface className(categoryName):BaseClass' sp_oc_classname_paren = ignore # ignore/add/remove/force # (D) Add or remove space between 'version' and '(' # in 'version (something) { }'. If set to ignore, sp_before_sparen is used. sp_version_paren = ignore # ignore/add/remove/force # (D) Add or remove space between 'scope' and '(' # in 'scope (something) { }'. If set to ignore, sp_before_sparen is used. sp_scope_paren = ignore # ignore/add/remove/force # Add or remove space between 'super' and '(' in 'super (something)'. # # Default: remove sp_super_paren = remove # ignore/add/remove/force # Add or remove space between 'this' and '(' in 'this (something)'. # # Default: remove sp_this_paren = remove # ignore/add/remove/force # Add or remove space between a macro name and its definition. sp_macro = ignore # ignore/add/remove/force # Add or remove space between a macro function ')' and its definition. sp_macro_func = ignore # ignore/add/remove/force # Add or remove space between 'else' and '{' if on the same line. sp_else_brace = force # ignore/add/remove/force # Add or remove space between '}' and 'else' if on the same line. sp_brace_else = force # ignore/add/remove/force # Add or remove space between '}' and the name of a typedef on the same line. sp_brace_typedef = force # ignore/add/remove/force # Add or remove space before the '{' of a 'catch' statement, if the '{' and # 'catch' are on the same line, as in 'catch (decl) {'. sp_catch_brace = force # ignore/add/remove/force # (OC) Add or remove space before the '{' of a '@catch' statement, if the '{' # and '@catch' are on the same line, as in '@catch (decl) {'. # If set to ignore, sp_catch_brace is used. sp_oc_catch_brace = ignore # ignore/add/remove/force # Add or remove space between '}' and 'catch' if on the same line. sp_brace_catch = force # ignore/add/remove/force # (OC) Add or remove space between '}' and '@catch' if on the same line. # If set to ignore, sp_brace_catch is used. sp_oc_brace_catch = ignore # ignore/add/remove/force # Add or remove space between 'finally' and '{' if on the same line. sp_finally_brace = force # ignore/add/remove/force # Add or remove space between '}' and 'finally' if on the same line. sp_brace_finally = force # ignore/add/remove/force # Add or remove space between 'try' and '{' if on the same line. sp_try_brace = force # ignore/add/remove/force # Add or remove space between get/set and '{' if on the same line. sp_getset_brace = force # ignore/add/remove/force # Add or remove space between a variable and '{' for C++ uniform # initialization. # # Default: add sp_word_brace = add # ignore/add/remove/force # Add or remove space between a variable and '{' for a namespace. # # Default: add sp_word_brace_ns = add # ignore/add/remove/force # Add or remove space before the '::' operator. sp_before_dc = remove # ignore/add/remove/force # Add or remove space after the '::' operator. sp_after_dc = remove # ignore/add/remove/force # (D) Add or remove around the D named array initializer ':' operator. sp_d_array_colon = ignore # ignore/add/remove/force # Add or remove space after the '!' (not) unary operator. # # Default: remove sp_not = remove # ignore/add/remove/force # Add or remove space after the '~' (invert) unary operator. # # Default: remove sp_inv = remove # ignore/add/remove/force # Add or remove space after the '&' (address-of) unary operator. This does not # affect the spacing after a '&' that is part of a type. # # Default: remove sp_addr = remove # ignore/add/remove/force # Add or remove space around the '.' or '->' operators. # # Default: remove sp_member = remove # ignore/add/remove/force # Add or remove space after the '*' (dereference) unary operator. This does # not affect the spacing after a '*' that is part of a type. # # Default: remove sp_deref = remove # ignore/add/remove/force # Add or remove space after '+' or '-', as in 'x = -5' or 'y = +7'. # # Default: remove sp_sign = remove # ignore/add/remove/force # Add or remove space between '++' and '--' the word to which it is being # applied, as in '(--x)' or 'y++;'. # # Default: remove sp_incdec = remove # ignore/add/remove/force # Add or remove space before a backslash-newline at the end of a line. # # Default: add sp_before_nl_cont = add # ignore/add/remove/force # (OC) Add or remove space after the scope '+' or '-', as in '-(void) foo;' # or '+(int) bar;'. sp_after_oc_scope = ignore # ignore/add/remove/force # (OC) Add or remove space after the colon in message specs, # i.e. '-(int) f:(int) x;' vs. '-(int) f: (int) x;'. sp_after_oc_colon = ignore # ignore/add/remove/force # (OC) Add or remove space before the colon in message specs, # i.e. '-(int) f: (int) x;' vs. '-(int) f : (int) x;'. sp_before_oc_colon = ignore # ignore/add/remove/force # (OC) Add or remove space after the colon in immutable dictionary expression # 'NSDictionary *test = @{@"foo" :@"bar"};'. sp_after_oc_dict_colon = ignore # ignore/add/remove/force # (OC) Add or remove space before the colon in immutable dictionary expression # 'NSDictionary *test = @{@"foo" :@"bar"};'. sp_before_oc_dict_colon = ignore # ignore/add/remove/force # (OC) Add or remove space after the colon in message specs, # i.e. '[object setValue:1];' vs. '[object setValue: 1];'. sp_after_send_oc_colon = ignore # ignore/add/remove/force # (OC) Add or remove space before the colon in message specs, # i.e. '[object setValue:1];' vs. '[object setValue :1];'. sp_before_send_oc_colon = ignore # ignore/add/remove/force # (OC) Add or remove space after the (type) in message specs, # i.e. '-(int)f: (int) x;' vs. '-(int)f: (int)x;'. sp_after_oc_type = ignore # ignore/add/remove/force # (OC) Add or remove space after the first (type) in message specs, # i.e. '-(int) f:(int)x;' vs. '-(int)f:(int)x;'. sp_after_oc_return_type = ignore # ignore/add/remove/force # (OC) Add or remove space between '@selector' and '(', # i.e. '@selector(msgName)' vs. '@selector (msgName)'. # Also applies to '@protocol()' constructs. sp_after_oc_at_sel = ignore # ignore/add/remove/force # (OC) Add or remove space between '@selector(x)' and the following word, # i.e. '@selector(foo) a:' vs. '@selector(foo)a:'. sp_after_oc_at_sel_parens = ignore # ignore/add/remove/force # (OC) Add or remove space inside '@selector' parentheses, # i.e. '@selector(foo)' vs. '@selector( foo )'. # Also applies to '@protocol()' constructs. sp_inside_oc_at_sel_parens = ignore # ignore/add/remove/force # (OC) Add or remove space before a block pointer caret, # i.e. '^int (int arg){...}' vs. ' ^int (int arg){...}'. sp_before_oc_block_caret = ignore # ignore/add/remove/force # (OC) Add or remove space after a block pointer caret, # i.e. '^int (int arg){...}' vs. '^ int (int arg){...}'. sp_after_oc_block_caret = ignore # ignore/add/remove/force # (OC) Add or remove space between the receiver and selector in a message, # as in '[receiver selector ...]'. sp_after_oc_msg_receiver = ignore # ignore/add/remove/force # (OC) Add or remove space after '@property'. sp_after_oc_property = ignore # ignore/add/remove/force # (OC) Add or remove space between '@synchronized' and the open parenthesis, # i.e. '@synchronized(foo)' vs. '@synchronized (foo)'. sp_after_oc_synchronized = ignore # ignore/add/remove/force # Add or remove space around the ':' in 'b ? t : f'. sp_cond_colon = force # ignore/add/remove/force # Add or remove space before the ':' in 'b ? t : f'. # # Overrides sp_cond_colon. sp_cond_colon_before = force # ignore/add/remove/force # Add or remove space after the ':' in 'b ? t : f'. # # Overrides sp_cond_colon. sp_cond_colon_after = force # ignore/add/remove/force # Add or remove space around the '?' in 'b ? t : f'. sp_cond_question = force # ignore/add/remove/force # Add or remove space before the '?' in 'b ? t : f'. # # Overrides sp_cond_question. sp_cond_question_before = force # ignore/add/remove/force # Add or remove space after the '?' in 'b ? t : f'. # # Overrides sp_cond_question. sp_cond_question_after = force # ignore/add/remove/force # In the abbreviated ternary form '(a ?: b)', add or remove space between '?' # and ':'. # # Overrides all other sp_cond_* options. sp_cond_ternary_short = force # ignore/add/remove/force # Fix the spacing between 'case' and the label. Only 'ignore' and 'force' make # sense here. sp_case_label = force # ignore/add/remove/force # (D) Add or remove space around the D '..' operator. sp_range = ignore # ignore/add/remove/force # Add or remove space after ':' in a Java/C++11 range-based 'for', # as in 'for (Type var : expr)'. sp_after_for_colon = ignore # ignore/add/remove/force # Add or remove space before ':' in a Java/C++11 range-based 'for', # as in 'for (Type var : expr)'. sp_before_for_colon = ignore # ignore/add/remove/force # (D) Add or remove space between 'extern' and '(' as in 'extern (C)'. sp_extern_paren = ignore # ignore/add/remove/force # Add or remove space after the opening of a C++ comment, # i.e. '// A' vs. '//A'. sp_cmt_cpp_start = force # ignore/add/remove/force # If true, space is added with sp_cmt_cpp_start will be added after doxygen # sequences like '///', '///<', '//!' and '//!<'. sp_cmt_cpp_doxygen = false # true/false # If true, space is added with sp_cmt_cpp_start will be added after Qt # translator or meta-data comments like '//:', '//=', and '//~'. sp_cmt_cpp_qttr = false # true/false # Add or remove space between #else or #endif and a trailing comment. sp_endif_cmt = remove # ignore/add/remove/force # Add or remove space after 'new', 'delete' and 'delete[]'. sp_after_new = force # ignore/add/remove/force # Add or remove space between 'new' and '(' in 'new()'. sp_between_new_paren = ignore # ignore/add/remove/force # Add or remove space between ')' and type in 'new(foo) BAR'. sp_after_newop_paren = ignore # ignore/add/remove/force # Add or remove space inside parenthesis of the new operator # as in 'new(foo) BAR'. sp_inside_newop_paren = ignore # ignore/add/remove/force # Add or remove space after the open parenthesis of the new operator, # as in 'new(foo) BAR'. # # Overrides sp_inside_newop_paren. sp_inside_newop_paren_open = ignore # ignore/add/remove/force # Add or remove space before the close parenthesis of the new operator, # as in 'new(foo) BAR'. # # Overrides sp_inside_newop_paren. sp_inside_newop_paren_close = ignore # ignore/add/remove/force # Add or remove space before a trailing or embedded comment. sp_before_tr_emb_cmt = force # ignore/add/remove/force # Number of spaces before a trailing or embedded comment. sp_num_before_tr_emb_cmt = 0 # unsigned number # (Java) Add or remove space between an annotation and the open parenthesis. sp_annotation_paren = ignore # ignore/add/remove/force # If true, vbrace tokens are dropped to the previous token and skipped. sp_skip_vbrace_tokens = false # true/false # Add or remove space after 'noexcept'. sp_after_noexcept = ignore # ignore/add/remove/force # Add or remove space after '_'. sp_vala_after_translation = remove # ignore/add/remove/force # If true, a is inserted after #define. force_tab_after_define = false # true/false # # Indenting options # # The number of columns to indent per level. Usually 2, 3, 4, or 8. # # Default: 8 indent_columns = 4 # unsigned number # The continuation indent. If non-zero, this overrides the indent of '(', '[' # and '=' continuation indents. Negative values are OK; negative value is # absolute and not increased for each '(' or '[' level. # # For FreeBSD, this is set to 4. indent_continue = 0 # number # The continuation indent, only for class header line(s). If non-zero, this # overrides the indent of 'class' continuation indents. indent_continue_class_head = 0 # unsigned number # Whether to indent empty lines (i.e. lines which contain only spaces before # the newline character). indent_single_newlines = false # true/false # The continuation indent for func_*_param if they are true. If non-zero, this # overrides the indent. indent_param = 0 # unsigned number # How to use tabs when indenting code. # # 0: Spaces only # 1: Indent with tabs to brace level, align with spaces (default) # 2: Indent and align with tabs, using spaces when not on a tabstop # # Default: 1 indent_with_tabs = 0 # unsigned number # Whether to indent comments that are not at a brace level with tabs on a # tabstop. Requires indent_with_tabs=2. If false, will use spaces. indent_cmt_with_tabs = false # true/false # Whether to indent strings broken by '\' so that they line up. indent_align_string = false # true/false # The number of spaces to indent multi-line XML strings. # Requires indent_align_string=true. indent_xml_string = 0 # unsigned number # Spaces to indent '{' from level. indent_brace = 0 # unsigned number # Whether braces are indented to the body level. indent_braces = false # true/false # Whether to disable indenting function braces if indent_braces=true. indent_braces_no_func = false # true/false # Whether to disable indenting class braces if indent_braces=true. indent_braces_no_class = false # true/false # Whether to disable indenting struct braces if indent_braces=true. indent_braces_no_struct = false # true/false # Whether to indent based on the size of the brace parent, # i.e. 'if' => 3 spaces, 'for' => 4 spaces, etc. indent_brace_parent = false # true/false # Whether to indent based on the open parenthesis instead of the open brace # in '({\n'. indent_paren_open_brace = false # true/false # (C#) Whether to indent the brace of a C# delegate by another level. indent_cs_delegate_brace = false # true/false # (C#) Whether to indent a C# delegate (to handle delegates with no brace) by # another level. indent_cs_delegate_body = false # true/false # Whether to indent the body of a 'namespace'. indent_namespace = true # true/false # Whether to indent only the first namespace, and not any nested namespaces. # Requires indent_namespace=true. indent_namespace_single_indent = false # true/false # The number of spaces to indent a namespace block. # If set to zero, use the value indent_columns indent_namespace_level = 0 # unsigned number # If the body of the namespace is longer than this number, it won't be # indented. Requires indent_namespace=true. 0 means no limit. indent_namespace_limit = 0 # unsigned number # Whether the 'extern "C"' body is indented. indent_extern = false # true/false # Whether the 'class' body is indented. indent_class = true # true/false # Whether to indent the stuff after a leading base class colon. indent_class_colon = false # true/false # Whether to indent based on a class colon instead of the stuff after the # colon. Requires indent_class_colon=true. indent_class_on_colon = false # true/false # Whether to indent the stuff after a leading class initializer colon. indent_constr_colon = false # true/false # Virtual indent from the ':' for member initializers. # # Default: 2 indent_ctor_init_leading = 2 # unsigned number # Additional indent for constructor initializer list. # Negative values decrease indent down to the first column. indent_ctor_init = 0 # number # Whether to indent 'if' following 'else' as a new block under the 'else'. # If false, 'else\nif' is treated as 'else if' for indenting purposes. indent_else_if = false # true/false # Amount to indent variable declarations after a open brace. # # <0: Relative # >=0: Absolute indent_var_def_blk = 0 # number # Whether to indent continued variable declarations instead of aligning. indent_var_def_cont = false # true/false # Whether to indent continued shift expressions ('<<' and '>>') instead of # aligning. Set align_left_shift=false when enabling this. indent_shift = false # true/false # Whether to force indentation of function definitions to start in column 1. indent_func_def_force_col1 = false # true/false # Whether to indent continued function call parameters one indent level, # rather than aligning parameters under the open parenthesis. indent_func_call_param = false # true/false # Same as indent_func_call_param, but for function definitions. indent_func_def_param = false # true/false # Same as indent_func_call_param, but for function prototypes. indent_func_proto_param = false # true/false # Same as indent_func_call_param, but for class declarations. indent_func_class_param = false # true/false # Same as indent_func_call_param, but for class variable constructors. indent_func_ctor_var_param = false # true/false # Same as indent_func_call_param, but for template parameter lists. indent_template_param = false # true/false # Double the indent for indent_func_xxx_param options. # Use both values of the options indent_columns and indent_param. indent_func_param_double = false # true/false # Indentation column for standalone 'const' qualifier on a function # prototype. indent_func_const = 0 # unsigned number # Indentation column for standalone 'throw' qualifier on a function # prototype. indent_func_throw = 0 # unsigned number # The number of spaces to indent a continued '->' or '.'. # Usually set to 0, 1, or indent_columns. indent_member = 1 # unsigned number # Whether lines broken at '.' or '->' should be indented by a single indent. # The indent_member option will not be effective if this is set to true. indent_member_single = false # true/false # Spaces to indent single line ('//') comments on lines before code. indent_sing_line_comments = 0 # unsigned number # Whether to indent trailing single line ('//') comments relative to the code # instead of trying to keep the same absolute column. indent_relative_single_line_comments = false # true/false # Spaces to indent 'case' from 'switch'. Usually 0 or indent_columns. indent_switch_case = 0 # unsigned number # Whether to indent preprocessor statements inside of switch statements. # # Default: true indent_switch_pp = true # true/false # Spaces to shift the 'case' line, without affecting any other lines. # Usually 0. indent_case_shift = 0 # unsigned number # Spaces to indent '{' from 'case'. By default, the brace will appear under # the 'c' in case. Usually set to 0 or indent_columns. Negative values are OK. indent_case_brace = 0 # number # Whether to indent comments found in first column. indent_col1_comment = false # true/false # Whether to indent multi string literal in first column. indent_col1_multi_string_literal = false # true/false # How to indent goto labels. # # >0: Absolute column where 1 is the leftmost column # <=0: Subtract from brace indent # # Default: 1 indent_label = 1 # number # Same as indent_label, but for access specifiers that are followed by a # colon. # # Default: 1 indent_access_spec = 1 # number # Whether to indent the code after an access specifier by one level. # If true, this option forces 'indent_access_spec=0'. indent_access_spec_body = false # true/false # If an open parenthesis is followed by a newline, whether to indent the next # line so that it lines up after the open parenthesis (not recommended). indent_paren_nl = false # true/false # How to indent a close parenthesis after a newline. # # 0: Indent to body level (default) # 1: Align under the open parenthesis # 2: Indent to the brace level indent_paren_close = 0 # unsigned number # Whether to indent the open parenthesis of a function definition, # if the parenthesis is on its own line. indent_paren_after_func_def = false # true/false # Whether to indent the open parenthesis of a function declaration, # if the parenthesis is on its own line. indent_paren_after_func_decl = false # true/false # Whether to indent the open parenthesis of a function call, # if the parenthesis is on its own line. indent_paren_after_func_call = false # true/false # Whether to indent a comma when inside a parenthesis. # If true, aligns under the open parenthesis. indent_comma_paren = false # true/false # Whether to indent a Boolean operator when inside a parenthesis. # If true, aligns under the open parenthesis. indent_bool_paren = false # true/false # Whether to indent a semicolon when inside a for parenthesis. # If true, aligns under the open for parenthesis. indent_semicolon_for_paren = false # true/false # Whether to align the first expression to following ones # if indent_bool_paren=true. indent_first_bool_expr = false # true/false # Whether to align the first expression to following ones # if indent_semicolon_for_paren=true. indent_first_for_expr = false # true/false # If an open square is followed by a newline, whether to indent the next line # so that it lines up after the open square (not recommended). indent_square_nl = false # true/false # (ESQL/C) Whether to preserve the relative indent of 'EXEC SQL' bodies. indent_preserve_sql = false # true/false # Whether to align continued statements at the '='. If false or if the '=' is # followed by a newline, the next line is indent one tab. # # Default: true indent_align_assign = true # true/false # Whether to align continued statements at the '('. If false or the '(' is # followed by a newline, the next line indent is one tab. # # Default: true indent_align_paren = true # true/false # (OC) Whether to indent Objective-C blocks at brace level instead of usual # rules. indent_oc_block = false # true/false # (OC) Indent for Objective-C blocks in a message relative to the parameter # name. # # =0: Use indent_oc_block rules # >0: Use specified number of spaces to indent indent_oc_block_msg = 0 # unsigned number # (OC) Minimum indent for subsequent parameters indent_oc_msg_colon = 0 # unsigned number # (OC) Whether to prioritize aligning with initial colon (and stripping spaces # from lines, if necessary). # # Default: true indent_oc_msg_prioritize_first_colon = true # true/false # (OC) Whether to indent blocks the way that Xcode does by default # (from the keyword if the parameter is on its own line; otherwise, from the # previous indentation level). Requires indent_oc_block_msg=true. indent_oc_block_msg_xcode_style = true # true/false # (OC) Whether to indent blocks from where the brace is, relative to a # message keyword. Requires indent_oc_block_msg=true. indent_oc_block_msg_from_keyword = true # true/false # (OC) Whether to indent blocks from where the brace is, relative to a message # colon. Requires indent_oc_block_msg=true. indent_oc_block_msg_from_colon = true # true/false # (OC) Whether to indent blocks from where the block caret is. # Requires indent_oc_block_msg=true. indent_oc_block_msg_from_caret = true # true/false # (OC) Whether to indent blocks from where the brace caret is. # Requires indent_oc_block_msg=true. indent_oc_block_msg_from_brace = true # true/false # When indenting after virtual brace open and newline add further spaces to # reach this minimum indent. indent_min_vbrace_open = 0 # unsigned number # Whether to add further spaces after regular indent to reach next tabstop # when identing after virtual brace open and newline. indent_vbrace_open_on_tabstop = false # true/false # How to indent after a brace followed by another token (not a newline). # true: indent all contained lines to match the token # false: indent all contained lines to match the brace # # Default: true indent_token_after_brace = true # true/false # Whether to indent the body of a C++11 lambda. indent_cpp_lambda_body = false # true/false # (C#) Whether to indent a 'using' block if no braces are used. # # Default: true indent_using_block = true # true/false # How to indent the continuation of ternary operator. # # 0: Off (default) # 1: When the `if_false` is a continuation, indent it under `if_false` # 2: When the `:` is a continuation, indent it under `?` indent_ternary_operator = 0 # unsigned number # If true, the indentation of the chunks after a `return new` sequence will be set at return indentation column. indent_off_after_return_new = false # true/false # If true, the tokens after return are indented with regular single indentation. By default (false) the indentation is after the return token. indent_single_after_return = false # true/false # Whether to ignore indent and alignment for 'asm' blocks (i.e. assume they # have their own indentation). indent_ignore_asm_block = false # true/false # # Newline adding and removing options # # Whether to collapse empty blocks between '{' and '}'. nl_collapse_empty_body = false # true/false # Don't split one-line braced assignments, as in 'foo_t f = { 1, 2 };'. nl_assign_leave_one_liners = true # true/false # Don't split one-line braced statements inside a 'class xx { }' body. nl_class_leave_one_liners = false # true/false # Don't split one-line enums, as in 'enum foo { BAR = 15 };' nl_enum_leave_one_liners = false # true/false # Don't split one-line get or set functions. nl_getset_leave_one_liners = false # true/false # (C#) Don't split one-line property get or set functions. nl_cs_property_leave_one_liners = false # true/false # Don't split one-line function definitions, as in 'int foo() { return 0; }'. nl_func_leave_one_liners = false # true/false # Don't split one-line C++11 lambdas, as in '[]() { return 0; }'. nl_cpp_lambda_leave_one_liners = false # true/false # Don't split one-line if/else statements, as in 'if(...) b++;'. nl_if_leave_one_liners = false # true/false # Don't split one-line while statements, as in 'while(...) b++;'. nl_while_leave_one_liners = false # true/false # Don't split one-line for statements, as in 'for(...) b++;'. nl_for_leave_one_liners = false # true/false # (OC) Don't split one-line Objective-C messages. nl_oc_msg_leave_one_liner = false # true/false # (OC) Add or remove newline between method declaration and '{'. nl_oc_mdef_brace = ignore # ignore/add/remove/force # (OC) Add or remove newline between Objective-C block signature and '{'. nl_oc_block_brace = ignore # ignore/add/remove/force # (OC) Add or remove newline between '@interface' and '{'. nl_oc_interface_brace = ignore # ignore/add/remove/force # (OC) Add or remove newline between '@implementation' and '{'. nl_oc_implementation_brace = ignore # ignore/add/remove/force # Add or remove newlines at the start of the file. nl_start_of_file = ignore # ignore/add/remove/force # The minimum number of newlines at the start of the file (only used if # nl_start_of_file is 'add' or 'force'). nl_start_of_file_min = 0 # unsigned number # Add or remove newline at the end of the file. nl_end_of_file = ignore # ignore/add/remove/force # The minimum number of newlines at the end of the file (only used if # nl_end_of_file is 'add' or 'force'). nl_end_of_file_min = 0 # unsigned number # Add or remove newline between '=' and '{'. nl_assign_brace = ignore # ignore/add/remove/force # (D) Add or remove newline between '=' and '['. nl_assign_square = ignore # ignore/add/remove/force # Add or remove newline between '[]' and '{'. nl_tsquare_brace = ignore # ignore/add/remove/force # (D) Add or remove newline after '= ['. Will also affect the newline before # the ']'. nl_after_square_assign = ignore # ignore/add/remove/force # Add or remove newline between a function call's ')' and '{', as in # 'list_for_each(item, &list) { }'. nl_fcall_brace = ignore # ignore/add/remove/force # Add or remove newline between 'enum' and '{'. nl_enum_brace = remove # ignore/add/remove/force # Add or remove newline between 'enum' and 'class'. nl_enum_class = ignore # ignore/add/remove/force # Add or remove newline between 'enum class' and the identifier. nl_enum_class_identifier = ignore # ignore/add/remove/force # Add or remove newline between 'enum class' type and ':'. nl_enum_identifier_colon = ignore # ignore/add/remove/force # Add or remove newline between 'enum class identifier :' and type. nl_enum_colon_type = ignore # ignore/add/remove/force # Add or remove newline between 'struct and '{'. nl_struct_brace = remove # ignore/add/remove/force # Add or remove newline between 'union' and '{'. nl_union_brace = remove # ignore/add/remove/force # Add or remove newline between 'if' and '{'. nl_if_brace = remove # ignore/add/remove/force # Add or remove newline between '}' and 'else'. nl_brace_else = remove # ignore/add/remove/force # Add or remove newline between 'else if' and '{'. If set to ignore, # nl_if_brace is used instead. nl_elseif_brace = remove # ignore/add/remove/force # Add or remove newline between 'else' and '{'. nl_else_brace = remove # ignore/add/remove/force # Add or remove newline between 'else' and 'if'. nl_else_if = remove # ignore/add/remove/force # Add or remove newline before 'if'/'else if' closing parenthesis. nl_before_if_closing_paren = ignore # ignore/add/remove/force # Add or remove newline between '}' and 'finally'. nl_brace_finally = remove # ignore/add/remove/force # Add or remove newline between 'finally' and '{'. nl_finally_brace = remove # ignore/add/remove/force # Add or remove newline between 'try' and '{'. nl_try_brace = remove # ignore/add/remove/force # Add or remove newline between get/set and '{'. nl_getset_brace = remove # ignore/add/remove/force # Add or remove newline between 'for' and '{'. nl_for_brace = remove # ignore/add/remove/force # Add or remove newline before the '{' of a 'catch' statement, as in # 'catch (decl) {'. nl_catch_brace = remove # ignore/add/remove/force # (OC) Add or remove newline before the '{' of a '@catch' statement, as in # '@catch (decl) {'. If set to ignore, nl_catch_brace is used. nl_oc_catch_brace = ignore # ignore/add/remove/force # Add or remove newline between '}' and 'catch'. nl_brace_catch = remove # ignore/add/remove/force # (OC) Add or remove newline between '}' and '@catch'. If set to ignore, # nl_brace_catch is used. nl_oc_brace_catch = ignore # ignore/add/remove/force # Add or remove newline between '}' and ']'. nl_brace_square = remove # ignore/add/remove/force # Add or remove newline between '}' and ')' in a function invocation. nl_brace_fparen = remove # ignore/add/remove/force # Add or remove newline between 'while' and '{'. nl_while_brace = remove # ignore/add/remove/force # (D) Add or remove newline between 'scope (x)' and '{'. nl_scope_brace = ignore # ignore/add/remove/force # (D) Add or remove newline between 'unittest' and '{'. nl_unittest_brace = ignore # ignore/add/remove/force # (D) Add or remove newline between 'version (x)' and '{'. nl_version_brace = ignore # ignore/add/remove/force # (C#) Add or remove newline between 'using' and '{'. nl_using_brace = remove # ignore/add/remove/force # Add or remove newline between two open or close braces. Due to general # newline/brace handling, REMOVE may not work. nl_brace_brace = ignore # ignore/add/remove/force # Add or remove newline between 'do' and '{'. nl_do_brace = remove # ignore/add/remove/force # Add or remove newline between '}' and 'while' of 'do' statement. nl_brace_while = remove # ignore/add/remove/force # Add or remove newline between 'switch' and '{'. nl_switch_brace = remove # ignore/add/remove/force # Add or remove newline between 'synchronized' and '{'. nl_synchronized_brace = ignore # ignore/add/remove/force # Add a newline between ')' and '{' if the ')' is on a different line than the # if/for/etc. # # Overrides nl_for_brace, nl_if_brace, nl_switch_brace, nl_while_switch and # nl_catch_brace. nl_multi_line_cond = false # true/false # Force a newline in a define after the macro name for multi-line defines. nl_multi_line_define = false # true/false # Whether to add a newline before 'case', and a blank line before a 'case' # statement that follows a ';' or '}'. nl_before_case = false # true/false # Whether to add a newline after a 'case' statement. nl_after_case = false # true/false # Add or remove newline between a case ':' and '{'. # # Overrides nl_after_case. nl_case_colon_brace = ignore # ignore/add/remove/force # Add or remove newline between ')' and 'throw'. nl_before_throw = remove # ignore/add/remove/force # Add or remove newline between 'namespace' and '{'. nl_namespace_brace = remove # ignore/add/remove/force # Add or remove newline between 'template<>' and whatever follows. nl_template_class = ignore # ignore/add/remove/force # Add or remove newline between 'class' and '{'. nl_class_brace = remove # ignore/add/remove/force # Add or remove newline before or after (depending on pos_class_comma, # may not be IGNORE) each',' in the base class list. nl_class_init_args = remove # ignore/add/remove/force # Add or remove newline after each ',' in the constructor member # initialization. Related to nl_constr_colon, pos_constr_colon and # pos_constr_comma. nl_constr_init_args = ignore # ignore/add/remove/force # Add or remove newline before first element, after comma, and after last # element, in 'enum'. nl_enum_own_lines = ignore # ignore/add/remove/force # Add or remove newline between return type and function name in a function # definition. nl_func_type_name = remove # ignore/add/remove/force # Add or remove newline between return type and function name inside a class # definition. If set to ignore, nl_func_type_name or nl_func_proto_type_name # is used instead. nl_func_type_name_class = remove # ignore/add/remove/force # Add or remove newline between class specification and '::' # in 'void A::f() { }'. Only appears in separate member implementation (does # not appear with in-line implementation). nl_func_class_scope = ignore # ignore/add/remove/force # Add or remove newline between function scope and name, as in # 'void A :: f() { }'. nl_func_scope_name = ignore # ignore/add/remove/force # Add or remove newline between return type and function name in a prototype. nl_func_proto_type_name = remove # ignore/add/remove/force # Add or remove newline between a function name and the opening '(' in the # declaration. nl_func_paren = remove # ignore/add/remove/force # Overrides nl_func_paren for functions with no parameters. nl_func_paren_empty = ignore # ignore/add/remove/force # Add or remove newline between a function name and the opening '(' in the # definition. nl_func_def_paren = remove # ignore/add/remove/force # Overrides nl_func_def_paren for functions with no parameters. nl_func_def_paren_empty = ignore # ignore/add/remove/force # Add or remove newline between a function name and the opening '(' in the # call. nl_func_call_paren = ignore # ignore/add/remove/force # Overrides nl_func_call_paren for functions with no parameters. nl_func_call_paren_empty = ignore # ignore/add/remove/force # Add or remove newline after '(' in a function declaration. nl_func_decl_start = remove # ignore/add/remove/force # Add or remove newline after '(' in a function definition. nl_func_def_start = remove # ignore/add/remove/force # Overrides nl_func_decl_start when there is only one parameter. nl_func_decl_start_single = ignore # ignore/add/remove/force # Overrides nl_func_def_start when there is only one parameter. nl_func_def_start_single = ignore # ignore/add/remove/force # Whether to add a newline after '(' in a function declaration if '(' and ')' # are in different lines. If false, nl_func_decl_start is used instead. nl_func_decl_start_multi_line = false # true/false # Whether to add a newline after '(' in a function definition if '(' and ')' # are in different lines. If false, nl_func_def_start is used instead. nl_func_def_start_multi_line = false # true/false # Add or remove newline after each ',' in a function declaration. nl_func_decl_args = ignore # ignore/add/remove/force # Add or remove newline after each ',' in a function definition. nl_func_def_args = ignore # ignore/add/remove/force # Whether to add a newline after each ',' in a function declaration if '(' # and ')' are in different lines. If false, nl_func_decl_args is used instead. nl_func_decl_args_multi_line = false # true/false # Whether to add a newline after each ',' in a function definition if '(' # and ')' are in different lines. If false, nl_func_def_args is used instead. nl_func_def_args_multi_line = false # true/false # Add or remove newline before the ')' in a function declaration. nl_func_decl_end = remove # ignore/add/remove/force # Add or remove newline before the ')' in a function definition. nl_func_def_end = remove # ignore/add/remove/force # Overrides nl_func_decl_end when there is only one parameter. nl_func_decl_end_single = ignore # ignore/add/remove/force # Overrides nl_func_def_end when there is only one parameter. nl_func_def_end_single = ignore # ignore/add/remove/force # Whether to add a newline before ')' in a function declaration if '(' and ')' # are in different lines. If false, nl_func_decl_end is used instead. nl_func_decl_end_multi_line = false # true/false # Whether to add a newline before ')' in a function definition if '(' and ')' # are in different lines. If false, nl_func_def_end is used instead. nl_func_def_end_multi_line = false # true/false # Add or remove newline between '()' in a function declaration. nl_func_decl_empty = remove # ignore/add/remove/force # Add or remove newline between '()' in a function definition. nl_func_def_empty = remove # ignore/add/remove/force # Add or remove newline between '()' in a function call. nl_func_call_empty = ignore # ignore/add/remove/force # Whether to add a newline after '(' in a function call, # has preference over nl_func_call_start_multi_line. nl_func_call_start = ignore # ignore/add/remove/force # Whether to add a newline after '(' in a function call if '(' and ')' are in # different lines. nl_func_call_start_multi_line = false # true/false # Whether to add a newline after each ',' in a function call if '(' and ')' # are in different lines. nl_func_call_args_multi_line = false # true/false # Whether to add a newline before ')' in a function call if '(' and ')' are in # different lines. nl_func_call_end_multi_line = false # true/false # (OC) Whether to put each Objective-C message parameter on a separate line. # See nl_oc_msg_leave_one_liner. nl_oc_msg_args = false # true/false # Add or remove newline between function signature and '{'. nl_fdef_brace = remove # ignore/add/remove/force # Add or remove newline between function signature and '{', # if signature ends with ')'. Overrides nl_fdef_brace. nl_fdef_brace_cond = ignore # ignore/add/remove/force # Add or remove newline between C++11 lambda signature and '{'. nl_cpp_ldef_brace = ignore # ignore/add/remove/force # Add or remove newline between 'return' and the return expression. nl_return_expr = remove # ignore/add/remove/force # Whether to add a newline after semicolons, except in 'for' statements. nl_after_semicolon = false # true/false # (Java) Add or remove newline between the ')' and '{{' of the double brace # initializer. nl_paren_dbrace_open = ignore # ignore/add/remove/force # Whether to add a newline after the type in an unnamed temporary # direct-list-initialization. nl_type_brace_init_lst = ignore # ignore/add/remove/force # Whether to add a newline after the open brace in an unnamed temporary # direct-list-initialization. nl_type_brace_init_lst_open = ignore # ignore/add/remove/force # Whether to add a newline before the close brace in an unnamed temporary # direct-list-initialization. nl_type_brace_init_lst_close = ignore # ignore/add/remove/force # Whether to add a newline after '{'. This also adds a newline before the # matching '}'. nl_after_brace_open = false # true/false # Whether to add a newline between the open brace and a trailing single-line # comment. Requires nl_after_brace_open=true. nl_after_brace_open_cmt = false # true/false # Whether to add a newline after a virtual brace open with a non-empty body. # These occur in un-braced if/while/do/for statement bodies. nl_after_vbrace_open = false # true/false # Whether to add a newline after a virtual brace open with an empty body. # These occur in un-braced if/while/do/for statement bodies. nl_after_vbrace_open_empty = false # true/false # Whether to add a newline after '}'. Does not apply if followed by a # necessary ';'. nl_after_brace_close = false # true/false # Whether to add a newline after a virtual brace close, # as in 'if (foo) a++; return;'. nl_after_vbrace_close = false # true/false # Add or remove newline between the close brace and identifier, # as in 'struct { int a; } b;'. Affects enumerations, unions and # structures. If set to ignore, uses nl_after_brace_close. nl_brace_struct_var = ignore # ignore/add/remove/force # Whether to alter newlines in '#define' macros. nl_define_macro = false # true/false # Whether to alter newlines between consecutive parenthesis closes. The number # of closing parentheses in a line will depend on respective open parenthesis # lines. nl_squeeze_paren_close = false # true/false # Whether to remove blanks after '#ifxx' and '#elxx', or before '#elxx' and # '#endif'. Does not affect top-level #ifdefs. nl_squeeze_ifdef = false # true/false # Makes the nl_squeeze_ifdef option affect the top-level #ifdefs as well. nl_squeeze_ifdef_top_level = false # true/false # Add or remove blank line before 'if'. nl_before_if = ignore # ignore/add/remove/force # Add or remove blank line after 'if' statement. Add/Force work only if the # next token is not a closing brace. nl_after_if = ignore # ignore/add/remove/force # Add or remove blank line before 'for'. nl_before_for = ignore # ignore/add/remove/force # Add or remove blank line after 'for' statement. nl_after_for = ignore # ignore/add/remove/force # Add or remove blank line before 'while'. nl_before_while = ignore # ignore/add/remove/force # Add or remove blank line after 'while' statement. nl_after_while = ignore # ignore/add/remove/force # Add or remove blank line before 'switch'. nl_before_switch = ignore # ignore/add/remove/force # Add or remove blank line after 'switch' statement. nl_after_switch = ignore # ignore/add/remove/force # Add or remove blank line before 'synchronized'. nl_before_synchronized = ignore # ignore/add/remove/force # Add or remove blank line after 'synchronized' statement. nl_after_synchronized = ignore # ignore/add/remove/force # Add or remove blank line before 'do'. nl_before_do = ignore # ignore/add/remove/force # Add or remove blank line after 'do/while' statement. nl_after_do = ignore # ignore/add/remove/force # Whether to put a blank line before 'return' statements, unless after an open # brace. nl_before_return = false # true/false # Whether to put a blank line after 'return' statements, unless followed by a # close brace. nl_after_return = false # true/false # Whether to double-space commented-entries in 'struct'/'union'/'enum'. nl_ds_struct_enum_cmt = false # true/false # Whether to force a newline before '}' of a 'struct'/'union'/'enum'. # (Lower priority than eat_blanks_before_close_brace.) nl_ds_struct_enum_close_brace = false # true/false # Add or remove newline before or after (depending on pos_class_colon) a class # colon, as in 'class Foo : public Bar'. nl_class_colon = ignore # ignore/add/remove/force # Add or remove newline around a class constructor colon. The exact position # depends on nl_constr_init_args, pos_constr_colon and pos_constr_comma. nl_constr_colon = ignore # ignore/add/remove/force # Whether to collapse a two-line namespace, like 'namespace foo\n{ decl; }' # into a single line. If true, prevents other brace newline rules from turning # such code into four lines. nl_namespace_two_to_one_liner = false # true/false # Whether to remove a newline in simple unbraced if statements, turning them # into one-liners, as in 'if(b)\n i++;' => 'if(b) i++;'. nl_create_if_one_liner = false # true/false # Whether to remove a newline in simple unbraced for statements, turning them # into one-liners, as in 'for (...)\n stmt;' => 'for (...) stmt;'. nl_create_for_one_liner = false # true/false # Whether to remove a newline in simple unbraced while statements, turning # them into one-liners, as in 'while (expr)\n stmt;' => 'while (expr) stmt;'. nl_create_while_one_liner = false # true/false # Whether to collapse a function definition whose body (not counting braces) # is only one line so that the entire definition (prototype, braces, body) is # a single line. nl_create_func_def_one_liner = false # true/false # Whether to split one-line simple unbraced if statements into two lines by # adding a newline, as in 'if(b) i++;'. nl_split_if_one_liner = false # true/false # Whether to split one-line simple unbraced for statements into two lines by # adding a newline, as in 'for (...) stmt;'. nl_split_for_one_liner = false # true/false # Whether to split one-line simple unbraced while statements into two lines by # adding a newline, as in 'while (expr) stmt;'. nl_split_while_one_liner = false # true/false # # Blank line options # # The maximum number of consecutive newlines (3 = 2 blank lines). nl_max = 0 # unsigned number # The maximum number of consecutive newlines in a function. nl_max_blank_in_func = 0 # unsigned number # The number of newlines before a function prototype. nl_before_func_body_proto = 0 # unsigned number # The number of newlines before a multi-line function definition. nl_before_func_body_def = 0 # unsigned number # The number of newlines before a class constructor/destructor prototype. nl_before_func_class_proto = 0 # unsigned number # The number of newlines before a class constructor/destructor definition. nl_before_func_class_def = 0 # unsigned number # The number of newlines after a function prototype. nl_after_func_proto = 0 # unsigned number # The number of newlines after a function prototype, if not followed by # another function prototype. nl_after_func_proto_group = 2 # unsigned number # The number of newlines after a class constructor/destructor prototype. nl_after_func_class_proto = 0 # unsigned number # The number of newlines after a class constructor/destructor prototype, # if not followed by another constructor/destructor prototype. nl_after_func_class_proto_group = 0 # unsigned number # Whether one-line method definitions inside a class body should be treated # as if they were prototypes for the purposes of adding newlines. # # Requires nl_class_leave_one_liners=true. Overrides nl_before_func_body_def # and nl_before_func_class_def for one-liners. nl_class_leave_one_liner_groups = false # true/false # The number of newlines after '}' of a multi-line function body. nl_after_func_body = 2 # unsigned number # The number of newlines after '}' of a multi-line function body in a class # declaration. Also affects class constructors/destructors. # # Overrides nl_after_func_body. nl_after_func_body_class = 2 # unsigned number # The number of newlines after '}' of a single line function body. Also # affects class constructors/destructors. # # Overrides nl_after_func_body and nl_after_func_body_class. nl_after_func_body_one_liner = 0 # unsigned number # The number of blank lines after a block of variable definitions at the top # of a function body. # # 0 = No change (default). nl_func_var_def_blk = 0 # unsigned number # The number of newlines before a block of typedefs. If nl_after_access_spec # is non-zero, that option takes precedence. # # 0 = No change (default). nl_typedef_blk_start = 0 # unsigned number # The number of newlines after a block of typedefs. # # 0 = No change (default). nl_typedef_blk_end = 0 # unsigned number # The maximum number of consecutive newlines within a block of typedefs. # # 0 = No change (default). nl_typedef_blk_in = 0 # unsigned number # The number of newlines before a block of variable definitions not at the top # of a function body. If nl_after_access_spec is non-zero, that option takes # precedence. # # 0 = No change (default). nl_var_def_blk_start = 0 # unsigned number # The number of newlines after a block of variable definitions not at the top # of a function body. # # 0 = No change (default). nl_var_def_blk_end = 0 # unsigned number # The maximum number of consecutive newlines within a block of variable # definitions. # # 0 = No change (default). nl_var_def_blk_in = 0 # unsigned number # The minimum number of newlines before a multi-line comment. # Doesn't apply if after a brace open or another multi-line comment. nl_before_block_comment = 0 # unsigned number # The minimum number of newlines before a single-line C comment. # Doesn't apply if after a brace open or other single-line C comments. nl_before_c_comment = 0 # unsigned number # The minimum number of newlines before a CPP comment. # Doesn't apply if after a brace open or other CPP comments. nl_before_cpp_comment = 0 # unsigned number # Whether to force a newline after a multi-line comment. nl_after_multiline_comment = false # true/false # Whether to force a newline after a label's colon. nl_after_label_colon = false # true/false # The number of newlines after '}' or ';' of a struct/enum/union definition. nl_after_struct = 0 # unsigned number # The number of newlines before a class definition. nl_before_class = 0 # unsigned number # The number of newlines after '}' or ';' of a class definition. nl_after_class = 0 # unsigned number # The number of newlines before an access specifier label. This also includes # the Qt-specific 'signals:' and 'slots:'. Will not change the newline count # if after a brace open. # # 0 = No change (default). nl_before_access_spec = 0 # unsigned number # The number of newlines after an access specifier label. This also includes # the Qt-specific 'signals:' and 'slots:'. Will not change the newline count # if after a brace open. # # 0 = No change (default). # # Overrides nl_typedef_blk_start and nl_var_def_blk_start. nl_after_access_spec = 0 # unsigned number # The number of newlines between a function definition and the function # comment, as in '// comment\n void foo() {...}'. # # 0 = No change (default). nl_comment_func_def = 0 # unsigned number # The number of newlines after a try-catch-finally block that isn't followed # by a brace close. # # 0 = No change (default). nl_after_try_catch_finally = 0 # unsigned number # (C#) The number of newlines before and after a property, indexer or event # declaration. # # 0 = No change (default). nl_around_cs_property = 0 # unsigned number # (C#) The number of newlines between the get/set/add/remove handlers. # # 0 = No change (default). nl_between_get_set = 0 # unsigned number # (C#) Add or remove newline between property and the '{'. nl_property_brace = ignore # ignore/add/remove/force # The number of newlines after '{' of a namespace. This also adds newlines # before the matching '}'. # # 0 = Apply eat_blanks_after_open_brace or eat_blanks_before_close_brace if # applicable, otherwise no change. # # Overrides eat_blanks_after_open_brace and eat_blanks_before_close_brace. nl_inside_namespace = 0 # unsigned number # Whether to remove blank lines after '{'. eat_blanks_after_open_brace = false # true/false # Whether to remove blank lines before '}'. eat_blanks_before_close_brace = false # true/false # How aggressively to remove extra newlines not in preprocessor. # # 0: No change (default) # 1: Remove most newlines not handled by other config # 2: Remove all newlines and reformat completely by config nl_remove_extra_newlines = 0 # unsigned number # (Java) Add or remove newline after an annotation statement. Only affects # annotations that are after a newline. nl_after_annotation = ignore # ignore/add/remove/force # (Java) Add or remove newline between two annotations. nl_between_annotation = ignore # ignore/add/remove/force # # Positioning options # # The position of arithmetic operators in wrapped expressions. pos_arith = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force # The position of assignment in wrapped expressions. Do not affect '=' # followed by '{'. pos_assign = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force # The position of Boolean operators in wrapped expressions. pos_bool = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force # The position of comparison operators in wrapped expressions. pos_compare = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force # The position of conditional operators, as in the '?' and ':' of # 'expr ? stmt : stmt', in wrapped expressions. pos_conditional = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force # The position of the comma in wrapped expressions. pos_comma = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force # The position of the comma in enum entries. pos_enum_comma = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force # The position of the comma in the base class list if there is more than one # line. Affects nl_class_init_args. pos_class_comma = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force # The position of the comma in the constructor initialization list. # Related to nl_constr_colon, nl_constr_init_args and pos_constr_colon. pos_constr_comma = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force # The position of trailing/leading class colon, between class and base class # list. Affects nl_class_colon. pos_class_colon = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force # The position of colons between constructor and member initialization. # Related to nl_constr_colon, nl_constr_init_args and pos_constr_comma. pos_constr_colon = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force # # Line splitting options # # Try to limit code width to N columns. code_width = 0 # unsigned number # Whether to fully split long 'for' statements at semi-colons. ls_for_split_full = false # true/false # Whether to fully split long function prototypes/calls at commas. # The option ls_code_width has priority over the option ls_func_split_full. ls_func_split_full = false # true/false # Whether to split lines as close to code_width as possible and ignore some # groupings. # The option ls_code_width has priority over the option ls_func_split_full. ls_code_width = false # true/false # # Code alignment options (not left column spaces/tabs) # # Whether to keep non-indenting tabs. align_keep_tabs = false # true/false # Whether to use tabs for aligning. align_with_tabs = false # true/false # Whether to bump out to the next tab when aligning. align_on_tabstop = false # true/false # Whether to right-align numbers. align_number_right = false # true/false # Whether to keep whitespace not required for alignment. align_keep_extra_space = true # true/false # Whether to align variable definitions in prototypes and functions. align_func_params = false # true/false # The span for aligning parameter definitions in function on parameter name. # # 0 = Don't align (default). align_func_params_span = 0 # unsigned number # The threshold for aligning function parameter definitions. # Use a negative number for absolute thresholds. # # 0 = No limit (default). align_func_params_thresh = 0 # number # The gap for aligning function parameter definitions. align_func_params_gap = 0 # unsigned number # The span for aligning constructor value. # # 0 = Don't align (default). align_constr_value_span = 0 # unsigned number # The threshold for aligning constructor value. # Use a negative number for absolute thresholds. # # 0 = No limit (default). align_constr_value_thresh = 0 # number # The gap for aligning constructor value. align_constr_value_gap = 0 # unsigned number # Whether to align parameters in single-line functions that have the same # name. The function names must already be aligned with each other. align_same_func_call_params = false # true/false # The span for aligning function-call parameters for single line functions. # # 0 = Don't align (default). align_same_func_call_params_span = 0 # unsigned number # The threshold for aligning function-call parameters for single line # functions. # Use a negative number for absolute thresholds. # # 0 = No limit (default). align_same_func_call_params_thresh = 0 # number # The span for aligning variable definitions. # # 0 = Don't align (default). align_var_def_span = 0 # unsigned number # How to consider (or treat) the '*' in the alignment of variable definitions. # # 0: Part of the type 'void * foo;' (default) # 1: Part of the variable 'void *foo;' # 2: Dangling 'void *foo;' # Dangling: the '*' will not be taken into account when aligning. align_var_def_star_style = 0 # unsigned number # How to consider (or treat) the '&' in the alignment of variable definitions. # # 0: Part of the type 'long & foo;' (default) # 1: Part of the variable 'long &foo;' # 2: Dangling 'long &foo;' # Dangling: the '&' will not be taken into account when aligning. align_var_def_amp_style = 0 # unsigned number # The threshold for aligning variable definitions. # Use a negative number for absolute thresholds. # # 0 = No limit (default). align_var_def_thresh = 0 # number # The gap for aligning variable definitions. align_var_def_gap = 0 # unsigned number # Whether to align the colon in struct bit fields. align_var_def_colon = false # true/false # The gap for aligning the colon in struct bit fields. align_var_def_colon_gap = 0 # unsigned number # Whether to align any attribute after the variable name. align_var_def_attribute = false # true/false # Whether to align inline struct/enum/union variable definitions. align_var_def_inline = false # true/false # The span for aligning on '=' in assignments. # # 0 = Don't align (default). align_assign_span = 0 # unsigned number # The span for aligning on '=' in function prototype modifier. # # 0 = Don't align (default). align_assign_func_proto_span = 0 # unsigned number # The threshold for aligning on '=' in assignments. # Use a negative number for absolute thresholds. # # 0 = No limit (default). align_assign_thresh = 0 # number # How to apply align_assign_span to function declaration "assignments", i.e. # 'virtual void foo() = 0' or '~foo() = {default|delete}'. # # 0: Align with other assignments (default) # 1: Align with each other, ignoring regular assignments # 2: Don't align align_assign_decl_func = 0 # unsigned number # The span for aligning on '=' in enums. # # 0 = Don't align (default). align_enum_equ_span = 0 # unsigned number # The threshold for aligning on '=' in enums. # Use a negative number for absolute thresholds. # # 0 = no limit (default). align_enum_equ_thresh = 0 # number # The span for aligning class member definitions. # # 0 = Don't align (default). align_var_class_span = 0 # unsigned number # The threshold for aligning class member definitions. # Use a negative number for absolute thresholds. # # 0 = No limit (default). align_var_class_thresh = 0 # number # The gap for aligning class member definitions. align_var_class_gap = 0 # unsigned number # The span for aligning struct/union member definitions. # # 0 = Don't align (default). align_var_struct_span = 0 # unsigned number # The threshold for aligning struct/union member definitions. # Use a negative number for absolute thresholds. # # 0 = No limit (default). align_var_struct_thresh = 0 # number # The gap for aligning struct/union member definitions. align_var_struct_gap = 0 # unsigned number # The span for aligning struct initializer values. # # 0 = Don't align (default). align_struct_init_span = 0 # unsigned number # The span for aligning single-line typedefs. # # 0 = Don't align (default). align_typedef_span = 0 # unsigned number # The minimum space between the type and the synonym of a typedef. align_typedef_gap = 0 # unsigned number # How to align typedef'd functions with other typedefs. # # 0: Don't mix them at all (default) # 1: Align the open parenthesis with the types # 2: Align the function type name with the other type names align_typedef_func = 0 # unsigned number # How to consider (or treat) the '*' in the alignment of typedefs. # # 0: Part of the typedef type, 'typedef int * pint;' (default) # 1: Part of type name: 'typedef int *pint;' # 2: Dangling: 'typedef int *pint;' # Dangling: the '*' will not be taken into account when aligning. align_typedef_star_style = 0 # unsigned number # How to consider (or treat) the '&' in the alignment of typedefs. # # 0: Part of the typedef type, 'typedef int & intref;' (default) # 1: Part of type name: 'typedef int &intref;' # 2: Dangling: 'typedef int &intref;' # Dangling: the '&' will not be taken into account when aligning. align_typedef_amp_style = 0 # unsigned number # The span for aligning comments that end lines. # # 0 = Don't align (default). align_right_cmt_span = 0 # unsigned number # Minimum number of columns between preceding text and a trailing comment in # order for the comment to qualify for being aligned. Must be non-zero to have # an effect. align_right_cmt_gap = 0 # unsigned number # If aligning comments, whether to mix with comments after '}' and #endif with # less than three spaces before the comment. align_right_cmt_mix = false # true/false # Whether to only align trailing comments that are at the same brace level. align_right_cmt_same_level = false # true/false # Minimum column at which to align trailing comments. Comments which are # aligned beyond this column, but which can be aligned in a lesser column, # may be "pulled in". # # 0 = Ignore (default). align_right_cmt_at_col = 0 # unsigned number # The span for aligning function prototypes. # # 0 = Don't align (default). align_func_proto_span = 0 # unsigned number # The threshold for aligning function prototypes. # Use a negative number for absolute thresholds. # # 0 = No limit (default). align_func_proto_thresh = 0 # number # Minimum gap between the return type and the function name. align_func_proto_gap = 0 # unsigned number # Whether to align function prototypes on the 'operator' keyword instead of # what follows. align_on_operator = false # true/false # Whether to mix aligning prototype and variable declarations. If true, # align_var_def_XXX options are used instead of align_func_proto_XXX options. align_mix_var_proto = false # true/false # Whether to align single-line functions with function prototypes. # Uses align_func_proto_span. align_single_line_func = false # true/false # Whether to align the open brace of single-line functions. # Requires align_single_line_func=true. Uses align_func_proto_span. align_single_line_brace = false # true/false # Gap for align_single_line_brace. align_single_line_brace_gap = 0 # unsigned number # (OC) The span for aligning Objective-C message specifications. # # 0 = Don't align (default). align_oc_msg_spec_span = 0 # unsigned number # Whether to align macros wrapped with a backslash and a newline. This will # not work right if the macro contains a multi-line comment. align_nl_cont = false # true/false # Whether to align macro functions and variables together. align_pp_define_together = false # true/false # The span for aligning on '#define' bodies. # # =0: Don't align (default) # >0: Number of lines (including comments) between blocks align_pp_define_span = 0 # unsigned number # The minimum space between label and value of a preprocessor define. align_pp_define_gap = 0 # unsigned number # Whether to align lines that start with '<<' with previous '<<'. # # Default: true align_left_shift = true # true/false # Whether to align text after 'asm volatile ()' colons. align_asm_colon = false # true/false # (OC) Span for aligning parameters in an Objective-C message call # on the ':'. # # 0 = Don't align. align_oc_msg_colon_span = 0 # unsigned number # (OC) Whether to always align with the first parameter, even if it is too # short. align_oc_msg_colon_first = false # true/false # (OC) Whether to align parameters in an Objective-C '+' or '-' declaration # on the ':'. align_oc_decl_colon = false # true/false # # Comment modification options # # Try to wrap comments at N columns. cmt_width = 0 # unsigned number # How to reflow comments. # # 0: No reflowing (apart from the line wrapping due to cmt_width) (default) # 1: No touching at all # 2: Full reflow cmt_reflow_mode = 0 # unsigned number # Whether to convert all tabs to spaces in comments. If false, tabs in # comments are left alone, unless used for indenting. cmt_convert_tab_to_spaces = false # true/false # Whether to apply changes to multi-line comments, including cmt_width, # keyword substitution and leading chars. # # Default: true cmt_indent_multi = true # true/false # Whether to group c-comments that look like they are in a block. cmt_c_group = false # true/false # Whether to put an empty '/*' on the first line of the combined c-comment. cmt_c_nl_start = false # true/false # Whether to add a newline before the closing '*/' of the combined c-comment. cmt_c_nl_end = false # true/false # Whether to change cpp-comments into c-comments. cmt_cpp_to_c = false # true/false # Whether to group cpp-comments that look like they are in a block. Only # meaningful if cmt_cpp_to_c=true. cmt_cpp_group = false # true/false # Whether to put an empty '/*' on the first line of the combined cpp-comment # when converting to a c-comment. # # Requires cmt_cpp_to_c=true and cmt_cpp_group=true. cmt_cpp_nl_start = false # true/false # Whether to add a newline before the closing '*/' of the combined cpp-comment # when converting to a c-comment. # # Requires cmt_cpp_to_c=true and cmt_cpp_group=true. cmt_cpp_nl_end = false # true/false # Whether to put a star on subsequent comment lines. cmt_star_cont = false # true/false # The number of spaces to insert at the start of subsequent comment lines. cmt_sp_before_star_cont = 0 # unsigned number # The number of spaces to insert after the star on subsequent comment lines. cmt_sp_after_star_cont = 0 # unsigned number # For multi-line comments with a '*' lead, remove leading spaces if the first # and last lines of the comment are the same length. # # Default: true cmt_multi_check_last = true # true/false # For multi-line comments with a '*' lead, remove leading spaces if the first # and last lines of the comment are the same length AND if the length is # bigger as the first_len minimum. # # Default: 4 cmt_multi_first_len_minimum = 4 # unsigned number # Path to a file that contains text to insert at the beginning of a file if # the file doesn't start with a C/C++ comment. If the inserted text contains # '$(filename)', that will be replaced with the current file's name. cmt_insert_file_header = "" # string # Path to a file that contains text to insert at the end of a file if the # file doesn't end with a C/C++ comment. If the inserted text contains # '$(filename)', that will be replaced with the current file's name. cmt_insert_file_footer = "" # string # Path to a file that contains text to insert before a function definition if # the function isn't preceded by a C/C++ comment. If the inserted text # contains '$(function)', '$(javaparam)' or '$(fclass)', these will be # replaced with, respectively, the name of the function, the javadoc '@param' # and '@return' stuff, or the name of the class to which the member function # belongs. cmt_insert_func_header = "" # string # Path to a file that contains text to insert before a class if the class # isn't preceded by a C/C++ comment. If the inserted text contains '$(class)', # that will be replaced with the class name. cmt_insert_class_header = "" # string # Path to a file that contains text to insert before an Objective-C message # specification, if the method isn't preceded by a C/C++ comment. If the # inserted text contains '$(message)' or '$(javaparam)', these will be # replaced with, respectively, the name of the function, or the javadoc # '@param' and '@return' stuff. cmt_insert_oc_msg_header = "" # string # Whether a comment should be inserted if a preprocessor is encountered when # stepping backwards from a function name. # # Applies to cmt_insert_oc_msg_header, cmt_insert_func_header and # cmt_insert_class_header. cmt_insert_before_preproc = false # true/false # Whether a comment should be inserted if a function is declared inline to a # class definition. # # Applies to cmt_insert_func_header. # # Default: true cmt_insert_before_inlines = true # true/false # Whether a comment should be inserted if the function is a class constructor # or destructor. # # Applies to cmt_insert_func_header. cmt_insert_before_ctor_dtor = false # true/false # # Code modifying options (non-whitespace) # # Add or remove braces on a single-line 'do' statement. mod_full_brace_do = ignore # ignore/add/remove/force # Add or remove braces on a single-line 'for' statement. mod_full_brace_for = ignore # ignore/add/remove/force # (Pawn) Add or remove braces on a single-line function definition. mod_full_brace_function = ignore # ignore/add/remove/force # Add or remove braces on a single-line 'if' statement. Braces will not be # removed if the braced statement contains an 'else'. mod_full_brace_if = ignore # ignore/add/remove/force # Whether to enforce that all blocks of an 'if'/'else if'/'else' chain either # have, or do not have, braces. If true, braces will be added if any block # needs braces, and will only be removed if they can be removed from all # blocks. # # Overrides mod_full_brace_if. mod_full_brace_if_chain = false # true/false # Whether to add braces to all blocks of an 'if'/'else if'/'else' chain. # If true, mod_full_brace_if_chain will only remove braces from an 'if' that # does not have an 'else if' or 'else'. mod_full_brace_if_chain_only = false # true/false # Add or remove braces on single-line 'while' statement. mod_full_brace_while = ignore # ignore/add/remove/force # Add or remove braces on single-line 'using ()' statement. mod_full_brace_using = ignore # ignore/add/remove/force # Don't remove braces around statements that span N newlines mod_full_brace_nl = 0 # unsigned number # Whether to prevent removal of braces from 'if'/'for'/'while'/etc. blocks # which span multiple lines. # # Affects: # mod_full_brace_for # mod_full_brace_if # mod_full_brace_if_chain # mod_full_brace_if_chain_only # mod_full_brace_while # mod_full_brace_using # # Does not affect: # mod_full_brace_do # mod_full_brace_function mod_full_brace_nl_block_rem_mlcond = false # true/false # Add or remove unnecessary parenthesis on 'return' statement. mod_paren_on_return = ignore # ignore/add/remove/force # (Pawn) Whether to change optional semicolons to real semicolons. mod_pawn_semicolon = false # true/false # Whether to fully parenthesize Boolean expressions in 'while' and 'if' # statement, as in 'if (a && b > c)' => 'if (a && (b > c))'. mod_full_paren_if_bool = false # true/false # Whether to remove superfluous semicolons. mod_remove_extra_semicolon = false # true/false # If a function body exceeds the specified number of newlines and doesn't have # a comment after the close brace, a comment will be added. mod_add_long_function_closebrace_comment = 0 # unsigned number # If a namespace body exceeds the specified number of newlines and doesn't # have a comment after the close brace, a comment will be added. mod_add_long_namespace_closebrace_comment = 0 # unsigned number # If a class body exceeds the specified number of newlines and doesn't have a # comment after the close brace, a comment will be added. mod_add_long_class_closebrace_comment = 0 # unsigned number # If a switch body exceeds the specified number of newlines and doesn't have a # comment after the close brace, a comment will be added. mod_add_long_switch_closebrace_comment = 0 # unsigned number # If an #ifdef body exceeds the specified number of newlines and doesn't have # a comment after the #endif, a comment will be added. mod_add_long_ifdef_endif_comment = 0 # unsigned number # If an #ifdef or #else body exceeds the specified number of newlines and # doesn't have a comment after the #else, a comment will be added. mod_add_long_ifdef_else_comment = 0 # unsigned number # Whether to sort consecutive single-line 'import' statements. mod_sort_import = false # true/false # (C#) Whether to sort consecutive single-line 'using' statements. mod_sort_using = false # true/false # Whether to sort consecutive single-line '#include' statements (C/C++) and # '#import' statements (Objective-C). Be aware that this has the potential to # break your code if your includes/imports have ordering dependencies. mod_sort_include = false # true/false # Whether to move a 'break' that appears after a fully braced 'case' before # the close brace, as in 'case X: { ... } break;' => 'case X: { ... break; }'. mod_move_case_break = false # true/false # Add or remove braces around a fully braced case statement. Will only remove # braces if there are no variable declarations in the block. mod_case_brace = ignore # ignore/add/remove/force # Whether to remove a void 'return;' that appears as the last statement in a # function. mod_remove_empty_return = false # true/false # Add or remove the comma after the last value of an enumeration. mod_enum_last_comma = ignore # ignore/add/remove/force # (OC) Whether to organize the properties. If true, properties will be # rearranged according to the mod_sort_oc_property_*_weight factors. mod_sort_oc_properties = false # true/false # (OC) Weight of a class property modifier. mod_sort_oc_property_class_weight = 0 # number # (OC) Weight of 'atomic' and 'nonatomic'. mod_sort_oc_property_thread_safe_weight = 0 # number # (OC) Weight of 'readwrite' when organizing properties. mod_sort_oc_property_readwrite_weight = 0 # number # (OC) Weight of a reference type specifier ('retain', 'copy', 'assign', # 'weak', 'strong') when organizing properties. mod_sort_oc_property_reference_weight = 0 # number # (OC) Weight of getter type ('getter=') when organizing properties. mod_sort_oc_property_getter_weight = 0 # number # (OC) Weight of setter type ('setter=') when organizing properties. mod_sort_oc_property_setter_weight = 0 # number # (OC) Weight of nullability type ('nullable', 'nonnull', 'null_unspecified', # 'null_resettable') when organizing properties. mod_sort_oc_property_nullability_weight = 0 # number # # Preprocessor options # # Add or remove indentation of preprocessor directives inside #if blocks # at brace level 0 (file-level). pp_indent = ignore # ignore/add/remove/force # Whether to indent #if/#else/#endif at the brace level. If false, these are # indented from column 1. pp_indent_at_level = false # true/false # Specifies the number of columns to indent preprocessors per level # at brace level 0 (file-level). If pp_indent_at_level=false, also specifies # the number of columns to indent preprocessors per level # at brace level > 0 (function-level). # # Default: 1 pp_indent_count = 1 # unsigned number # Add or remove space after # based on pp_level of #if blocks. pp_space = ignore # ignore/add/remove/force # Sets the number of spaces per level added with pp_space. pp_space_count = 0 # unsigned number # The indent for '#region' and '#endregion' in C# and '#pragma region' in # C/C++. Negative values decrease indent down to the first column. pp_indent_region = 0 # number # Whether to indent the code between #region and #endregion. pp_region_indent_code = false # true/false # If pp_indent_at_level=true, sets the indent for #if, #else and #endif when # not at file-level. Negative values decrease indent down to the first column. # # =0: Indent preprocessors using output_tab_size # >0: Column at which all preprocessors will be indented pp_indent_if = 0 # number # Whether to indent the code between #if, #else and #endif. pp_if_indent_code = false # true/false # Whether to indent '#define' at the brace level. If false, these are # indented from column 1. pp_define_at_level = false # true/false # Whether to ignore the '#define' body while formatting. pp_ignore_define_body = false # true/false # Whether to indent case statements between #if, #else, and #endif. # Only applies to the indent of the preprocesser that the case statements # directly inside of. # # Default: true pp_indent_case = true # true/false # Whether to indent whole function definitions between #if, #else, and #endif. # Only applies to the indent of the preprocesser that the function definition # is directly inside of. # # Default: true pp_indent_func_def = true # true/false # Whether to indent extern C blocks between #if, #else, and #endif. # Only applies to the indent of the preprocesser that the extern block is # directly inside of. # # Default: true pp_indent_extern = true # true/false # Whether to indent braces directly inside #if, #else, and #endif. # Only applies to the indent of the preprocesser that the braces are directly # inside of. # # Default: true pp_indent_brace = true # true/false # # Sort includes options # # The regex for include category with priority 0. include_category_0 = "" # string # The regex for include category with priority 1. include_category_1 = "" # string # The regex for include category with priority 2. include_category_2 = "" # string # # Use or Do not Use options # # true: indent_func_call_param will be used (default) # false: indent_func_call_param will NOT be used # # Default: true use_indent_func_call_param = true # true/false # The value of the indentation for a continuation line is calculated # differently if the statement is: # - a declaration: your case with QString fileName ... # - an assignment: your case with pSettings = new QSettings( ... # # At the second case the indentation value might be used twice: # - at the assignment # - at the function call (if present) # # To prevent the double use of the indentation value, use this option with the # value 'true'. # # true: indent_continue will be used only once # false: indent_continue will be used every time (default) use_indent_continue_only_once = false # true/false # The value might be used twice: # - at the assignment # - at the opening brace # # To prevent the double use of the indentation value, use this option with the # value 'true'. # # true: indentation will be used only once # false: indentation will be used every time (default) indent_cpp_lambda_only_once = false # true/false # Whether to apply special formatting for Qt SIGNAL/SLOT macros. Essentially, # this tries to format these so that they match Qt's normalized form (i.e. the # result of QMetaObject::normalizedSignature), which can slightly improve the # performance of the QObject::connect call, rather than how they would # otherwise be formatted. # # See options_for_QT.cpp for details. # # Default: true use_options_overriding_for_qt_macros = true # true/false # # Warn levels - 1: error, 2: warning (default), 3: note # # (C#) Warning is given if doing tab-to-\t replacement and we have found one # in a C# verbatim string literal. # # Default: 2 warn_level_tabs_found_in_verbatim_string_literals = 2 # unsigned number # Meaning of the settings: # Ignore - do not do any changes # Add - makes sure there is 1 or more space/brace/newline/etc # Force - makes sure there is exactly 1 space/brace/newline/etc, # behaves like Add in some contexts # Remove - removes space/brace/newline/etc # # # - Token(s) can be treated as specific type(s) with the 'set' option: # `set tokenType tokenString [tokenString...]` # # Example: # `set BOOL __AND__ __OR__` # # tokenTypes are defined in src/token_enum.h, use them without the # 'CT_' prefix: 'CT_BOOL' => 'BOOL' # # # - Token(s) can be treated as type(s) with the 'type' option. # `type tokenString [tokenString...]` # # Example: # `type int c_uint_8 Rectangle` # # This can also be achieved with `set TYPE int c_uint_8 Rectangle` # # # To embed whitespace in tokenStrings use the '\' escape character, or quote # the tokenStrings. These quotes are supported: "'` # # # - Support for the auto detection of languages through the file ending can be # added using the 'file_ext' command. # `file_ext langType langString [langString..]` # # Example: # `file_ext CPP .ch .cxx .cpp.in` # # langTypes are defined in uncrusify_types.h in the lang_flag_e enum, use # them without the 'LANG_' prefix: 'LANG_CPP' => 'CPP' # # # - Custom macro-based indentation can be set up using 'macro-open', # 'macro-else' and 'macro-close'. # `(macro-open | macro-else | macro-close) tokenString` # # Example: # `macro-open BEGIN_TEMPLATE_MESSAGE_MAP` # `macro-open BEGIN_MESSAGE_MAP` # `macro-close END_MESSAGE_MAP` # # # option(s) with 'not default' value: 151 # Akira-0.0.16/vapi/000077500000000000000000000000001410625726100135705ustar00rootroot00000000000000Akira-0.0.16/vapi/goocanvas-3.0.deps000066400000000000000000000000701410625726100167200ustar00rootroot00000000000000atk cairo pango gdk-3.0 gio-2.0 gtk+-3.0 gdk-pixbuf-2.0 Akira-0.0.16/vapi/goocanvas-3.0.vapi000066400000000000000000001417631410625726100167430ustar00rootroot00000000000000/* goocanvas-3.0.vapi generated by vapigen, do not modify. */ [CCode (cprefix = "Goo", gir_namespace = "GooCanvas", gir_version = "3.0", lower_case_cprefix = "goo_")] namespace Goo { [CCode (cheader_filename = "goocanvas.h", type_id = "goo_canvas_get_type ()")] public class Canvas : Gtk.Container, Atk.Implementor, Gtk.Buildable, Gtk.Scrollable { [CCode (has_construct_function = false, type = "GtkWidget*")] public Canvas (); public void convert_bounds_to_item_space (Goo.CanvasItem item, ref Goo.CanvasBounds bounds); public void convert_from_item_space (Goo.CanvasItem item, ref double x, ref double y); public void convert_from_pixels (ref double x, ref double y); public void convert_to_item_space (Goo.CanvasItem item, ref double x, ref double y); public void convert_to_pixels (ref double x, ref double y); [Version (since = "2.0.1")] public void convert_units_from_pixels (ref double x, ref double y); [Version (since = "2.0.1")] public void convert_units_to_pixels (ref double x, ref double y); public Cairo.Context create_cairo_context (); public virtual Goo.CanvasItem create_item (Goo.CanvasItemModel model); public static void create_path (GLib.Array commands, Cairo.Context cr); public void get_bounds (out double left, out double top, out double right, out double bottom); public double get_default_line_width (); public unowned Goo.CanvasItem get_item (Goo.CanvasItemModel model); public unowned Goo.CanvasItem get_item_at (double x, double y, bool is_pointer_event); public GLib.List get_items_at (double x, double y, bool is_pointer_event); public GLib.List get_items_in_area (Goo.CanvasBounds area, bool inside_area, bool allow_overlaps, bool include_containers); public unowned Goo.CanvasItem get_root_item (); public unowned Goo.CanvasItemModel get_root_item_model (); public double get_scale (); public unowned Goo.CanvasItem get_static_root_item (); public unowned Goo.CanvasItemModel get_static_root_item_model (); public void grab_focus (Goo.CanvasItem item); public Gdk.GrabStatus keyboard_grab (Goo.CanvasItem item, bool owner_events, uint32 time); public void keyboard_ungrab (Goo.CanvasItem item, uint32 time); public static GLib.Array parse_path_data (string path_data); public Gdk.GrabStatus pointer_grab (Goo.CanvasItem item, Gdk.EventMask event_mask, Gdk.Cursor cursor, uint32 time); public void pointer_ungrab (Goo.CanvasItem item, uint32 time); public void register_widget_item (Goo.CanvasWidget witem); public void render (Cairo.Context cr, Goo.CanvasBounds? bounds, double scale); public void request_item_redraw (Goo.CanvasBounds bounds, bool is_static); public void request_redraw (Goo.CanvasBounds bounds); public void request_update (); public void scroll_to (double left, double top); public void set_bounds (double left, double top, double right, double bottom); public void set_root_item (Goo.CanvasItem item); public void set_root_item_model (Goo.CanvasItemModel model); public void set_scale (double scale); public void set_static_root_item (Goo.CanvasItem item); public void set_static_root_item_model (Goo.CanvasItemModel model); public void unregister_item (Goo.CanvasItemModel model); public void unregister_widget_item (Goo.CanvasWidget witem); public void update (); [NoAccessorMethod] public Goo.CanvasAnchorType anchor { get; set; } [NoAccessorMethod] public bool automatic_bounds { get; set; } [NoAccessorMethod] public string background_color { set; } [NoAccessorMethod] [Version (since = "2.0.1")] public Gdk.RGBA background_color_gdk_rgba { set; } [NoAccessorMethod] public uint background_color_rgb { set; } [NoAccessorMethod] public bool bounds_from_origin { get; set; } [NoAccessorMethod] public double bounds_padding { get; set; } [NoAccessorMethod] public bool clear_background { get; set; } [NoAccessorMethod] public bool integer_layout { get; set; } [NoAccessorMethod] public bool redraw_when_scrolled { get; set; } [NoAccessorMethod] public double resolution_x { get; set; } [NoAccessorMethod] public double resolution_y { get; set; } public double scale { get; set; } [NoAccessorMethod] public double scale_x { get; set; } [NoAccessorMethod] public double scale_y { get; set; } [NoAccessorMethod] public Gtk.Unit units { get; set; } [NoAccessorMethod] public double x1 { get; set; } [NoAccessorMethod] public double x2 { get; set; } [NoAccessorMethod] public double y1 { get; set; } [NoAccessorMethod] public double y2 { get; set; } public virtual signal void item_created (Goo.CanvasItem item, Goo.CanvasItemModel model); } [CCode (cheader_filename = "goocanvas.h", type_id = "goo_canvas_accessible_factory_get_type ()")] public class CanvasAccessibleFactory : Atk.ObjectFactory { [CCode (has_construct_function = false)] protected CanvasAccessibleFactory (); } [CCode (cheader_filename = "goocanvas.h", type_id = "goo_canvas_ellipse_get_type ()")] public class CanvasEllipse : Goo.CanvasItemSimple, Goo.CanvasItem { public Goo.CanvasEllipseData? ellipse_data; [CCode (has_construct_function = false, type = "GooCanvasItem*")] public CanvasEllipse (Goo.CanvasItem? parent, double center_x, double center_y, double radius_x, double radius_y, ...); [NoAccessorMethod] public double center_x { get; set; } [NoAccessorMethod] public double center_y { get; set; } [NoAccessorMethod] public double height { get; set; } [NoAccessorMethod] public double radius_x { get; set; } [NoAccessorMethod] public double radius_y { get; set; } [NoAccessorMethod] public double width { get; set; } [NoAccessorMethod] public double x { get; set; } [NoAccessorMethod] public double y { get; set; } } [CCode (cheader_filename = "goocanvas.h", type_id = "goo_canvas_ellipse_model_get_type ()")] public class CanvasEllipseModel : Goo.CanvasItemModelSimple, Goo.CanvasItemModel { public Goo.CanvasEllipseData ellipse_data; [CCode (has_construct_function = false, type = "GooCanvasItemModel*")] public CanvasEllipseModel (Goo.CanvasItemModel? parent, double center_x, double center_y, double radius_x, double radius_y, ...); [NoAccessorMethod] public double center_x { get; set; } [NoAccessorMethod] public double center_y { get; set; } [NoAccessorMethod] public double height { get; set; } [NoAccessorMethod] public double radius_x { get; set; } [NoAccessorMethod] public double radius_y { get; set; } [NoAccessorMethod] public double width { get; set; } [NoAccessorMethod] public double x { get; set; } [NoAccessorMethod] public double y { get; set; } } [CCode (cheader_filename = "goocanvas.h", type_id = "goo_canvas_grid_get_type ()")] public class CanvasGrid : Goo.CanvasItemSimple, Goo.CanvasItem { public Goo.CanvasGridData? grid_data; [CCode (has_construct_function = false, type = "GooCanvasItem*")] public CanvasGrid (Goo.CanvasItem? parent, double x, double y, double width, double height, double x_step, double y_step, double x_offset, double y_offset, ...); [NoAccessorMethod] public string border_color { set; } [NoAccessorMethod] [Version (since = "2.0.1")] public Gdk.RGBA border_color_gdk_rgba { owned get; set; } [NoAccessorMethod] public uint border_color_rgba { get; set; } [NoAccessorMethod] public Cairo.Pattern? border_pattern { owned get; set; } [NoAccessorMethod] public Gdk.Pixbuf border_pixbuf { set; } [NoAccessorMethod] public double border_width { get; set; } [NoAccessorMethod] public double height { get; set; } [NoAccessorMethod] public string horz_grid_line_color { set; } [NoAccessorMethod] [Version (since = "2.0.1")] public Gdk.RGBA horz_grid_line_color_gdk_rgba { owned get; set; } [NoAccessorMethod] public uint horz_grid_line_color_rgba { get; set; } [NoAccessorMethod] public Cairo.Pattern? horz_grid_line_pattern { owned get; set; } [NoAccessorMethod] public Gdk.Pixbuf horz_grid_line_pixbuf { set; } [NoAccessorMethod] public double horz_grid_line_width { get; set; } [NoAccessorMethod] public bool show_horz_grid_lines { get; set; } [NoAccessorMethod] public bool show_vert_grid_lines { get; set; } [NoAccessorMethod] public string vert_grid_line_color { set; } [NoAccessorMethod] [Version (since = "2.0.1")] public Gdk.RGBA vert_grid_line_color_gdk_rgba { owned get; set; } [NoAccessorMethod] public uint vert_grid_line_color_rgba { get; set; } [NoAccessorMethod] public Cairo.Pattern? vert_grid_line_pattern { owned get; set; } [NoAccessorMethod] public Gdk.Pixbuf vert_grid_line_pixbuf { set; } [NoAccessorMethod] public double vert_grid_line_width { get; set; } [NoAccessorMethod] public bool vert_grid_lines_on_top { get; set; } [NoAccessorMethod] public double width { get; set; } [NoAccessorMethod] public double x { get; set; } [NoAccessorMethod] public double x_offset { get; set; } [NoAccessorMethod] public double x_step { get; set; } [NoAccessorMethod] public double y { get; set; } [NoAccessorMethod] public double y_offset { get; set; } [NoAccessorMethod] public double y_step { get; set; } } [CCode (cheader_filename = "goocanvas.h", type_id = "goo_canvas_grid_model_get_type ()")] public class CanvasGridModel : Goo.CanvasItemModelSimple, Goo.CanvasItemModel { public Goo.CanvasGridData grid_data; [CCode (has_construct_function = false, type = "GooCanvasItemModel*")] public CanvasGridModel (Goo.CanvasItemModel? parent, double x, double y, double width, double height, double x_step, double y_step, double x_offset, double y_offset, ...); [NoAccessorMethod] public string border_color { set; } [NoAccessorMethod] public Gdk.RGBA border_color_gdk_rgba { owned get; set; } [NoAccessorMethod] public uint border_color_rgba { get; set; } [NoAccessorMethod] public Cairo.Pattern? border_pattern { owned get; set; } [NoAccessorMethod] public Gdk.Pixbuf border_pixbuf { set; } [NoAccessorMethod] public double border_width { get; set; } [NoAccessorMethod] public double height { get; set; } [NoAccessorMethod] public string horz_grid_line_color { set; } [NoAccessorMethod] public Gdk.RGBA horz_grid_line_color_gdk_rgba { owned get; set; } [NoAccessorMethod] public uint horz_grid_line_color_rgba { get; set; } [NoAccessorMethod] public Cairo.Pattern? horz_grid_line_pattern { owned get; set; } [NoAccessorMethod] public Gdk.Pixbuf horz_grid_line_pixbuf { set; } [NoAccessorMethod] public double horz_grid_line_width { get; set; } [NoAccessorMethod] public bool show_horz_grid_lines { get; set; } [NoAccessorMethod] public bool show_vert_grid_lines { get; set; } [NoAccessorMethod] public string vert_grid_line_color { set; } [NoAccessorMethod] public Gdk.RGBA vert_grid_line_color_gdk_rgba { owned get; set; } [NoAccessorMethod] public uint vert_grid_line_color_rgba { get; set; } [NoAccessorMethod] public Cairo.Pattern? vert_grid_line_pattern { owned get; set; } [NoAccessorMethod] public Gdk.Pixbuf vert_grid_line_pixbuf { set; } [NoAccessorMethod] public double vert_grid_line_width { get; set; } [NoAccessorMethod] public bool vert_grid_lines_on_top { get; set; } [NoAccessorMethod] public double width { get; set; } [NoAccessorMethod] public double x { get; set; } [NoAccessorMethod] public double x_offset { get; set; } [NoAccessorMethod] public double x_step { get; set; } [NoAccessorMethod] public double y { get; set; } [NoAccessorMethod] public double y_offset { get; set; } [NoAccessorMethod] public double y_step { get; set; } } [CCode (cheader_filename = "goocanvas.h", type_id = "goo_canvas_group_get_type ()")] public class CanvasGroup : Goo.CanvasItemSimple, Goo.CanvasItem { public weak GLib.GenericArray items; [CCode (has_construct_function = false, type = "GooCanvasItem*")] public CanvasGroup (Goo.CanvasItem? parent, ...); [NoAccessorMethod] public double height { get; set; } [NoAccessorMethod] public double width { get; set; } [NoAccessorMethod] public double x { get; set; } [NoAccessorMethod] public double y { get; set; } } [CCode (cheader_filename = "goocanvas.h", type_id = "goo_canvas_group_model_get_type ()")] public class CanvasGroupModel : Goo.CanvasItemModelSimple, Goo.CanvasItemModel { public weak GLib.GenericArray children; [CCode (has_construct_function = false, type = "GooCanvasItemModel*")] public CanvasGroupModel (Goo.CanvasItemModel? parent, ...); [NoAccessorMethod] public double height { get; set; } [NoAccessorMethod] public double width { get; set; } [NoAccessorMethod] public double x { get; set; } [NoAccessorMethod] public double y { get; set; } } [CCode (cheader_filename = "goocanvas.h", type_id = "goo_canvas_image_get_type ()")] public class CanvasImage : Goo.CanvasItemSimple, Goo.CanvasItem { public Goo.CanvasImageData? image_data; [CCode (has_construct_function = false, type = "GooCanvasItem*")] public CanvasImage (Goo.CanvasItem? parent, Gdk.Pixbuf? pixbuf, double x, double y, ...); [NoAccessorMethod] public double alpha { get; set; } [NoAccessorMethod] public double height { get; set; } [NoAccessorMethod] public Cairo.Pattern? pattern { owned get; set; } [NoAccessorMethod] public Gdk.Pixbuf pixbuf { set; } [NoAccessorMethod] public bool scale_to_fit { get; set; } [NoAccessorMethod] public double width { get; set; } [NoAccessorMethod] public double x { get; set; } [NoAccessorMethod] public double y { get; set; } } [CCode (cheader_filename = "goocanvas.h", type_id = "goo_canvas_image_model_get_type ()")] public class CanvasImageModel : Goo.CanvasItemModelSimple, Goo.CanvasItemModel { public Goo.CanvasImageData image_data; [CCode (has_construct_function = false, type = "GooCanvasItemModel*")] public CanvasImageModel (Goo.CanvasItemModel? parent, Gdk.Pixbuf? pixbuf, double x, double y, ...); [NoAccessorMethod] public double alpha { get; set; } [NoAccessorMethod] public double height { get; set; } [NoAccessorMethod] public Cairo.Pattern? pattern { owned get; set; } [NoAccessorMethod] public Gdk.Pixbuf pixbuf { set; } [NoAccessorMethod] public bool scale_to_fit { get; set; } [NoAccessorMethod] public double width { get; set; } [NoAccessorMethod] public double x { get; set; } [NoAccessorMethod] public double y { get; set; } } [CCode (cheader_filename = "goocanvas.h", type_id = "goo_canvas_item_accessible_factory_get_type ()")] public class CanvasItemAccessibleFactory : Atk.ObjectFactory { [CCode (has_construct_function = false)] protected CanvasItemAccessibleFactory (); } [CCode (cheader_filename = "goocanvas.h", type_id = "goo_canvas_item_model_simple_get_type ()")] public class CanvasItemModelSimple : GLib.Object, Goo.CanvasItemModel { public weak string description; public weak Goo.CanvasItemModel parent; public Goo.CanvasItemSimpleData simple_data; public weak string title; [CCode (has_construct_function = false)] protected CanvasItemModelSimple (); [NoAccessorMethod] public Goo.CairoAntialias antialias { get; set; } [NoAccessorMethod] public Goo.CairoFillRule clip_fill_rule { get; set; } [NoAccessorMethod] public string clip_path { set; } [NoAccessorMethod] public string fill_color { set; } [NoAccessorMethod] public Gdk.RGBA fill_color_gdk_rgba { owned get; set; } [NoAccessorMethod] public uint fill_color_rgba { get; set; } [NoAccessorMethod] public Cairo.Pattern? fill_pattern { owned get; set; } [NoAccessorMethod] public Gdk.Pixbuf fill_pixbuf { set; } [NoAccessorMethod] public Goo.CairoFillRule fill_rule { get; set; } [NoAccessorMethod] public string font { owned get; set; } [NoAccessorMethod] public Pango.FontDescription font_desc { owned get; set; } [NoAccessorMethod] public Goo.CairoHintMetrics hint_metrics { get; set; } [NoAccessorMethod] public Goo.CairoLineCap line_cap { get; set; } [NoAccessorMethod] public Goo.CanvasLineDash line_dash { owned get; set; } [NoAccessorMethod] public Goo.CairoLineJoin line_join { get; set; } [NoAccessorMethod] public double line_join_miter_limit { get; set; } [NoAccessorMethod] public double line_width { get; set; } [NoAccessorMethod] public Goo.CairoOperator operator { get; set; } [NoAccessorMethod] public string stroke_color { set; } [NoAccessorMethod] public Gdk.RGBA stroke_color_gdk_rgba { owned get; set; } [NoAccessorMethod] public uint stroke_color_rgba { get; set; } [NoAccessorMethod] public Cairo.Pattern? stroke_pattern { owned get; set; } [NoAccessorMethod] public Gdk.Pixbuf stroke_pixbuf { set; } } [CCode (cheader_filename = "goocanvas.h", type_id = "goo_canvas_item_simple_get_type ()")] public class CanvasItemSimple : GLib.Object, Goo.CanvasItem { public Goo.CanvasBounds bounds; public weak Goo.Canvas canvas; public weak Goo.CanvasItemModelSimple model; public uint need_entire_subtree_update; public uint need_update; public weak Goo.CanvasItem parent; public Goo.CanvasItemSimpleData? simple_data; [CCode (has_construct_function = false)] protected CanvasItemSimple (); public void changed (bool recompute_bounds); public bool check_in_path (double x, double y, Cairo.Context cr, Goo.CanvasPointerEvents pointer_events); public void check_style (); public double get_line_width (); public void get_path_bounds (Cairo.Context cr, out Goo.CanvasBounds bounds); public void paint_path (Cairo.Context cr); [NoWrapper] public virtual void simple_create_path (Cairo.Context cr); [NoWrapper] public virtual bool simple_is_item_at (double x, double y, Cairo.Context cr, bool is_pointer_event); [NoWrapper] public virtual void simple_paint (Cairo.Context cr, Goo.CanvasBounds bounds); [NoWrapper] public virtual void simple_update (Cairo.Context cr); public void user_bounds_to_device (Cairo.Context cr, Goo.CanvasBounds bounds); public void user_bounds_to_parent (Cairo.Context cr, Goo.CanvasBounds bounds); [NoAccessorMethod] public Goo.CairoAntialias antialias { get; set; } [NoAccessorMethod] public Goo.CairoFillRule clip_fill_rule { get; set; } [NoAccessorMethod] public string clip_path { set; } [NoAccessorMethod] public string fill_color { set; } [NoAccessorMethod] [Version (since = "2.0.1")] public Gdk.RGBA fill_color_gdk_rgba { owned get; set; } [NoAccessorMethod] public uint fill_color_rgba { get; set; } [NoAccessorMethod] public Cairo.Pattern? fill_pattern { owned get; set; } [NoAccessorMethod] public Gdk.Pixbuf fill_pixbuf { set; } [NoAccessorMethod] public Goo.CairoFillRule fill_rule { get; set; } [NoAccessorMethod] public string font { owned get; set; } [NoAccessorMethod] public Pango.FontDescription font_desc { owned get; set; } [NoAccessorMethod] public Goo.CairoHintMetrics hint_metrics { get; set; } [NoAccessorMethod] public Goo.CairoLineCap line_cap { get; set; } [NoAccessorMethod] public Goo.CanvasLineDash line_dash { owned get; set; } [NoAccessorMethod] public Goo.CairoLineJoin line_join { get; set; } [NoAccessorMethod] public double line_join_miter_limit { get; set; } [NoAccessorMethod] public double line_width { get; set; } [NoAccessorMethod] public Goo.CairoOperator operator { get; set; } [NoAccessorMethod] public string stroke_color { set; } [NoAccessorMethod] [Version (since = "2.0.1")] public Gdk.RGBA stroke_color_gdk_rgba { owned get; set; } [NoAccessorMethod] public uint stroke_color_rgba { get; set; } [NoAccessorMethod] public Cairo.Pattern? stroke_pattern { owned get; set; } [NoAccessorMethod] public Gdk.Pixbuf stroke_pixbuf { set; } } [CCode (cheader_filename = "goocanvas.h", ref_function = "goo_canvas_line_dash_ref", type_id = "goo_canvas_line_dash_get_type ()", unref_function = "goo_canvas_line_dash_unref")] [Compact] public class CanvasLineDash { public double dash_offset; [CCode (array_length_cname = "num_dashes")] public double[] dashes; public int num_dashes; public int ref_count; [CCode (has_construct_function = false)] public CanvasLineDash (int num_dashes, ...); [CCode (cname = "goo_canvas_line_dash_newv", has_construct_function = false)] public CanvasLineDash.newv ([CCode (array_length_cname = "num_dashes", array_length_pos = 0.5)] owned double[] dashes); public Goo.CanvasLineDash @ref (); [Version (since = "2.0.2")] public void set_offset (double dash_offset); public void unref (); } [CCode (cheader_filename = "goocanvas.h", type_id = "goo_canvas_path_get_type ()")] public class CanvasPath : Goo.CanvasItemSimple, Goo.CanvasItem { public Goo.CanvasPathData? path_data; [CCode (has_construct_function = false, type = "GooCanvasItem*")] public CanvasPath (Goo.CanvasItem? parent, string path_data, ...); [NoAccessorMethod] public string data { set; } [NoAccessorMethod] public double height { get; set; } [NoAccessorMethod] public double width { get; set; } [NoAccessorMethod] public double x { get; set; } [NoAccessorMethod] public double y { get; set; } } [CCode (cheader_filename = "goocanvas.h", type_id = "goo_canvas_path_model_get_type ()")] public class CanvasPathModel : Goo.CanvasItemModelSimple, Goo.CanvasItemModel { public Goo.CanvasPathData path_data; [CCode (has_construct_function = false, type = "GooCanvasItemModel*")] public CanvasPathModel (Goo.CanvasItemModel? parent, string path_data, ...); [NoAccessorMethod] public string data { set; } [NoAccessorMethod] public double height { get; set; } [NoAccessorMethod] public double width { get; set; } [NoAccessorMethod] public double x { get; set; } [NoAccessorMethod] public double y { get; set; } } [CCode (cheader_filename = "goocanvas.h", ref_function = "goo_canvas_points_ref", type_id = "goo_canvas_points_get_type ()", unref_function = "goo_canvas_points_unref")] [Compact] public class CanvasPoints { [CCode (array_length_cname = "num_points")] public double[] coords; public int num_points; public int ref_count; [CCode (has_construct_function = false)] public CanvasPoints (int num_points); [Version (since = "2.0.1")] public void get_point (int idx, out double x, out double y); public Goo.CanvasPoints @ref (); [Version (since = "2.0.1")] public void set_point (int idx, double x, double y); public void unref (); } [CCode (cheader_filename = "goocanvas.h", type_id = "goo_canvas_polyline_get_type ()")] public class CanvasPolyline : Goo.CanvasItemSimple, Goo.CanvasItem { public Goo.CanvasPolylineData? polyline_data; [CCode (has_construct_function = false, type = "GooCanvasItem*")] public CanvasPolyline (Goo.CanvasItem? parent, bool close_path, int num_points, ...); [CCode (has_construct_function = false, type = "GooCanvasItem*")] public CanvasPolyline.line (Goo.CanvasItem? parent, double x1, double y1, double x2, double y2, ...); [NoAccessorMethod] public double arrow_length { get; set; } [NoAccessorMethod] public double arrow_tip_length { get; set; } [NoAccessorMethod] public double arrow_width { get; set; } [NoAccessorMethod] public bool close_path { get; set; } [NoAccessorMethod] public bool end_arrow { get; set; } [NoAccessorMethod] public double height { get; set; } [NoAccessorMethod] public Goo.CanvasPoints points { owned get; set; } [NoAccessorMethod] public bool start_arrow { get; set; } [NoAccessorMethod] public double width { get; set; } [NoAccessorMethod] public double x { get; set; } [NoAccessorMethod] public double y { get; set; } } [CCode (cheader_filename = "goocanvas.h", type_id = "goo_canvas_polyline_model_get_type ()")] public class CanvasPolylineModel : Goo.CanvasItemModelSimple, Goo.CanvasItemModel { public Goo.CanvasPolylineData polyline_data; [CCode (has_construct_function = false, type = "GooCanvasItemModel*")] public CanvasPolylineModel (Goo.CanvasItemModel? parent, bool close_path, int num_points, ...); [CCode (has_construct_function = false, type = "GooCanvasItemModel*")] public CanvasPolylineModel.line (Goo.CanvasItemModel? parent, double x1, double y1, double x2, double y2, ...); [NoAccessorMethod] public double arrow_length { get; set; } [NoAccessorMethod] public double arrow_tip_length { get; set; } [NoAccessorMethod] public double arrow_width { get; set; } [NoAccessorMethod] public bool close_path { get; set; } [NoAccessorMethod] public bool end_arrow { get; set; } [NoAccessorMethod] public double height { get; set; } [NoAccessorMethod] public Goo.CanvasPoints points { owned get; set; } [NoAccessorMethod] public bool start_arrow { get; set; } [NoAccessorMethod] public double width { get; set; } [NoAccessorMethod] public double x { get; set; } [NoAccessorMethod] public double y { get; set; } } [CCode (cheader_filename = "goocanvas.h", type_id = "goo_canvas_rect_get_type ()")] public class CanvasRect : Goo.CanvasItemSimple, Goo.CanvasItem { public Goo.CanvasRectData? rect_data; [CCode (has_construct_function = false, type = "GooCanvasItem*")] public CanvasRect (Goo.CanvasItem? parent, double x, double y, double width, double height, ...); [NoAccessorMethod] public double height { get; set; } [NoAccessorMethod] public double radius_x { get; set; } [NoAccessorMethod] public double radius_y { get; set; } [NoAccessorMethod] public double width { get; set; } [NoAccessorMethod] public double x { get; set; } [NoAccessorMethod] public double y { get; set; } } [CCode (cheader_filename = "goocanvas.h", type_id = "goo_canvas_rect_model_get_type ()")] public class CanvasRectModel : Goo.CanvasItemModelSimple, Goo.CanvasItemModel { public Goo.CanvasRectData rect_data; [CCode (has_construct_function = false, type = "GooCanvasItemModel*")] public CanvasRectModel (Goo.CanvasItemModel? parent, double x, double y, double width, double height, ...); [NoAccessorMethod] public double height { get; set; } [NoAccessorMethod] public double radius_x { get; set; } [NoAccessorMethod] public double radius_y { get; set; } [NoAccessorMethod] public double width { get; set; } [NoAccessorMethod] public double x { get; set; } [NoAccessorMethod] public double y { get; set; } } [CCode (cheader_filename = "goocanvas.h", type_id = "goo_canvas_style_get_type ()")] public class CanvasStyle : GLib.Object { public weak Goo.CanvasStyle parent; public weak GLib.Array properties; [CCode (has_construct_function = false)] public CanvasStyle (); public Goo.CanvasStyle copy (); public unowned Goo.CanvasStyle get_parent (); public GLib.Value? get_property (GLib.Quark property_id); public bool set_fill_options (Cairo.Context cr); public void set_parent (Goo.CanvasStyle parent); public void set_property (GLib.Quark property_id, GLib.Value value); public bool set_stroke_options (Cairo.Context cr); } [CCode (cheader_filename = "goocanvas.h", type_id = "goo_canvas_table_get_type ()")] public class CanvasTable : Goo.CanvasGroup, Goo.CanvasItem { public Goo.CanvasTableData? table_data; [CCode (has_construct_function = false, type = "GooCanvasItem*")] public CanvasTable (Goo.CanvasItem? parent, ...); [NoAccessorMethod] public double column_spacing { get; set; } [NoAccessorMethod] public bool homogeneous_columns { get; set; } [NoAccessorMethod] public bool homogeneous_rows { get; set; } [NoAccessorMethod] public double horz_grid_line_width { get; set; } [NoAccessorMethod] public double row_spacing { get; set; } [NoAccessorMethod] public double vert_grid_line_width { get; set; } [NoAccessorMethod] public double x_border_spacing { get; set; } [NoAccessorMethod] public double y_border_spacing { get; set; } } [CCode (cheader_filename = "goocanvas.h", has_type_id = false)] [Compact] public class CanvasTableLayoutData { } [CCode (cheader_filename = "goocanvas.h", type_id = "goo_canvas_table_model_get_type ()")] public class CanvasTableModel : Goo.CanvasGroupModel, Goo.CanvasItemModel { public Goo.CanvasTableData table_data; [CCode (has_construct_function = false, type = "GooCanvasItemModel*")] public CanvasTableModel (Goo.CanvasItemModel? parent, ...); [NoAccessorMethod] public double column_spacing { get; set; } [NoAccessorMethod] public bool homogeneous_columns { get; set; } [NoAccessorMethod] public bool homogeneous_rows { get; set; } [NoAccessorMethod] public double horz_grid_line_width { get; set; } [NoAccessorMethod] public double row_spacing { get; set; } [NoAccessorMethod] public double vert_grid_line_width { get; set; } [NoAccessorMethod] public double x_border_spacing { get; set; } [NoAccessorMethod] public double y_border_spacing { get; set; } } [CCode (cheader_filename = "goocanvas.h", type_id = "goo_canvas_text_get_type ()")] public class CanvasText : Goo.CanvasItemSimple, Goo.CanvasItem { public double layout_width; public Goo.CanvasTextData? text_data; [CCode (has_construct_function = false, type = "GooCanvasItem*")] public CanvasText (Goo.CanvasItem? parent, string string, double x, double y, double width, Goo.CanvasAnchorType anchor, ...); public void get_natural_extents (out Pango.Rectangle ink_rect, out Pango.Rectangle logical_rect); [NoAccessorMethod] public Pango.Alignment alignment { get; set; } [NoAccessorMethod] public Goo.CanvasAnchorType anchor { get; set; } [NoAccessorMethod] public Pango.EllipsizeMode ellipsize { get; set; } [NoAccessorMethod] public double height { get; set; } [NoAccessorMethod] public string text { owned get; set; } [NoAccessorMethod] public bool use_markup { get; set; } [NoAccessorMethod] public double width { get; set; } [NoAccessorMethod] public Pango.WrapMode wrap { get; set; } [NoAccessorMethod] public double x { get; set; } [NoAccessorMethod] public double y { get; set; } } [CCode (cheader_filename = "goocanvas.h", type_id = "goo_canvas_text_model_get_type ()")] public class CanvasTextModel : Goo.CanvasItemModelSimple, Goo.CanvasItemModel { public Goo.CanvasTextData text_data; [CCode (has_construct_function = false, type = "GooCanvasItemModel*")] public CanvasTextModel (Goo.CanvasItemModel? parent, string string, double x, double y, double width, Goo.CanvasAnchorType anchor, ...); [NoAccessorMethod] public Pango.Alignment alignment { get; set; } [NoAccessorMethod] public Goo.CanvasAnchorType anchor { get; set; } [NoAccessorMethod] public Pango.EllipsizeMode ellipsize { get; set; } [NoAccessorMethod] public double height { get; set; } [NoAccessorMethod] public string text { owned get; set; } [NoAccessorMethod] public bool use_markup { get; set; } [NoAccessorMethod] public double width { get; set; } [NoAccessorMethod] public Pango.WrapMode wrap { get; set; } [NoAccessorMethod] public double x { get; set; } [NoAccessorMethod] public double y { get; set; } } [CCode (cheader_filename = "goocanvas.h", type_id = "goo_canvas_widget_get_type ()")] public class CanvasWidget : Goo.CanvasItemSimple, Goo.CanvasItem { [CCode (has_construct_function = false, type = "GooCanvasItem*")] public CanvasWidget (Goo.CanvasItem? parent, Gtk.Widget widget, double x, double y, double width, double height, ...); [NoAccessorMethod] public Goo.CanvasAnchorType anchor { get; set; } [NoAccessorMethod] public double height { get; set; } [NoAccessorMethod] public Gtk.Widget widget { owned get; set; } [NoAccessorMethod] public double width { get; set; } [NoAccessorMethod] public double x { get; set; } [NoAccessorMethod] public double y { get; set; } } [CCode (cheader_filename = "goocanvas.h", type_id = "goo_canvas_widget_accessible_factory_get_type ()")] public class CanvasWidgetAccessibleFactory : Atk.ObjectFactory { [CCode (has_construct_function = false)] protected CanvasWidgetAccessibleFactory (); } [CCode (cheader_filename = "goocanvas.h", type_id = "goo_canvas_item_get_type ()")] public interface CanvasItem : GLib.Object { public abstract void add_child (Goo.CanvasItem child, int position); public abstract void allocate_area (Cairo.Context cr, Goo.CanvasBounds requested_area, Goo.CanvasBounds allocated_area, double x_offset, double y_offset); public void animate (double x, double y, double scale, double degrees, bool absolute, int duration, int step_time, Goo.CanvasAnimateType type); public static unowned GLib.ParamSpec class_find_child_property (GLib.ObjectClass iclass, string property_name); public static void class_install_child_property (GLib.ObjectClass iclass, uint property_id, GLib.ParamSpec pspec); [CCode (array_length_pos = 1.1, array_length_type = "guint")] public static (unowned GLib.ParamSpec)[] class_list_child_properties (GLib.ObjectClass iclass); public void ensure_updated (); public int find_child (Goo.CanvasItem child); public abstract void get_bounds (out Goo.CanvasBounds bounds); public abstract unowned Goo.Canvas get_canvas (); public abstract unowned Goo.CanvasItem get_child (int child_num); public void get_child_properties (Goo.CanvasItem child, ...); public void get_child_properties_valist (Goo.CanvasItem child, va_list var_args); [NoWrapper] public abstract void get_child_property (Goo.CanvasItem child, uint property_id, GLib.Value value, GLib.ParamSpec pspec); public abstract bool get_is_static (); public abstract unowned GLib.List get_items_at (double x, double y, Cairo.Context cr, bool is_pointer_event, bool parent_is_visible, GLib.List found_items); public abstract unowned Goo.CanvasItemModel get_model (); public abstract int get_n_children (); public abstract unowned Goo.CanvasItem get_parent (); public abstract bool get_requested_area (Cairo.Context cr, Goo.CanvasBounds requested_area); [Version (since = "2.0.1")] public abstract bool get_requested_area_for_width (Cairo.Context cr, double width, Goo.CanvasBounds requested_area); public abstract double get_requested_height (Cairo.Context cr, double width); public bool get_simple_transform (out double x, out double y, out double scale, out double rotation); public abstract unowned Goo.CanvasStyle get_style (); public abstract bool get_transform (out Cairo.Matrix transform); public abstract bool get_transform_for_child (Goo.CanvasItem child, out Cairo.Matrix transform); public bool is_container (); public abstract bool is_visible (); public void lower (Goo.CanvasItem? below); public abstract void move_child (int old_position, int new_position); public abstract void paint (Cairo.Context cr, Goo.CanvasBounds bounds, double scale); public void raise (Goo.CanvasItem? above); public void remove (); public abstract void remove_child (int child_num); public abstract void request_update (); public void rotate (double degrees, double cx, double cy); public void scale (double sx, double sy); public abstract void set_canvas (Goo.Canvas canvas); public void set_child_properties (Goo.CanvasItem child, ...); public void set_child_properties_valist (Goo.CanvasItem child, va_list var_args); [NoWrapper] public abstract void set_child_property (Goo.CanvasItem child, uint property_id, GLib.Value value, GLib.ParamSpec pspec); public abstract void set_is_static (bool is_static); public abstract void set_model (Goo.CanvasItemModel model); public abstract void set_parent (Goo.CanvasItem parent); public void set_simple_transform (double x, double y, double scale, double rotation); public abstract void set_style (Goo.CanvasStyle style); public abstract void set_transform (Cairo.Matrix? transform); public void skew_x (double degrees, double cx, double cy); public void skew_y (double degrees, double cx, double cy); public void stop_animation (); public void translate (double tx, double ty); public abstract void update (bool entire_tree, Cairo.Context cr, Goo.CanvasBounds bounds); [NoAccessorMethod] public abstract bool can_focus { get; set; } [NoAccessorMethod] public abstract string description { owned get; set; } public abstract Goo.CanvasItem parent { get; set; } [NoAccessorMethod] public abstract Goo.CanvasPointerEvents pointer_events { get; set; } [NoAccessorMethod] public abstract string title { owned get; set; } [NoAccessorMethod] public abstract string tooltip { owned get; set; } [NoAccessorMethod] public abstract Cairo.Matrix? transform { owned get; set; } [NoAccessorMethod] public abstract Goo.CanvasItemVisibility visibility { get; set; } [NoAccessorMethod] public abstract double visibility_threshold { get; set; } public virtual signal void animation_finished (bool stopped); public virtual signal bool button_press_event (Goo.CanvasItem target, Gdk.EventButton event); public virtual signal bool button_release_event (Goo.CanvasItem target, Gdk.EventButton event); public virtual signal void child_notify (GLib.ParamSpec pspec); public virtual signal bool enter_notify_event (Goo.CanvasItem target, Gdk.EventCrossing event); public virtual signal bool focus_in_event (Goo.CanvasItem target, Gdk.EventFocus event); public virtual signal bool focus_out_event (Goo.CanvasItem target, Gdk.EventFocus event); public virtual signal bool grab_broken_event (Goo.CanvasItem target, Gdk.EventGrabBroken event); public virtual signal bool key_press_event (Goo.CanvasItem target, Gdk.EventKey event); public virtual signal bool key_release_event (Goo.CanvasItem target, Gdk.EventKey event); public virtual signal bool leave_notify_event (Goo.CanvasItem target, Gdk.EventCrossing event); public virtual signal bool motion_notify_event (Goo.CanvasItem target, Gdk.EventMotion event); public virtual signal bool query_tooltip (double x, double y, bool keyboard_tooltip, Gtk.Tooltip tooltip); public virtual signal bool scroll_event (Goo.CanvasItem target, Gdk.EventScroll event); } [CCode (cheader_filename = "goocanvas.h", type_id = "goo_canvas_item_model_get_type ()")] public interface CanvasItemModel : GLib.Object { public abstract void add_child (Goo.CanvasItemModel child, int position); public void animate (double x, double y, double scale, double degrees, bool absolute, int duration, int step_time, Goo.CanvasAnimateType type); public static unowned GLib.ParamSpec class_find_child_property (GLib.ObjectClass mclass, string property_name); public static void class_install_child_property (GLib.ObjectClass mclass, uint property_id, GLib.ParamSpec pspec); [CCode (array_length_pos = 1.1, array_length_type = "guint")] public static (unowned GLib.ParamSpec)[] class_list_child_properties (GLib.ObjectClass mclass); [NoWrapper] public abstract unowned Goo.CanvasItem create_item (Goo.Canvas canvas); public int find_child (Goo.CanvasItemModel child); public abstract unowned Goo.CanvasItemModel get_child (int child_num); public void get_child_properties (Goo.CanvasItemModel child, ...); public void get_child_properties_valist (Goo.CanvasItemModel child, va_list var_args); [NoWrapper] public abstract void get_child_property (Goo.CanvasItemModel child, uint property_id, GLib.Value value, GLib.ParamSpec pspec); public abstract int get_n_children (); public abstract unowned Goo.CanvasItemModel get_parent (); public bool get_simple_transform (out double x, out double y, out double scale, out double rotation); public abstract unowned Goo.CanvasStyle get_style (); public abstract bool get_transform (out Cairo.Matrix transform); public bool is_container (); public void lower (Goo.CanvasItemModel? below); public abstract void move_child (int old_position, int new_position); public void raise (Goo.CanvasItemModel? above); public void remove (); public abstract void remove_child (int child_num); public void rotate (double degrees, double cx, double cy); public void scale (double sx, double sy); public void set_child_properties (Goo.CanvasItemModel child, ...); public void set_child_properties_valist (Goo.CanvasItemModel child, va_list var_args); [NoWrapper] public abstract void set_child_property (Goo.CanvasItemModel child, uint property_id, GLib.Value value, GLib.ParamSpec pspec); public abstract void set_parent (Goo.CanvasItemModel parent); public void set_simple_transform (double x, double y, double scale, double rotation); public abstract void set_style (Goo.CanvasStyle style); public abstract void set_transform (Cairo.Matrix? transform); public void skew_x (double degrees, double cx, double cy); public void skew_y (double degrees, double cx, double cy); public void stop_animation (); public void translate (double tx, double ty); [NoAccessorMethod] public abstract bool can_focus { get; set; } [NoAccessorMethod] public abstract string description { owned get; set; } public abstract Goo.CanvasItemModel parent { get; set; } [NoAccessorMethod] public abstract Goo.CanvasPointerEvents pointer_events { get; set; } [NoAccessorMethod] public abstract string title { owned get; set; } [NoAccessorMethod] public abstract string tooltip { owned get; set; } [NoAccessorMethod] public abstract Cairo.Matrix? transform { owned get; set; } [NoAccessorMethod] public abstract Goo.CanvasItemVisibility visibility { get; set; } [NoAccessorMethod] public abstract double visibility_threshold { get; set; } public virtual signal void animation_finished (bool stopped); public virtual signal void changed (bool recompute_bounds); public virtual signal void child_added (int child_num); public virtual signal void child_moved (int old_child_num, int new_child_num); public virtual signal void child_notify (GLib.ParamSpec pspec); public virtual signal void child_removed (int child_num); } [CCode (cheader_filename = "goocanvas.h", copy_function = "g_boxed_copy", free_function = "g_boxed_free", type_id = "goo_canvas_bounds_get_type ()")] public struct CanvasBounds { public double x1; public double y1; public double x2; public double y2; } [CCode (cheader_filename = "goocanvas.h", has_type_id = false)] public struct CanvasEllipseData { public double center_x; public double center_y; public double radius_x; public double radius_y; } [CCode (cheader_filename = "goocanvas.h", has_type_id = false)] public struct CanvasGridData { public double x; public double y; public double width; public double height; public double x_step; public double y_step; public double x_offset; public double y_offset; public double horz_grid_line_width; public double vert_grid_line_width; public Cairo.Pattern? horz_grid_line_pattern; public Cairo.Pattern? vert_grid_line_pattern; public double border_width; public Cairo.Pattern? border_pattern; public uint show_horz_grid_lines; public uint show_vert_grid_lines; public uint vert_grid_lines_on_top; } [CCode (cheader_filename = "goocanvas.h", has_type_id = false)] public struct CanvasImageData { public Cairo.Pattern? pattern; public double x; public double y; public double width; public double height; } [CCode (cheader_filename = "goocanvas.h", has_type_id = false)] public struct CanvasItemSimpleData { public Goo.CanvasStyle style; public Cairo.Matrix? transform; public GLib.Array clip_path_commands; public string tooltip; public double visibility_threshold; public uint visibility; public uint pointer_events; public uint can_focus; public uint own_style; public uint clip_fill_rule; public uint is_static; public uint cache_setting; public uint has_tooltip; } [CCode (cheader_filename = "goocanvas.h")] public struct CanvasPathCommand { [CCode (cname = "simple.type")] public uint simple_type; [CCode (cname = "simple.relative")] public uint simple_relative; [CCode (cname = "simple.x")] public double simple_x; [CCode (cname = "simple.y")] public double simple_y; [CCode (cname = "curve.type")] public uint curve_type; [CCode (cname = "curve.relative")] public uint curve_relative; [CCode (cname = "curve.x")] public double curve_x; [CCode (cname = "curve.y")] public double curve_y; [CCode (cname = "curve.x1")] public double curve_x1; [CCode (cname = "curve.y1")] public double curve_y1; [CCode (cname = "curve.x2")] public double curve_x2; [CCode (cname = "curve.y2")] public double curve_y2; [CCode (cname = "arc.type")] public uint arc_type; [CCode (cname = "arc.relative")] public uint arc_relative; [CCode (cname = "arc.large_arc_flag")] public uint arc_large_arc_flag; [CCode (cname = "arc.sweep_flag")] public uint arc_sweep_flag; [CCode (cname = "arc.rx")] public double arc_rx; [CCode (cname = "arc.ry")] public double arc_ry; [CCode (cname = "arc.x_axis_rotation")] public double arc_x_axis_rotation; [CCode (cname = "arc.x")] public double arc_x; [CCode (cname = "arc.y")] public double arc_y; } [CCode (cheader_filename = "goocanvas.h", has_type_id = false)] public struct CanvasPathData { public GLib.Array path_commands; } [CCode (cheader_filename = "goocanvas.h", has_type_id = false)] public struct CanvasPolylineArrowData { public double arrow_width; public double arrow_length; public double arrow_tip_length; [CCode (array_length = false)] public double line_start[2]; [CCode (array_length = false)] public double line_end[2]; [CCode (array_length = false)] public double start_arrow_coords[10]; [CCode (array_length = false)] public double end_arrow_coords[10]; } [CCode (cheader_filename = "goocanvas.h", has_type_id = false)] public struct CanvasPolylineData { public double coords; public Goo.CanvasPolylineArrowData? arrow_data; public uint num_points; public uint close_path; public uint start_arrow; public uint end_arrow; public uint reconfigure_arrows; } [CCode (cheader_filename = "goocanvas.h", has_type_id = false)] public struct CanvasRectData { public double x; public double y; public double width; public double height; public double radius_x; public double radius_y; } [CCode (cheader_filename = "goocanvas.h", has_type_id = false)] public struct CanvasStyleProperty { public GLib.Quark id; public GLib.Value value; } [CCode (cheader_filename = "goocanvas.h", has_type_id = false)] public struct CanvasTableData { public double width; public double height; [CCode (array_length = false)] public Goo.CanvasTableDimension dimensions[2]; public double border_width; public GLib.Array children; public Goo.CanvasTableLayoutData? layout_data; } [CCode (cheader_filename = "goocanvas.h", has_type_id = false)] public struct CanvasTableDimension { public int size; public double default_spacing; public double spacings; public uint homogeneous; } [CCode (cheader_filename = "goocanvas.h", has_type_id = false)] public struct CanvasTextData { public string text; public double x; public double y; public double width; public uint use_markup; public uint anchor; public uint alignment; public uint ellipsize; public uint wrap; } [CCode (cheader_filename = "goocanvas.h", cprefix = "CAIRO_ANTIALIAS_", type_id = "goo_cairo_antialias_get_type ()")] public enum CairoAntialias { DEFAULT, NONE, GRAY, SUBPIXEL } [CCode (cheader_filename = "goocanvas.h", cprefix = "CAIRO_FILL_RULE_", type_id = "goo_cairo_fill_rule_get_type ()")] public enum CairoFillRule { WINDING, EVEN_ODD } [CCode (cheader_filename = "goocanvas.h", cprefix = "CAIRO_HINT_METRICS_", type_id = "goo_cairo_hint_metrics_get_type ()")] public enum CairoHintMetrics { DEFAULT, OFF, ON } [CCode (cheader_filename = "goocanvas.h", cprefix = "CAIRO_LINE_CAP_", type_id = "goo_cairo_line_cap_get_type ()")] public enum CairoLineCap { BUTT, ROUND, SQUARE } [CCode (cheader_filename = "goocanvas.h", cprefix = "CAIRO_LINE_JOIN_", type_id = "goo_cairo_line_join_get_type ()")] public enum CairoLineJoin { MITER, ROUND, BEVEL } [CCode (cheader_filename = "goocanvas.h", cprefix = "CAIRO_OPERATOR_", type_id = "goo_cairo_operator_get_type ()")] public enum CairoOperator { CLEAR, SOURCE, OVER, IN, OUT, ATOP, DEST, DEST_OVER, DEST_IN, DEST_OUT, DEST_ATOP, XOR, ADD, SATURATE } [CCode (cheader_filename = "goocanvas.h", cprefix = "GOO_CANVAS_ANCHOR_", type_id = "goo_canvas_anchor_type_get_type ()")] public enum CanvasAnchorType { CENTER, NORTH, NORTH_WEST, NORTH_EAST, SOUTH, SOUTH_WEST, SOUTH_EAST, WEST, EAST, N, NW, NE, S, SW, SE, W, E } [CCode (cheader_filename = "goocanvas.h", cprefix = "GOO_CANVAS_ANIMATE_", type_id = "goo_canvas_animate_type_get_type ()")] public enum CanvasAnimateType { FREEZE, RESET, RESTART, BOUNCE } [CCode (cheader_filename = "goocanvas.h", cprefix = "GOO_CANVAS_ITEM_", type_id = "goo_canvas_item_visibility_get_type ()")] public enum CanvasItemVisibility { HIDDEN, INVISIBLE, VISIBLE, VISIBLE_ABOVE_THRESHOLD } [CCode (cheader_filename = "goocanvas.h", cprefix = "GOO_CANVAS_PATH_", type_id = "goo_canvas_path_command_type_get_type ()")] public enum CanvasPathCommandType { MOVE_TO, CLOSE_PATH, LINE_TO, HORIZONTAL_LINE_TO, VERTICAL_LINE_TO, CURVE_TO, SMOOTH_CURVE_TO, QUADRATIC_CURVE_TO, SMOOTH_QUADRATIC_CURVE_TO, ELLIPTICAL_ARC } [CCode (cheader_filename = "goocanvas.h", cprefix = "GOO_CANVAS_EVENTS_", type_id = "goo_canvas_pointer_events_get_type ()")] [Flags] public enum CanvasPointerEvents { VISIBLE_MASK, PAINTED_MASK, FILL_MASK, STROKE_MASK, NONE, VISIBLE_PAINTED, VISIBLE_FILL, VISIBLE_STROKE, VISIBLE, PAINTED, FILL, STROKE, ALL } [CCode (cheader_filename = "goocanvas.h", cname = "GOO_CANVAS_POLYLINE_NUM_ARROW_POINTS")] public const int NUM_ARROW_POINTS; }