pax_global_header00006660000000000000000000000064147132544630014523gustar00rootroot0000000000000052 comment=f37cf09c02b0ebd81d29c67be9741f54d76a9171 mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/000077500000000000000000000000001471325446300201535ustar00rootroot00000000000000mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/COPYING000066400000000000000000001045131471325446300212120ustar00rootroot00000000000000 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. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 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: Copyright (C) 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 . mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/Makefile000066400000000000000000000004371471325446300216170ustar00rootroot00000000000000include _conf.txt all: $(subdirs) .PHONY: $(subdirs) $(subdirs): $(MAKE) -C $@ install: for dir in $(subdirs); do $(MAKE) -C $$dir install; done uninstall: for dir in $(subdirs); do $(MAKE) -C $$dir uninstall; done clean: for dir in $(subdirs); do $(MAKE) -C $$dir clean; done mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/NEWS000066400000000000000000001505251471325446300206620ustar00rootroot00000000000000------------ mtPaint NEWS ------------ Here is a summary of the main changes in this release (see handbook for full details): 3.51 2024-??-?? * Kabyle translation added by Yacine Bouklif * Czech translation updated by Pavel Fric * Slovak translation updated by Jozef Riha * Spanish translation updated by Adolfo Jayme * Tagalog translation updated by Anjelo delCarmen * Environment variable MTPAINT_INIT to hold a script to be run at initializing the GUI * Environment variable MTPAINT_INI to use a nondefault user settings file * Animated WebP files now can be loaded into layers, or exploded into frames * Animated PNG (APNG) files now can be loaded into layers, or exploded into frames * GIF file format support now is builtin (does not use giflib anymore) * GIF loader made yet more tolerant to malformed GIF files * ICC colour profiles embedded in GIF and WebP images now can be applied on load * BMP loader made more tolerant to malformed BMP files * Better support for OS/2 BMP varieties * SVGZ (compressed SVG) files now can be imported * Counting used colours and exact conversion to indexed now are 9-19 times faster * Multithreaded decompression enabled for OpenJPEG 2.2+ in Windows version too * Support for multithreaded compression in OpenJPEG 2.4+ added * Support for compiling with libtiff 3 restored * Support for compiling with gcc builds (mis)configured with --with-gcc-major-version-only added * Support for compiling with FreeType 2.8 and GTK+1 added * Configure script now works with gcc-14 or clang-16 * Workaround for bug in glibc versions 2.15 - 2.16 added (crashed when comparing empty strings) * BUGFIX - RGB clipboard when used in Map effect now is padded with black if too small, as it should * BUGFIX - Gradient editor now displays correct overlay colours for utility channels again * BUGFIX - Saved GIF files are now properly labeled GIF89 if transparent and GIF87 if not * BUGFIX - GIF files without any image blocks now properly fail to load (instead of producing a 0x0 image) * BUGFIX - Composited GIF animation frames that use more than 256 colours now do not come out with wrong colours in certain cases * BUGFIX - Composited GIF animation frames now do not come out wrong in certain cases (after restore to previous that follows restore to background) * BUGFIX - Exploding, or loading into layers, GIF animation files with screen size and/or frame position outside canvas size limit no longer causes crash * BUGFIX - When first frame of GIF animation is loaded, ".000" is added to the filename, as it should be * BUGFIX - Animation frames and the layers file from loading an image now are ensured not to clash with it or each other when exceeding the path length limit * BUGFIX - When loading animation, raw/composited/nonzero-delay selection now works correctly again * BUGFIX - Loading certain broken BMP files no longer causes crash * BUGFIX - Ctrl+N and Ctrl+P keys now work, or do nothing, properly when focus is on a list in GTK+2/3 mode * BUGFIX - Horizontal separators in GTK+ 3.20 and later no longer are drawn as wide bars * BUGFIX - Problem with some scrollable areas in GTK+ 3.22 and later being smaller than they should be is now eliminated * BUGFIX - Response and redraw lag in GTK+3 when moving a large clipboard are now greatly reduced * BUGFIX - Closing pan window with a keypress while moving the panning frame with the mouse now cannot cause crash 3.50 2020-12-31 * Dutch translation updated by Pjotr * French translation updated by Victor Copovi * German translation updated by Simon Brixel * Russian translation updated * GTK+3 support - "./configure gtk3" * Scripting added - "Image->Script" to enter or run a script : See handbook chapter 10 for details * Commandline mode added - use "mtpaint --cmd" to run a script without GUI * Keyboard shortcuts can now be reconfigured - "Help->Keyboard shortcuts" * New keyboard shortcut Ctrl+H added for Channels->Hide image * Keyboard shortcuts now can be assigned for choosing previous/next pattern, and larger/smaller brush size * Optional gamma correction for painting and masking (Preferences->General->Use gamma correction when painting) * Rendering now uses multiple threads to utilize all available CPU cores * Text tools now allow selection of DPI value, letter-spacing, and alignment for multiline text * Distance function for shapeburst gradients is now selectable : "Distance type" * Composite images now can have alpha transparency, when background is non-opaque * Background layer now can use transparency like any other layer * Background layer position now can be changed via Ctrl+arrows or layers window spinbuttons, like any other layer * Patterns for colours A and B can now be chosen separately (Preferences->General->Separate patterns for A&B) * Builtin Bayer patterns now can be redefined : See handbook section A.6.1 for details * Threshold effect with interactive preview added (see handbook section 6.6.7) * Normalize effect added * Map effect added: map image's value/red/green/blue to gradient/palette/clipboard * Solid Noise effect with interactive preview added (Perlin noise generation) * Colour transform and source selection added to blend mode options * Threshold blend mode added * "Saturate more" blend mode redefined to not ignore source (previous behaviour available with "Image" source selected) * Horizontal and vertical ramps now respect drawing modes, opacity and masking * Lasso tool can be configured to shrink selection based on the selection channel - right click the tool icon * Clone tool is now continuous * Clone tool can be configured to work in unaligned mode - right click the tool icon * Ctrl+Left click now positions clone source when using clone tool * Ctrl+Right click now deletes last point when making polygonal selection (from a closed polygon, deletes the point nearest to cursor) * Shift and Shift+Ctrl now constrain selection box width/height when resizing it by clicking and dragging * Arrow keys can now be used for scrolling (Preferences->Interface->Arrow keys scroll canvas) * Zooming now can use mouse cursor position as its fixed point (Preferences->Interface->Zoom on cursor position) * Scroll wheel zoom now works for view window too * Zoom is now up to 8000% * "Hide image" and "View alpha as an overlay" can now be toggled separately for each layer (Preferences->General->Enable overlays by layer) * Colours A and B now highlighted in palette window * File actions can now enable and use an extended set of variable substitutions (see handbook section A.7) * New image format PMM (Portable MultiMap) added for interoperable storage and exchange of images : See handbook section A.2.4 for details * WebP file format save/load added * LBM file format (ILBM/PBM) save/load added * XPM files with 65-92 colours are now saved with smaller size * XPM files with up to 16M colours can now be saved and loaded as RGB images * ICC colour profiles embedded in BMP images now can be applied on load * OS/2 BMP files now load properly * Raw RGB palette files (6-bit PAL and 8-bit ACT) can now be loaded/saved via the Palette menu * TIFF compression made configurable * Dimensions can now be specified when loading SVG files * SVG files now can be loaded through 'rsvg-convert', in absence of GTK+2 librsvg plugin * Animation frames now can be saved in any suitable supported file format * Animation cycles can now specify sequence steps as containing several layers, or none : See handbook section 9.3.3 for details * Passing a list of files on command line is now possible using --flist option * Filenames passed on command line can now be sorted alphabetically with --sort option * Image loading and new image creation are now undoable by default * Committing paste when changing tool is now enabled by default * Saving an image now commits paste if auto commit mode is enabled * "Scale canvas" and "Resize canvas" now remember their aspect ratio toggle setting * The Free Rotate window now remembers the previous rotation angle in that mtPaint session * Dock area state is now remembered across sessions (unless opened automatically, for multiple files on command line) * Unmaximized window position and size are now remembered across sessions * Alpha values for colours A & B are now displayed on settings toolbar when editing image with alpha in coupled alpha mode * Drawing and fill operations on RGB images with colour protection mask now are up to 20 times faster * Undo system now uses a bit less memory * Initial undo memory size is now 1/4 of available memory * Support for compiling with giflib 5, libpng 1.6, libjpeg 9, OpenJPEG 2.3 added * Compilation now works using gcc-5.5 or clang and GTK+1 * Compilation now works using gcc-10 or clang-11 * BUGFIX - Compilation without JPEG and TIFF support now works again * BUGFIX - FreeType text tool now skips directory loops when scanning font directories * BUGFIX - Geometry info on the status bar now correctly updates after arrow keys or Escape key * BUGFIX - Gradient button no longer fails to show current gradient mode after showing settings toolbar * BUGFIX - Preview of Transform Colour no longer ignores area within paste marquee * BUGFIX - Ctrl+left/right/double click now set both colour and alpha from canvas in coupled alpha mode, as they should * BUGFIX - New image creation from system clipboard now respects "Undoable" toggle * BUGFIX - "Fix aspect ratio" now doesn't sometimes adjust both dimensions * BUGFIX - Problem with layers list in inactive dock tab sometimes not updating is now eliminated * BUGFIX - All keyboard shortcuts now work in Image View mode, as they should * BUGFIX - Transparent colour in composite images now works again * BUGFIX - Flood fill with shapeburst gradient now works again * BUGFIX - Flood fill with pattern now works when starting on colour A * BUGFIX - Saving LSS16 images no longer produces broken files in certain rare cases * BUGFIX - Trying to load a broken LSS16 file (truncated to header or less) no longer causes crash * BUGFIX - Loading certain broken BMP files no longer causes crash * BUGFIX - JPEG and PNG files damaged beyond all hope now properly fail to load (instead of just a library error and 0x0 image) * BUGFIX - PAM files with type BLACKANDWHITE are no longer loaded as grayscale (except if written as grayscale - ImageMagick does that) * BUGFIX - Loading PAM files with unknown TUPLTYPE doesn't cause crash * BUGFIX - SVG files starting with "Snap To Tile Grid" restricts the positions of tools to tile grid points - B key toggles on/off * sRGB colour scale generation added to palette editor * sRGB gradients added * Line tool now uses stroke gradient when no gradient placement exists * "Palette->Pick Gradient" approximates an A->B gradient using colours from current palette (see handbook section 3.3.9) * New palette sort mode added - Brightness * "Image->Segment" added : See handbook section 6.10 for details * Colour chooser popup added - press 'E' to open * Posterize function in Transform Colour window now has 3 types - Bitwise, Truncated, Rounded * Toggle to transform RGB clipboard image added to Transform Colour window * The Convert To Indexed window now remembers the previous settings in that mtPaint session * Text pasting tools now support multiline text (use Ctrl+Enter to insert line breaks) * "~/.fonts" directory added to default font paths for FreeType text tool on Linux * Animated GIF and multipage TIFF files now can be loaded into layers (one frame/page per layer) * GIF animation file exploding is now done internally in mtPaint, not Gifsicle * "Explode Frames" can now save frames in any suitable supported file format * File actions can now specify file format conversion : See handbook section A.7 for details * Netpbm file formats (PBM/PGM/PPM/PAM) save/load added * PCX file format save/load added * SVG file format import added (using librsvg; requires GTK+ 2.4 or later) * Better support for loading CMYK TIFF files as RGB/RGBA * ICC colour profiles embedded in PNG, JPEG and TIFF images now can be applied on load (using LittleCMS) * JPEG2000 file format support now can be compiled with either JasPer or OpenJPEG library * GIF loader made more tolerant to truncated or malformed GIF files * PNG and TGA loaders now convert palette-based alpha into an alpha channel * "Palette->Open" now can extract palette from indexed images in any supported file format * "Scale Canvas" now has 3 boundary extension modes - Mirror, Tile, Void * Filename and modified status now part of undo system * Transparent colour now part of undo system * Palette sorting, dragging a colour, or removing duplicate colours now do not lose transparent colour * New keyboard shortcuts added - J for lasso tool, D for line tool, F for flood fill tool * Toolbar and menu icons are now themeable (Preferences->Paths->Default Theme) * Command line globbing now possible using -w option, e.g. mtpaint -w "*.jpg" * Loading default settings from /etc/mtpaint/mtpaintrc is now supported in Windows version * Name and location of user settings file is now configurable : See handbook section A.6.4 for details * "Smart grid" and gamma correction are now enabled by default * "Selective error propagation" for dithering is now at 85% by default * Drawing and fill tools now are 2-3 times faster * Support for compiling with libpng 1.4, libjpeg 8a, and zlib 1.2.5 added * Configure script rewritten, now understands standard variables and options for installation paths and (cross-)compilation settings * Minimum required GTK+2 version now can be specified as configure option (e.g., "./configure gtk2.8") * Workaround for bug in GTK+ versions 2.14.0 - 2.14.2, 2.16.0, 2.16.1 added (spin buttons had wrong max values) * Workaround for unknown problem in GTK+ version 2.24.4 added (program locked up when trying to save a file when layers list is active) * BUGFIX - Problems with editing large images at high zoom levels are now eliminated * BUGFIX - Titlebar now displays new image's filename after loading layers file, as it should * BUGFIX - Layers list now correctly displays selected layer after loading layers file * BUGFIX - Layers window now correctly displays transparent colour after it has been modified elsewhere * BUGFIX - Other layers shown on canvas are now redrawn properly when current layer is moved * BUGFIX - Loading TIFF files with X or Y mirroring doesn't cause crash * BUGFIX - Planar TIFF files with alpha now load properly * BUGFIX - Transparency in indexed TGA files is now read properly * BUGFIX - Failed operations now do not flag image as modified * BUGFIX - Gradient colours are now properly updated after converting indexed image to RGB * BUGFIX - Cut operation in gradient mode when no placement exists now draws shapeburst gradient as it should * BUGFIX - Drawing arrowheads with tablet enabled now works properly * BUGFIX - Drawing arrowheads now doesn't produce corrupted undo frames * BUGFIX - Builtin file selector now properly handles manual edits in directory box * BUGFIX - Problem with FreeType text dialog occasionally hiding behind main window is now eliminated * BUGFIX - Lists in FreeType text dialog now don't fail to update or scroll * BUGFIX - FreeType text renderer now can handle PCF bitmap fonts * BUGFIX - FreeType text renderer now properly handles TTF fonts with embedded bitmaps * BUGFIX - FreeType text renderer now doesn't mistake some Unicode fonts for non-Unicode * BUGFIX - ":unscaled" font paths in xorg.conf are now parsed properly * BUGFIX - Redraw lag when moving a dialog over main window in Windows is now greatly reduced (fixed in GTK+) * BUGFIX - Ctrl+T key now draws selection outline as it should - keyboard shortcut for text tool is now Shift+T * BUGFIX - Handbook installed into a path with spaces in it no longer fails to open in nondefault browser on Windows * BUGFIX - Internationalization no longer fails on Windows when the current directory is not the installation directory * BUGFIX - Redraw glitches in builtin file selector on Windows are now eliminated * BUGFIX - Drag 'n' drop of files with non ASCII characters in names now works on Windows * "Distance to A+B" palette sort mode removed due to utter uselessness 3.31 2009-4-15 * Japanese translation updated by Norihiro YONEDA * Swedish translation updated by Daniel Nylander and Fredrik Forsmo * French translation updated by Plume * Builtin file selector uses stock file and directory icons on GTK+2 * Default settings are loaded from file /etc/mtpaint/mtpaintrc if it exists * BUGFIX - Compilation with GTK+ colour selector now works * BUGFIX - Escape key now works properly in builtin file selector in GTK+1 * BUGFIX - Filename length in builtin file selector no longer is limited to 100 characters * BUGFIX - Resizing the canvas window now doesn't cause polygon marquee to slide out of place * BUGFIX - Polygon marquee shrunk by resizing the canvas is now redrawn properly * BUGFIX - Problem with message windows not responding to mouse in some cases is now eliminated 3.30 2009-2-12 * Chinese (Simplified) translation updated by Cecc * Dutch translation added by Hans Strijards * Italian translation added by Angelo Gemmi * Swedish translation added by Daniel Nylander * Spanish translation updated by Miguel Anxo Bouzada, Francisco Jose Rey * Galician translation updated by Miguel Anxo Bouzada * Czech translation updated by Martin Petricek * French translation updated by Johan Serre * Portuguese translation updated by Tiago Silva * Turkish translation updated by Tutku Dalmaz * Russian translation updated * New colour picker (old one available as configure option) * New file picker (old one available as configure option) * Some menu items can have an icon (if set in the preferences) * Dock area added which now holds the former command line window (View->Show Dock) * Layers window handling reworked to make it more responsive * Layers window: position now editable via spin buttons * Layers window: transparent colour toggle removed * L key now toggles the layers window off (if the main window has focus) * "Composite to New Layer" operation added to Layers menu * Palette can be copied to or from the canvas using the Edit menu * System clipboard can be imported or exported using the Edit menu * Horizontal and vertical ramps can be created using the Selection menu * Shapeburst gradient now used for filling gradients when no placement exists (see handbook section 3.5.6.5) * Angular and conical gradients added * New image creation can now be made undoable * New image or layer can now be created from system clipboard or internal clipboard * Screenshots can now be grabbed into a new layer * Lasso tool now trims existing clipboard if no selection is present * Image->Skew skews image in one or two directions * View->Configure Grid sets grid colour preferences * "Smart Grid" toggle shows layer boundaries around transparent pixels * "View->Tracing Image" added : See handbook section 5.5 for details * Gaussian blur effect for images with alpha now is about 40% faster and uses less memory * Kuwahara-Nagao blur effect added (edge-preserving blur) * Dilation and erosion effects added * Seven new edge detection filters added - Sobel, Prewitt, Kirsch, Gradient, Roberts, Laplace, Morphological * Invert effect now respects masking * Drawing operations on utility channels now respect tool opacity * Drawing in image channel with coupled alpha now ignores drawing modes for alpha channel * Smudge tool now works about two times faster * 12 new blend modes added - Multiply, Divide, Screen, Dodge, Burn, Hard Light, Soft Light, Difference, Darken, Lighten, Grain Extract, Grain Merge * Ctrl+Double click selects average colour underneath brush square or selection marquee * "Convert to indexed" using current palette now truncates the palette only if requested * "Convert to indexed" PNN and Wu quantizers now have diameter based weighting option * Brush preview area, canvas, view and palette window now do not lose mouse button release events in GTK+1 * Brush preview area border now can't be messed up by theme engines * Makefiles now honor DESTDIR * Configure script now honors CC * Shift+Enter while pasting swaps clipboard with canvas (see handbook section 4.9) * Communal memory space now implemented for layers (see handbook section 8.2.1) * Support using ImageMagick for GIF animation, instead of Gifsicle - "./configure imagick" * BUGFIX - Polygon line selection now clearer in Windows version * BUGFIX - Occasional redraw glitches in paste and gradient previews eliminated * BUGFIX - "Remove All Layers" with layers window closed doesn't cause crash * BUGFIX - Pasting in tint mode into indexed images' utility channels now works correctly * BUGFIX - Gradient preview now properly shows effect of mask channel on alpha channel * BUGFIX - Alt+S key now opens Selection menu as it should * BUGFIX - Directory for animation frames is created relative to layers file, as it should be * BUGFIX - Saving animation frames in PNG format doesn't cause crash * BUGFIX - When pasting to a new layer it is created untitled, as it should * BUGFIX - CMYK JPEG files now load properly as RGB * BUGFIX - Drawing with A to B gradient in utility channels now respects left/right button * BUGFIX - Saving PNG images with more than one utility channel now works properly 3.21 2008-6-8 * Russian translation added by Sergey Irupin * Spanish translation updated by Antonio Sanchez Leon * Galician translation added by Miguel Anxo Bouzada * Use 'xdg-open' if available to open HTML help in default browser on Linux * Relaxed sanity checking in XPM loader to accept files with malformed headers * "Exact Conversion" option added to Palette->Create Quantized * Counting used colours now about twice as fast * Workaround for bug in libpng versions 1.2.17 - 1.2.24 added (was losing extra channels when loading) * BUGFIX - Canvas, view and palette area borders now can't be messed up by theme engines * BUGFIX - Persistent rectangle selection now doesn't steal arrow keys from gradient placement tool * BUGFIX - Internationalization now works properly in GTK+1 * BUGFIX - FreeType text rendering quality improved on Windows * BUGFIX - Text in active menu items no longer becomes invisible on Windows Vista (fixed in GTK+) * BUGFIX - Removable drives are now visible in fileselector on Windows (fixed in GTK+) 3.20 2007-12-27 * mtPaint is now licensed as GPL version 3 (or later) * Chinese (Simplified) added by puppychinese(Cecc) * Japanese translation added by Norihiro YONEDA * Polish translation updated by Groszek150(LucaS) * FreeType text pasting facility added * Actions section added to File menu * Sharper image reduction toggle added to "Scale Canvas" * Spacing for non-continuous tools is now configurable - right click the continuous mode toggle * "Blend" drawing mode added * "Unassociate Alpha" operation added to Channels menu * Palette is now stored in RGB PNG files * PNG compression level made configurable * TGA file format save/load added * JPEG2000 file format save/load added (EXPERIMENTAL) * XPM files with up to 4096 colours can now be saved and loaded as RGB images * Palette->Dither A sets colour A/B and the pattern based on the current A colour and the palette * Max-min quantizer added - creates small palettes with higher saturation and contrast * Faster and better PNN quantizer replaces the old DL3 quantizer * Full error precision toggle added to settings page of 'Convert To Indexed' window * Eliminated flicker when scrolling canvas in GTK+1 and GTK+2/Windows * Dragging the main/view window divider made to behave in GTK+1 * Main menu now rearranges itself to fit in window * Tile based undo system introduced to save memory when changes affect only small areas of the canvas * Max undo levels now configurable (from 10 to 1000) * Image loading now can be made undoable * mtPaint can now be compiled as a library (libmtpaint) * Image rotation now sharper and faster * Difference of Gaussians effect added * Patterns increased to 100 and now stored in xbm_patterns.xbm file * Edit->Create Patterns removed as patterns are now saved as standard XBM file * Preferences->Paths : Default palette and patterns now selectable * BUGFIX - Colour selective mode with zoom < 100% doesn't cause crash * BUGFIX - Gradient preview now properly shows effect of mask channel * BUGFIX - "Resize Canvas" with negative offset now works correctly * BUGFIX - Clipboard rotation now properly handles clipboard alpha * BUGFIX - Transparency in greyscale PNG files is now read properly * Lanczos3 rescaling filter removed due to unfavourable results * DL1 quantizer removed for the same reason 3.11 2007-4-2 * Slovak translation added by Jozef Riha * French translation updated by Sylvain Cresto * LSS16 file format load/save added to support syslinux bootup splash screens * Clipboard alpha is now used as clipboard mask when pasting to image without alpha channel * "Resize Canvas" can now be used to offset an image, with or without changing its size * TIFF files with alpha saved by Photoshop now load properly * Bash-specific idioms in configure script replaced by POSIXy equivalents * Zoom combo boxes are now better behaved in GTK+1 * DL3 quantizer now faster by about 30% * BUGFIX - Negative values in "Transform Colour" and "Resize Canvas" dialogs are read correctly again * BUGFIX - Drawing a 2 pixels high filled ellipse doesn't cause crash * BUGFIX - Tool cursor now doesn't revert to default one after showing or hiding view window * BUGFIX - Keyboard shortcut for swapping colours A & B now works in GTK+1 * BUGFIX - Clicking the palette grid in gradient editor now works properly in GTK+1 * BUGFIX - All spin buttons are now wide enough in GTK+1 * BUGFIX - No more redraw glitches when toggling view window on/off in GTK+1 3.10 2007-1-22 * Gradient drawing mode added * Palette shifting feature added to Palette menu * Turkish translation added by Muhammet Kara, Tutku Dalmaz * Taiwanese Chinese translation added by Wei-Lun Chao * Image tiling mode added to "Resize Canvas" * Greyscale effect now respects masking * Gamma corrected greyscale effect added * Gaussian blur effect replaces the old blur effect * Unsharp mask effect added * More palette sort modes added * Controls for alpha/selection/mask A/B added to "Edit colour A & B" * RGB and HSV colour scales generation integrated into palette editor * New advanced dithering modes with many configuration options added to "Convert To Indexed" window * Optional gamma correction for image scaling, rotation, Gaussian blur and unsharp mask * Smudge tool can be configured to ignore opacity mode - right click the tool icon * Smudge tool respects tool opacity for RGB images * Channel deletion made easier to use * View window can now be placed under drawing window using the View menu or 'H' key * "Blend A to B" with colour A identical to B now works like GIMP's Color To Alpha filter * Arrows and Shift+Arrows now move cursor around on canvas * Enter now simulates left mouse click, and Backspace, right click * '[' ']' and '{' '}' keys now used to change colour A/B * Ctrl+scroll wheel now scrolls canvas left-right (GTK+2 only) * Shift-+/- keys now zooms view window in/out * Shift-1...Shift-4 keys now switch to image/alpha/selection/mask channel * Selection marquee now persists through tool changes * Lasso tool now works for rectangular selections too * Indexed clipboard can now be pasted into RGB image * Image save/load completely rewritten, now with better support for TIFF, BMP, XPM and XBM formats * Channels, composite images and undo images can now be saved to any suitable supported file format * Image channel can now be saved and loaded just like other channels * Paint tool in tint mode now respects both Tint +/- toggle and left/right mouse button * "By image channel" flood fill option now works in non-fuzzy mode too * BUGFIX - Polygonal selections now respect selection channel * BUGFIX - Effects menu items now remain enabled for indexed images' utility channels * BUGFIX - 'Focus View Window' toggle now doesn't cause snatching during layer drags * BUGFIX - Smudge now doesn't make pixels darker than it should 3.02 2006-10-14 * Polish translation added by Simek * Spanish translation updated for version 3 by Antonio San * All menu items on all translations updated * Saving compressed GIF files now supported (using libgif) * Library detection in configure script improved * BUGFIX - Image scaling and rotation in nearest-neighbour mode now work correctly * BUGFIX - Lasso tool now properly handles clipboard alpha * BUGFIX - Clipboard save path now can be changed in Preferences * BUGFIX - XPM files smaller than 4*4 pixels can now be loaded 3.01 2006-7-15 * German translation updated for version 3 * BUGFIX - Memory alignment problems on Windows fixed (might affect speed) * BUGFIX - RGB-specific menu items now properly disabled in indexed mode 3.00 2006-6-21 * Channels facilities added * Menus & toolbars reworked to be more task oriented * Toolbars can now be toggled on and off via the View menu * Drag 'n' drop from file managers supported for loading new layers * Animation preview has a play toggle * Clicking palette numbers opens up "Palette Editor" window * Paste preview now respects the palette protection mask * Transform Colour Window - Hue control added * Transform Colour Window - Selective palette option * Undo now less wasteful of memory when adjusting the palette * Major rewrite of back end code to improve performance * Colour A/B editor now uses GTK+ colour dialog * Ctrl+Arrows resizes selection area * Flood fill has fuzzy mode - right click icon for controls * Saving/Loading clipboards now includes mask data * Saving a composite layer image now de-coupled from saving the layer data file * Most documentation has been removed from the F1 help and is now in HTML form * HTML documentation available as a separate download package * mtPaint mailing lists set up - http://sourceforge.net/mail/?group_id=155874 * configure script makes no assumptions about CPU - ./configure --help * BUGFIX - Saving a composite layer image does not occasionally leave transparent areas * BUGFIX - Transforming colour of palette with preview (RGB images) now works properly * BUGFIX - Status bar now updated after removing all layers * BUGFIX - Scaling image to width/height 1/2 does not cause crash 2.31 2006-5-31 * German translation contributed by Oliver Frommel 2.30 2006-3-1 * Animation of layers is now possible - see 'Animation' in docs for info * Animated GIF files can now be opened frame by frame if you have Gifsicle installed * File->Export Animated GIF ... can create an animated GIF file if you have Gifsicle installed * Image can now be centralized in the window - Preferences->Zoom to toggle * Image scaling facilities improved and extended by Dmitry Groshev * Edit->Tint Mode added by Dmitry Groshev - see bottom of Tools section in docs for info * Ellipse outline code improved by Dmitry Groshev * Selection->Alpha Blend A,B : see website tutorial for example * Various tutorials added to website * BUGFIX - Clone tool does not misbehave when dragging beyond image edge with CTRL pressed * BUGFIX - Text rotation should now work properly in Windows XP * BUGFIX - Files with UTF8 characters in the filenames can now be opened in Windows * BUGFIX - Status bar wobbling with some Windows systems resolved * BUGFIX - Text paste + selection mask + zoom doesn't lose mask 2.20 2006-1-1 * mtPaint web site is now at http://mtpaint.sourceforge.net/ * View window now part of the main window - V key toggles on/off * Ctrl+Arrows or Ctrl+Shift+Arrows moves a layer around * View->Set Zoom window sets zoom for main/view window + focus toggle - Z key toggles on/off * Palette scaling now uses colour A/B as start/finish colour & index * Gimp palette files (*.gpl) can now be loaded/saved via the Palette menu * If file ~/mtpaint.gpl exists, it is loaded as the default palette on startup * Transparent GIF information can now be loaded/saved + general GIF import improvements * Transparent pixels in main edit area are now grey chequers in single layer mode * Counting all RGB colours now requires 2MB not 16MB * Custom icons can now be compiled for mtPaint - see ./src/icons1/README for details * Maximum layers increased to 100 * Windows binary installation has been simplified with standard setup.exe * BUGFIX - When changing tool with function key, brush perimeter is now cleared properly 2.10 2005-11-20 * Support for pressure sensitive tablets via Preferences window, see 'Tools' in docs * Colour histogram added to Information window (Ctrl-I) * Palette->Create Quantized (Wu) method added - Good for small palettes e.g. 32 * Convert to Indexed window improved * View window now has focus toggle to keep locked on the main window centre position * Info window now counts all colours in RGB images - if 16MB memory is available * Preferences window is now non-modal and has an apply button * ./src/Makefile simplified * Brazilian Portuguese translation contributed by Paulo Trevizan * BUGFIX - memory leak fixed with DL1 Quantize & Floyd-Steinberg * BUGFIX - segfault fixed when pressing * and - keys simultaneously in pan window * BUGFIX - segfault fixed when using read only filesystems with no ~/.mtpaint write access * BUGFIX - segfault fixed when loading certain animated GIFs - warning message instead 2.03 2005-9-23 * BUGFIX - Resolved rare segfault when shifting a layer up/down with no view window showing 2.02 2005-9-19 * PNG files with a transparency can now be loaded and saved - See 'Limitations' * View->Show zoom grid - Parameters set in Preferences window->Zoom * "Save As" window improved with new file attribute widgets * Status bar changes - (T=?) for transparencies, 'x' in selection geometry * mtPaint project registered with Launchpad/Rosetta to help with translations: https://launchpad.net/products/mtpaint/+translations * Partial French translation contributed by Nicolas Velin * Partial Portuguese translation contributed by Israel G. Lugo * BUGFIX - Copy/Paste in auto commit mode followed by paint tool does not draw extra line 2.01 2005-8-14 * BUGFIX - Resolved occasional segfault when loading and showing all layers in the main window * BUGFIX - Windows version: screenshot grabbing now hides the new image window 2.00 2005-8-7 * View -> Layers Window - See 'Layers' in docs for info * Edit -> Paste To New Layer * Polygon selection tool added - See 'Selections' in docs for info * Selection -> Lasso Selection & Cut * Clone tool added - See 'Tools' in docs for info * View window now has zoom facility * Line tool now has the ability to draw an arrowhead - See 'Tools' in docs for info * Relative filenames passed at command line now converted to absolutes * GTK+2: Grabbing a screenshot via the new image window minimizes main window first * Preferences toggle to commit paste when changing tool * Keyboard shortcuts for recently used files - Shift+Ctrl+F1 = Revert * Icons on toolbar reworked to accommodate most commonly used functions * BUGFIX - Greyscale PNG files are now loaded properly 0.97 2005-6-4 * Text tool: Antialiasing without a background colour now possible (alpha blended edges) * Text tool: Changing colour/pattern during paste updates text * Text tool: Independent toggles for background colour and rotation * Changes are flagged in the titlebar * Brushes and patterns increased to 81 * Maximum tool size/flow increased to 200 * Logic of colour A/B editor improved for RGB images * Help docs now supported with international po files * Accuracy of circle brush in continuous mode improved * Specifying a CPU is now more generic - see "./configure --help" * BUGFIX - Loading a large image now correctly adjusts the scrollbars * BUGFIX - Czech characters improved in Windows 0.95 2005-5-4 * Text tool added - See "Tools" for usage * View window now available via View menu or 'V' key * Brush presets now available via Edit menu, F3, icon on toolbar or preview area * Screenshot grabbing facility - "mtpaint -s" or File->New - See "Tips" section * Right mouse button paints with A/B reversed * Palette -> Swap A & B * Mouse scroll wheel zooms in/out if set in Preferences - GTK+2 only * Function keys don't zoom any more - use numbers 1-9 instead * Various new keyboard shortcuts added/changed * Website redesign contributed by Abdulla Al Muhairi * BUGFIX - Xine does not now close Pan Window/Pattern chooser popup * BUGFIX - Occasional pasting 'slips' eliminated * BUGFIX - Edit all colours window now works properly when screen depth <24 bpp 0.90 2005-4-12 * Internationalization now supported with "./configure intl" * Spanish translation contributed by the Guadalinex team * Czech translation contributed by Pavel Ruzicka * Preferences window allows the manual selection of language translations * Man page contributed by Guadalinex team - "./configure man" to install * Pasting with less than 100% opacity now shows preview of resulting transparency * Widget behaviour improved in Quantize & Transform Colour windows * Page Up/Down keys now work as expected in Command Line Window * Changing tool does not tax the CPU as much on older hardware * Accuracy improvements for line tool and circle in continuous mode when size>1 * Max geometry is now 16384x16384 * New typeface for palette numbers * Several more configure script options added - "./configure --help" for details * BUGFIX - Pattern flood fills now work under all conditions * BUGFIX - In GTK+2, filenames with non ASCII characters are now be handled properly * BUGFIX - Attempting to fill on a protected colour does not set opacity to 100% * BUGFIX - Ctrl -/+ Adjusts opacity as originally designed * BUGFIX - Undo/Redo to an indexed image with smudge does not cause segfault 0.75 2005-2-15 * Pan window added - See "Tools" for usage * Colour protection mask now works with RGB images * Selection -> Outline Ellipse + New icon : Thickness = tool size * Converting RGB images to indexed improved: * i) 'Exact' option now uses less memory + slightly quicker * ii) Accuracy of 'Dither' method is now better * iii) Floyd-Steinberg option added * iv) Palette quantization DL1 & DL3 options added with[out] Floyd-Steinberg * Palette -> Create Quantized (DL1 & DL3) : RGB images only * Palette -> Sort -> Frequency : Sorts an indexed palette by pixel frequency on canvas * Palette Sort window has apply button * File -> Export Undo Images (reversed) * Transform Colour window improved: * i) Apply button added * ii) Toggles to transform RGB image and/or palette * iii) Gamma moved to top and is now the 1st operation to be done * iv) Window now pops up where the mouse pointer is positioned * v) Return/Enter keys now press 'OK' button * Tips section added to README & help * Progress window is now movable and does not remain above other windows * configure script improved to cater for systems without pkg-config, i.e. GTK+1 only * BUGFIX - Memory leaks in read_png & read_jpeg cleaned up * BUGFIX - Corrupt PNG & JPEG files are now handled properly * BUGFIX - Palette area update invisibility on some systems corrected * BUGFIX - Jerking of vertical/horizontal scrollbars when zooming eliminated * BUGFIX - Zooming in GTK+1 now respects the specified zoom centre * BUGFIX - While pasting, cursor flickering on slow hardware has been eliminated 0.50 2005-1-1 * Smudge tool - RGB images only, continuous or non-continuous modes * Image -> Free Rotate : Rotate image at any angle * Selection -> Mask Colour A,B : See 'Selections' in README/Help for example * Selection -> Unmask Colour A,B * Selection -> Mask All Colours * Selection -> Clear Mask : Revert to normal opaque rectangular paste * Counting unique RGB pixels is faster (particularly GTK+2) * Selection geometry on status bar now also shows selection diagonal angle + length * Preferences -> Force zoom to 100% or current zoom with a new file * Numbers 1-9 set zoom, Insert=Transform colours, Delete=Crop, Page Up/Down=Scale/Resize * 1-9, +, -, =, Q, Home, Insert, etc... keys work while Command Line window selected * Compilation now works using gcc-2.95 and libpng-1.0 * Configure script contains example of how to compile with Slackware 8.0 * Undo/Redo stops current paste only when changing to/from Indexed/RGB * BUGFIX - Occasional Pango warnings in GTK+2 upon startup stopped * BUGFIX - When undo/redo clears paste the cursor is not stuck as 4 way arrow * BUGFIX - Last pixel of straight line now painted if size=1 0.47 2004-12-11 * View -> 10%, 25%, 50% : +, -/= keys can be used to get zoom below 100% * View -> Toggle Image View (Home key) : Show/Hide palette, menu, status bar etc * View -> Command Line Window : Shows files passed in command line (if > 1) * Effects -> Isometric Transformations * Palette colours : Shift + click/drag moves a colour to a new index * Posterize effect merged with brightness/contrast/saturation window -> Transform Colour * Gamma added to Transform Colour window * Using "mtpaint -v" or calling from other binary name starts in full image view * Selection resize method improved + right button = clear * Limitation relating to flood fill colour resolved for most situations * Using arrow keys while painting changes colour A/B * Edit -> Opacity Undo Mode (F12) replaces Preferences option * Greyscale now in Effects menu * Escape key now selects first button of alert box * Default tool is now selection * Colour toolbar icons moved together * Keyboard shortcuts added for Cropping/Transforming colours/Invert/Greyscale * Compiler options tweaked - faster/smaller binary * BUGFIX - Undo/Redo to indexed/RGB while pasting RGB/indexed does not cause segfault 0.45 2004-11-21 * Tool opacity is now variable so subtle RGB painting is now possible * Effects -> Edge Detect, Sharpen, Soften, Blur, Emboss * Scaling a 24 bit RGB image is now smoother * Image -> Convert To Indexed : Exact conversion, Quantized Palette, Dithered, Scattered * Save TIFF files (uncompressed RGB) * Save GIF files (uncompressed indexed 256 colours) * Save BMP files (uncompressed indexed & RGB) * File -> Export Undo Images * File -> Export ASCII Art * Palette -> Add Colours changed to Set Palette Size, i.e. reduction is now possible * File -> Save As : If image has a filename, put this into the filename box * When loading a png/tiff/jpeg/gif only use progress bar if image is large * Middle mouse button sets the zoom centre * Image -> Preferences : Q key can now quit mtPaint * Spray/shuffle mouse pointers made more consistent * BUGFIX - Rotating the image with no undo memory does not cause image corruption * BUGFIX in GTK+2.4 - Pressing enter while pasting does not press toolbar button 0.40 2004-11-8 * File -> New : Create 24 bit RGB image * Most functions/tools now work on a 24 bit RGB canvas (except colour protection mask) * Load/Save 24 bit RGB PNG files * Load 24 bit RGB/Greyscale, Save 24 bit RGB JPEG files - Quality set by Preferences * Load TIFF files * Load uncompressed BMP files * Image -> Convert To RGB * Image -> Convert To Indexed * Edit -> Load Clipboard -> 1-12 * Edit -> Save Clipboard -> 1-12 * More icons have been added to the toolbar * File menu now contains a recently used file list - Set limit in Preferences window (0-20) * Maximum canvas height/width set to 8192, minimum set to 1 * Last directory loaded from command line is now correctly remembered * Palette -> Load default * BUGFIX - Resizing/Scaling with no undo memory does not cause segfault * BUGFIX - Using a static tool after resize/scale/rotate does not create unwanted shapes * BUGFIX - An occasional crash when using the GTK+ colour selector was corrected 0.37 2004-10-25 * Image -> Brightness-Contrast-Saturation * Image -> Scale Canvas * Image -> Resize Canvas * Image -> Preferences : The user can specify what info is displayed on the status bar * Image -> Rotate Clockwise * Image -> Rotate Anti-Clockwise * Selection -> Rotate Clockwise * Selection -> Rotate Anti-Clockwise * Help -> About (F1) : Reflects the current README file * File -> New : User can now create a greyscale image * Palette -> Edit All Colours * Palette -> Create Scale : Create blended colours from one index to another * Palette -> Sort * Image -> Bacteria Effect : Try it a few times with "mtpaint graphics/bacteria.png" * File selection window geometry stored independently from main window geometry * BUGFIX - Progress window now appears above file selector in GTK+2 Windows/Gnome * BUGFIX - Maximizing A/B colour editor window does not cause segfault or window corruption 0.35 2004-10-16 * Sources can now be compiled using MinGW/MSYS to create a Windows version of mtPaint * XPM & XBM images can now be loaded and saved * File -> Preferences : User can view/set XPM/XBM transparency/hotspot info * Straight line tool added to toolbar * Image menu now houses Convert to greyscale, Posterize, Information, Preferences and Crop * Image -> Flip Vertically * Image -> Flip Horizontally * Image -> Invert * Selection -> Flip Vertically * Selection -> Flip Horizontally * Undo/redo levels displayed on status bar * Progress bar is now used for load/save/flip - Useful for large images or slow machines * Minimum main window size set so 640x480 screens can use mtPaint * Setting zoom centre now requires Shift+Right button - Avoids clash with paste/line tools * BUGFIX - Save failure does not now clear the mem_changed flag * BUGFIX - Accuracy of max undo levels improved in Information window * BUGFIX - Menus updated when loading file from command line (no option to crop to 1x1) 0.30 2004-10-4 * GIF images can now be loaded into mtPaint * Mouse pointers for static shapes improved * Selection menu now houses "Select All", "Select None" * Selection -> Outline Rectangle : Draws outline of tool size pixels around current selection * Selection -> Filled Rectangle : Fills the current selection area * Selection -> Filled Ellipse : Draws a filled ellipse inside the current selection area * Selection -> Line - Slash : Draws straight line on selection from top left to bottom right * Selection -> Line - Backslash : Draws straight line on selection from top right to bottom left * Edit -> Continuous Painting : Makes painting the 6 static shapes continuous and smooth * Status bar has "CON" to indicate if the program is in Continuous Painting mode * Information window now contains details of current clipboard data * Ctrl+Left Button while over palette sets colour B (useful for stylus/tablet users) * configure script extended - use "./configure --help" for details * BUGFIX - Selecting None during paste at high zoom does not tax the CPU * BUGFIX - Changing tool during paste at high zoom does not tax the CPU * BUGFIX - Pasting while already pasting at high zoom does not cause program termination * BUGFIX - Selection/Paste perimeter does not get corrupted in GTK+2 while using scrollbars 0.25 2004-9-24 * Palette -> Convert To Greyscale : Converts current palette to greyscale * Edit -> Crop : Crops the canvas to the current selection * The red/white selection box can now be resized by clicking and dragging the corners * Selection geometry is now displayed on the status bar * Start with blank canvas if file was not successfully loaded from the command line * Enter/Return now commits a paste even when Shift/Ctrl are pressed * Loading a palette can now be undone/redone * BUGFIX - Errors while trying to "Save As" are now treated properly * BUGFIX - Pressing CTRL and moving the mouse without pressing a button does not tax the CPU * BUGFIX - Loading a palette with 256 colours is now possible * BUGFIX - Paste To Centre menu item now behaves as expected * BUGFIX - mem_changed flag now cleared properly after saving - no more false warnings * BUGFIX - Fixed segfault when cutting during a paste (edit menu logic improved) * Select/Paste now uses less CPU and doesn't flicker as much * Undo system rewritten: * Accommodates geometry changes from cropping * Only malloc's memory as required, not en masse at beginning * Tool perimeter shows correct position when mouse is over the grey background 0.24 2004-9-19 * Makefile - Default compiler options changed to make no optimizations * Preferences -> Option to show mouse cursor as the tool shape * Preferences -> Confirm exit alert now optional * When quitting/opening/file-new without saving changes, the user is warned * TODO list in README updated with my plans for the next few months * File -> Save As given shortcut Shift+Ctrl-S * Selection tool added to toolbar * Edit -> Cut * Edit -> Copy * Edit -> Paste To Centre * Edit -> Paste * Edit -> Select All * Edit -> Select None * Preferences -> Option to not display clipboard image while pasting * README updated with details about selection, copy, cut, paste etc. * BUGFIX in memory.c - correct posterizing now happens whether using -ffast-math or not * BUGFIX in GTK+1 - CTRL shortcuts are now not blocked by size/spray spin buttons * First public release of mtPaint on gnomefiles.org 0.23 2004-9-13 First public release of mtPaint on freshmeat.net 0.21 2004-9-6 Beta testing begins! 0.20 2004-9-5 9 basic tools + palette edit/add/posterize/merge/load/save finished 0.16 2004-8-31 Undo/Redo implemented - default MAX_UNDO = 100 0.15 2004-8-28 Patterns implemented with square tool + colour protection mask implemented 0.05 2004-8-14 PNG load + image display & zoom features 0.04 2004-8-12 Program structure fixated 0.02 2004-8-7 GUI fixated 0.00 2004-7-4 Project started - GUI & back end designs kicked around on paper and in Glade mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/README000066400000000000000000000234061471325446300210400ustar00rootroot00000000000000-------------------------------------------------- mtPaint 3.51 - Copyright (C) 2004-2024 The Authors -------------------------------------------------- See 'Credits' section for a list of the authors. mtPaint 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. mtPaint 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. mtPaint is a simple GTK+1/2/3 painting program designed for creating icons and pixel based artwork. It can edit indexed palette or 24 bit RGB images and offers basic painting and palette manipulation tools. It also has several other more powerful features such as channels, layers and animation. Due to its simplicity and lack of dependencies it runs well on GNU/Linux, Windows and older PC hardware. There is full documentation of mtPaint's features contained in a handbook. If you don't already have this, you can download it from the mtPaint website. If you like mtPaint and you want to keep up to date with new releases, or you want to give some feedback, then the mailing lists may be of interest to you: http://sourceforge.net/mail/?group_id=155874 ----------- Compilation ----------- In order to compile mtPaint on a GNU/Linux system you will need to have the libraries and headers for GTK+1 and/or GTK+2 and/or GTK+3, libpng and zlib. If you want to load or save JPEG, TIFF, JPEG2000 and WebP files you will also need libjpeg, libtiff, libopenjpeg or libjasper, and libwebp. If you want to compile the international version you will need to have the gettext system and headers installed. You may then adjust the Makefile/sources to cater for your needs and then: For GTK+2 ========= ./configure make su -c "make install" For GTK+1 ========= ./configure gtk1 make su -c "make install" For GTK+3 ========= ./configure gtk3 make su -c "make install" If you want to uninstall these files from your system, you should type: su -c "make uninstall" There are various configure options that may be useful for some people. Use "./configure --help" to find out what options are available. If you are compiling a binary for distribution to other peoples systems, the option 'asneeded' is particularly useful (if the gcc option -Wl,--as-needed is available, i.e. binutils >=2.17), as it only creates links to libraries which are absolutely necessary to mtPaint. For example, without this option if you compile mtPaint against GTK+2.10 you will find it will not run on GTK+2.6 systems because Cairo doesn't exist on the older system. Use "./configure release" to compile mtPaint with the same optimizations we use for distribution packages; this includes the "asneeded" option. To enable internationalization, add the "intl" option. If you are compiling mtPaint on an older system without gtk-config, you may need to adjust the configure script so that the GTK+1 settings are done manually. I have provided an example in the configure script to demonstrate. You can call mtpaint with the -v option and the program will start in viewer mode so there will be no palette, menu bar, etc. You can restore these items by pressing the "Home" key. After installation you can create a symlink to add a viewer command, e.g. su -c "ln -s mtpaint /usr/local/bin/mtv" Then you can open some graphics files with "mtv *.jpg". This is a shortcut to writing "mtpaint -v *.jpg". mtPaint can only edit one image at a time, but when you have more than one filename in the command line a window will appear with all of the filenames in a list. If you select one of the names, it will be loaded. I find this is helpful for editing several icons or digital photos. After running mtPaint for the first time, a new file is created to store your preferred settings and previously used files etc. This file is named ".mtpaint" and stored in the user's home directory. If you rename or remove this file then the next time mtPaint is run it will use the default settings. The easiest way to compile mtPaint for Windows is using MinGW cross-compiler on a GNU/Linux system, and the included "winbuild.sh" shell script. The script will compile mtPaint and all required runtime files from source code, and prepare a binary package and a separate development package, with headers and development libraries; see "gtk/README" for details. Another alternative is doing a manual build with MinGW on GNU/Linux, for which you'll need to have installed requisite library and header files, corresponding to the runtime libraries you intend to use. Since version 3.40, the official mtPaint package for Windows uses custom-built runtime files, and development libraries and headers, produced in the automated build process described above; with version 3.31 and earlier, you could use the packages listed below for MinGW/MSYS build. Either way, after the headers and libraries are installed where MinGW expects them, you configure mtPaint for cross-compiling, then run "make" as usual. Like this: PATH=/usr/i586-mingw32/bin:$PATH ./configure --host=i586-mingw32 [options] make It should also still be possible to compile mtPaint for Windows the old way, using MinGW/MSYS on a Windows system. However this wasn't done for quite some time, so the description below still refers to older versions of MinGW, MSYS and library packages. mtpaint.exe compiled according to it, will only be compatible with runtime libraries packaged with mtPaint 3.31 or older; to use the newer runtime (of version 3.40+), you'll need to use library and header files produced while cross-compiling the runtime (see above). If you want to do this you must first download the mtPaint 3.31 setup program and install the files to "C:/Program Files/mtPaint/" and then: 1) Install MinGW and MSYS - http://www.mingw.org/ MinGW-3.1.0-1.exe - to c:/MinGW/ MSYS-1.0.10.exe - to c:/msys/ 2) Install the GTK+2 developer packages (and dependencies like libpng) - ftp://ftp.gtk.org/pub/gtk/v2.6/win32/ and http://gnuwin32.sourceforge.net/packages.html For GTK+2 you will need to download and extract the following zip files to c:/msys: gtk+-dev-2.6.4.zip pango-dev-1.8.0.zip atk-dev-1.9.0.zip You will also need to download and extract the following zip files to c:/msys: glib-dev-2.6.4.zip libpng-1.2.7-lib.zip zlib-1.2.1-1-lib.zip libungif-4.1.4-lib.zip jpeg-6b-3-lib.zip tiff-3.6.1-2-lib.zip If you want to compile the internationlized version you will need to download and extract to c:/msys the following zip files from http://sourceforge.net/projects/gettext : gettext-runtime-0.13.1.bin.woe32.zip gettext-tools-0.13.1.bin.woe32.zip libiconv-1.9.1.bin.woe32.zip For some reason I needed to move c:/msys/bin/msgfmt & xgettext to c:/msys/local/bin/ in order to get it to run properly. If you have trouble running msgfmt you may need to do the same. 3) Download the latest mtPaint sources and unpack them to c:/msys. 4) To compile the code you must then use MSYS to "./configure", then "make" and "make install" 5) If all goes well, you should have mtpaint.exe which you can run using the same method described above. You may have compiled mtPaint using more recent versions of libraries so you may need to change the filenames, such as libpng12.dll -> libpng13.dll and libungif.dll -> libungif4.dll. Because I very rarely use Windows, I am sadly unable to support any other version of GTK+ but the one in the official package. That is, while mtPaint should in principle be able to compile and run with any version of GTK+2, only the packaged version has undergone real testing on Windows, and has been patched to fix all known Windows-specific bugs in it. ------- Credits ------- mtPaint is maintained by Dmitry Groshev. wjaguar@users.sourceforge.net http://mtpaint.sourceforge.net/ The following people (in alphabetical order) have contributed directly to the project, and are therefore worthy of gracious thanks for their generosity and hard work: Authors Dmitry Groshev - Contributing developer for version 2.30. Lead developer and maintainer from version 3.00 to the present. Mark Tyler - Original author and maintainer up to version 3.00, occasional contributor thereafter. Xiaolin Wu - Wrote the Wu quantizing method - see wu.c for more information. General Contributions (Feedback and Ideas for improvements unless otherwise stated) Abdulla Al Muhairi - Website redesign April 2005 Alan Horkan Alexandre Prokoudine Antonio Andrea Bianco Charlie Ledocq Dennis Lee Donald White Ed Jason Eddie Kohler - Created Gifsicle which is needed for the creation and viewing of animated GIF files http://www.lcdf.org/gifsicle/ Guadalinex Team (Junta de Andalucia) - man page, Launchpad/Rosetta registration Lou Afonso Magnus Hjorth Martin Zelaia Pasi Kallinen Pavel Ruzicka Puppy Linux (Barry Kauler) Victor Copovi Vlastimil Krejcir William Kern Translations Brazilian Portuguese - Paulo Trevizan, Valter Nazianzeno Czech - Pavel Ruzicka, Martin Petricek, Roman Hornik, Pavel Fric Dutch - Hans Strijards, Pjotr French - Nicolas Velin, Pascal Billard, Sylvain Cresto, Johan Serre, Philippe Etienne, Victor Copovi Galician - Miguel Anxo Bouzada German - Oliver Frommel, B. Clausius, Ulrich Ringel, Simon Brixel Hungarian - Ur Balazs Italian - Angelo Gemmi Japanese - Norihiro YONEDA Kabyle - Yacine Bouklif Polish - Bartosz Kaszubowski, LucaS Portuguese - Israel G. Lugo, Tiago Silva Russian - Sergey Irupin, Dmitry Groshev Simplified Chinese - Cecc Slovak - Jozef Riha Spanish - Guadalinex Team (Junta de Andalucia), Antonio Sanchez Leon, Miguel Anxo Bouzada, Francisco Jose Rey, Adolfo Jayme Swedish - Daniel Nylander, Daniel Eriksson Tagalog - Anjelo delCarmen Taiwanese Chinese - Wei-Lun Chao Turkish - Muhammet Kara, Tutku Dalmaz mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/configure000077500000000000000000000563471471325446300221010ustar00rootroot00000000000000#!/bin/sh # Mini configure script # 26-01-2011 echo MT_V="3.50.11" MT_DATE="2024-11-08" MT_VERSION="mtPaint $MT_V" MT_LANG=NO MT_MAN=NO MT_POD=NO MT_CPICK=mtpaint MT_FPICK=mtpaint MT_LISTS=2 MT_ANIM=Gifsicle ICON_SET=icons1 GTK_FILE=_conf.txt HELP=1 OS= MARCH= OPTS=YES USE_THREADS=YES AS_NEEDED= DEFS= WARN= # Path overrides MT_BINDIR= MT_DATAROOT= MT_DOCDIR= MT_LOCDIR= MT_MANDIR= MT_PO= MT_HOST= # Initialize library-tracking vars STATICLIBS= for A in PNG JPEG JP2 TIFF WEBP FT CMS do eval "N$A=" eval "STATIC_$A=" STATICLIBS="$STATICLIBS \$STATIC_$A" done GTK= GTKVERSION= # Prevent nasty surprises from locale unset LC_ALL export LC_COLLATE=C # LC_CTYPE=C LC_NUMERIC=C for A in "$@" do case "$A" in "staticpng" ) STATIC_PNG=PNG;; "jpeg" ) NJPEG=YES;; "nojpeg" ) NJPEG=NO;; "staticjpeg" ) STATIC_JPEG=JPEG;; "jp2v1" ) NJP2=OpenJPEG;; "jp2v2" ) NJP2=OpenJPEG2;; "jasper" ) NJP2=JasPer;; "nojp2" ) NJP2=NO;; "staticjp2" ) STATIC_JP2=JPEG2000;; "tiff" ) NTIFF=YES;; "notiff" ) NTIFF=NO;; "statictiff" ) STATIC_TIFF=TIFF;; "webp" ) NWEBP=YES;; "nowebp" ) NWEBP=NO;; "staticwebp" ) STATIC_WEBP=WebP;; "noft" ) NFT=NO;; "staticft" ) STATIC_FT=FreeType;; "lcms" ) NCMS=LittleCMS;; "lcms2" ) NCMS=LittleCMS2;; "nolcms" ) NCMS=NO;; "staticlcms" ) STATIC_CMS=LittleCMS;; "gtk1" ) GTK=1;; "gtk"[23]* ) GTK=2 [ "$A" != "${A#gtk3}" ] && GTK=3 # Override minor version of installed GTK+ GTKVERSION="`echo "$A" | sed -e 's/gtk[23]\.\{0,1\}\([0-9]*\).*/\1/'`";; "intl" ) MT_LANG=YES;; "man" ) MT_MAN=YES;; "pod" ) MT_POD=YES;; "gtkfilesel" ) MT_FPICK=gtkfilesel;; "gtkcolsel" ) MT_CPICK=gtkcolsel;; "oldlists" ) MT_LISTS=1;; "imagick" ) MT_ANIM=ImageMagick;; "icons"* ) ICON_SET=$A;; "win" ) OS="MinGW/MSYS" GTK=2;; "cflags" ) OPTS=CFLAGS;; "386" ) MARCH='-march=i386';; "486" ) MARCH='-march=i486';; "586" ) MARCH='-march=i586';; "686" ) MARCH='-march=i686';; "--cpu="* ) MARCH="-march=${A#*=}";; "slow" ) OPTS=NO;; "debug" ) OPTS=DEBUG;; "release" ) OPTS=RELEASE;; "thread" ) USE_THREADS=YES;; "nothread" ) USE_THREADS=NO;; "asneeded" ) AS_NEEDED=-Wl,--as-needed;; "--help" ) HELP=0;; "--prefix="* ) MT_PREFIX="${A#*=}";; "--bindir="* ) MT_BINDIR="${A#*=}";; "--datarootdir="* ) MT_DATAROOT="${A#*=}";; "--docdir="* ) MT_DOCDIR="${A#*=}";; "--localedir="* ) MT_LOCDIR="${A#*=}";; "--mandir="* ) MT_MANDIR="${A#*=}";; "--host="* ) MT_HOST="${A#*=}";; "--fakeroot"* ) FAKE_ROOT="${A#*=}" FAKE_LL="${A%%=*}" FAKE_LL="${FAKE_LL#--fakeroot}";; "panic" ) WARN="-Wextra -Wno-missing-field-initializers -Wno-unused-parameter";; "flush" ) echo Clearing out directory to original state echo make clean echo rm $GTK_FILE rm po/mtpaint.pot rm -rf src/graphics exit;; "merge" ) xgettext src/*.c src/*.h --keyword=_ --keyword=__ -o po/mtpaint.pot cd po NEW_DIR=trans_ mkdir $NEW_DIR`date +%d-%m-%Y-%H-%M-%S` for file in *.po do echo New file = $file-a mv "$file" "$file-a" msgmerge -N "$file-a" mtpaint.pot > "$file" mv "$file-a" $NEW_DIR* done rm mtpaint.pot mv $NEW_DIR* ../../old_trans exit;; "newpo" ) xgettext src/*.c src/*.h --keyword=_ --keyword=__ -o po/mtpaint.pot exit;; # Override variable [!=]*=* ) MT_VAR=${A%%=*} if [ "$MT_VAR" != "${MT_VAR#*[!A-Za-z0-9_]}" ] then echo "Invalid variable: '$MT_VAR'" else eval $MT_VAR=\${A#*=} export $MT_VAR fi;; * ) echo "Unrecognized option '$A'" exit;; esac done if [ "$HELP" = 0 ] then cat << 'EOF' ; exit Usage: ./configure [OPTION] ... [VAR=VALUE] ... Options: win .............. Configure for Windows MinGW / MSYS gtk1 ............. Configure for GTK+1 gtk2 ............. Configure for GTK+2 gtk2.VER ......... Configure for GTK+2, minor version VER gtk3 ............. Configure for GTK+3 gtk3.VER ......... Configure for GTK+3, minor version VER gtkfilesel ....... Use GtkFileSelection file picker gtkcolsel ........ Use GtkColorSelection colour picker oldlists ......... Use GtkList and GtkCList lists imagick .......... Use ImageMagick for GIF animation tasks thread ........... Use multithreading nothread ......... Don't use multithreading cflags ........... Use CFLAGS environment variable --cpu= ........... Target a specific CPU, e.g. athlon-xp, x86-64 686 .............. Target 686 machines 586 .............. Target 586 machines 486 .............. Target 486 machines 386 .............. Target 386 machines slow ............. Don't use compiler optimizations asneeded ......... Use linker optimization --as-needed release .......... Use the set of optimizations which work best for mtPaint code debug ............ Include debugging info in binary --host= .......... Cross-compile with a specific toolchain, e.g. i586-mingw32 staticpng ........ Statically link PNG library jpeg ............. Use libjpeg nojpeg ........... Don't use libjpeg staticjpeg ....... Statically link JPEG library jp2v1 ............ Use libopenjpeg jp2v2 ............ Use libopenjpeg2 jasper............ Use libjasper nojp2 ............ Don't use libopenjpeg and libjasper staticjp2 ........ Statically link JPEG 2000 library tiff ............. Use libtiff notiff ........... Don't use libtiff statictiff ....... Statically link TIFF library webp ............. Use libwebp nowebp ........... Don't use libwebp staticwebp ....... Statically link WebP library noft ............. Don't use FreeType staticft ......... Statically link FreeType library lcms ............. Use LittleCMS lcms2............. Use LittleCMS2 nolcms ........... Don't use LittleCMS staticlcms ....... Statically link LittleCMS library intl ............. Use internationalized po files man .............. Install the mtPaint man page --fakeroot=DIR ... DIR = location of library and include files to use for cross-compilation --fakeroot64=DIR . DIR = ... when targeting a 64-bit system icons ............ Compile with alternative icon set - see ./src/icons1/README for details --prefix=DIR ..... DIR = prefix location of all installs, e.g. /usr or /usr/local (default) --bindir=DIR ..... DIR = location of bin file to install, ${prefix}/bin by default --docdir=DIR ..... DIR = location of documentation to install, ${prefix}/share/doc/mtpaint by default --localedir=DIR .. DIR = location of locale files to install, ${prefix}/share/locale by default --mandir=DIR ..... DIR = location of man page to install, ${prefix}/share/man/man1 by default panic ............ Enable rarely-useful warnings - developers only flush ............ Flush directories to initial state newpo ............ Create ./po/mtpaint.pot merge ............ Update all po files with new strings - developers only Environment variables: CC ............... C compiler (defaults to gcc) CFLAGS ........... C compiler flags (not recommended; for enabling better optimizations use 'release' option instead) LDFLAGS .......... linker flags, e.g. -L CPPFLAGS ......... C preprocessor flags, e.g. -I CCLD ............. "test link" command (defaults to $CC -nostartfiles) Default settings: GNU/Linux system, O2 optimizations, English only version, mtpaint file picker, mtpaint colour picker. pkg-config gtk+-2.0 is checked to determine GTK+2 availability in GNU/Linux EOF fi ### Detect the OS if [ -n "$OS" ] ; then : # Do nothing elif [ "$OSTYPE" = "msys" ] ; then OS="MinGW/MSYS" elif [ "$OSTYPE" != "${OSTYPE#darwin}" ] ; then OS="Darwin" elif [ -z "$MT_HOST" ] ; then OS="GNU/Linux" elif [ "$MT_HOST" != "${MT_HOST%mingw32*}" ] ; then OS="MinGW/GNU/Linux" else OS="Other/GNU/Linux" fi ### Prepare to use selected icon set mkdir -p src/graphics cp src/$ICON_SET/*.xpm src/$ICON_SET/*.xbm src/graphics ### Choose which sub-makefiles to run MAKE_DIRS=src [ "$MT_LANG" = YES ] && MAKE_DIRS="$MAKE_DIRS po" # translations [ "$MT_MAN" = YES ] && MAKE_DIRS="$MAKE_DIRS doc" # man page ### Setup directories if [ "$OS" != "${OS#MinGW/}" ] then EXEEXT=".exe" MT_PREFIX="${MT_PREFIX-/c/Program Files/mtPaint}" else MT_PREFIX="${MT_PREFIX-/usr/local}" fi MT_BINDIR="${MT_BINDIR:-$MT_PREFIX/bin}" MT_DATAROOT="${MT_DATAROOT:-$MT_PREFIX/share}" MT_DOCDIR="${MT_DOCDIR:-$MT_DATAROOT/doc/mtpaint}" MT_MANDIR="${MT_MANDIR:-$MT_DATAROOT/man}" if [ "$OS" != "${OS#MinGW/}" ] then MT_LOCDIR="${MT_LOCDIR:-$MT_BINDIR/locale}" # Want package-relative path on Windows MT_PKGDIR=${MT_BINDIR%/bin} [ "$MT_PKGDIR" = "$MT_BINDIR" ] && MT_PKGDIR=${MT_BINDIR%/lib} MT_PKGDIR="$MT_PKGDIR/" MT_PO="/" while [ "$MT_LOCDIR" = "${MT_LOCDIR#$MT_PKGDIR}" ] do MT_PO="/..$MT_PO" if [ "$MT_PKGDIR" = "${MT_PKGDIR%/[!/]*/}" ] then # Cannot relativize path - leave it be MT_PO= break fi MT_PKGDIR="${MT_PKGDIR%/[!/]*/}/" done MT_PO="$MT_PO${MT_LOCDIR#$MT_PKGDIR}" else MT_LOCDIR="${MT_LOCDIR:-$MT_DATAROOT/locale}" MT_PO="$MT_LOCDIR" fi ### Setup compiler # Only GCC and GNU toolchain are fully supported at the time # Clang is recognized mainly to avoid mixups with GCC version checks # No support for GNU-incompatible linkers in fakeroot mode INCLUDES= LIBS= if [ "$OS" != "${OS%GNU/Linux}" ] || [ "$OS" = "Darwin" ] then CC=${CC:-`which ${MT_HOST:+$MT_HOST-}gcc`} PKG_CONFIG=${PKG_CONFIG:-${MT_HOST:+$MT_HOST-}pkg-config} fi CC=${CC:-gcc} # Use compiler as linker in tests - this way, both accept "-Wl," in LDFLAGS CCLD=${CCLD:-$CC -nostartfiles} # Get compiler type CCNAME=gcc # by default $CC -v 2>&1 | grep -q "clang version" && CCNAME=clang # Get compiler version CCVER=`$CC -dumpfullversion -dumpversion` # Get target architecture CCARCH=`$CC -dumpmachine` # For eternally misconfigured, Windows-hosted MinGW [ "$CCARCH" != "${CCARCH#mingw32}" ] && CCARCH=i586-mingw32 # For any properly built toolchain ARCH=${ARCH:-${CCARCH%%-*}} if [ -n "$FAKE_ROOT" ] # A way to replace just some libraries, leaving others be then PKGCONFIG () # Check both locations in turn { PKG_CONFIG_PATH= PKG_CONFIG_LIBDIR="$FAKE_ROOT/lib$FAKE_LL/pkgconfig" \ pkg-config --define-variable=prefix="$FAKE_ROOT" "$@" \ 2> /dev/null || "$PKG_CONFIG" "$@" } MT_TESTLINK="$CCLD -L$FAKE_ROOT/lib$FAKE_LL -Wl,--unresolved-symbols=ignore-in-shared-libs $LDFLAGS" MT_TESTCOMP="$CC -std=c89 -fno-builtin -isystem $FAKE_ROOT/include $CPPFLAGS ${MT_TESTLINK#$CCLD}" else PKGCONFIG () { "$PKG_CONFIG" "$@" } MT_TESTLINK="$CCLD $LDFLAGS" MT_TESTCOMP="$CC -std=c89 -fno-builtin $CPPFLAGS $LDFLAGS" fi if [ "$OS" != "${OS%/MSYS}" ] then MT_TESTLINK="redir -e /dev/null $MT_TESTLINK -L/lib" MT_TESTCOMP="redir -e /dev/null $MT_TESTCOMP -L/lib" INCLUDES="-I/include" LIBS="-L/lib" fi IS_LIB() { $MT_TESTLINK -$1 -o _conf.tmp > /dev/null 2>&1 } CAN_DO() { echo "main() { $1; }" > _conf.c $MT_TESTCOMP _conf.c -o _conf.tmp > /dev/null 2>&1 } HAVE_FUNC() { CAN_DO "$1()" } HAVE_CC_VER() { # First 2 parts of GCC or Clang version MT_VN0=${CCVER%%.*} MT_VN1=${CCVER#$MT_VN0} MT_VN0=${MT_VN0%%[!0-9]*} MT_VN1=${MT_VN1#.} MT_VN1=${MT_VN1%%[!0-9]*} # Compare them to given version [ ${1%%.*} -eq "$MT_VN0" ] && [ ${1#*.} -le "$MT_VN1" ] || \ [ ${1%%.*} -lt "$MT_VN0" ] } HAVE_GCC_VER() { [ "$CCNAME" = gcc ] && HAVE_CC_VER $1 } HAVE_CLANG() { [ "$CCNAME" = clang ] } HAVE_CLANG_VER() { [ "$CCNAME" = clang ] && HAVE_CC_VER $1 } ### Detect libraries and functions if CAN_DO "volatile int v, z; z = __sync_fetch_and_add(&v, 1)" then DEFS="$DEFS -DHAVE__SFA" fi if HAVE_FUNC "mkdtemp" then DEFS="$DEFS -DHAVE_MKDTEMP" fi if IS_LIB "ljpeg" then NJPEG=${NJPEG:-YES} fi NJPEG=${NJPEG:-NO} if IS_LIB "lopenjp2" then NJP2=${NJP2:-OpenJPEG2} fi if IS_LIB "lm -lopenjpeg" then NJP2=${NJP2:-OpenJPEG} fi if IS_LIB "ljasper" then NJP2=${NJP2:-JasPer} fi NJP2=${NJP2:-NO} if IS_LIB "ltiff" then NTIFF=${NTIFF:-YES} fi NTIFF=${NTIFF:-NO} if IS_LIB "lwebp" then NWEBP=${NWEBP:-YES} fi NWEBP=${NWEBP:-NO} if IS_LIB "lfreetype" then NFT=${NFT:-YES} fi NFT=${NFT:-NO} if IS_LIB "llcms2" then NCMS=${NCMS:-LittleCMS2} fi if IS_LIB "llcms" then NCMS=${NCMS:-LittleCMS} fi NCMS=${NCMS:-NO} ### Setup optimizations if [ "$OPTS" = RELEASE ] then # Target i386 when compiling for any x86 CPU with GCC; # this produces smallest *AND* fastest binary # !!! Questionable, now; need retesting, and proper cross-configuring too # With Clang, target pentium4; no incompatible HW expected in the wild, # and anything lesser results in much slower code case $ARCH in i?86) HAVE_CLANG && MARCH=${MARCH:--march=pentium4} MARCH=${MARCH:--march=i386};; esac CFLAGS="-O2 $MARCH" # Add optimizations which are proven to really make mtPaint code faster if HAVE_CLANG then : # Clang - no useful extra flags elif HAVE_GCC_VER 4.0 then # GCC 4.x CFLAGS="$CFLAGS -fweb -fomit-frame-pointer -fmodulo-sched" else # GCC 3.x CFLAGS="$CFLAGS -fweb" fi # Do not add unneeded dependencies AS_NEEDED="-Wl,--as-needed" # Disable GTK+ debug code DEFS="$DEFS -DGTK_NO_CHECK_CASTS -DG_DISABLE_CAST_CHECKS" elif [ "$OPTS" = DEBUG ] then CFLAGS="-ggdb" elif [ "$OPTS" = YES ] then CFLAGS="-O2 $MARCH" elif [ "$OPTS" = NO ] then CFLAGS="$MARCH" else # $OPTS = CFLAGS MARCH= # And leave CFLAGS alone fi [ "$OPTS" != DEBUG ] && LDFLAGS="-s $LDFLAGS" # Strip debug info # Set Windows-specific flags if [ "$OS" != "${OS#MinGW/}" ] then CFLAGS="-mms-bitfields $CFLAGS" LDFLAGS="-mwindows $LDFLAGS" fi # Revert the changed defaults in GCC 10 and Clang 11 { HAVE_GCC_VER 10.0 || HAVE_CLANG_VER 11.0; } && CFLAGS="$CFLAGS -fcommon" # Enable warnings WARN="-Wall $WARN" if HAVE_GCC_VER 4.0 then # Tell gcc 4.x to shut up WARN="$WARN -Wno-pointer-sign" fi if HAVE_GCC_VER 4.1 then # Tell gcc 4.1+ to shut up some more WARN="$WARN -Wno-int-to-pointer-cast -Wno-pointer-to-int-cast" fi if HAVE_GCC_VER 6.0 then # Tell gcc 6.x to stop misleading WARN="$WARN -Wno-misleading-indentation" fi if HAVE_GCC_VER 9.3 then # Tell gcc 9.3+ to cut it short WARN="$WARN -Wno-stringop-truncation -Wformat-truncation=0 -Wformat-overflow=0" fi if HAVE_CLANG then # Tell Clang to clang less WARN="$WARN -Wno-pointer-sign -Wno-int-to-pointer-cast -Wno-string-plus-int" fi if HAVE_CLANG_VER 11.0 then # Tell Clang 11.x to clang yet less WARN="$WARN -Wno-pointer-to-int-cast -Wno-misleading-indentation" fi # Deterministic compile SET_RANDSEED= if HAVE_CLANG || HAVE_GCC_VER 3.3 then SET_RANDSEED='-frandom-seed=$*' fi # Apple linker [ "$OS" = "Darwin" ] && AS_NEEDED= ### Setup libraries MT_DLIBS= MT_SLIBS= LIB_NAME () # ( lib_ID , static_mode , libs ) { if [ "$2" ] then MT_SLIBS="$MT_SLIBS ${1:+-l$1}$3" else MT_DLIBS="$MT_DLIBS ${1:+-l$1}$3" fi } if [ "$NJP2" = OpenJPEG2 ] then INCLUDES="$INCLUDES `PKGCONFIG libopenjp2 --cflags 2>/dev/null`" || \ INCLUDES="$INCLUDES -I/usr/include/openjpeg-2.0" LIB_NAME openjp2 "$STATIC_JP2" DEFS="$DEFS -DU_JP2=2" fi if [ "$NJP2" = OpenJPEG ] then INCLUDES="$INCLUDES `PKGCONFIG libopenjpeg1 --cflags 2>/dev/null`" || \ INCLUDES="$INCLUDES `PKGCONFIG libopenjpeg --cflags 2>/dev/null`" || \ INCLUDES="$INCLUDES -I/usr/include/openjpeg" LIB_NAME openjpeg "$STATIC_JP2" DEFS="$DEFS -DU_JP2" if [ "$STATIC_JP2" ] || [ "$OS" != "${OS#MinGW}" ] then DEFS="$DEFS -DOPJ_STATIC" fi fi if [ "$NJP2" = JasPer ] then LIB_NAME jasper "$STATIC_JP2" DEFS="$DEFS -DU_JASPER" fi if [ "$NWEBP" = YES ] then LIB_NAME webp "$STATIC_WEBP" DEFS="$DEFS -DU_WEBP" fi if [ "$NTIFF" = YES ] then LIB_NAME tiff "$STATIC_TIFF" DEFS="$DEFS -DU_TIFF" fi if [ "$NJPEG" = YES ] then LIB_NAME jpeg "$STATIC_JPEG" DEFS="$DEFS -DU_JPEG" fi if [ "$NFT" = YES ] then DEFS="$DEFS -DU_FREETYPE" if [ "$OS" = "GNU/Linux" ] && which freetype-config > /dev/null 2>&1 then # Do it the old way, for native builds on *very* old distros FT_INCLUDES="`freetype-config --cflags`" LIB_NAME "" "$STATIC_FT" "`freetype-config --libs`" elif [ "$OS" != "${OS%/MSYS}" ] then # pkg-config may be missing on Windows - hardcode its results FT_INCLUDES="-I/include/freetype2" LIB_NAME "" "$STATIC_FT" "-lfreetype -lz" else # Use pkg-config FT_INCLUDES="`PKGCONFIG freetype2 --cflags`" LIB_NAME "" "$STATIC_FT" "`PKGCONFIG freetype2 --libs`" fi # Remove irrelevant GLib2 headers when compiling for GTK+1 if [ "$GTK" = 1 ] then for ZAD in $FT_INCLUDES do [ "$ZAD" = "${ZAD#*/glib-2.0}" ] && INCLUDES="$INCLUDES $ZAD" done else INCLUDES="$INCLUDES $FT_INCLUDES" fi # libiconv may be separate, or part of libc HAVE_FUNC "iconv_open" || LIB_NAME iconv "$STATIC_FT" fi if [ "$NCMS" = LittleCMS2 ] then LIB_NAME lcms2 "$STATIC_CMS" DEFS="$DEFS -DU_LCMS=2" fi if [ "$NCMS" = LittleCMS ] then LIB_NAME lcms "$STATIC_CMS" DEFS="$DEFS -DU_LCMS" fi if [ -n "$FAKE_ROOT" ] then INCLUDES="$INCLUDES `PKGCONFIG libpng --cflags`" LIB_NAME "" "$STATIC_PNG" "`PKGCONFIG libpng --libs`" else LIB_NAME png "$STATIC_PNG" fi LIB_NAME z "$STATIC_PNG" LIB_NAME m if [ "$MT_LANG" = YES ] then HAVE_FUNC "gettext" || LIB_NAME intl DEFS="$DEFS -DU_NLS -DMT_LANG_DEST='\"$MT_PO\"'" fi # !!! Would be nice to subtract MT_SLIBS from MT_DLIBS first LIBS="$LIBS $MT_DLIBS${MT_SLIBS:+ -Wl,-dn $MT_SLIBS -Wl,-dy}" rm -f _conf.c _conf.tmp ### Setup GTK+ FOUND_GTK= [ "$OS" != "${OS#MinGW/}" ] && GTK=2 [ "${GTK:-2}" = 2 ] && PKGCONFIG gtk+-2.0 --cflags > /dev/null 2>&1 && FOUND_GTK=2 GTK=2 [ "${GTK:-1}" = 1 ] && PKGCONFIG gtk+ --cflags > /dev/null 2>&1 && FOUND_GTK=1 GTK=1 [ "${GTK:-3}" = 3 ] && PKGCONFIG gtk+-3.0 --cflags > /dev/null 2>&1 && FOUND_GTK=3 GTK=3 GTK=${GTK:-1} if [ "$USE_THREADS" = NO ] ; then THREADS= elif [ "$GTK" -ge 2 ] ; then THREADS="gthread-2.0" else # "$GTK" = 1 THREADS="gthread" fi # !!! It is assumed that the nondefault install prefix is the one GTK+ lives in if [ "$FOUND_GTK" = 3 ] && [ ${GTKVERSION:-12} -ge 12 ] && PKGCONFIG --atleast-version=3.12 gtk+-3.0 then GTKPREFIX=`PKGCONFIG gtk+-3.0 --variable=prefix` INCLUDES="$INCLUDES `PKGCONFIG gtk+-3.0 $THREADS --cflags`" LIBS="$LIBS `PKGCONFIG gtk+-3.0 $THREADS --libs`" elif [ "$FOUND_GTK" = 3 ] then echo "GTK+3 versions prior to 3.12 are not and can not be supported" exit 1 elif [ "$FOUND_GTK" = 2 ] then GTKPREFIX=`PKGCONFIG gtk+-2.0 --variable=prefix` INCLUDES="$INCLUDES `PKGCONFIG gtk+-2.0 $THREADS --cflags`" LIBS="$LIBS `PKGCONFIG gtk+-2.0 $THREADS --libs`" elif [ "$FOUND_GTK" = 1 ] then # !!! Full equivalent to "gtk-config gtk" would be "pkg-config gtk+ gmodule", # but for mtPaint, 'gmodule' is nothing but a nuisance anyway GTKPREFIX=`PKGCONFIG gtk+ --variable=prefix` INCLUDES="$INCLUDES `PKGCONFIG gtk+ $THREADS --cflags`" LIBS="$LIBS `PKGCONFIG gtk+ $THREADS --libs`" elif [ "$GTK" = 2 ] && [ "$OS" != "${OS%/MSYS}" ] then # Windows system w/o working pkg-config GTKPREFIX=/ INCLUDES="$INCLUDES -I/include/gtk-2.0 -I/lib/gtk-2.0/include -I/include/atk-1.0 -I/include/pango-1.0 -I/include/freetype2 -I/include/glib-2.0 -I/lib/glib-2.0/include" LIBS="$LIBS -lgtk-win32-2.0 -lgdk-win32-2.0 -lpango-1.0 -lglib-2.0 -lgobject-2.0 -lgdk_pixbuf-2.0 ${THREADS:+-lgthread-2.0}" elif [ "$GTK" = 1 ] && gtk-config --cflags > /dev/null then # Very old GNU/Linux system GTKPREFIX=`gtk-config gtk --prefix` INCLUDES="$INCLUDES `gtk-config gtk $THREADS --cflags`" LIBS="$LIBS `gtk-config gtk $THREADS --libs | sed 's/-rdynamic//'`" elif [ "$GTK" = 1 ] then # Even older GNU/Linux system GTKPREFIX=/opt/gnome GTK_INCLUDE="-I$GTKPREFIX/include/gtk-1.2 -I$GTKPREFIX/include/glib-1.2 -I$GTKPREFIX/lib/glib/include -I/usr/X11R6/include" GTK_LIB="-L/usr/lib -L/usr/X11R6/lib -L$GTKPREFIX/lib -lgtk -lgdk -lgmodule -lglib -ldl -lXext -lX11 -lm" echo echo I have not been able to find gtk-config so I am assuming the following: echo echo GTK_INCLUDE = $GTK_INCLUDE echo GTK_LIB = $GTK_LIB echo echo If these values are not right for your system, edit the configure script echo INCLUDES="$INCLUDES $GTK_INCLUDE" LIBS="$LIBS $GTK_LIB" else echo "Failed to find required GTK+$GTK libraries" 1>&2 exit 1 fi # Need to add this to use GTK+1 with GCC 5 or Clang [ "$GTK" = 1 ] && { HAVE_CLANG || HAVE_GCC_VER 5.0; } && CFLAGS="$CFLAGS -std=gnu89" # Also need to add "-lX11" on GTK+2/X systems [ "$GTK" = 2 ] && [ "$LIBS" != "${LIBS#*gdk-x11}" ] && LIBS="$LIBS -lX11" # Need the same on GTK+3/X systems even more [ "$GTK" = 3 ] && PKGCONFIG gtk+-x11-3.0 && LIBS="$LIBS -lX11" # GTK+ minor version to use DEFS="$DEFS${GTKVERSION:+ -DGTK${GTK}VERSION=$GTKVERSION}" # Widgets to use if [ "$GTK" = 3 ] then MT_LISTS=2 # GtkList & GtkCList are with us no more MT_FPICK=mtpaint # Neither is GtkFileSelection elif [ "$GTK" = 2 ] then # GTK+3 compatible things need some compatibility [ ${GTKVERSION:-18} -lt 18 ] && MT_LISTS=1 [ "$FOUND_GTK" != 2 ] || PKGCONFIG --atleast-version=2.18 gtk+-2.0 || MT_LISTS=1 else # GTK+1 MT_LISTS=1 fi # Stop the spam [ "$GTK" = 2 ] && WARN="$WARN -Wno-deprecated-declarations" ### Set feature flags [ "$USE_THREADS" = "YES" ] && DEFS="$DEFS -DU_THREADS" if [ "$MT_FPICK" = mtpaint ] then DEFS="$DEFS -DU_FPICK_MTPAINT" else # "$MT_FPICK" = gtkfilesel DEFS="$DEFS -DU_FPICK_GTKFILESEL" fi if [ "$MT_CPICK" = mtpaint ] then DEFS="$DEFS -DU_CPICK_MTPAINT" else # "$MT_CPICK" = gtkcolsel DEFS="$DEFS -DU_CPICK_GTK" fi [ "$MT_LISTS" = 1 ] && DEFS="$DEFS -DU_LISTS_GTK1" [ "$MT_ANIM" = ImageMagick ] && DEFS="$DEFS -DU_ANIM_IMAGICK" # mtPaint version DEFS="$DEFS -DMT_VERSION='\"$MT_VERSION\"'" ### ### Rebase the paths, for '--fakeroot' substitutions to work FAKE_PATHS () # variable, key { FAKE_KEYS=" " for A in $1 do [ "$A" = "${A#$2/}" ] && continue for B in "$GTKPREFIX/include" "$GTKPREFIX/lib"\ /usr/include /usr/lib /usr/local/include /usr/local/lib do [ "$A" != "${A#$2$B}" ] || continue C="$2$FAKE_ROOT${A#$2${B%/*}}" [ "$C" != "$A" ] && [ "$FAKE_KEYS" = "${FAKE_KEYS#* $C }" ] &&\ FAKE_KEYS="$FAKE_KEYS$C " break done done echo "$FAKE_KEYS" } if [ "$FAKE_ROOT" ] then # !!! Spaces in paths will NOT be well received here FAKE_PATHS "$LIBS" -L LIBS="-L$FAKE_ROOT/lib$FAKE_LL $FAKE_KEYS $LIBS" FAKE_PATHS "$INCLUDES" -I INCLUDES="-isystem $FAKE_ROOT/include $FAKE_KEYS $INCLUDES" AS_NEEDED="-Wl,--as-needed,--no-add-needed,--unresolved-symbols=ignore-in-shared-libs" fi ### Write config cat << CONFIG > "$GTK_FILE" CC = $CC $WARN EXEEXT = $EXEEXT MT_VERSION=$MT_VERSION MT_DATE=$MT_DATE MT_PREFIX="$MT_PREFIX" MT_DATAROOT="$MT_DATAROOT" MT_LANG_DEST="$MT_LOCDIR" MT_MAN_DEST="$MT_MANDIR" LDFLAG = $AS_NEEDED $LIBS $LDFLAGS CFLAG = $DEFS $INCLUDES $CPPFLAGS $CFLAGS subdirs = $MAKE_DIRS BIN_INSTALL="$MT_BINDIR" SET_RANDSEED = $SET_RANDSEED CONFIG ### Report config eval STATICLIBS=\"$STATICLIBS\" STATICLIBS=`echo -n "$STATICLIBS" | sed -e 's/ */ /g' -e 's/^ //'` cat << CONFIG --------------------- mtPaint Configuration --------------------- ------- General ------- Version $MT_V System $OS Toolkit GTK+$GTK${GTKVERSION:+.$GTKVERSION} Lists GTK+$MT_LISTS File Picker $MT_FPICK Colour Picker $MT_CPICK Animation Package $MT_ANIM Use FreeType $NFT Use CMS $NCMS Icon set $ICON_SET Internationalized $MT_LANG Multithreaded $USE_THREADS -------- Compiler -------- Optimizations $OPTS CFLAGS $CFLAGS LDFLAGS ${AS_NEEDED:+$AS_NEEDED }$LDFLAGS Static libraries ${STATICLIBS:-NONE} ---------- File Types ---------- Use JPEG $NJPEG Use JPEG 2000 $NJP2 Use TIFF $NTIFF Use WebP $NWEBP ------------ Installation ------------ Binary install $MT_BINDIR CONFIG [ "$MT_LANG" = YES ] && cat << CONFIG Locale install $MT_LOCDIR Locale program $MT_PO CONFIG cat << CONFIG Install man page $MT_MAN CONFIG [ "$MT_MAN" = YES ] && cat << CONFIG Man page install $MT_MANDIR CONFIG echo mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/doc/000077500000000000000000000000001471325446300207205ustar00rootroot00000000000000mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/doc/HELP000066400000000000000000000126301471325446300213750ustar00rootroot00000000000000------------------ Keyboard shortcuts ------------------ Ctrl-N Create new image Ctrl-O Open Image Ctrl-S Save Image Ctrl-Shift-S Save layers file Ctrl-Q Quit program Ctrl-A Select whole image Escape Select nothing, cancel paste box J Lasso selection Ctrl-C Copy selection to clipboard Ctrl-X Copy selection to clipboard, and then paint current pattern to selection area Ctrl-V Paste clipboard to centre of current view Ctrl-K Paste clipboard to location it was copied from Ctrl-Shift-V Paste clipboard to new layer Enter/Return Commit paste to canvas Shift+Enter/Return Commit paste and swap canvas into the clipboard Arrow keys Paint Mode - Move the mouse pointer Arrow keys Selection Mode - Nudge selection box or paste box by one pixel Shift+Arrow keys Nudge mouse pointer, selection box or paste box by x pixels - x is defined by the Preferences window Ctrl+Arrows Move layer or resize selection box Ctrl+Shift+Arrows Move layer or resize selection box by x pixels Enter/Return Paint Mode - Simulate left click Backspace Paint Mode - Simulate right click [ or ] Change colour A to the next or previous palette item Shift+[ or ] Change colour B to the next or previous palette item Delete Crop image to selection Insert Transform colours - i.e. Brightness, Contrast, Saturation, Posterize, Gamma Ctrl-G Greyscale the image Shift-Ctrl-G Greyscale the image (Gamma corrected) Ctrl+M Mirror the image Shift-Ctrl-I Invert the image Ctrl-T Draw a rectangle around the selection area with the current fill Ctrl-Shift-T Fill in the selection area with the current fill Ctrl-L Draw an ellipse spanning the selection area Ctrl-Shift-L Draw a filled ellipse spanning the selection area Ctrl-E Edit the RGB values for colours A & B Ctrl-W Edit all palette colours Ctrl-P Preferences Ctrl-I Information Ctrl-Z Undo last action Ctrl-R Redo an undone action Shift-T Text Tool (GTK+) T Text Tool (FreeType) V View Window L Layers Window Ctrl-H Toggle Hide Image mode B Toggle Snap to Tile Grid mode X Swap Colours A & B E Choose Colour A Draw open arrow head when using the line tool (size set by flow setting) S Draw closed arrow head when using the line tool (size set by flow setting) D Line Tool F Flood Fill Tool +,= Main edit window - Zoom in - Main edit window - Zoom out Shift +,= View window - Zoom in Shift - View window - Zoom out 1 10% zoom 2 25% zoom 3 50% zoom 4 100% zoom 5 400% zoom 6 800% zoom 7 1200% zoom 8 1600% zoom 9 2000% zoom Shift + 1 Edit image channel Shift + 2 Edit alpha channel Shift + 3 Edit selection channel Shift + 4 Edit mask channel F1 Help F2 Choose Pattern F3 Choose Brush F4 Paint Tool F5 Toggle Main Toolbar F6 Toggle Tools Toolbar F7 Toggle Settings Toolbar F8 Toggle Palette F9 Selection Tool F12 Toggle Dock Area Ctrl + F1 - F12 Save current clipboard to file 1-12 Shift + F1 - F12 Load clipboard from file 1-12 Ctrl + 1, 2, ... , 0 Set opacity to 10%, 20%, ... , 100% (main or keypad numbers) Ctrl + + or = Increase opacity by 1 Ctrl + - Decrease opacity by 1 Home Show or hide main window menu/toolbar/status bar/palette Page Up Scale Image Page Down Resize Image canvas End Pan Window --------------- Mouse shortcuts --------------- Left button Paint to canvas using the current tool Middle button Selects the point which will be the centre of the image after the next zoom Right button Commit paste to canvas / Stop drawing current line / Cancel selection Scroll Wheel In GTK+2/3 the user can have the scroll wheel zoom in or out via the Preferences window Ctrl+Left button Choose colour A from under mouse pointer Ctrl+Left button Clone tool - Select source Ctrl+Middle button Create colour A/B and pattern based on the RGB colour in A (RGB images only) Ctrl+Right button Choose colour B from under mouse pointer Ctrl+Right button Polygon tool - Delete last point / Delete nearest point Ctrl+Scroll Wheel Scroll the main edit window left or right Ctrl+Double click Set colour A or B to average colour under brush square or selection marquee (RGB only) Shift+Right button Selects the point which will be the centre of the image after the next zoom You can fixate the X/Y co-ordinates while moving the mouse: Shift Constrain mouse movements to vertical line Shift+Ctrl Constrain mouse movements to horizontal line mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/doc/Makefile000066400000000000000000000013001471325446300223520ustar00rootroot00000000000000include ../_conf.txt MAN_PAGE=mtpaint.1 all: $(MAN_PAGE) $(MAN_PAGE): mtpaint.pod pod2man "--release=$(MT_VERSION)" "--date=$(MT_DATE)" "--center=Mark Tyler's Painting Program" mtpaint.pod > $(MAN_PAGE) html: vcode.html %.html: %.t2t txt2tags -t html $*.t2t install: mkdir -p $(DESTDIR)$(MT_MAN_DEST)/man1 $(DESTDIR)$(MT_DATAROOT)/applications $(DESTDIR)$(MT_DATAROOT)/pixmaps cp $(MAN_PAGE) $(DESTDIR)$(MT_MAN_DEST)/man1 cp mtpaint.desktop $(DESTDIR)$(MT_DATAROOT)/applications cp mtpaint.png $(DESTDIR)$(MT_DATAROOT)/pixmaps uninstall: rm $(DESTDIR)$(MT_MAN_DEST)/man1/$(MAN_PAGE) rm $(DESTDIR)$(MT_DATAROOT)/applications/mtpaint.desktop rm $(DESTDIR)$(MT_DATAROOT)/pixmaps/mtpaint.png mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/doc/README000066400000000000000000000006761471325446300216110ustar00rootroot00000000000000This directory contains the mtPaint man page. Users of mtPaint should not need to edit or make anything here - just use the configure script as normal. Package maintainers may wish to put their details into the man page for their users. Put these lines near the end of mtpaint.pod, just before the '=cut' at the end: =head1 MAINTAINER Your Name Eyour.name@email.addressE Then from the command line: ./configure pod ... make etc. mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/doc/alien-desc000066400000000000000000000004161471325446300226500ustar00rootroot00000000000000mtPaint - Mark Tyler's Painting Program mtPaint is a GTK+2 based painting program designed for creating icons and pixel based artwork. It can edit indexed palette or 24 bit RGB images and offers painting and palette manipulation tools. http://mtpaint.sourceforge.net/ mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/doc/makehelp.pl000077500000000000000000000047541471325446300230600ustar00rootroot00000000000000#! /usr/bin/perl # Script to generate README, help.ccc & POD for mtPaint tarball, then HTML for website # Written for Bash by Mark Tyler, 14-10-2004 # Rewritten in Perl by Dmitry Groshev, 20-04-2007 # New help.c file format implemented, 12-05-2007 # Stored source textfiles inline, 14-01-2009 # Pared down to generating only help.c with README & HELP as source, 07-02-2016 # ============================================================================ $HELP = <<"HELPFILE"; /* help.c Copyright (C) 2004-$WHEN Mark Tyler and Dmitry Groshev This file is part of mtPaint. mtPaint 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. mtPaint 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 mtPaint in the file COPYING. */ #undef _ #define _(X) X #define HELP_PAGE_COUNT $HELP_PAGE_COUNT static char *help_titles[HELP_PAGE_COUNT] = { $help_titles}; $help_pages #define HELP_PAGE_MAX $HELP_PAGE_MAX static char **help_pages[HELP_PAGE_COUNT] = { $help_page_names }; #undef _ #define _(X) __(X) HELPFILE INIT { # Read in ../README @parts = split /^---.*\n/m, `cat ../README`; s/\n+$/\n/s foreach @parts; for ($i = 0; $i < @parts; $i++) { last if $parts[$i] =~ /^Credits/; } $parts[1] =~ /2004-(\d{4})/ or die "Lost in time"; $WHEN = $1; # Read in ./HELP @help = split /^---.*\n/m, `cat ./HELP`; s/\n+$/\n/s foreach @help; # Generate help parts @inf = ( "General\n\n" . $parts[1] . $parts[2], $help[1] . $help[2], $help[3] . $help[4], $parts[$i] . $parts[$i + 1] ); s/\r//g foreach @inf; # To be sure $HELP_PAGE_COUNT = @inf; $i = 0; foreach (@inf) { /^([^\n]*)/; $help_titles .= "_(\"$1\"),\n"; $help_page_names .= "help_page$i, "; $help_pages .= "static char *help_page$i\[] = {\n"; $i++; s/([\\"])/\\$1/g; # Quote s/\n(?=\n)/\\n/g; @lines = split /\n/s; shift @lines; # Drop header $max = @lines unless $max > @lines; $help_pages .= "_(\"$_\"),\n" foreach @lines; $help_pages .= "NULL };\n"; } $HELP_PAGE_MAX = $max + 1; } open HELP, ">help.c"; binmode HELP; print HELP $HELP; close HELP; #`mv -f help.c ../src`; #`chmod a-w ../src/help.c`; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/doc/mtpaint.1000066400000000000000000000133321471325446300224600ustar00rootroot00000000000000.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is turned on, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{ . if \nF \{ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "MTPAINT 1" .TH MTPAINT 1 "2020-03-18" "mtPaint 3.49.26" "Mark Tyler's Painting Program" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" mtpaint \- A pixel based painting program .SH "SYNOPSIS" .IX Header "SYNOPSIS" mtpaint\ [option]\ [imagefile\ ...\ ] .SH "DESCRIPTION" .IX Header "DESCRIPTION" mtPaint is a \s-1GTK+1/2/3\s0 based painting program designed for creating icons and pixel based artwork. It can edit indexed palette or 24 bit \s-1RGB\s0 images and offers painting and palette manipulation tools. Its main file format is \s-1PNG,\s0 although it can also handle \s-1JPEG, GIF, TIFF, JPEG2000, WEBP, BMP, PCX, TGA, LBM, PBM, PGM, PPM, PAM, LSS16, XPM,\s0 and \s-1XBM\s0 files. Due to its simplicity and lack of dependencies it runs well on GNU/Linux, Windows and older \s-1PC\s0 hardware. There is full documentation of mtPaint's features contained in a handbook. If you don't already have this, you can download it from the mtPaint website. .SH "OPTIONS" .IX Header "OPTIONS" mtPaint can accept one of the following options: .PP .Vb 8 \& \-\-help Output usage information \& \-\-version Output version information \& \-\-flist Read a list of files from a file \& \-\-sort Sort files passed as arguments \& \-\-cmd Start mtPaint in commandline scripting mode without GUI \& \-s Grab a screenshot \& \-v Start mtPaint in viewer mode \& \-\- End of options .Ve .SH "HOMEPAGE" .IX Header "HOMEPAGE" http://mtpaint.sourceforge.net/ .SH "AUTHOR" .IX Header "AUTHOR" Original author: .IP "\(bu" 4 Mark Tyler .PP Current maintainer: .IP "\(bu" 4 Dmitry Groshev \f(CW\*(C`\*(C'\fR .PP The development of mtPaint has been helped by various people from the free software community. See \*(L"Credits\*(R" in the \s-1README\s0 or the mtPaint help system for details. .PP You can follow or contribute to mtPaint's development at . mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/doc/mtpaint.desktop000066400000000000000000000011641471325446300237710ustar00rootroot00000000000000[Desktop Entry] Version=1.0 Encoding=UTF-8 Type=Application Name=mtPaint GenericName=Image Editor Comment=Painting program to create pixel art and manipulate digital photos TryExec=mtpaint Exec=mtpaint %F Icon=mtpaint Terminal=false Categories=Graphics;2DGraphics;RasterGraphics;GTK; MimeType=image/bmp;image/x-bmp;image/x-ms-bmp;image/gif;image/jpeg;image/jpg;image/pjpeg;image/x-pcx;image/png;image/x-png;image/x-portable-anymap;image/x-portable-bitmap;image/x-portable-graymap;image/x-portable-pixmap;image/svg;image/svg+xml;image/x-tga;image/tiff;image/xbm;image/x-xbm;image/x-xbitmap;image/xpm;image/x-xpm;image/x-xpixmap; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/doc/mtpaint.png000066400000000000000000000022501471325446300231010ustar00rootroot00000000000000‰PNG  IHDR00Wù‡'PLTE´Üÿ2““ÉÉÿÿPPÿhˆÿ€¿ÿm’mž¹…ÕÕªLo[ ßË­ÍÍ È‹—òÔÕ˜hïlø‹l¢,¬J ¶ÖzüèÑ·È­L`4¨0°Ø,´w¶o¯¨\ìjžýû_uKRóÙô¥ÍT‰ ,ßÚæmÃl1YSÊŪÞëëëzt‘ÉçT¦¦Êåãbm¸w¹·]O«~…:ú?CÁ˜^ ™]P×8K5Ós´}ŽWƼ«+CGÇLjâo©¢¬‰9š çpÖ®gGéf"ý,9¥²(›“›™½y„|ôÀ:VX}³0ŸÀñÃ/HCç™nnQMÔ81CáÆ¹¥ÕÃ^àwAˆãp|‡$%yQ]ꄬ† g33c²‡¿Ò­äîÙUl8Ø@äÖv”Beñu‹ÕVa>ÁÖK#ª±¹•ßšp¬c…8 f5»(@B›)˜ ‡_QÉqP ³üÏCÐt]@Ðt]@Ðt]@Ðt]@Ðt² „sMЃ"cá°¶E>’Ê1mp&.)pÒLÈS‘ø8ãÀ”Šõ!OM•ÞÀÅ‹0:ºžýþ˜ONÌ–†ƒÁ/…¾Y˪š|¡H¾àN,z’œÏ'Õ†qà+à, )ðâÀŠDðãI&qº\êÅ€K—R”õlêAļ6ìYL'¢èU±³“cܸúÁà—CŠRXËbØ@x/ð9êÖf˜å^­ü0óÀ·@¬œ¬¡DÖ×7ê>B#Àýr³ gǘWŸ¥•§ÂÓÀþ ÆhçX¸ŠFiIEND®B`‚mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/doc/mtpaint.pod000066400000000000000000000031551471325446300231040ustar00rootroot00000000000000=pod =head1 NAME mtpaint - A pixel based painting program =head1 SYNOPSIS S =head1 DESCRIPTION mtPaint is a GTK+1/2/3 based painting program designed for creating icons and pixel based artwork. It can edit indexed palette or 24 bit RGB images and offers painting and palette manipulation tools. Its main file format is PNG, although it can also handle JPEG, GIF, TIFF, JPEG2000, WEBP, BMP, PCX, TGA, LBM, PBM, PGM, PPM, PAM, LSS16, XPM, and XBM files. Due to its simplicity and lack of dependencies it runs well on GNU/Linux, Windows and older PC hardware. There is full documentation of mtPaint's features contained in a handbook. If you don't already have this, you can download it from the mtPaint website. =head1 OPTIONS mtPaint can accept one of the following options: --help Output usage information --version Output version information --flist Read a list of files from a file --sort Sort files passed as arguments --cmd Start mtPaint in commandline scripting mode without GUI -s Grab a screenshot -v Start mtPaint in viewer mode -- End of options =head1 HOMEPAGE http://mtpaint.sourceforge.net/ =head1 AUTHOR Original author: =over =item * Mark Tyler =back Current maintainer: =over =item * Dmitry Groshev S >>> =back The development of mtPaint has been helped by various people from the free software community. See "Credits" in the README or the mtPaint help system for details. You can follow or contribute to mtPaint's development at L<< https://github.com/wjaguar/mtPaint >>. =cut mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/doc/slack-desc000066400000000000000000000005631471325446300226600ustar00rootroot00000000000000mtpaint: mtPaint - Mark Tyler's Painting Program mtpaint: mtpaint: mtPaint is a GTK+1/2/3 based painting program designed for creating mtpaint: icons and pixel based artwork. It can edit indexed palette or 24 bit mtpaint: RGB images and offers painting and palette manipulation tools. mtpaint: mtpaint: http://mtpaint.sourceforge.net/ mtpaint: mtpaint: mtpaint: mtpaint: mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/doc/vcode.t2t000066400000000000000000002534771471325446300224750ustar00rootroot00000000000000V-code Technical Reference ------------------------------------------------- == Introduction == V-code got its name from a void pointer. As bytecode is comprised of 'char', so V-code is of 'void *'. Therefore, "V". V-code engine runs mtPaint's GUI - and its commandline and scripts - but it is less a widget toolkit per se, than a technique of abstraction. The idea was to decouple the semantics of controls from the particulars of implementation - and to get rid of the mind-numbing boilerplate that invariably accompanies anything having to do with a GUI. And when I compare what it takes to create a new dialog now with V-code, to what it had taken without - I much prefer the new way. V-code is declarative. I describe an interface component, and leave it to the engine to make it - or to pretend convincingly enough, so that the rest of the program does not notice a difference. Whatever specialcasing is needed, is done within the engine, never to poke its ugly snout outside. While the declarative part is quite extensive, the runtime API is simplistic. It does not need complexity; when creation is firmly separated into its own phase, only a few tweaks remain to be done at runtime. Another reason for the simplicity is that I made things interchangeable. There are no special accessor functions for any type of widget, and callback signatures never differ without a very compelling reason. This way, one event handler can serve a number of different widgets with minimal effort. This absence of widget functions/methods is an intentional feature and the core difference of V-code from usual GUI toolkits. All actions are done through a compact set of call points, and while internally tasks get routed to specific effector modules, calling code takes no part in the decisions what to use, how, and when. Interdependences of some operations arising in some cases are thus easily tracked and handled, entirely within the engine. Equally easy are conditional replacements of a component with a differently implemented, or a simulated one. V-code is not told what to do; it receives commands as to what it should make happen. It is the principle of the thing. The function handlers are minimalistic. No sanity checks; if something is done wrong, code signals that by crashing. But no strictness either; if a function is called on an unhandled widget type, it simply does nothing. Default values are sometimes substituted, but only where doing it once in the handler made more sense than repeating the same at several call sites. Neither declarative nor runtime part is providing complete coverage; only the widgets and operations needed by mtPaint. When for a new feature I need something that is not yet there, I extend the V-code engine. == Overview == The pegasus-eye view of how V-code is used, is this. - You prepare a V-code description of, say, a dialog window. - You fill a struct with initial values for it. - You hand off both to **run_create_()**. - It executes the description: allocates memory, copies the struct in there, creates widgets, setups callbacks, does initializations, and shows the finished result to the user. - User does some things to controls in the dialog, changing some values, then presses "OK". - The callback sees that it was "OK", calls **run_query()** to read back values from all the controls. - The new values in the copy of struct and/or in global variables are used to do something. - The callback calls **run_destroy()** to finish off the window, and returns. - Done. There are ways and means to do more complicated things, but this simple scenario is done this simply; in exactly 3 function calls. This is how it can work. Every V-code command describing a control - say, a spinbutton or a text entry - has a memory reference; either to a global variable, or to a field in a struct. When the control is created, it is initialized from that memory; when it is read, the result goes to that memory. When **run_create()** makes that control, it saves the address of that V-code command, and the widget it created, into its "tape" (a flat array of "slots"). When you call **run_query()**, it iterates over slots in the "tape" and looks at commands; it reads back values from every control it finds, each into the place that its command refers to. When you call **run_destroy()**, after the widgets get destroyed it again iterates over slots and looks at commands, to do cleanup actions if needed; after that, the attached struct and "tape" are freed. When you need to add a callback, you put an //EVENT()// command, with a type ID and a function reference, after a control; this command also gets a slot in the "tape". The function gets called when the control sitting before it in the "tape" wants to raise an event of that type. With the //TRIGGER// command, you can raise the preceding //EVENT()// just after **run_create()** finishes creating things; doing it to a list control's //SELECT// event is the natural way to make other controls reflect initial selection in the list. Some commands that create controls, have //EVENT()// built in, some even two of them; for them, function references go as parameters to the commands. A //TRIGGER// command after a two-event control triggers its second builtin //EVENT()//. When you need to, say, hide a control, you pass address of its slot to **cmd_showhide()**. To get that address, you put a //REF()// command right before the command that creates the control. //REF()//, again, has a memory reference (to a field of type **void**** ; for a variable, you use //REFv()//); into that memory, **run_create()** will put the current position in the "tape". For a container widget, you create it with a command such as //VBOX//, and everything you create after it will go into it, till you close it with //WEND//. One-place containers, such as //FRAME()//, close by themselves after accepting a widget (or you can close them by //WEND// leaving them empty). One command can also create more than one container; //DOCK()// has two panes, each filled separately and finished by its own //WEND//. Most container widgets do not get slots of their own, but are fill-and-forget. If you need to interact with them, say hide a box with all its contents, you need a version with a slot; those are tagged with "r", like //VBOXr// vs //VBOX//. When you want to include some commands only if a condition holds (say, with an RGB image you offer to select red, green, or blue channel, and with indexed ones you don't), you can use simple conditionals //IF()// and //UNLESS()//, affecting one command, or extended ones //IFx()// and //UNLESSx()// that affect everything till the matching //ENDIF()//. They get a memory reference (to an **int**), and check it for being zero or nonzero. When you need to allocate some memory (say, a buffer for a histogram image to be displayed), you use the //TALLOC()// command; it takes two fields - from one it takes the size, into the other it puts the resulting pointer. Such memory is allocated as part of the same memory block that holds the struct and the "tape", so if there isn't enough memory for it, then nothing at all gets allocated and **run_create()** itself fails (returning NULL). If you put a pointer to some separately allocated object into the struct, you can even tell **run_destroy()** to free it along with everything else; for that, you use the //CLEANUP()// command. A complete command sequence is one that creates a self-contained interface element (usually a toplevel window, but not necessarily). There are two things required from it. It has to define something in where all the controls will go; a //WINDOW()//, //TOPVBOX// etc. And it has to terminate the sequence, telling **run_create()** what to do with it; use //WDIALOG()// command to run it as a dialog, //WSHOW// to show it to the user, or //WEND// to hand it off to the program to be shown later. == V-code as written == Declarative V-code is an array of pointers to void: **void *whatever_code[] = { ... };** The array is initialized by a sequence of command macros, with their parameters. In case the commands are referring to **ddata** fields, the struct type to use must be set before that, as the //WBbase// macro: **#define WBbase whatever_dd** So nearly all V-code chunks in mtPaint look like this: ``` #define WBbase whatever_dd void *whatever_code[] = { ... }; #undef WBbase ``` In a simplest case, one V-code chunk creates something from beginning to end, but there are also other possibilities. The most complex part of mtPaint, the main window, is defined part by part in several chunks in several source files, which the main chunk, fittingly named **main_code[]**, calls one by one using the //CALL()// command; some then call yet other chunks in their turn. The least complex parts, the lowly filter windows, use a reverse approach; a small filter-specific code chunk which is a V-code subroutine, indirectly called (with //CALLp()// command) by **filterwindow_code[]** chunk between it building the generic top part and the equally generic bottom part of the window. == In-memory structure == The memory block allocated by **run_create_()** is structured this way: | ddata | User-provided backing struct | | vdata | Internal window-info struct | | wdata | "Tape" of "slots" referring to widgets, events, etc. | | dtail | Extra memory allocated to widgets and to/by other V-code commands | All this is allocated as one single block, which not only greatly simplifies memory management, but also, with all references to anything of note sitting in a flat array of "slots", makes all kinds of reflection trivial. This is by virtue of V-code being processed in two passes; first, **predict_size()** counts how many "slots" and how much extra memory the V-code sequence wants, then memory for all that is allocated and partitioned up, the user-provided struct copied in, and only then the commands actually get executed one after another; creating and setting up widgets, taking up chunks of dtail area, and filling "slots". A canonical reference to a block is the address of its **wdata**; i.e. it points into middle of the block. The reason for that is purely historical; nothing prevents setting up **ddata** and **vdata** after **dtail** area instead, but given that a block should never be deallocated in any other way than by calling **run_destroy()**, the arrangement is not relevant to anything. A "slot" in **wdata** consists of 3 pointers: | 0 | Widget/something else | | 1 | V-code command that set up the slot | | 2 | Dtail chunk | Slot where "something else" is its **dtail** chunk (i.e. 0th cell equals 2nd) is considered "unreal"; such slots are set up by pseudo-widgets used to simulate real ones when running scripts, thus the name. With the V-code command obviously being the same in either case (real and simulated), this is the only way to tell the two apart. The first slot of **wdata** is a fake one, used for linking all this together: | 0 | **ddata** | | 1 | **vdata** | | 2 | Dtail chunk | The **vdata** structure masquerades as a V-code command //WDONE//; as no regular //WDONE// gets a slot of its own, the slot is thus unique. The **wdata_slot()** function just steps through the "tape" before a slot till it finds this marker, and returns its address. The second slot must belong to a toplevel widget. No other thing should be put into the "tape" before it. And the last slot in **wdata**, marking its end, is all NULLs; all functions iterating over slots, depend on it being there. //WEND//, //WSHOW// and //WDIALOG()// put it into the "tape", before doing all other finishing touches. Macro **GET_DDATA()** gets from **wdata** to **ddata** (just reads the 0th cell of the first slot). The macro GET_VDATA(), internal to vcode.c, gets from **wdata** to **vdata** (by reading the 1st cell). == Structure of V-codes == As said above, V-code is an array of pointers to void. The array contains a sequence of commands - each consisting of one or more pointer values: an instruction header, and a specified number of parameters. The parameters can be either constants, or memory references. The latter may be either addresses of globals (string constants, variables, cells in global arrays, functions), or offsets in **ddata** struct, of the type designated by the //WBbase// macro. Encoding the field references is done with the //WBfield()// macro: **..., WBfield(field), ...** Other things are encoded as per usual; variables with the "&" operator, strings, arrays and functions as is, constants with a "(void *)" cast: **&(variable), "string", array, array + 2, function, (void *)1** The responsibility of a high-level command macro is to pack its parameters in the way and order that the underlying instruction code expects them. Like this: **OKBTN(_("OK"), conf_done)** translates to this: **WBr2h_x(OKBTN, 1 + 2), (_("OK")), EVENT(OK, conf_done)** Here you see a command macro expanding into an instruction header macro, a string constant (wrapped in a no-op translation marker), and a nested command macro which in its turn expands to another header and a function constant: **WBrh(EVT_OK, 1), (conf_done)** Instruction headers are in fact 31-bit integer values, to be able to comfortably reside in a pointer on a 32-bit system, and to avoid the signed/unsigned hassle. As of mtPaint 3.50, the bits are allocated this way: || Bits | Function | Values | | 0-11 | Instruction code | op_* | | 12-15 | Packing mode | pk_* | | 16-17 | Number of slots | WB_REF* | | 18 | Indirection flag | WB_NFLAG | | 19 | Field flag | WB_FFLAG | | 20 | Script flag | WB_SFLAG | | 21-23 | Reserved | 0 | | 24-30 | Number of parameters | 0-127 | The number of parameters is how many pointers after the header are part of the command in question; i.e. how many to skip to get to the next header. In the example above it is 1 + 2: 1 for the string, and 2 more for the nested //EVENT()// command (which in its own header has 1, for the function). The first pointer after the header (given the number of parameters is nonzero) is intended to be interpreted as pointer to data; this is in no way a hard requirement, and many instructions use it for constants instead, but the prologue code in V-code functions pre-interprets this field in accordance to field flag and indirection flag, so if an instruction refers to in-memory data, it is easiest to place the most used (or only) location in there. - Initially, the first pointer is read as, well, a pointer (and by default, left unmodified); - With the field flag on, it is reinterpreted as an integer offset from the start of **ddata**, and the current **ddata** base address gets added to it; - With the indirection flag on, it is interpreted as a pointer to a pointer, and that pointer is read in. The script flag, if set, selects nondefault scripting-related behaviour for some few commands (specifics depend on command). Not even looked at for all the rest of them. The number of slots (from 0 to 3) tells //run_create_()// how many slots in the "tape" this command needs. The first slot refers to the command itself, the second and third are set up for its builtin //EVENT()// subcommands (each one a pair of pointers at end of the parameters area). A command not taking any slots, is executed and forgotten; this fits the widgets that do not need any interaction (such as most containers) and modifier commands. The example command above takes two slots; it is what the "r2" in its header macro means. The //EVENT// command on its own takes one, thus the plain "r" in its. The packing mode denotes how the widget the command creates should be packed into its container, in case the container supports this mode of packing. The small assortment of choices is this: | pk_NONE | not intended to be packed (modifier, event, etc.) | | pk_PACK | from beginning of container, not expanding | | pk_XPACK | from beginning, expanding | | pk_EPACK | from end, expanding | | pk_PACKEND | from end, not expanding | | pk_TABLE1x | into first free cell in first/second column of a table, not expanding | | pk_TABLE | into specified row and column(s) of a table, not expanding | | pk_TABLEx | into specified row and column(s) of a table, expanding | - //pk_PACK// and //pk_XPACK// are allowed for any kind of container, other modes require a matching container type. - //pk_TABLE// and //pk_TABLEx// take an extra pointer value, from the very end of command's parameters, and interpret it as 3 byte values denoting X, Y, and length, as packed by the //WBxyl()// macro. Like in this command macro for a horizontal box that can take several table columns: **#define TLHBOXl(X,Y,L) WBh_t(HBOX, 1), WBxyl(X, Y, L)** Returning to the example, //OKBTN()// command does //pk_XPACK//, as denoted by the "_x" in its header macro; the //EVENT()// command does //pk_NONE//, as denoted by the lack of "_" in its. And finally, the instruction code tells //run_create_()// what to do with it all (and later, is used to recognize the objects to which the slots in the "tape" refer). In the example, it is //op_OKBTN// for the command itself, and //op_EVT_OK// for its builtin //EVENT()// command. On the preprocessor side of things, instruction codes are assembled in stages. First, a set of macros is used as shorthand representations for every combination of flags and slots that ever arises in some command. For example, //WB_R2F// denotes two slots asked for, and the field flag set: **#define WB_R2F (WB_REF2 + WB_FFLAG)** Then goes the basic macro encoding the instruction header: //WBp_()//, taking instruction code, length, packing mode, and a flags and slots combination. However, for brevity, actual command macros use one of the many pre-encoded //WB*h*()// macros that need take only instruction name and length. Like the one from the example: **#define WBr2h_x(NM,L) WBp_(op_##NM, L, XPACK, R2)** In these macros, the part between "WB" and "h" denotes the slots and flags, and the part after "h", packing mode. Additionally, there is a set of helper macros that some commands use to pack two byte values into a single pointer: //WBwh()//, //WBnh()//, and //WBbs()//; the difference is purely semantic, they do the same thing. And another set for three values: //WBpbs()// and //WBppa()//, again doing the same. == V-code commands == All high-level command macros are listed below. The list is not final, for new commands can be derived from opcodes and lower-level macros any time when existing combinations of parameters do not cover a new use case. In the descriptions below, unless noted differently, the string parameters are constants or global **char** arrays, the numeric parameters are constants. Packing mode for the commands producing widgets (controls and containers), unless noted differently, is the default one, //pk_PACK//. Naming guidelines (not 100% followed) for the macros: - "**u**" prefixed to "unreal" (script-only, simulated) version of a widget: //uSPIN()// - "**a**" affixed to a version that takes an array instead of several constant parameters: //TSPINa()// - "**c**" affixed to a version that is centered: //MLABELc()// - "**e**" affixed to a version that has a builtin event: //RPACKe()// - "**p**" affixed to a version that takes string parameter by reference instead of a string constant: //WINDOWp()// - "**r**" affixed to a version that has a slot in the "tape": //VBOXr// - "**s**" affixed to a version that is scriptable: //MENUITEMs()// - "**v**" affixed to a version that refers to a variable/array instead of a field: //CSCROLLv()// - "**x**" affixed to a version that has extra parameters: //TLABELx()// - "**T**" or "**T1**" prefixed to a version packed in first/second table column: //TLABEL()//, //TSPIN()//, //T1SPIN()// - "**TL**" prefixed to a version packed into table at (//x, y//): //TLLABEL()// - "**TL...l**" circumfixed to a version packed into table at (//x, y//) taking //length// cells: //TLLABELl()// - "**X**" prefixed to a version that is packed expanding: //XTABLE()// - "**F**" prefixed to a version that has a frame around: //FTABLE()// === Finalizers === All these commands finish element creation and cause **run_create()** to return. They differ in what else they do between those two points. : //WDONE// : do nothing extra : //WSHOW// : show the toplevel : //WDIALOG(field)// : show, then process input till the **void**** field changes to non-NULL === Toplevels === All toplevels are one-place containers, unless noted differently. All have a slot in the "tape" (and extra slots for builtin events, if have any). : //MAINWINDOW(title, icon, width, height)// : program's main window, with specified title, XPM icon, default width and height : //WINDOW(title)// : a regular non-modal window with specified title : //WINDOWp(field)// : as above, with title passed in a **char*** field : //WINDOWm(title)// : a regular modal window with title : //WINDOWpm(field)// : as above, with title in a **char*** field : //DIALOGpm(field)// : a modal dialog, with title in a **char*** field; is a double container: the top (the first accessible) is dialog's "content area" (a vertical box), the bottom/second is its "action area" (the one with buttons, a horizontal box) : //FPICKpm(title_field, mode_field, filename_field, OK_handler, CANCEL_handler)// : a file selector window, with **char*** title, **int** mode, and **char[]** filename (in system encoding) in fields, and handlers for //OK// and //CANCEL// events; is a box container (horizontal) for extra controls : //POPUP(title)// : a popup window with specified title (which, while not shown, is still useful for identifying the window in window manager's lists) : //TOPVBOX// : a pseudo-toplevel, for elements created to sit in //MOUNT// containers or purely for scripting; is a box container (vertical) : //TOPVBOXV// : same thing but with different sizing: fills space vertically, but horizontally is only centered, not stretched : //IDENT(id)// : set a non-default identifying string for the toplevel; is needed when one toplevel has separate V-code descriptions for different parts: the case in point is file selector, where the //FPICKpm()// command builds its fixed part through a nested **run_create()** using an //IDENT()// === Containers === Table containers have a border area by default; its size can be set by //BORDER(TABLE)// (see "Sizing and placement" category below). Other containers do not, unless specifically noted. : //WEND// : close the current container : //TABLE(columns, rows)// : a table of given dimensions (those currently are initial, not a hard limit) : //TABLE2(rows)// : a two-column table : //TABLEs(columns, rows, spacing)// : a table with specified spacing (same for rows and columns) : //TABLEr(columns, rows)// : a table that gets a slot in the "tape" : //XTABLE(columns, rows)// : a table that is packed expanding (//pk_XPACK//) : //ETABLE(columns, rows)// : a table that is packed from the end (//pk_PACKEND//) : //VBOX// : a vertical box : //VBOXr// : a vertical box with slot in the "tape" : //VBOXbp(spacing, border, padding)// : a vertical box with specified spacing, border, and padding : //VBOXP// : a vertical box with padding of default size (5 pixels) : //VBOXB// : a vertical box with border of default size (5 pixels) : //VBOXS// : a vertical box with spacing of default size (5 pixels) : //VBOXPS// : a vertical box with padding and spacing of default size (5 pixels each) : //VBOXBS// : a vertical box with border and spacing of default size (5 pixels each) : //VBOXPBS// : a vertical box with padding, border and spacing of default size (5 pixels each) : //XVBOX// : a vertical box that is packed expanding : //XVBOXbp(spacing, border, padding)// : same, with specified spacing, border, and padding : //XVBOXP// : a vertical box, packed expanding, with default padding : //XVBOXB// : a vertical box, packed expanding, with default border : //XVBOXBS// : a vertical box, packed expanding, with default border and spacing : //EVBOX// : a vertical box, packed from the end : //HBOX// : a horizontal box : //HBOXbp(spacing, border, padding)// : a horizontal box with specified spacing, border, and padding : //HBOXP// : a horizontal box, with default padding : //HBOXPr// : same, with slot in the "tape" : //HBOXB// : a horizontal box, with default border : //XHBOX// : a horizontal box, packed expanding : //XHBOXbp(spacing, border, padding)// : same, with specified spacing, border, and padding : //XHBOXP// : a horizontal box, packed expanding, with default padding : //XHBOXS// : a horizontal box, packed expanding, with default spacing : //XHBOXBS// : a horizontal box, packed expanding, with default border and spacing : //TLHBOXl(x, y, length)// : a horizontal box, packed into //length// columns in a table, starting at column //x//, row //y// : //TLHBOXpl(x, y, length)// : same, with default padding : //EQBOX// : a horizontal box with equal space allocated to contents : //EQBOXbp(spacing, border, padding)// : same, with specified spacing, border, and padding : //EQBOXP// : a horizontal box with equal space, with default padding : //EQBOXB// : a horizontal box with equal space, with default border : //EQBOXS// : a horizontal box with equal space, with default spacing : //EEQBOX// : a horizontal box with equal space, packed from the end ==== Frames ==== Frames have an empty border area around them by default, its size can be set by //BORDER(FRAME)//. A container sitting inside a frame can also have a border of its own, even if both are created by one command. : //FRAME(name)// : a frame with specified name : //XFRAME(name)// : same, packed expanding : //XFRAMEp(field)// : a frame, packed expanding, with name passed in a **char*** field : //EFRAME// : a frame without name, with an "etched out" look : //FTABLE(name, columns, rows)// : a table of given dimensions sitting in a named frame : //FVBOX(name)// : a vertical box sitting in a named frame : //FVBOXB(name)// : a vertical box in a named frame, with default border : //FVBOXBS(name)// : a vertical box in a named frame, with default border and spacing : //FXVBOX(name)// : a vertical box in a named frame, packed expanding : //FXVBOXB(name)// : same, with default border : //EFVBOX// : a vertical box with twice the default border (10 pixels), sitting in an "etched out" nameless frame : //FHBOXB(name)// : a horizontal box in a named frame, with default border ==== Scrolling ==== Scrolling containers have a default border area: //BORDER(SCROLL)//. : //SCROLL(horiz_mode, vert_mode)// : a scrolling container, with display modes for its horizontal and vertical scrollbar: 0 - do not show, 1 - show when needed, 2 - show always : //XSCROLL(horiz_mode, vert_mode)// : same, packed expanding : //FSCROLL(horiz_mode, vert_mode)// : a scrolling container in an unnamed frame, packed expanding : //CSCROLLv(array)// : a scrolling container acting as a control: with its own slot, and with horizontal and vertical positions read into/reset from **int[2]** array (zeroed out by **run_create()**); horizontal and vertical scrollbars are shown when needed ==== Notebook ==== Regular notebook widgets have a default border area: //BORDER(NBOOK)//. : //NBOOK// : a notebook with tabs on top, packed expanding; is a container for //PAGE//'s : //NBOOKr// : same, with a slot in the "tape" : //NBOOKl// : a notebook with tabs on the left, packed expanding : //PAGE(name)// : a page for a notebook, with a name; is a box container (vertical) : //PAGEvp(var)// : same, with name passed in a **char*** variable : //PAGEi(icon, spacing)// : a page for a notebook, with an icon instead of name, and specified spacing : //PAGEir(icon, spacing)// : same, with a slot in the "tape" : //PLAINBOOK// : a "notebook" without any visible trappings, just to show either of two boxes in same place; has a slot in the "tape", through which to command it to switch pages; is a double container - page 0 is the top, all pages vertical boxes : //PLAINBOOKn(num_pages)// : same but with specified number of pages (3 or more); a multiple container, page 0 is the top : //BOOKBTN(name, field)// : a toggle button with a name, for switching pages of a //PLAINBOOK// whose slot is in the **void**** field: show page 1 if toggled, page 0 if not ==== Special ==== : //DOCK(ini_var_name)// : a splitter adding a dock pane on the right, that can be hidden/shown; the specified inifile variable (integer) holds the pane's width when it is shown; has a slot in the "tape"; is a double container, with left (main) pane the top, and dock pane the bottom, both panes are vertical boxes : //HVSPLIT// : a splitter that can be switched between single-pane, horizontal, and vertical; packed expanding, has a slot; is a container for two widgets, the first for single/left/top pane, the second for hidden/right/bottom one; still needs //WEND// after them : //VSPLIT// : a regular vertical splitter, packed expanding, has a slot; a container for two widgets, first is for the top pane, the second for the bottom, needs //WEND// after them : //TWOBOX// : a container for two widgets, holding them in one row if enough horizontal space, or in two rows if not : //MOUNT(field, create_func, CHANGE_handler)// : a container holding and "leasing" an element created by a specified **mnt_fn** function (returns **wdata**), with **int** field set to TRUE while holding it, and a handler for //CHANGE// event, triggered when leasing/unleasing; has a slot for itself and another for the event : //PMOUNT(field, create_func, CHANGE_handler, ini_var_name, def_height)// : same, but with the element held in a resizable vertical pane with specified default height, with specified inifile variable (integer) storing modified height : //REMOUNTv(var)// : a container that, when created, "leases" the element from the //MOUNT// whose slot is in the **void**** variable, and when destroyed, returns it back; is packed expanding, has a slot : //HEIGHTBAR// : a modifier that requests the max height of all the widgets following it in the same container, whether visible or not; used to prevent jitter when those widgets get shown/hidden later ==== Statusbar ==== : //STATUSBAR// : a statusbar, packed from the end, has a slot, is a box container (horizontal) : //STLABEL(width, align)// : a statusbar label, with specified width and alignment: 0 - left, 1 - center, 2 - right; has a slot : //STLABELe(width, align)// : same, packed from the end === Separators === : //HSEP// : a horizontal separator : //HSEPl(width)// : same, with specified minimum width : //HSEPt// : a thin (minimum height) horizontal separator === Labels === All labels, when packed into boxes and tables, have padding by default; its size can be set by //BORDER(LABEL)//. Labels are left aligned by default. Labels identify adjacent controls to scripts, unless prevented from it or have no control to attach to. : //MLABEL(text)// : a regular label with text : //MLABELr(text)// : same, with a slot of its own : //MLABELc(text)// : a centered label with text : //MLABELcp(field)// : same, with text passed in a **char*** field : //MLABELxr(text, x_padding, y_padding, x_align)// : a label with text, with specified extra horizontal and vertical padding, and horizontal alignment at //x_align/10//: 0 - left, 5 - center, 10 - right; has a slot : //MLABELpx(field, x_padding, y_padding, x_align)// : same, but with text passed in a **char*** field, and without a slot of its own : //WLABELp(field)// : a centered label with text passed in a **char*** field, packed expanding, ignored by scripts : //XLABELcr(text)// : a centered label with text, packed expanding, has a slot : //TLABEL(text)// : a label with text, packed into the first free cell of the first column of a table : //TLABELr(text)// : same, with a slot of its own : //TLABELx(text, x_padding, y_padding, x_align)// : same, with specified padding and alignment, and without a slot : //TLLABELl(text, x, y, length)// : a label with text, packed into //length// columns in a table, starting at column //x//, row //y// : //TLLABEL(text, x, y)// : same, packed into one column : //TLLABELx(text, x, y, x_padding, y_padding, x_align)// : same, with specified padding and alignment : //TLLABELxr(text, x, y, x_padding, y_padding, x_align)// : same, with a slot of its own : //TLLABELp(field, x, y)// : a label with text passed in a **char*** field, packed into a table at column //x//, row //y// : //TLLABELpx(field, x, y, x_padding, y_padding, x_align)// : same, with specified padding and alignment : //TXLABEL(text, x, y)// : a label with text, packed expanding into a table at column //x//, row //y//, aligned at 0.3 of its width : //HLABELp(field)// : a helptext label with text passed in a **char*** field : //HLABELmp(field)// : same with monospace font : //TLTEXT(text, x, y)// : text, separated into columns by tabs and into rows by newlines, is placed into a table starting at column //x//, row //y// : //TLTEXTf(field, x, y)// : same, with text stored in a **char** array field : //TLTEXTp(field, x, y)// : same, but with text passed in a **char*** field === Image display === All widgets in this group have slots in the "tape". : //COLORPATCHv(rgb_array, width, height)// : areа of specified size, filled with RGB color passed in an **unsigned char[3]** array (or a string constant), packed expanding : //RGBIMAGE(image_field, w_h_array_field)// : area of size passed in **int[2]** array field, displaying an image pointed to by **unsigned char*** field : //TLRGBIMAGE(image_field, w_h_array_field, x, y)// : same, packed into a table at column //x//, row //y// : //RGBIMAGEP(array_field, width, height)// : area of specified size, displaying an image stored in **unsigned char[]** array field : //CANVASIMGv(array, width, height)// : framed canvas widget (one able to properly receive clicks, releases, and movement, and efficiently handle scrolling) of specified size, displaying an image stored in **unsigned char[]** array : //CCANVASIMGv(array, width, height)// : same, packed from the end, expanding (//pk_EPACK//) : //CANVASIMGB(image_field, w_h_bkg_array_field)// : framed canvas widget of minimum size passed in first 2 cells of **int[3]** array field, displaying an image pointed to by **unsigned char*** field, and filling the extra space, if any, with RGB color packed in an **int** in the cell 2 of the **int[3]** array : //FCIMAGEP(image_field, x_y_array_field, w_h_array_field)// : focusable widget displaying an image pointed to by **unsigned char*** field, of size passed in **int[2]** array field, contoured by a frame, with a ring-shaped location marker on it at coordinates given in another **int[2]** array field : //TLFCIMAGEP(image_field, x_y_array_field, w_h_array_field, x, y)// : same, packed into a table at column //x//, row //y// : //TLFCIMAGEPn(image_field, w_h_array_field, x, y)// : same, but without a location marker : //CANVAS(init_width, init_height, cost, EXT_handler)// : framed canvas widget of specified initial size, that triggers //EXT// event to redraw an area (handled by an **evtxr_fn**); the //cost// value is defined as how many pixels likely could be redrawn in the time needed to call the event once more (i.e. its init+teardown cost), and is used for deciding whether to redraw multiple subregions one by one, or their encompassing region once; has a slot for itself and an extra one for the event The //EXT// handler of //CANVAS()// receives in its //xdata// parameter a pointer to **rgbcontext** (see mygtk.h). Its task is to render into the buffer there an RGB image of the denoted area of canvas, and return TRUE. === Spinbuttons and spinsliders === All spinbuttons and spinsliders, when packed into boxes and tables, have padding by default; its size can be set by //BORDER(SPIN)// and //BORDER(SPINSLIDE)//. They all have slots in the "tape", unless specifically noted. : //NOSPINv(var)// : displays an **int** variable in a non-modifiable spinbutton, has no slot : //TLNOSPIN(field, x, y)// : displays an **int** field value in a non-modifiable spinbutton, packed into a table at column //x//, row //y//, has no slot : //TLNOSPINr(field, x, y)// : same but has a slot : //TLSPIN(field, min, max, x, y)// : a spinbutton with **int** field, range //min// to //max//, packed into a table at column //x//, row //y// : //TLXSPIN(field, min, max, x, y)// : same, packed there expanding : //TLXSPINv(var, min, max, x, y)// : same, with **int** variable : //T1SPIN(field, min, max)// : a spinbutton with **int** field, packed into the first free cell of the second column of a table : //TSPIN(text, field, min, max)// : same combined with label that goes into the first column : //TSPINv(text, var, min, max)// : same, with **int** variable : //TSPINa(text, array_field)// : same, but with value, min and max in **int[3]** array field : //SPIN(field, min, max)// : a spinbutton with **int** field, range //min// to //max// : //SPINv(var, min, max)// : same, with **int** variable : //SPINc(field, min, max)// : a spinbutton with **int** field, centering the value : //XSPIN(field, min, max)// : a spinbutton with **int** field, packed expanding : //FSPIN(field, min, max)// : a fixedpoint spinbutton with **int** field holding value * 100, range //min// to //max// (both * 100) : //FSPINv(field, min, max)// : same, with **int** variable : //TFSPIN(text, field, min, max)// : a fixedpoint spinbutton with **int** field, packed into the second column of a table, combined with label that goes into the first column : //FSPIN(field, min, max, x, y)// : a fixedpoint spinbutton with **int** field, packed into a table at column //x//, row //y// : //SPINa(array_field)// : a spinbutton with value, min and max in **int[3]** array field : //XSPINa(array_field)// : same, packed expanding : //uSPIN(field, min, max)// : a script-only simulated spinbutton with **int** field, range //min// to //max// : //uSPINv(var, min, max)// : same, with **int** variable : //uFSPINv(var, min, max)// : same, but fixedpoint : //uSPINa(array_field)// : a script-only simulated spinbutton with value, min and max in **int[3]** array field : //uSCALE(field, min, max)// : a script-only simulated spinbutton with **int** field, with extended syntax: interprets values like "x1.5" as "original value multiplied by 1.5" : //TLSPINPACKv(array, count, CHANGE_handler, width, x, y)// : a grid of //count// spinbuttons arranged in //width// columns, packed into a table starting at column //x//, row //y//, with values, min and max for each in **int[][3]** array which is automatically updated when any of values changes, with a handler for //CHANGE// event that is triggered after (handled by an **evtx_fn**); has a slot for itself and another for the event : //T1SPINSLIDE(field, min, max)// : a spinslider with **int** field, range //min// to //max//, packed into the first free cell of the second column of a table, with preset size (255 x 20 pixels) : //TSPINSLIDE(text, field, min, max)// : same combined with label that goes into the first column : //TSPINSLIDEa(text, array_field)// : same, but with value, min and max in **int[3]** array field : //TLSPINSLIDE(field, min, max, x, y)// : a spinslider with **int** field, packed into a table at column //x//, row //y// : //TLSPINSLIDEvs(var, min, max, x, y)// : same, with **int** variable and preset width (150 pixels) : //TLSPINSLIDExl(field, min, max, x, y, length)// : a spinslider with **int** field, packed expanding into //length// columns in a table, starting at column //x//, row //y// : //TLSPINSLIDEx(field, min, max, x, y)// : same, packed into one column : //SPINSLIDEa(array_field)// : a spinslider with value, min and max in **int[3]** array field : //XSPINSLIDEa(array_field)// : same, packed expanding The //CHANGE// handler of //TLSPINPACKv()// receives in its //xdata// parameter an **int** index of the spinbutton that changed, cast into **void***. === Checkbuttons === All checkbuttons have a default border area: //BORDER(CHECK)//. They all have slots in the "tape". : //CHECK(name, field)// : a named checkbutton with **int** field : //CHECKv(name, var)// : same, with **int** variable : //CHECKb(name, field, ini_var_name)// : a named checkbutton with **int** field, with specified inifile variable (integer) storing its value : //XCHECK(name, field)// : a named checkbutton with **int** field, packed expanding : //TLCHECKl(name, field, x, y, length)// : same, packed into //length// columns in a table, starting at column //x//, row //y// : //TLCHECK(name, field, x, y)// : same, packed into one column : //TLCHECKvl(name, var, x, y, length)// : a named checkbutton with **int** variable, packed into //length// columns in a table, starting at column //x//, row //y// : //TLCHECKv(name, var, x, y)// : same, packed into one column : //uCHECK(name, field)// : a script-only simulated named checkbutton with **int** field : //uCHECKv(name, var)// : same, with **int** variable === Radiobutton packs === All radiobutton packs have a default border area: //BORDER(RPACK)//. They all have slots in the "tape", those with a builtin event have an extra slot for the event. : //RPACK(names_array, count, height, field)// : a box of radiobuttons with **int** field that stores the index of the active one, with names in **char*[]** array, //count// of them in total (0 if array of names is NULL-terminated), arranged in columns of no more than //height// (0 if all in a single column), packed expanding : //RPACKv(names_array, count, height, var)// : same, with **int** variable : //FRPACK(frame_name, names_array, count, height, field)// : a box of radiobuttons with **int** field, sitting in a named frame : //FRPACKv(frame_name, names_array, count, height, var)// : same, with **int** variable : //RPACKe(names_array, count, height, field, SELECT_handler)// : a box of radiobuttons with **int** field and a handler for //SELECT// event, packed expanding : //FRPACKe(frame_name, names_array, count, height, field, SELECT_handler)// : same, sitting in a named frame : //RPACKD(names_field, height, field)// : a box of radiobuttons with **int** field, with **char**** field pointing to a NULL-terminated **char*[]** array of names, packed expanding : //RPACKDv(names_field, height, var)// : same, with **int** variable : //RPACKDve(names_field, height, var, SELECT_handler)// : same, with a handler for //SELECT// event In case a radiobutton's name is an empty string, the corresponding index is just skipped. === Option menus and comboboxes === All option menus and comboboxes have a default border area: //BORDER(OPT)//. They all have slots in the "tape", those with a builtin event have an extra slot for the event. : //OPT(names_array, count, field)// : an option menu with **int** field, with list of choices' names in **char*[]** array, //count// of them in total (0 if array of choices is NULL-terminated) : //OPTv(names_array, count, var)// : same, with **int** variable : //TOPTv(text, names_array, count, var)// : same, packed into the second column of a table, combined with label that goes into the first column : //TLOPT(names_array, count, field, x, y)// : an option menu with **int** field, packed into a table at column //x//, row //y// : //TLOPTv(names_array, count, var, x, y)// : same, with **int** variable : //OPTe(names_array, count, field, SELECT_handler)// : an option menu with **int** field and a handler for //SELECT// event : //OPTve(names_array, count, var, SELECT_handler)// : same, with **int** variable : //XOPTe(names_array, count, field, SELECT_handler)// : an option menu with **int** field and a handler for //SELECT// event, packed expanding : //TLOPTle(names_array, count, field, SELECT_handler, x, y, length)// : same, packed into //length// columns in a table, starting at column //x//, row //y// : //TLOPTvle(names_array, count, var, SELECT_handler, x, y, length)// : same, with **int** variable : //TLOPTve(names_array, count, var, SELECT_handler, x, y)// : same, packed into one column : //OPTD(names_field, field)// : an option menu with **int** field, with **char**** field pointing to a NULL-terminated **char*[]** array of choices' names : //XOPTD(names_field, field)// : same, packed expanding : //TOPTDv(text, names_field, field)// : same with **int** variable, packed into the second column of a table, combined with label that goes into the first column : //OPTDe(names_field, field, SELECT_handler)// : an option menu with **int** field, **char**** field pointing to choices' names, and a handler for //SELECT// event : //XOPTDe(names_field, field, SELECT_handler)// : same, packed expanding : //TOPTDe(text, names_field, field, SELECT_handler)// : same, packed into the second column of a table, combined with label that goes into the first column : //COMBO(names_array, count, field)// : a combobox with **int** field, with list of choices' names in **char*[]** array, //count// of them in total (0 if array of choices is NULL-terminated) : //PCTCOMBOv(var, array, CHANGE_handler)// : a combobox displaying percent zoom values, with **int** variable, an **int[]** array (0-terminated) of some values, and a handler for //CHANGE// event; has no border In case a choice's name is an empty string, the corresponding index is just skipped. === Specialized controls === All widgets in this group have slots in the "tape", those with a builtin event have an extra slot for the event. : //PROGRESSp(text_field)// : a progressbar, with text for it passed in a **char*** field : //GRADBAR(chan_field, idx_field, len_field, max, map_array_field, cmap_array_field, SELECT_handler)// : a "gradient bar" for displaying and selecting points in a gradient, with currently selected index in **int** //idx_field//, gradient's length in //len_field//, gradient's channel in **int** //chan_field//, colormap for non-RGB cases in **unsigned char[768]** //cmap_array_field//, gradient's values/colors at points in **unsigned char[]** //map_array_field//, and a handler for //SELECT// event : //KEYBUTTON(field)// : a button for choosing key combos, with **char*** field where it places keyname string : //TABLETBTN(name)// : a named button for calling up tablet configuration dialog : //FONTSEL(array_field)// : a font chooser, with font description string and the text to render in a **char*[2]** array field, packed expanding : //EYEDROPPER(field, CHANGE_handler, x, y)// : a button calling up eyedropper, with color it picked up in an **int** field, and a handler for //CHANGE// event, packed into a table at column //x//, row //y// : //COLOR(array_field)// : a color chooser for opaque colors, with RGBA in **unsigned char[4]** array field : //TCOLOR(array_field)// : same for colors with alpha === Lists === The //LISTCC*// widgets have a default border area: //BORDER(LISTCC)//. All list widgets and columns have slots in the "tape", those with a builtin event have an extra slot for the event, those with two, extra two slots. : //COLORLIST(names_field, idx_field, rgb_array_field, SELECT_handler, EXT_handler)// : a list of named colors, with currently selected index in **int** field, a **char**** field pointing to a NULL-terminated **char*[]** array of names, colors themselves in **unsigned char[]** array field, a handler for //SELECT// event, and a handler for //EXT// event (an **evtx_fn**) : //COLORLISTN(cnt_field, idx_field, rgb_array_field, SELECT_handler, EXT_handler)// : same for numbered colors, with count of them in **int** field : //LISTCCHr(idx_field, len_field, max, SELECT_handler)// : a simpler (headerless, unsorted) columned list, with index and length (dynamic, limited to //max// items) in **int** fields, and a handler for //SELECT// event : //LISTCCHr(idx_field, len_field, SELECT_handler)// : same with static (unchanging) length : //LISTC(idx_field, len_field, SELECT_handler)// : a complex (with column headers and sorting) columned list, with index and length in **int** fields, and a handler for //SELECT// event : //LISTCu(idx_field, len_field, SELECT_handler)// : same, unsorted : //LISTCd(idx_field, len_field, SELECT_handler)// : same, with draggable rows : //LISTCS(idx_field, len_field, sortmode_field, SELECT_handler)// : a complex columned list, with selectable sort column and direction; the sort mode in **int** field is column+1 if sorted ascending, and the same negated if descending : //LISTCX(idx_field, len_field, sortmode_field, map_field, SELECT_handler, EXT_handler)// : same, with user-resizable columns and filtering: **int**** field points to mapping array (row indices to display, in order; also used for sorting); and with a handler for //EXT// event (an **evtx_fn**) Index in //LISTC()// and its brethren refers to raw (unsorted and unfiltered) data. The //EXT// handler of //LISTCX()// is triggered by right click on a row, and receives in its //xdata// parameter an **int** index of that row. The //EXT// handler of //COLORLIST()// and //COLORLISTN()// is triggered by click on a color, and receives in its //xdata// parameter a pointer to **colorlist_ext**. The columns of a columned list sit between //WLIST// command and the list itself, and describe what, how, and where from goes into each. They can refer either to an array, or to a structure and a field in it; if the latter, the //COLUMNDATA()// command is needed, describing an array of those structures. : //WLIST// : start a group of columns : //COLUMNDATA(field, step)// : set a **void*** field as pointer to the array of data structures for columns in this group : //IDXCOLUMN(init, step, width, align)// : add a column of indices, starting at //init// and changing by //step//, //width// pixels wide, aligned per //align//: 0 - left, 1 - center, 2 - right : //TXTCOLUMNv(array, step, width, align)// : add a column of text strings from **char[]** array (buffers, not pointers), with specified step, width and alignment : //XTXTCOLUMNv(array, step, width, align)// : same, expanding : //NTXTCOLUMNv(name, array, step, width, align)// : add a column of text strings from **char[]** array, with column name/title : //NTXTCOLUMND(name, struct_type, struct_field, width, align)// : same, from a **char[]** array field (buffer) in //COLUMNDATA// : //PTXTCOLUMN(array_field, step, width, align)// : add a column of text strings from **char*[]** array field (pointers) : //PTXTCOLUMNp(field, step, width, align)// : same, from **char*[]** array pointed to by //field// : //RTXTCOLUMNDi(width, align)// : add a column of text strings relative to elements of **int[]** array that is //COLUMNDATA//: each element holds an offset **from itself** to the string : //RTXTCOLUMND(struct_type, struct_field, width, align)// : same, relative to **int** field in //COLUMNDATA// : //NRTXTCOLUMND(name, struct_type, struct_field, width, align)// : same, with column name/title : //NRTXTCOLUMNDax(name, index, width, align, ini_var_name)// : same, relative to //index//-th element of **int[]** sub-array in //COLUMNDATA//, with inifile variable (integer) storing modified width : //NRTXTCOLUMNDaxx(name, index, width, align, ini_var_name, test_string)// : same, at least wide enough for //test_string// : //NRFILECOLUMNDax(name, index, width, align, ini_var_name)// : add a column of filenames relative to element of sub-array: the 0th character denotes the type: 'F' for file, 'D' for directory, ' ' for ".." : //CHKCOLUMNv(array, step, width, align, CHANGE_handler)// : add a column of checkbuttons from **int[]** array, with a handler for //CHANGE// event (an **evtxr_fn**) The //CHANGE// handler of //CHKCOLUMNv()// receives in its //xdata// parameter an **int** index of the row that was toggled. === Text entry fields === All entry widgets, when packed into boxes and tables, have padding by default; its size can be set by //BORDER(ENTRY)//. All pathboxes have a default border area: //BORDER(PATH)//. All widgets in this group have slots in the "tape", those with a builtin event have an extra slot for the event. : //XENTRY(field)// : an entry with **char*** field, packed expanding : //XLENTRY(field, max)// : same, with max length in chars : //TLENTRY(field, max, x, y, length)// : same, packed into //length// columns in a table, starting at column //x//, row //y// : //MLENTRY(field)// : a multiline entry (accepts **Ctrl+Enter** for a newline) with **char*** field : //XPENTRY(field, max)// : an entry for filenames (in system encoding) with **char*** field, with max length in chars, packed expanding : //TPENTRYv(text, var, max)// : an entry for filenames with **char*** variable, with max length, packed into the second column of a table, combined with label that goes into the first column : //PATH(name, fsel_name, mode, field)// : a pathbox (a named frame with entry in system encoding and button calling up file selector) with **char*** field, with name and mode for the fileselector : //PATHv(name, fsel_name, mode, var)// : same, with **char*** variable : //PATHv(name, fsel_name, mode, ini_var_name)// : same, with inifile variable (string) : //TPATHv(name, fsel_name, mode, var)// : a frameless pathbox with **char*** variable, packed into the second column of a table, combined with label that goes into the first column : //uPATHSTR(field)// : a script-only simulated entry for filenames with **char*** field : //TEXT(field)// : a text widget with **char*** field, packed expanding : //COMBOENTRY(field, list_field, OK_handler)// : an entry with dropdown list with **char*** field, with **char**** //list_field// pointing to NULL-terminated **char*[]** array of choices, and a handler for //OK// event, packed expanding : //HEXENTRY(field, CHANGE_handler, x, y)// : an entry for color hex code / name, with **int** field (packed RGB), and a handler for //CHANGE// event, packed into a table at column //x//, row //y// The //XENTRY//, //*LENTRY// and //COMBOENTRY// widgets immediately replace the string values used for initialization with copies owned by the widgets, so that there is no chance of incidental access if the original strings are freed after **run_create()**. The //TEXT// widget just replaces it with NULL, for the same reason. === Buttons === All buttons have a default border area: //BORDER(BUTTON)//. They all have two slots in the "tape": for themselves and for their builtin event. Buttons, except toggle buttons, are not scriptable by default, unless explicitly tagged by the "script flag"; some of macros below are for such buttons. : //OKBTN(name, OK_handler)// : a named button reacting to **Enter** key, with //OK// event handler, packed expanding : //uOKBTN(OK_handler)// : a script-only simulated button with //OK// event handler : //CANCELBTN(name, CANCEL_handler)// : a named button reacting to **Esc** key, with //CANCEL// event handler, packed expanding : //CANCELBTNp(field, CANCEL_handler)// : same, with name in a **char*** field : //UCANCELBTN(name, CANCEL_handler)// : a cancel button packed the default way (//pk_PACK//) : //ECANCELBTN(name, CANCEL_handler)// : same, packed from the end : //UDONEBTN(name, OK_handler)// : a named button reacting to **Enter** and **Esc** keys, with //OK// event handler : //TOGGLE(name, field, CHANGE_handler)// : a named toggle button with an **int** field and //CHANGE// event handler, packed expanding : //UTOGGLEv(name, var, CHANGE_handler)// : same with an **int** variable, packed the default way : //BUTTON(name, CLICK_handler)// : a named button with //CLICK// event handler, packed expanding : //BUTTONs(name, CLICK_handler)// : same, scriptable : //BUTTONp(field, CLICK_handler)// : same, with name in a **char*** field, not scriptable : //UBUTTON(name, CLICK_handler)// : a named button with //CLICK// event handler, packed the default way : //EBUTTON(name, CLICK_handler)// : same, packed from the end : //EBUTTONs(name, CLICK_handler)// : same, scriptable : //TLBUTTON(name, CLICK_handler, x, y)// : a named button with //CLICK// event handler, packed into a table at column //x//, row //y// : //TLBUTTONs(name, CLICK_handler, x, y)// : same, scriptable : //uBUTTONs(name, CLICK_handler)// : a script-only simulated named button with //CLICK// event handler, scriptable (obviously) : //OKBOX(ok_name, OK_handler, cancel_name, CANCEL_handler)// : a convenience macro creating an //EQBOX// with //CANCELBTN// and //OKBTN//; the box is left unclosed (without //WEND//) but no practical reason to add more things into it, and it is normally the last thing in a dialog anyway : //OKBOXP(ok_name, OK_handler, cancel_name, CANCEL_handler)// : same, with a box with padding (//EQBOXP//) : //OKBOXB(ok_name, OK_handler, cancel_name, CANCEL_handler)// : same, with a box with border (//EQBOXB//) : //OKBOX3(ok_name, OK_handler, cancel_name, CANCEL_handler, button_name, CLICK_handler)// : an //EQBOX// with //CANCELBTN//, regular //BUTTON//, and //OKBTN// : //OKBOX3B(ok_name, OK_handler, cancel_name, CANCEL_handler, button_name, CLICK_handler)// : same, with a box with border === Toolbar === Toolbars are containers for their buttons, and need //WEND// to close. //TOOLBAR*// widgets have a default border area: //BORDER(TOOLBAR)//. All toolbars and toolbar buttons have slots in the "tape"; the toolbars have an extra slot or two for their builtin events. Toolbar buttons call their toolbar's event handlers when things happen to them, so that they do not need //EVENT//s of their own. : //TOOLBAR(CHANGE_handler)// : a regular toolbar with //CHANGE// event handler (to which, despite the name, regular toolbuttons getting pressed is routed too) : //TOOLBARx(CHANGE_handler, CLICK_handler)// : same, with also a //CLICK// event handler for right-clicking on a button : //SMARTTBAR(CHANGE_handler)// : a toolbar that, if buttons do not fit, adds a dropdown with the overflow ones; with //CHANGE// event handler : //SMARTTBARx(CHANGE_handler, CLICK_handler)// : same, with also a //CLICK// event handler : //SMARTTBMORE(name)// : a button that shows said dropdown; after it go regular widgets (not toolbuttons) that will stay displayed regardless : //TBBUTTON(name, icon, action)// : a toolbar button with icon, tooltip (also used for scripting), and action code (two numbers packed into one by //ACTMOD()// macro) : //TBBUTTON(name, icon, action, rclick_action)// : same, with another action code for right click : //TBTOGGLE(name, icon, action, field)// : a toolbar toggle button with an **int** field, icon, tooltip, and action code : //TBTOGGLEv(name, icon, action, var)// : same, with an **int** variable : //TBTOGGLExv(name, icon, action, rclick_action, var)// : same, with another action code for right click : //TBBOXTOGxv(name, icon, action, rclick_action, var)// : a regular toggle button that actually goes into the container that the toolbar sits in, but still acts like //TBTOGGLExv// : //TBRBUTTONv(name, icon, action, var)// : a toolbar radiobutton with an **int** variable, icon, tooltip, and action code : //TBRBUTTONxv(name, icon, action, rclick_action, var)// : same, with another action code for right click : //TBSPACE// : a toolbar separator === Menu === Menubars and submenus are containers for menuitems and submenus, and need //WEND// to close. They and menuitems all have slots in the "tape"; the menubars have an extra slot for their builtin event. Menuitems call their menubar's event handler when they activate. Menuitems are not scriptable by default; those that are (tagged by "script flag") have their macros' names ending in "s". : //MENUBAR(CHANGE_handler)// : a regular menubar with //CHANGE// event handler, to which all its menuitems' activations get routed : //SMARTMENU(CHANGE_handler)// : a menubar that, if not wide enough, moves some of regular submenus into an overflow submenu; with //CHANGE// event handler : //SUBMENU(name)// : a submenu : //ESUBMENU(name)// : a submenu placed at the end of menubar : //SSUBMENU(name)// : the overflow submenu : //MENUITEM(name, action)// : a menuitem with action code (//ACTMOD()// made) : //MENUITEMs(name, action)// : same, scriptable : //MENUITEMi(name, action, icon)// : a menuitem with an icon, with action code : //MENUITEMis(name, action, icon)// : same, scriptable : //MENUCHECKv(name, action, var)// : a check menuitem with an **int** variable, with action code : //MENUCHECKvs(name, action, var)// : same, scriptable : //MENURITEMv(name, action, var)// : a radio menuitem with an **int** variable, with action code : //MENURITEMvs(name, action, var)// : same, scriptable : //MENUTEAR// : a tearoff menuitem : //MENUSEP// : a menu separator : //MENUSEPr// : same, with a slot of its own (to hide/show it) : //uMENUBAR(CHANGE_handler)// : a script-only simulated menubar with //CHANGE// event handler : //uMENUITEM(name, action)// : a script-only simulated menuitem; not scriptable, is used for keybindings : //uMENUITEMs(name, action)// : same, scriptable === Control flow === The commands in this group control what other commands get executed after. : //GOTO(array)// : go execute specified V-code array : //CALL(array)// : push current execution address onto return stack, and go execute specified V-code array : //CALLp(field)// : same, with address of the array given in **void**** field : //RET// : pop execution address from return stack, and continue from there : //IF(field)// : if **int** field is 0, skip the next command (caution: do not put before those macros that are internally multiple commands) : //IFv(var)// same, if **int** variable is 0 : //IFx(field, id)// : if **int** field is 0, skip the following commands till an //ENDIF()// with the same id number : //IFx(var, id)// : same, if **int** variable is 0 : //UNLESS(field)// : if **int** field isn't 0, skip the next command : //UNLESSv(field)// : same, if **int** variable isn't 0 : //UNLESSx(field, id)// : if **int** field isn't 0, skip the following commands till an //ENDIF()// with the same id : //UNLESSbt(ini_var_name)// : if inifile variable (boolean) isn't FALSE, skip the next command : //ENDIF(id)// : mark the point for //IFx/UNLESSx// with corresponding id, otherwise do nothing Complex conditions can be implemented in three ways; either the flag variable/field itself can be calculated from the condition, or //IFx/UNLESSx// can be wrapped around another (sharing the same //ENDIF//), or //IF//UNLESS// can precede another conditional to skip it: "//IF(A), IF(B), command//" results in "if (!a || b) command". === Memory allocation and referencing === : //REF(field)// : put address of current slot in the "tape" into **void**** field : //REFv(var)// : same, into **void**** variable : //CLEANUP(field)// : in **run_destroy()** free the memory block pointed to by the **void*** field : //TALLOC(field, length_field)// : in **run_create()** allocate **int** //length_field// bytes (**void*** aligned) below current **dtail** and put their address (new **dtail**) into **void*** field : //TCOPY(field, length_field)// : same but copy whatever the **void*** field was pointing to into the allocated block before overwriting the field with its (now the copy's) address In case //TALLOC()// is used to allocate **double** arrays on a 32-bit architecture, the block will need be allocated with one **double** extra, and properly aligned on **double** afterwards. === Keymap and action map === Action map serves to easily enable/disable or show/hide multiple widgets in response to combinations of various conditions. : //VISMASK(mask)// : choose which bits of action map will control visibility instead of sensitivity (default is none) : //ACTMAP(mask)// : the widget after whose slot in the "tape" this goes, will be sensitive/shown when any bits in the mask are set in the action map, and insensitive/hidden when none are Keymap serves to dynamically map keys to widgets (represented as their slots in the "tape"). The default mappings are set in V-code, and keymap allows to modify them afterwards and saves/restores the modifications using the inifile. : //KEYMAP(field, name)// : add a named keymap, with **void**** field to put the found slot into : //SHORTCUTs(string)// : add a shortcut represented in GTK+ string format, like "F1" : //SHORTCUT(keyval, mods)// : add a shortcut representes as keyname and modifiers, like //SHORTCUT(F2, CS)// for Ctrl+Shift+F2 : //SHORTCUT0// add no shortcut but tell the keymap to allow user to add one (or more) All //SHORTCUT*// commands affect the last widget with a slot in the "tape" before them, as does //ACTMAP// and other "postfix modifier" commands. === Grouping === Group marks serve to direct **cmd_reset()** to a range of widgets all at once, and to differentiate groups of like-named widgets for scripting. They all have a slot in the "tape". : //GROUPR// : begin a resetting-group : //GROUPN// : begin a scripting-group, taking its name from the preceding label : //GROUP(name)// : begin a scripting-group with specified name : //GROUP0// : end the current group === Sizing and placement === : //BORDER(category, num)// : set border/spacing for specified category of widgets to specified number of pixels : //DEFBORDER(category)// : set border/spacing for specified category of widgets to the default (5 pixels) : The categories are: | TABLE | tables | NBOOK | notebooks | SCROLL | scrolledwindows | SPIN | spinbuttons | SPINSLIDE | spinsliders | LABEL | labels | OPT | option menus | BUTTON | buttons | TOOLBAR | toolbars | POPUP | popup windows | TOPVBOX | toplevel vboxes | CHECK | checkbuttons | FRAME | frames | RPACK | radiobutton packs | ENTRY | text entries | LISTCC | simple lists | PATH | pathboxes : //MKSHRINK// : make toplevel window shrinkable (to prevent it becoming larger than screen) : //NORESIZE// : make toplevel window not user-resizable (to make it automatically shrink when widgets get hidden) : //WANTMAX// : tell scrolledwindow that goes //after// it to request full size of its contents : //WANTMAXW// : same, for width only : //WXYWH(prefix, width, height)// make the toplevel save/restore its size and position using inifile variables with specified prefix, and set default width and height for it : //DEFW(width)// : set default width for toplevel : //DEFH(height)// : set default height for toplevel : //DEFSIZE(width, height)// : set default width and height for toplevel : //WPMOUSE// : tell window manager to show the toplevel at the mouse cursor location : //WPWHEREVER// : tell window manager to show the toplevel wherever it chooses : //WIDTH(width)// : set width for the next widget : HEIGHT(height)// : set height for the next widget : //MINWIDTH(width)// : set minimum width for the next widget : //KEEPWIDTH// : make the //preceding// widget to never shrink in width : //KEEPHEIGHT// : same in height : //ONTOP(field)// : make the toplevel sit above the one whose **wdata** is passed in **void**** field (set it as its transient parent) : //ONTOP0// : let the toplevel sit either over or under the main window (which is default transient parent of everything else **run_create()** makes); i.e. unset transient parent By default, **run_create()** tells window manager to show the toplevels in the center of the screen. === Initial state === : //HIDDEN// : make the preceding widget initially hidden : //INSENS// : make it initially insensitive : //FOCUS// : make it initially focused : //RAISED// : initially raise the toplevel above other windows === Cursors === These commands make cursors for later use. They all have slots in the "tape", by which the cursors can later be referred to. : //XBMCURSOR(xbm_name, x, y)// : a 21x21 cursor from two XBM bitmaps (image and mask) specified by the variable part of their filenames ("select" for xbm_select.xbm and xbm_select_mask.xbm, for example), with specified hotspot coordinates : //SYSCURSOR(id)// : a builtin cursor, identified as per GdkCursorType === Events === Event handlers, in V-code, get a slot in the "tape" after the widget they are attached to. There should be only one handler for a given event type per widget. : //EVENT(type, handler)// : add a handler for specified event type to the preceding widget : //TRIGGER// : trigger the preceding event handler after **run_create()** finishes creating widgets (but before the toplevel gets shown); has a slot of its own : //MTRIGGER(handler)// : trigger specified event handler (should be the same as on the menubar) for the preceding menuitem; has a slot of its own and another for the //CHANGE// event : //WANTKEYS(handler)// : install priority //KEY// event handler for when the preceding widget is focused; has a slot of its own and another for the //KEY// event The event types and their causes (widgets denoted by underlying opcodes): : OK : - pressing //OKBTN// or //DONEBTN// - pressing //Enter// in text entry or pathbox's entry - choosing from list or pressing //Enter// in //COMBOENTRY// - double click or pressing //Enter// in a complex list : CANCEL : - pressing //CANCELBTN// - closing a window (call **run_destroy()** if agreeing to it, return without doing that if ignoring the request) : CLICK : - pressing //BUTTON// - right click on a toolbar button : SELECT : - changing selection in radiobutton pack, option menu, list, or //GRADBAR// : CHANGE : - changing value in spinbutton or spinslider - changing value in //TLSPINPACK//, //PCTCOMBO//, //HEXENTRY//, //EYEDROPPER// - changing text in text entry, pathbox, or //TEXT// - changing color in color selector - changing state of //TOGGLE// or checkbutton - pressing a toolbar button - selecting a menuitem - leasing/unleasing the element from //MOUNT// - scrolling a //CSCROLL// - resizing //CANVAS// - changing sort mode in //LISTCX// (should re-sort its map array) : DESTROY : - running **run_destroy()** (after the toplevel is unrealized but before most everything else) : SCRIPT : - setting value in the widget from a script : MULTI : - setting a list of values to the widget from a script - **evtxr_fn** : KEY : - pressing a key when focus is in the widget - **evtxr_fn** : MOUSE and XMOUSE: - pressing a mouse button in the widget - **evtxr_fn** : MMOUSE and MXMOUSE: - moving mouse in the widget - **evtxr_fn** : RMOUSE and RXMOUSE: - releasing a mouse button after pressing it in the widget - **evtxr_fn** : CROSS : - cursor entering or leaving the widget - **evtx_fn** : SCROLL : - rotating mouse scroll wheel in the widget - **evtx_fn** : EXT : - needing to render an area of //CANVAS// - **evtxr_fn** - right click in //LISTCX// - **evtx_fn** - click in //COLORLIST// - **evtx_fn** : DRAGFROM : - dragging from //DRAGDROP//'s widget - **evtxr_fn** : DROP : - dropping to //DRAGDROP//'s widget - **evtx_fn** : COPY : - data request from //CLIPBOARD// - **evtx_fn** : PASTE : - data received by //CLIPBOARD// - **evtxr_fn** Unless otherwise noted, the event handlers are of type **evt_fn**. For those of types **evtx_fn** and **evtxr_fn**, what they get in the extra parameter and what their return value does, is described under "Callbacks" below. The difference between //MOUSE/MMOUSE/RMOUSE// and //XMOUSE/MXMOUSE/RXMOUSE// events is, the latter 3 ask for, and report, tablet pressure. Outside //EVENT()// commands, event types are referred to by their opcodes, which have "//op_EVT_//" prefix; like //op_EVT_OK// for //OK// event. === Clipboard and drag-drop === Clipboard and drag-drop use the same type of data format descriptions. The //CLIPFORM// command prepares those descriptions for them; its slot in the "tape" is then passed to the commands that use the formats. : //CLIPFORM(array, count)// : a group of formats from **clipform_dd[]** array; has a slot in the "tape" : //DRAGDROP(field, DRAGFROM_handler, DROP_handler)// : add handlers for drag and/or drop to the preceding widgets, with formats in **void**** field; has a slot for itself and two more for the events : //DRAGDROPm(field, DRAGFROM_handler, DROP_handler)// : the same but allows the "move" type of drop in addition to "copy" (some programs use the "move" type when they really should not) : //CLIPBOARD(field, which, COPY_handler, PASTE_handler)// : add handlers for copy and paste for specified clipboards (//which//: 1 if the regular clipboard, 2 if the "primary selection" i.e. what is highlighted, 3 if both at once), with formats in **void**** field; has a slot for itself and two more for the events The //DROP// event handler receives in its //xdata// parameter a pointer to **drag_ext**; the //PASTE// event, to **copy_ext** and returns TRUE if successfully imported the data. The //DRAGFROM// and //COPY// events are handled differently from most others; their handlers receive in their //xdata// parameter a slot (dynamically created) with which they then interact to send or receive the data. //DRAGFROM// handler also should return TRUE if it agrees to initiate drag, FALSE otherwise. === Scripting === The below commands exist solely to facilitate scripting. : //ALTNAME(name)// : add another name (identifier) for the preceding widget; has a slot in the "tape" : //FLATTEN// : make option names from the preceding option menu or radiobutton pack be directly referrable from script like widget names (in addition to being referrable as values); has a slot in the "tape" : //OPNAME(name)// : set (override) name for the preceding widget : //OPNAME0// : unset the current name (the initial empty-string one, or the preceding unattached label) to prevent it mis-attaching to the next widget : //UNNAME// : hide the preceding widget from scripts (by setting it an impossible name) : //SCRIPTED// : tell **run_create()** to start a range of "live-scriptable" widgets (those get extra //ALTNAME// slots automatically added, to make them visible from script despite being real widgets) : //ENDSCRIPT// : end a range of "live-scriptable" widgets; has a slot in the "tape" (to tell script interpreter where the range ends) == Functions and macros == There are two main groups of functions; the **run_*()** that affect the entire "tape", and the **cmd_*()** affecting a single slot. Also a few assorted helper functions and macros. : **void **run_create_(void **ifcode, void *ddata, int ddsize, char **script);** build a dialog window out of V-code decription; takes an array with that description, address and size of the struct that will be copied into its **ddata**, and an array of script commands or NULL; returns **wdata** of what got built (possibly already freed, if script was passed in), or NULL if failed : **void **run_create(void **ifcode, void *ddata, int ddsize);** same without script commands (a convenience macro) : **void run_query(void **wdata);** query dialog contents using its "tape"; takes dialog's **wdata** : **void run_destroy(void **wdata);** destroy a dialog; takes dialog's **wdata** : **void cmd_event(void **slot, int op);** raise event (specified by opcode) on slot : **void cmd_sensitive(void **slot, int state);** set sensitive state on slot : **void cmd_showhide(void **slot, int state);** set visible state on slot : **void cmd_set(void **slot, int v);** set value on slot : **int cmd_setstr(void **slot, char *s);** set text-encoded value on slot; returns -1 if failed, 0 if value was left unused (when only the fact of setting something mattered), 1 if set : **void *cmd_read(void **slot, void *ddata);** read back slot value (as is) given **ddata** (to calculate fields' addresses faster); returns the value's storage location : **void cmd_repaint(void **slot);** repaint slot : **void cmd_reset(void **slot, void *ddata);** reset slot or group given **ddata**; causes the widget(s) to reinitialize : **void cmd_cursor(void **slot, void **cursor);** set cursor on slot (for its widget's window) given the cursor's slot : **int cmd_run_script(void **slot, char **strs);** run script on slot; returns -1 if error happened, 0 if //OK// event handler got activated, 1 if not : **void **get_wdata(GtkWidget *widget, char *id);** from widget to its **wdata** : **void **wdata_slot(void **slot);** from slot to its **wdata** : **void **origin_slot(void **slot);** from event to its originator : **void *slot_data(void **slot, void *ddata);** from slot to its storage location (its own, //not// originator's), given **ddata** : **void **find_slot(void **slot, char *id, int l, int mlevel);** find slot by text name (with explicit length) and menu level (//MLEVEL_*//) : **void do_evt_1_d(void **slot);** run event handler in slot, defaulting to run_destroy() if NULL there : **void dialog_event(void *ddata, void **wdata, int what, void **where);** handle dialog buttons' events (from //OKBTN// and //CANCELBTN//) The next three are for those (widget-type-specific) actions that the above functions do not cover. Such actions were not made into functions to avoid the interface ballooning up with functions that are applicable to very few widgets each. Sending requests and receiving responses through a generic interface instead, is convenient enough in practice. : **void cmd_peekv(void **slot, void *res, int size, int idx);** read extra data from slot, given data's index/id, destination, and size : **void cmd_setv(void **slot, void *res, int idx);** set extra data on slot, given data's index/id and source; for some functions, //res// itself is the value (**int** converted to pointer) : **int cmd_checkv(void **slot, int idx);** check extra state on slot, given state's index/id Now, the indices/ids per slot type, what each does, and what type of data expects. Types are denoted by representative opcodes. Most actions are either get or set, only very few are valid for both; the check actions are not valid for either get or set and vice versa, as in totally unrelated. - //FPICK// : : //FPICK_VALUE// get/set the filename with full path, in system encoding: **char[]** : //FPICK_RAW// get/set the raw filename; only the file part without path, in UTF8: **char[]** - //PATH// and //PENTRY// : : //PATH_VALUE// get/set the filename: **char[]** : //PATH_RAW// get/set the raw filename: **char[]** - //LISTCC// : : //LISTCC_RESET_ROW// set the row index to reset: **int** - //LISTC// : : //LISTC_RESET_ROW// set the row index to reset: **int** : //LISTC_ORDER// get sort order: **int[]** : //LISTC_SORT// set sort mode: **int** - //LABEL// and //MENUITEM// : : //LABEL_VALUE// set label text: **char*** - //NBOOK// : : //NBOOK_TABS// set show/hide tabs: **int** - //ENTRY// and //COMBOENTRY// : : //ENTRY_VALUE// set value: **char*** - //TEXT// : : //TEXT_VALUE// set value: **char*** - **wdata** : : //WDATA_ACTMAP// set action map: **unsigned int** : //WDATA_TABLET// get name of tablet device: **char**** - //WINDOW// : : //WINDOW_TITLE// set window title: **char*** : //WINDOW_ESC_BTN// set slot to react (get "clicked") to //Esc// keypress in window: **void**** : //WINDOW_FOCUS// set focus to slot (or to nowhere if NULL): **void**** : //WINDOW_RAISE// set window to raise; value is ignored: **void** : //WINDOW_DISAPPEAR// set window to hide from view (to allow a screenshot), or to unhide: **int** : //WINDOW_DPI// get DPI: **int*** : //WINDOW_TEXTENG// set to render text: **texteng_dd*** - //COLOR// : : //COLOR_RGBA// set current color and alpha: **int[2]** : //COLOR_ALL// set current and previous color and alpha: **int[4]** - //SPIN// and //SPINSLIDE// : : //SPIN_ALL// set value, min and max: **int[3]** - //COLORLIST// : : //COLORLIST_RESET_ROW// set the row index to reset: **int** - //PROGRESS// : : //PROGRESS_PERCENT// set progress percentage: **int** - //CSCROLL// : : //CSCROLL_XYSIZE// get x offset, y offset, onscreen width, onscreen height: **int[4]** : //CSCROLL_LIMITS// get full width minus onscreen width, and full height minus onscreen height: **int[2]** : //CSCROLL_XYRANGE// set x offset, y offset, full width, and full height, for a delayed resize: **int[4]** - //CANVASIMG//: : CANVAS_SIZE set full size: **int[2]** - //CANVAS// : : CANVAS_SIZE get onscreen size / set full size: **int[2]** : CANVAS_VPORT get viewport (x, y, x + width, y + height): **int[4]** : CANVAS_REPAINT set area that needs repaint (x, y, x + width, y + height): **int[4]** : CANVAS_PAINT set area you want to repaint (//rgb// = NULL) - bounds will be modified and buffer allocated / set image data (//rgb// != NULL) - buffer will be painted into the bounded area: **rgbcontext*** : CANVAS_FIND_MOUSE get mouse state: **mouse_ext*** : CANVAS_BMOVE_MOUSE set to nudge mouse cursor by dx, dy: **int[2]** - //FCIMAGE// : : //FCIMAGE_XY// set location marker to x, y: **int[2]** - //KEYMAP// : : //KEYMAP_KEY// set key to map to slot: **key_ext*** : //KEYMAP_MAP// get/set keymap: **keymap_dd*** - //EV_MOUSE// : : //MOUSE_BOUND// check to keep cursor inside canvas' visible area, by scrolling the canvas & moving the cursor back in; return TRUE if moved it - //EV_DRAGFROM// : : //DRAG_DATA// set start & end of data exported through drag: **char*[2]** : //DRAG_ICON_RGB// set RGB color (packed) for drag icon (color patch): **int** - //EV_COPY// : : //COPY_DATA// set start & end of data exported through copying: **char*[2]** - //CLIPBOARD// : : //CLIP_TEXT// set text to export through clipboard: **char*** : //CLIP_OFFER// check to offer data through clipboard; return TRUE if successful : //CLIP_PROCESS// check to request data from clipboard; return TRUE if successful - all regular widgets : : //SLOT_SENSITIVE// check sensitive state; return TRUE if sensitive : //SLOT_FOCUSED// check focused state; return TRUE if focus in toplevel window is inside the widget : //SLOT_SCRIPTABLE// check scriptability; return TRUE if script flag is set in opcode : //SLOT_UNREAL// check unreality; return TRUE if the widget is simulated : //SLOT_RADIO// check radio-ness; return TRUE if the widget is radio toolbutton or radio menuitem - //FONTSEL// : : //FONTSEL_DPI// set DPI: **int** Finally, the macros. : //VSLOT_SIZE// : size of a slot, in void pointers: 3 : //GET_DDATA(wdata)// : from **wdata** to **ddata**: **void*** : //GET_WINDOW(wdata)// : from **wdata** to its toplevel widget's slot: **void**** : //GET_REAL_WINDOW(wdata)// : from **wdata** to actual toplevel widget: **void***, in fact **GtkWidget*** : //NEXT_SLOT(slot)// : from slot to the next one: **void**** : //PREV_SLOT(slot)// : from slot to the previous one: **void**** : //SLOT_N(slot, n)// : from slot to the n-th one after: **void**** : //TOOL_ID(slot)// : get toolbutton's action code: **int** : //TOOL_IR(slot)// : get toolbutton's right-click action code: **int** : //ACTMOD(action, mode)// : combine action and mode into action code == Callbacks == Most events are handled by **evt_fn** function (the default one): **void (*evt_fn)(void *ddata, void **wdata, int what, void **where);** The //ddata// and //wdata// parameters are precisely that; the backing struct, and the "tape". The //what// parameter is the event's opcode, and the //where// is its slot. One handler for all (or most) events happening in the dialog, is the usual pattern when using V-code. When inside it need do different things depending on what is happening to what, there are 3 ways to make the decision. One is to use the "//what//" parameter; it is mostly done to separate out final button presses (the //op_EVT_OK// and //op_EVT_CANCEL//) from everything else. Another is to do "**void *cause = cmd_read(where, ddata);**" and compare the "//cause//" to addresses of variables and/or fields that V-code commands refer to. This serves for most types of controls, and with them **cmd_read()** is usually needed anyway, to get the newly-modified value (a few are "self-reading" but that is rarely significant; only affects when to save the previous value if you need it). The third is to do "**void **slot = origin_slot(where);**" and compare the slot with controls' slots stored using //REF()// commands. This in practice is only needed when several //BUTTON()//s are in one dialog; with them all having //CLICK// events and not referring to any memory locations, their slots are the only thing differentiating them. Now, some events need send some extra data to their handler. Those are handled by **evtx_fn** function: **void (*evtx_fn)(void *ddata, void **wdata, int what, void **where, void *xdata);** What, specifically, the handler receives in //xdata//, depends on the event. : //CROSS// : TRUE if entering, FALSE if leaving: **int** converted to pointer : //SCROLL// : pointer to **scroll_ext** : //EXT// from //LISTCX// : row index where right click happened: **int** converted to pointer : //EXT// from //COLORLIST//: pointer to **colorlist_ext** : //DROP// : pointer to **drag_ext** : //COPY// : pointer to **copy_ext** Yet other events not only send extra data to the handler, but also await a return value from it. The value, for nearly all, is simply TRUE or FALSE, and the function handling them is **evtxr_fn**: **int (*evtxr_fn)(void *ddata, void **wdata, int what, void **where, void *xdata);** What the handler receives in //xdata//, and what its return value means, again depends on the event. : //KEY// : pointer to **key_ext**; return TRUE if the key was handled, FALSE otherwise : //MOUSE//, //XMOUSE//, //MMOUSE//, //MXMOUSE//, //RMOUSE//, //RXMOUSE//: pointer to **mouse_ext**; return TRUE if the mouse event was handled : //EXT// from //CANVAS//: pointer to **rgbcontext**; return TRUE if something was rendered into buffer : //DRAGFROM// : pointer to **drag_ext**; return TRUE to initiate drag : //PASTE// : pointer to **copy_ext**; return TRUE if data successfully imported : //MULTI// : pointer to **multi_ext**; return 0 if error, 1 if success and the //xdata// not needed anymore, -1 if success and the struct should be kept (not freed) Handling some events can include system-dependent interactions with their //xdata//. Instead of saddling some poor unsuspecting widget with those, an "intercessor" capable of processing that is passed as the originating event, in the "//where//" parameter. The intercessors' opcodes are //op_EV_*// to their events' //op_EVT_*//; their functions are described under the headings //EV_MOUSE//, //EV_DRAGFROM//, and //EV_COPY// in the "Functions and macros" chapter above. They are accessed like this: "**cmd_setv(where, pp, DRAG_DATA);**". == THE END == mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/gtk/000077500000000000000000000000001471325446300207405ustar00rootroot00000000000000mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/gtk/README000066400000000000000000000277421471325446300216340ustar00rootroot00000000000000----------- The History ----------- For simpler installation and more consistent behaviour, official Windows build of mtPaint is packaged with its own copy of GTK+ runtime environment. Prior to version 3.40, it was GTK+ 2.6.4 - or more accurately, a mix of DLLs from official Windows distributions of GTK+ 2.6.4 and 2.6.9, with libgdk and libgtk being from 2.6.4. This allowed mtPaint to continue to support Windows 98, which became unsupported with GTK+ 2.8. But since version 2.6.4 had been released in 2005, some improvements in Windows support in GTK+ had been made which were really desirable. Moreover, libraries such as libpng, libjpeg, LibTIFF, FreeType, and even zlib had undergone multiple version changes in the meantime, with bugfixes and other improvements. Still, upgrading the package to a newer official distribution of GTK+ would have meant exposing the program to a new set of GTK+ bugs and quirks - which would have been hard to detect and counter in time, because I myself do not run Windows. For this reason, mtPaint 3.40 came with a custom build of GTK+ based on version 2.6.7 with a set of patches backported from the later versions, compiled from source along with all its dependencies. With mtPaint 3.50, an updated version of that build, with updated libraries, comes with 32-bit build of mtPaint intended for old 32-bit Windows systems such as Windows XP, or even now-ancient Windows 98 in case someone somewhere has a reason to run one. On newer 64-bit Windows systems, specifically Windows 7 and later, the 64-bit build of mtPaint is expected to work better; however, the newer GTK+2 build coming with it is near untested (for I still do not run Windows) so if it misbehaves in any major way, this 32-bit build could serve as a fallback. For mtPaint 3.51, the only notable change is that giflib library which was a dependency before, now isn't and was removed. ------------- The Specifics ------------- Original patches from GTK+ tree contained in the cumulative patch: - svn 7886 / git d73fa807875951d0240dce572398992d395bbe77 Use GetDriveType() to recognize removable drives (in order to avoid (REVERTED: was making flash drives inaccessible from file selector) - svn 12881 / git 0604a90098416694c1d26bfa920e34c3f5d61493 Remove debugging output. (#302404, Frederic Crozat) (APPLIED: cleans up BMP loader) - svn 12899 / git cf5324d980fcddad8318bf52f5315d39fc4221f6 Don't grab focus to unrealized widgets. (#302240, Philip Langdale) (APPLIED: fixes possible glitch in radiobutton groups) - svn 12903 / git 0ae5528968af2b0e28eebdb9c4b38f76af129707 Take multi-monitor offset into account. (#302525) (APPLIED) - svn 12946 / git 35f75bd3401d498201327fe00fa454deb351cee1 Always initialize child-visible to FALSE, otherwise we may end up with the (PARTIALLY APPLIED: fixes possible glitch in GtkNotebook) - svn 12968 / git ff576e3fe7dce780f2b892967fb16c073656d29d Check that GDK_IS_SCREEN(screen) (like the X11 backend does), not screen (APPLIED) - svn 12991 / git 7c337b69f23d4200d4975cc35da13d1d3c00cc1f Don't blink the cursor if the entry is not editable. (#304171,Nikos (APPLIED) - svn 12992 / git ef25506011d6bfa67294cdcc8bbdd40185f0bfaa Don't bind GDK_Page_Up and GDK_Page_Down twice. (#168333, Hazael Maldonado (APPLIED: fixes reaction to PageUp & PageDown keys in sliders) - svn 12994 / git f4fc3fee869d901eba7b6eaf22a4794b15659a2e Keep the popup posted if the button is released over the cellview. This (APPLIED: fixes GtkComboBox) - svn 13027 / git a9c0d119133ea9c22017cf7bb567b5de54b538c0 If the keysym isn't one of the special cases this function takes care of, (APPLIED) - svn 13057 / git 67f3c556626c6e9fa06b2143c87633e635ed733c If blitting from the root window, take the multi-monitor offset into (APPLIED) - svn 13062 / git b27c1cc6ee8e5d86a628a3a96a8c3d56bdc00b7e Make autoscrolling work at the bottom of the screen. (APPLIED: fixes GtkComboBox) - svn 13095 / git 36c4c40f8822aa519aa33fa3222f42fc6563dfa8 Check for overflow. (#306394, Morten Welinder) (APPLIED: fixes PNM loader) - svn 13200 / git 5e575c6df3a3e407042a666a9ba9cbb1e01c0b6c [Win32] Borrow this function from GLib HEAD. (_gtk_get_localedir): [Win32] (APPLIED: fixes possible problem with non-ASCII installation path) - svn 13219 / git 4a37701aa1615c30d80a6840fbc836fc2896adaa Queue a draw on the old and new focus widgets, if their defaultness (APPLIED) - svn 13224 / git c943c3552a7a8f2aee2bad0d3d694b67c6c8e41c Set the actions and suggested_action fields in the GdkDragContext to (APPLIED) - svn 13267 / git 406be320feec1adec2e5794150cb3eea351cb1fb Connect to button-release-event as well, to handle touchscreen scenarios (APPLIED) - svn 13438 / git 5454441a8336a0f96a3999143903e394ce1498cd Fix handling of Aiptek and Aiptek-like graphical tablets such as Trust on (APPLIED) - svn 13493 / git 91f2fb2d4d3b8f5474121a396c1b191938ad3887 don't iterate past the end of the string, so pango_layout_get_cursor_pos() (APPLIED: fixes a glitch in GtkEntry) - svn 13498 / git 24d63ffe74df3b5f5780c8c9a8058c341f26da93 Don't fail if we can't get a keyboard grab. (#168351) (APPLIED) - svn 13588 / git 1cabe720eb48eb0fd29421b4dcdf8c3f58eaf71e Avoid spurious core pointer events when the tablet pen is lifted. (APPLIED) - svn 13738 / git bd80abab9f749698ad034aa2a3b313ac62344b9c Backport from 2.8. (APPLIED: fixes possible crash in GtkComboBox) - svn 14261 / git 21b6ed0024a44054d99c4930914f4eb81dfdd05b 2.8.7 (PARTIALLY APPLIED: fixes two vulnerabilities in XPM loader) - svn 14527 / git 3750d5da6b2dc7e104b9cc19f60b5724032e67c2 Get the invalidated region from ScrollWindowEx() instead of an incorrect (APPLIED: fixes scrolling of partially covered windows) - svn 15720 / git f93e5455e983144e133e18b5041aab29afc97360 [WM_WINDOWPOSCHANGED] Replace identical code as in (APPLIED: prerequisite for svn 17834) - svn 17096 / git 8d601fbde30fd28f9d9fc5e5ebc47cba5e56f351 New file. Downloaded from freedesktop.org's webcvs. Slighly edited cursors (APPLIED: changes to several builtin cursors) - svn 17299 / git ea7cc8d95eade637c67c5331a9f98863210ad8f1 Fix Win32 resize events and flickering (APPLIED) - svn 17615 / git f251591cf8d1d6c399485a4b0f95811e628e6b6f Fix menuitem rendering in Vista (BACKPORTED) - svn 17645 / git 2cf71073edccd5a445a3baef5a158d85caf16520 Use native Win32 cursors where it makes sense (APPLIED) - svn 17834 / git 50af49319ad07682cd15913d264cb4a9570e1f8c Fix context iterations for handle_configure_event() (APPLIED) - svn 20250 / git 710c9619b944e993f5402e04dc08846851b11f38 leak of GDI region in function 'handle_wm_paint' (APPLIED) - svn 20726 / git 0d0f9a7fc184db3ff8ce76e49256fee397de3d35 Windows' System Menu blocks main loop (APPLIED) - svn 20881 / git c8fef535b20ad75f82739f68fce2216c1d62f6ab Repaint glitches in widgets (APPLIED) - svn 22511 / git 703a18c25fc4b1e8f06c4b9c8ea7cb74c06b3871 Can not resize shaped windows on Windows (APPLIED) - git 106ddae86d5ffd3409901c5f9772b1a01f84ad04 Emit changed and notify:text only once. The same fix was applied for (BACKPORTED) In addition, there are couple of my own patches, solving the build problems arising from use of then-recent MinGW on a Linux box (in GTK+ 2.6.x time, official Windows packages were built with MSVC on Windows). And one my patch that fixes a critical bug afflicting the entire GTK+2 line for whole 20 years, causing random crashes on Windows; namely, mixing up GDI handles from CreateDIBSection() in gdk/win32/gdkpixmap-win32.c with HWND user handles from everywhere else, in one single hash. The two types of handles can clash, and when they do, GDK event dispatch is done for, with "invalid cast from `GdkPixmap' to `GdkWindow'" as its dying gasps. It managed to avoid my notice till now, accruing full benefit from my not using Windows; still, better late than never. Patch from Pango tree: - svn 2489 / git d686e1d4ae80b64390149e7336329c0254479161 On Windows store the default aliases file in a string array. (#492517) (BACKPORTED: needed to handle 'pango.aliases' for Windows Vista & Windows 7) --------- The Build --------- The build was done on a Slackware Linux system using MinGW cross-compiler installation combined of the following parts: - GCC 4.2.4 ( https://gcc.gnu.org/pub/gcc/releases/gcc-4.2.4/ ) - TDM patches to it ( https://sourceforge.net/projects/tdm-gcc/files/TDM-GCC%20Old%20Releases/TDM-GCC%204.2%20series/4.2.4-tdm-1/ ) - binutils 2.28 ( https://ftp.gnu.org/gnu/binutils/ ) - MinGW runtime 3.15.2 ( https://sourceforge.net/projects/mingw/files/OldFiles/mingwrt-3.15.2/ ) - Win32 API 3.13 ( https://sourceforge.net/projects/mingw/files/OldFiles/w32api-3.13/ ) And CMake 3.5.2 (for building OpenJPEG and zstd). The reason for using those old MinGW packages specifically, besides maximal similarity with the build packaged with mtPaint 3.40, is retaining support for old Windows versions, in case it was removed from MinGW (or bitrotten there) sometime later. To replicate it, you need the following source packages: - GTK+ 2.6.7 (this specific version and no other): gtk+-2.6.7.tar.bz2 https://download.gnome.org/sources/gtk+/2.6/gtk+-2.6.7.tar.bz2 - Wintab development package: wtkit126.zip https://web.archive.org/web/20070728143618/http://www.wacomeng.com/devsupport/downloads/pc/wtkit126.zip - Pango 1.8.2 (this specific version and no other): pango-1.8.2.tar.bz2 https://download.gnome.org/sources/pango/1.8/pango-1.8.2.tar.bz2 - ATK 1.9.0: atk-1.9.0.tar.bz2 https://download.gnome.org/sources/atk/1.9/atk-1.9.0.tar.bz2 - GLib 2.6.6: glib-2.6.6.tar.bz2 https://download.gnome.org/sources/glib/2.6/glib-2.6.6.tar.bz2 - GNU gettext 0.14.5: gettext-0.14.5.tar.gz https://ftp.gnu.org/pub/gnu/gettext/gettext-0.14.5.tar.gz - GNU libiconv 1.9.2: libiconv-1.9.2.tar.gz https://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.9.2.tar.gz - zlib 1.2.11: zlib-1.2.11.tar.gz https://zlib.net/zlib-1.2.11.tar.gz - XZ Utils 5.2.5: xz-5.2.5.tar.gz https://tukaani.org/xz/xz-5.2.5.tar.gz - zstd 1.4.5: zstd-1.4.5.tar.gz https://github.com/facebook/zstd/releases/download/v1.4.5/zstd-1.4.5.tar.gz - libpng 1.2.59 (not version 1.4+): libpng-1.2.59.tar.gz https://sourceforge.net/projects/libpng/files/libpng12/1.2.59/libpng-1.2.59.tar.gz/download - libjpeg 9d: jpegsrc.v9d.tar.gz https://www.ijg.org/files/jpegsrc.v9d.tar.gz - libwebp 1.1.0: libwebp-1.1.0.tar.gz https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-1.1.0.tar.gz - LibTIFF 4.1.0: tiff-4.1.0.tar.gz https://download.osgeo.org/libtiff/tiff-4.1.0.tar.gz - FreeType 2.10.4: freetype-2.10.4.tar.xz https://sourceforge.net/projects/freetype/files/freetype2/2.10.4/freetype-2.10.4.tar.xz/download - OpenJPEG 2.4.0: openjpeg-2.4.0.tar.gz https://github.com/uclouvain/openjpeg/archive/v2.4.0.tar.gz - Little CMS 2.11: lcms2-2.11.tar.gz https://sourceforge.net/projects/lcms/files/lcms/2.11/lcms2-2.11.tar.gz/download - Gifsicle 1.92: gifsicle-1.92.tar.gz https://www.lcdf.org/gifsicle/gifsicle-1.92.tar.gz - mtPaint 3.50 (or later): mtpaint-3.50.tar.bz2 - mtPaint handbook 3.50 (same version as mtPaint): mtpaint_handbook-3.50.zip Also you need the following files from 'gtk' subdirectory of mtPaint source package: winbuild.sh gtk267_7wj.patch gtkrc pango182_1wj.patch pango.aliases To recreate the "etc/pango/pango.modules" and "etc/gtk-2.0/gdk-pixbuf.loaders" files, you additionally need a working install of Wine. To do the build, put all requisite files into same directory, adjust the variables in "CONFIGURATION SETTINGS" section of 'winbuild.sh' if necessary, and run 'winbuild.sh'. Subdirectory 'zad' will be created for use in the build process; if the build succeeds, executables and runtime files will be placed under 'zad/pkg', and development libraries and headers, under 'zad/dev'. An alternative cross-compiler installation using MXE http://mxe.cc : git clone https://github.com/mxe/mxe.git cd mxe && make gcc MXE_TARGETS=i686-w64-mingw32.shared --------------------------------- Copyright (C) 2010,2011,2017,2019,2020,2021 Dmitry Groshev mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/gtk/README.rsvg000066400000000000000000000074211471325446300226040ustar00rootroot00000000000000----------- The History ----------- Since mtPaint 3.40, the program could load SVG files using a GTK+ plugin provided by librsvg. Unfortunately, any usable version of librsvg requires GTK+ libraries of a later generation than the ones packaged with mtPaint. As the result, the Windows build of mtPaint 3.40 lacked SVG support. In mtPaint 3.50, there is a fallback SVG loader, using 'rsvg-convert' binary. And a static build of said binary, being self-contained, can be included with the Windows build of mtPaint, no matter what GTK+ version is used. For this reason, a custom build of librsvg is done. This 32-bit static build is bundled with 32-bit build of mtPaint; 64-bit build, which uses newer GTK+, includes its own, dynamically linked build of librsvg with 'rsvg-convert'. ------------- The Specifics ------------- Original patches from Pango tree: - svn 2489 / git d686e1d4ae80b64390149e7336329c0254479161 On Windows store the default aliases file in a string array. (#492517) (BACKPORTED: needed to handle 'pango.aliases' for Windows Vista & Windows 7) - git 25ddf43c0185e3c7935414618bd21aee0c35dfe2 Bug 733137 - Don't force no static builds on Win32 (APPLIED) Implementation of function g_clear_object() from GLib 2.28.8 added to librsvg, to satisfy the dependencies. --------- The Build --------- The build was done on a Slackware Linux system using MinGW cross-compiler installation combined of the following parts: - GCC 4.2.4 ( https://gcc.gnu.org/pub/gcc/releases/gcc-4.2.4/ ) - TDM patches to it ( https://sourceforge.net/projects/tdm-gcc/files/TDM-GCC%20Old%20Releases/TDM-GCC%204.2%20series/4.2.4-tdm-1/ ) - binutils 2.28 ( https://ftp.gnu.org/gnu/binutils/ ) - MinGW runtime 3.15.2 ( https://sourceforge.net/projects/mingw/files/OldFiles/mingwrt-3.15.2/ ) - Win32 API 3.13 ( https://sourceforge.net/projects/mingw/files/OldFiles/w32api-3.13/ ) To replicate it, you need the following source packages: - GLib 2.26.1 (this specific version and no other): glib-2.26.1.tar.bz2 http://ftp.gnome.org/pub/GNOME/sources/glib/2.26/glib-2.26.1.tar.bz2 - Pango 1.16.5 (this specific version and no other): pango-1.16.5.tar.bz2 http://ftp.gnome.org/pub/GNOME/sources/pango/1.16/pango-1.16.5.tar.bz2 - Cairo 1.10.2 (this specific version and no other): cairo-1.10.2.tar.gz http://www.cairographics.org/releases/cairo-1.10.2.tar.gz - pixman 0.18.4 (this specific version and no other): pixman-0.18.4.tar.gz http://www.cairographics.org/releases/pixman-0.18.4.tar.gz - librsvg 2.36.4 (this specific version and no other): librsvg-2.36.4.tar.xz https://download.gnome.org/sources/librsvg/2.36/librsvg-2.36.4.tar.xz - gdk-pixbuf 2.22.1: gdk-pixbuf-2.22.1.tar.bz2 https://download.gnome.org/sources/gdk-pixbuf/2.22/gdk-pixbuf-2.22.1.tar.bz2 - libcroco 0.6.2: libcroco-0.6.2.tar.bz2 https://download.gnome.org/sources/libcroco/0.6/libcroco-0.6.2.tar.bz2 - libxml2 2.9.10: libxml2-2.9.10.tar.gz ftp://xmlsoft.org/libxml2/libxml2-2.9.10.tar.gz - dev files from Windows build of mtPaint, packaged: dev.tar.* ./zad/dev/ Also you need the following files from 'gtk' subdirectory of mtPaint source package: winbuild_rsvg.sh pango182_1wj.patch To do the build, put all requisite files into same directory, adjust the variables in "CONFIGURATION SETTINGS" section of 'winbuild_rsvg.sh' if necessary, and run 'winbuild_rsvg.sh'. Subdirectory 'zad' will be created for use in the build process; if the build succeeds, the executable will be placed under 'zad/pkg', and development libraries and headers, under 'zad/dev'. An alternative cross-compiler installation using MXE http://mxe.cc : git clone https://github.com/mxe/mxe.git cd mxe && make gcc MXE_TARGETS=i686-w64-mingw32.shared --------------------------------- Copyright (C) 2016,2017,2020 Dmitry Groshev mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/gtk/README.w64000066400000000000000000000162771471325446300222540ustar00rootroot00000000000000----------- The History ----------- For simpler installation and more consistent behaviour, official Windows build of mtPaint is packaged with its own copy of GTK+ runtime environment. With version 3.40, it was a 32-bit custom build of GTK+2 based on version 2.6.7 with a set of patches backported from the later versions. That build is still provided with mtPaint 3.50, to support old and ancient 32-bit Windows systems, but to make full use of capabilities of 64-bit CPUs, a 64-bit build for Windows systems of the newer generations is needed. This build is based on GTK+ 2.24, with patches taken from MXE, MSYS2 and mxe-octave. For mtPaint 3.51, the only notable change is that giflib library which was a dependency before, now isn't and was removed. ------------- The Specifics ------------- Original patch from GTK+ tree reverted by the cumulative patch: - svn 7886 / git d73fa807875951d0240dce572398992d395bbe77 Use GetDriveType() to recognize removable drives (in order to avoid (REVERTED: was making flash drives inaccessible from file selector) Other than that, there is a patch from MXE fixing docs generation. And my own patch that fixes a critical bug afflicting the entire GTK+2 line for whole 20 years, causing random crashes on Windows; namely, mixing up GDI handles from CreateDIBSection() in gdk/win32/gdkpixmap-win32.c with HWND user handles from everywhere else, in one single hash. The two types of handles can clash, and when they do, GDK event dispatch is done for, with "invalid cast from `GdkPixmap' to `GdkWindow'" as its dying gasps. It managed to avoid my notice till now, accruing full benefit from my not using Windows; still, better late than never. Patches contained in the cumulative patch for gettext, can be found in MSYS2: https://github.com/msys2/MINGW-packages/tree/75c080b98100d9ef0f3a5aa9eb55bbb01c12968e/mingw-w64-gettext --------- The Build --------- The build was done on a Slackware Linux system using MinGW-w64 cross-compiler installation combined of the following parts: - GCC 5.5.0 ( https://gcc.gnu.org/pub/gcc/releases/gcc-5.5.0/ ) - isl 0.15 ( https://gcc.gnu.org/pub/gcc/infrastructure/ ) - binutils 2.28 ( https://ftp.gnu.org/gnu/binutils/ ) - MinGW-w64 7.0.0 ( http://mingw-w64.org/ ) And CMake 3.5.2 (for building OpenJPEG and zstd). To replicate it, you need the following source packages: - GTK+ 2.24.29: gtk+-2.24.29.tar.xz https://download.gnome.org/sources/gtk+/2.24/gtk+-2.24.29.tar.xz - ATK 2.16.0: atk-2.16.0.tar.xz https://download.gnome.org/sources/atk/2.16/atk-2.16.0.tar.xz - Pango 1.42.1: pango-1.42.1.tar.xz https://download.gnome.org/sources/pango/1.42/pango-1.42.1.tar.xz - FriBidi 1.0.10: fribidi-1.0.10.tar.xz https://github.com/fribidi/fribidi/releases/download/v1.0.10/fribidi-1.0.10.tar.xz - HarfBuzz 2.7.2: harfbuzz-2.7.2.tar.gz https://github.com/harfbuzz/harfbuzz/archive/2.7.2.tar.gz - ICU 68.2: icu-release-68-2.tar.gz https://github.com/unicode-org/icu/archive/release-68-2.tar.gz - Cairo 1.16.0: cairo-1.16.0.tar.xz http://www.cairographics.org/releases/cairo-1.16.0.tar.xz - pixman 0.33.6: pixman-0.33.6.tar.gz https://www.cairographics.org/snapshots/pixman-0.33.6.tar.gz - librsvg 2.40.5 (this specific version and no other): librsvg-2.40.5.tar.xz https://download.gnome.org/sources/librsvg/2.40/librsvg-2.40.5.tar.xz - gdk-pixbuf 2.32.3: gdk-pixbuf-2.32.3.tar.xz https://download.gnome.org/sources/gdk-pixbuf/2.32/gdk-pixbuf-2.32.3.tar.xz - libgsf 1.14.30: libgsf-1.14.30.tar.xz https://download.gnome.org/sources/libgsf/1.14/libgsf-1.14.30.tar.xz - libcroco 0.6.2: libcroco-0.6.2.tar.bz2 https://download.gnome.org/sources/libcroco/0.6/libcroco-0.6.2.tar.bz2 - libxml2 2.9.10: libxml2-2.9.10.tar.gz ftp://xmlsoft.org/libxml2/libxml2-2.9.10.tar.gz - Fontconfig 2.13.1: fontconfig-2.13.1.tar.bz2 https://www.freedesktop.org/software/fontconfig/release/fontconfig-2.13.1.tar.bz2 - Expat 2.2.10: expat-2.2.10.tar.bz2 https://sourceforge.net/projects/expat/files/expat/2.2.10/expat-2.2.10.tar.bz2/download - GLib 2.50.2: glib-2.50.2.tar.xz https://download.gnome.org/sources/glib/2.50/glib-2.50.2.tar.xz - libffi 3.3: libffi-3.3.tar.gz https://sourceware.org/pub/libffi/libffi-3.3.tar.gz - PCRE 8.44: pcre-8.44.tar.bz2 https://ftp.pcre.org/pub/pcre/pcre-8.44.tar.bz2 - GNU gettext 0.19.8.1 (this specific version and no other): gettext-0.19.8.1.tar.xz https://ftp.gnu.org/pub/gnu/gettext/gettext-0.19.8.1.tar.xz - GNU libiconv 1.16: libiconv-1.16.tar.gz https://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.16.tar.gz - zlib 1.2.11: zlib-1.2.11.tar.gz https://zlib.net/zlib-1.2.11.tar.gz - bzip2 1.0.6: bzip2-1.0.6.tar.gz https://ftp.osuosl.org/pub/clfs/conglomeration/bzip2/bzip2-1.0.6.tar.gz - XZ Utils 5.2.5: xz-5.2.5.tar.gz https://tukaani.org/xz/xz-5.2.5.tar.gz - zstd 1.4.5: zstd-1.4.5.tar.gz https://github.com/facebook/zstd/releases/download/v1.4.5/zstd-1.4.5.tar.gz - libpng 1.6.37: libpng-1.6.37.tar.xz https://sourceforge.net/projects/libpng/files/libpng16/1.6.37/libpng-1.6.37.tar.xz/download - libjpeg 9d: jpegsrc.v9d.tar.gz https://www.ijg.org/files/jpegsrc.v9d.tar.gz - libwebp 1.1.0: libwebp-1.1.0.tar.gz https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-1.1.0.tar.gz - LibTIFF 4.1.0: tiff-4.1.0.tar.gz https://download.osgeo.org/libtiff/tiff-4.1.0.tar.gz - FreeType 2.10.4: freetype-2.10.4.tar.xz https://sourceforge.net/projects/freetype/files/freetype2/2.10.4/freetype-2.10.4.tar.xz/download - OpenJPEG 2.4.0: openjpeg-2.4.0.tar.gz https://github.com/uclouvain/openjpeg/archive/v2.4.0.tar.gz - Little CMS 2.11: lcms2-2.11.tar.gz https://sourceforge.net/projects/lcms/files/lcms/2.11/lcms2-2.11.tar.gz/download - Gifsicle 1.92: gifsicle-1.92.tar.gz https://www.lcdf.org/gifsicle/gifsicle-1.92.tar.gz - mtPaint 3.50 (or later): mtpaint-3.50.tar.bz2 - mtPaint handbook 3.50 (same version as mtPaint): mtpaint_handbook-3.50.zip Also you need the following files from 'gtk' subdirectory of mtPaint source package: winbuild64.sh gtk22429_1wj.patch gettext1981runtime.patch loaders.cache To recreate the "loaders.cache" file, you additionally need a working install of Wine64. To do the build, put all requisite files into same directory, adjust the variables in "CONFIGURATION SETTINGS" section of 'winbuild.sh' if necessary, and run 'winbuild.sh'. Subdirectory 'zad' will be created for use in the build process; if the build succeeds, executables and runtime files will be placed under 'zad/pkg', and development libraries and headers, under 'zad/dev'. An alternative cross-compiler installation using MXE http://mxe.cc : git clone https://github.com/mxe/mxe.git cd mxe && make gcc MXE_TARGETS=x86_64-w64-mingw32.shared Using GCC 10 is not recommended, as a compiler bug was directly observed when compiling Gifsicle with GCC 10.2.0. While a workaround had been found (now commented out in that part of the script), the bug's very presence in optimization level -O2 casts serious doubt on the quality of that compiler branch and the code it generates. --------------------------------- Copyright (C) 2010,2011,2017,2019,2020,2021 Dmitry Groshev mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/gtk/gettext1981runtime.patch000066400000000000000000000701731471325446300254040ustar00rootroot00000000000000diff -udrN gettext-runtime0/configure gettext-runtime/configure --- gettext-runtime0/configure 2016-06-11 16:00:53.000000000 +0300 +++ gettext-runtime/configure 2020-12-22 12:51:51.932861352 +0200 @@ -24603,7 +24603,7 @@ ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; } >/dev/null 2>&1 - if LC_ALL=C grep -E '(^|^a-zA-Z0-9_)_foo(^a-zA-Z0-9_|$)' conftest.$gl_asmext >/dev/null; then + if LC_ALL=C grep -E '(^|[^a-zA-Z0-9_])_foo(^[a-zA-Z0-9_]|$)' conftest.$gl_asmext >/dev/null; then gl_cv_prog_as_underscore=yes else gl_cv_prog_as_underscore=no diff -udrN gettext-runtime0/gnulib-m4/asm-underscore.m4 gettext-runtime/gnulib-m4/asm-underscore.m4 --- gettext-runtime0/gnulib-m4/asm-underscore.m4 2016-06-11 15:59:32.000000000 +0300 +++ gettext-runtime/gnulib-m4/asm-underscore.m4 2020-12-22 12:51:51.927861353 +0200 @@ -29,7 +29,7 @@ EOF # Look for the assembly language name in the .s file. AC_TRY_COMMAND(${CC-cc} $CFLAGS $CPPFLAGS $gl_c_asm_opt conftest.c) >/dev/null 2>&1 - if LC_ALL=C grep -E '(^|[^a-zA-Z0-9_])_foo([^a-zA-Z0-9_]|$)' conftest.$gl_asmext >/dev/null; then + if LC_ALL=C grep -E '(^|[[^a-zA-Z0-9_]])_foo([[^a-zA-Z0-9_]]|$)' conftest.$gl_asmext >/dev/null; then gl_cv_prog_as_underscore=yes else gl_cv_prog_as_underscore=no diff -udrN gettext-runtime0/intl/Makefile.in gettext-runtime/intl/Makefile.in --- gettext-runtime0/intl/Makefile.in 2016-06-11 10:37:41.000000000 +0300 +++ gettext-runtime/intl/Makefile.in 2020-12-22 12:51:51.884861353 +0200 @@ -126,6 +126,7 @@ localcharset.h \ lock.h \ relocatable.h \ + relocatex.h \ tsearch.h tsearch.c \ verify.h \ xsize.h \ @@ -156,6 +157,8 @@ threadlib.c \ lock.c \ relocatable.c \ + relocatex.c \ + canonicalize.c \ langprefs.c \ localename.c \ log.c \ @@ -189,6 +192,8 @@ threadlib.$lo \ lock.$lo \ relocatable.$lo \ + relocatex.$lo \ + canonicalize.$lo \ langprefs.$lo \ localename.$lo \ log.$lo \ @@ -298,6 +303,10 @@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC --mode=compile $(COMPILE) $(srcdir)/threadlib.c lock.lo: $(srcdir)/lock.c $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC --mode=compile $(COMPILE) $(srcdir)/lock.c +relocatex.lo: $(srcdir)/relocatex.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC --mode=compile $(COMPILE) $(srcdir)/relocatex.c +canonicalize.lo: $(srcdir)/canonicalize.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC --mode=compile $(COMPILE) $(srcdir)/canonicalize.c relocatable.lo: $(srcdir)/relocatable.c $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC --mode=compile $(COMPILE) $(srcdir)/relocatable.c langprefs.lo: $(srcdir)/langprefs.c diff -udrN gettext-runtime0/intl/bindtextdom.c gettext-runtime/intl/bindtextdom.c --- gettext-runtime0/intl/bindtextdom.c 2016-03-20 09:37:53.000000000 +0200 +++ gettext-runtime/intl/bindtextdom.c 2020-12-22 12:51:51.884861353 +0200 @@ -21,6 +21,7 @@ #include #include #include +#include #include "gettextP.h" #ifdef _LIBC @@ -65,6 +66,12 @@ # define BIND_TEXTDOMAIN_CODESET libintl_bind_textdomain_codeset #endif +#if ENABLE_RELOCATABLE +# include "relocatex.h" +#else +# define relocate(pathname) (pathname) +#endif + /* Specifies the directory name *DIRNAMEP and the output codeset *CODESETP to be used for the DOMAINNAME message catalog. If *DIRNAMEP or *CODESETP is NULL, the corresponding attribute is not @@ -340,11 +347,22 @@ } } #endif - set_binding_values (domainname, &dirname, NULL); + if (!dirname || !access (dirname, R_OK)) { + set_binding_values (domainname, &dirname, NULL); #ifdef __EMX__ - dirname = saved_dirname; + dirname = saved_dirname; #endif - return (char *) dirname; + return (char *) dirname; + } else { + char *locale_dirname, *installdir = strdup (dirname), *s; + if ((s = strrchr (installdir, '/'))) *s = '\0'; + if ((s = strrchr (installdir, '/'))) *s = '\0'; + locale_dirname = relocatex (installdir, dirname); + set_binding_values (domainname, (const char **) &locale_dirname, NULL); + if (installdir) + free (installdir); + return (char *) locale_dirname; + } } /* Specify the character encoding in which the messages from the diff -udrN gettext-runtime0/intl/canonicalize.c gettext-runtime/intl/canonicalize.c --- gettext-runtime0/intl/canonicalize.c 1970-01-01 03:00:00.000000000 +0300 +++ gettext-runtime/intl/canonicalize.c 2020-12-22 12:51:51.885861353 +0200 @@ -0,0 +1,343 @@ +/* Return the canonical absolute name of a given file. + Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef __WIN32__ +# include +# include +//# include +#endif /* __WIN32__ */ +#include "canonicalize.h" + +#ifndef MAXSYMLINKS +# define MAXSYMLINKS 20 +#endif + +#ifndef __set_errno +# define __set_errno(Val) errno = (Val) +#endif + +# ifdef VMS + /* We want the directory in Unix syntax, not in VMS syntax. */ +# define __getcwd(buf, max) getcwd (buf, max, 0) +# else +# define __getcwd getcwd +# endif + +#define weak_alias(local, symbol) + +#if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__ || defined __EMX__ || defined __DJGPP__ + /* Win32, Cygwin, OS/2, DOS */ +# define ISDIRSEP(C) ((C) == '/' || (C) == '\\') +#else + /* Unix */ +# define ISDIRSEP(C) ((C) == '/') +#endif + +#ifdef __WIN32__ +char *win2unixpath (char *FileName) +{ + char *s = FileName; + while (*s) { + if (*s == '\\') + *s = '/'; + *s++; + } + return FileName; +} +#endif + +/* Return the canonical absolute name of file NAME. A canonical name + does not contain any `.', `..' components nor any repeated path + separators ('/') or symlinks. All path components must exist. If + RESOLVED is null, the result is malloc'd; otherwise, if the + canonical name is PATH_MAX chars or more, returns null with `errno' + set to ENAMETOOLONG; if the name fits in fewer than PATH_MAX chars, + returns the name in RESOLVED. If the name cannot be resolved and + RESOLVED is non-NULL, it contains the path of the first component + that cannot be resolved. If the path can be resolved, RESOLVED + holds the same value as the value returned. + RESOLVED must be at least PATH_MAX long */ + +static char * +canonicalize (const char *name, char *resolved) +{ + char *rpath, *dest, *extra_buf = NULL; + const char *start, *end, *rpath_limit; + long int path_max; + int num_links = 0, old_errno; + + if (name == NULL) + { + /* As per Single Unix Specification V2 we must return an error if + either parameter is a null pointer. We extend this to allow + the RESOLVED parameter to be NULL in case the we are expected to + allocate the room for the return value. */ + __set_errno (EINVAL); + return NULL; + } + + if (name[0] == '\0') + { + /* As per Single Unix Specification V2 we must return an error if + the name argument points to an empty string. */ + __set_errno (ENOENT); + return NULL; + } +#ifdef __WIN32__ + { + char *lpFilePart; + int len; +// fprintf(stderr, "name: %s\n", name); + rpath = resolved ? __builtin_alloca (MAX_PATH) : malloc (MAX_PATH); +// unix2winpath (name); +// fprintf(stderr, "name: %s\n", name); + len = GetFullPathName(name, MAX_PATH, rpath, &lpFilePart); + /* GetFullPathName returns bogus paths for *nix-style paths, like + * /foo/bar - it just prepends current drive to them. Keep them + * intact (they need to be for relocation to work!). + */ + if (name[0] == '/') { + strncpy (rpath, name, MAX_PATH - 1); + rpath[MAX_PATH - 1] = '\0'; + len = strlen (rpath); + } +// fprintf(stderr, "rpath: %s\n", rpath); + if (len == 0) { + //set_werrno; + return NULL; + } + if (len > MAX_PATH) { + if (resolved) + __set_errno(ENAMETOOLONG); + else { + rpath = realloc(rpath, len + 2); + GetFullPathName(name, len, rpath, &lpFilePart); +// fprintf(stderr, "rpath: %s\n", rpath); + } + } +// if ( ISDIRSEP(name[strlen(name)]) && !ISDIRSEP(rpath[len]) ) { +// rpath[len] = '\\'; +// rpath[len + 1] = 0; +// } + old_errno = errno; + //if (!access (rpath, D_OK) && !ISDIRSEP(rpath[len - 1]) ){ + if (!access (rpath, R_OK) && !ISDIRSEP(rpath[len - 1]) ){ + rpath[len] = '\\'; + rpath[len + 1] = 0; + } + errno = old_errno; + win2unixpath (rpath); +// fprintf(stderr, "rpath: %s\n", rpath); + return resolved ? strcpy(resolved, rpath) : rpath ; + } +#else /* __WIN32__ */ + +#ifdef PATH_MAX + path_max = PATH_MAX; +#else + path_max = pathconf (name, _PC_PATH_MAX); + if (path_max <= 0) + path_max = 1024; +#endif + + rpath = resolved ? __builtin_alloca (path_max) : malloc (path_max); + rpath_limit = rpath + path_max; + + if (name[0] != '/') + { + if (!__getcwd (rpath, path_max)) + { + rpath[0] = '\0'; + goto error; + } + dest = strchr (rpath, '\0'); + } + else + { + rpath[0] = '/'; + dest = rpath + 1; + } + + for (start = end = name; *start; start = end) + { +#ifdef _LIBC + struct stat64 st; +#else + struct stat st; +#endif + int n; + + /* Skip sequence of multiple path-separators. */ + while (*start == '/') + ++start; + + /* Find end of path component. */ + for (end = start; *end && *end != '/'; ++end) + /* Nothing. */; + + if (end - start == 0) + break; + else if (end - start == 1 && start[0] == '.') + /* nothing */; + else if (end - start == 2 && start[0] == '.' && start[1] == '.') + { + /* Back up to previous component, ignore if at root already. */ + if (dest > rpath + 1) + while ((--dest)[-1] != '/'); + } + else + { + size_t new_size; + + if (dest[-1] != '/') + *dest++ = '/'; + + if (dest + (end - start) >= rpath_limit) + { + ptrdiff_t dest_offset = dest - rpath; + + if (resolved) + { + __set_errno (ENAMETOOLONG); + if (dest > rpath + 1) + dest--; + *dest = '\0'; + goto error; + } + new_size = rpath_limit - rpath; + if (end - start + 1 > path_max) + new_size += end - start + 1; + else + new_size += path_max; + rpath = realloc (rpath, new_size); + rpath_limit = rpath + new_size; + if (rpath == NULL) + return NULL; + + dest = rpath + dest_offset; + } + +#ifdef _LIBC + dest = __mempcpy (dest, start, end - start); +#else + memcpy (dest, start, end - start); + dest += end - start; +#endif + *dest = '\0'; + +#ifdef _LIBC + if (__lxstat64 (_STAT_VER, rpath, &st) < 0) +#else + if (lstat (rpath, &st) < 0) +#endif + goto error; + +#if HAVE_READLINK + if (S_ISLNK (st.st_mode)) + { + char *buf = __builtin_alloca (path_max); + size_t len; + + if (++num_links > MAXSYMLINKS) + { + __set_errno (ELOOP); + goto error; + } + + n = __readlink (rpath, buf, path_max); + if (n < 0) + goto error; + buf[n] = '\0'; + + if (!extra_buf) + extra_buf = __builtin_alloca (path_max); + + len = strlen (end); + if ((long int) (n + len) >= path_max) + { + __set_errno (ENAMETOOLONG); + goto error; + } + + /* Careful here, end may be a pointer into extra_buf... */ + memmove (&extra_buf[n], end, len + 1); + name = end = memcpy (extra_buf, buf, n); + + if (buf[0] == '/') + dest = rpath + 1; /* It's an absolute symlink */ + else + /* Back up to previous component, ignore if at root already: */ + if (dest > rpath + 1) + while ((--dest)[-1] != '/'); + } +#endif + } + } + if (dest > rpath + 1 && dest[-1] == '/') + --dest; + *dest = '\0'; + + return resolved ? memcpy (resolved, rpath, dest - rpath + 1) : rpath; + +error: + if (resolved) + strcpy (resolved, rpath); + else + free (rpath); + return NULL; + +#endif /* __WIN32__ */ +} + + +char * +__realpath (const char *name, char *resolved) +{ + if (resolved == NULL) + { + __set_errno (EINVAL); + return NULL; + } + + return canonicalize (name, resolved); +} +weak_alias (__realpath, realpath) + + +char * +__canonicalize_file_name (const char *name) +{ + return canonicalize (name, NULL); +} +weak_alias (__canonicalize_file_name, canonicalize_file_name) + +char * +canonicalize_file_name (const char *name) +{ + return canonicalize (name, NULL); +} diff -udrN gettext-runtime0/intl/canonicalize.h gettext-runtime/intl/canonicalize.h --- gettext-runtime0/intl/canonicalize.h 1970-01-01 03:00:00.000000000 +0300 +++ gettext-runtime/intl/canonicalize.h 2020-12-22 12:51:51.885861353 +0200 @@ -0,0 +1,18 @@ +#ifndef __CANONICALIZE_H__ +#define __CANONICALIZE_H__ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +char *canonicalize_file_name (const char *name); + +#ifdef __WIN32__ +char *win2unixpath (char *path); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __CANONICALIZE_H__ */ diff -udrN gettext-runtime0/intl/libgnuintl.in.h gettext-runtime/intl/libgnuintl.in.h --- gettext-runtime0/intl/libgnuintl.in.h 2016-06-10 01:56:00.000000000 +0300 +++ gettext-runtime/intl/libgnuintl.in.h 2020-12-22 12:51:51.926861353 +0200 @@ -336,7 +336,7 @@ #if !(defined printf && defined _GL_STDIO_H) /* don't override gnulib */ #undef printf -#if defined __NetBSD__ || defined __BEOS__ || defined __CYGWIN__ || defined __MINGW32__ +#if defined __NetBSD__ || defined __BEOS__ || defined __CYGWIN__ || defined __MINGW32__ || defined _MSC_VER /* Don't break __attribute__((format(printf,M,N))). This redefinition is only possible because the libc in NetBSD, Cygwin, mingw does not have a function __printf__. diff -udrN gettext-runtime0/intl/printf.c gettext-runtime/intl/printf.c --- gettext-runtime0/intl/printf.c 2016-03-20 09:37:53.000000000 +0200 +++ gettext-runtime/intl/printf.c 2020-12-22 12:51:51.897861353 +0200 @@ -208,7 +208,7 @@ int libintl_vsnprintf (char *resultbuf, size_t length, const char *format, va_list args) { - if (strchr (format, '$') == NULL) + if (0 && (strchr (format, '$') == NULL)) return system_vsnprintf (resultbuf, length, format, args); else { diff -udrN gettext-runtime0/intl/relocatex.c gettext-runtime/intl/relocatex.c --- gettext-runtime0/intl/relocatex.c 1970-01-01 03:00:00.000000000 +0300 +++ gettext-runtime/intl/relocatex.c 2020-12-22 12:51:51.885861353 +0200 @@ -0,0 +1,284 @@ +/* Provide relocatable packages. + Copyright (C) 2003 Free Software Foundation, Inc. + Written by Bruno Haible , 2003. + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published + by the Free Software Foundation; either version 2, 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + USA. */ + + +/* Specification. */ +#include +#define _GNU_SOURCE +#include +#include +#include +#include +/* #include */ +#include "relocatex.h" +#include "canonicalize.h" +/* #include */ + + +#if defined _WIN32 || defined __WIN32__ +# define WIN32_LEAN_AND_MEAN +# include +//# define __GW32__ +//# include +#endif +#define set_werrno + +#if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__ || defined __EMX__ || defined __DJGPP__ + /* Win32, Cygwin, OS/2, DOS */ +# define ISDIRSEP(C) ((C) == '/' || (C) == '\\') +#else + /* Unix */ +# define ISDIRSEP(C) ((C) == '/') +#endif + +/* Original installation prefix. */ +static char *orig_prefix = NULL; +static size_t orig_prefix_len = 0; +/* Current installation prefix. */ +static char *curr_prefix = NULL; +static size_t curr_prefix_len = 0; +/* These prefixes do not end in a slash. Anything that will be concatenated + to them must start with a slash. */ + + +int win2posixpath (const char *winpath, char *posixpath) +{ + strcpy (posixpath, winpath); + win2unixpath (posixpath); + return 0; +} + + +/* Sets the original and the current installation prefix of this module. + Relocation simply replaces a pathname starting with the original prefix + by the corresponding pathname with the current prefix instead. Both + prefixes should be directory names without trailing slash (i.e. use "" + instead of "/"). */ +static char * +set_orig_prefix (const char *orig_prefix_arg) +{ + char *memory; +// printf ("orig_prefix_arg: %s\n", orig_prefix_arg); + if (!orig_prefix_arg) { + orig_prefix = NULL; + orig_prefix_len = 0; + return NULL; + } + if (orig_prefix) + free (orig_prefix); + + memory = canonicalize_file_name (orig_prefix_arg); +// printf ("memory: %s\n", memory); +// memory = (char *) malloc (orig_prefix_len + 1); + if (!memory) { + set_werrno; + orig_prefix = NULL; + orig_prefix_len = 0; + return NULL; + } + win2unixpath (memory); +// win2posixpath (orig_prefix_arg, memory); + orig_prefix = memory; + orig_prefix_len = strlen (orig_prefix); +// printf ("orig_prefix: %s\n", orig_prefix); + if (ISDIRSEP (orig_prefix[orig_prefix_len-1])) { + orig_prefix[orig_prefix_len-1] = '\0'; + orig_prefix_len--; + } +// printf ("orig_prefix: %s\n", orig_prefix); +// printf ("orig_prefix_len: %d\n", orig_prefix_len); + return orig_prefix; +} + +#if defined __WIN32__ +static char * +set_current_prefix (const char *ModuleName) +{ + LPTSTR curr_prefix_arg, q, lpFilePart; + DWORD len; + int nDIRSEP = 0; + + if (curr_prefix) + free (curr_prefix); + curr_prefix_arg = malloc (MAX_PATH * sizeof (TCHAR)); + if (!curr_prefix_arg) { + set_werrno; + curr_prefix = NULL; + curr_prefix_len = 0; + return NULL; + } + if (ModuleName) { +// printf ("ModuleName: %s\n", ModuleName); + len = SearchPath (NULL, ModuleName, ".DLL", MAX_PATH, curr_prefix_arg, &lpFilePart); + if (len) { +// printf ("ModulePath: %s\n", curr_prefix_arg); +// printf ("FilePart: %s\n", lpFilePart); + } + } + if (!ModuleName || !len) { + len = GetModuleFileName (NULL, curr_prefix_arg, MAX_PATH); + if (!len) { + set_werrno; + curr_prefix = NULL; + curr_prefix_len = 0; + return NULL; + } + } +// strncpy (curr_prefix_arg, ModuleName, MAX_PATH); +// printf ("curr_prefix_arg: %s\n", curr_prefix_arg); + win2posixpath (curr_prefix_arg, curr_prefix_arg); + curr_prefix = curr_prefix_arg; + q = curr_prefix_arg + len - 1; + /* strip name of executable and its directory */ + while (!ISDIRSEP (*q) && (q > curr_prefix_arg) && nDIRSEP < 2) { + q--; + if (ISDIRSEP (*q)) { + *q = '\0'; + nDIRSEP++; + } + } + curr_prefix_len = q - curr_prefix_arg; +// printf ("curr_prefix: %s\n", curr_prefix); +// printf ("curr_prefix_len: %d\n", curr_prefix_len); + return curr_prefix; +} + +char *getshortpath (const char *longpath) +{ + char *shortpath = NULL; + DWORD len, res; + +// printf ("longpath: %s\n", longpath); + len = GetShortPathName(longpath, shortpath, 0); +// printf ("len: %ld\n", len); + if (!len) { +// WinErr ("getshortpath: len = 0"); + set_werrno; + return (char *) longpath; + } + shortpath = (char *) malloc (len + 1); + if (!shortpath) { +// WinErr ("getshortpath: malloc"); + set_werrno; + return (char *) longpath; + } + res = GetShortPathName(longpath, shortpath, len); +// printf ("res: %ld\n", res); + if (!res) { +// WinErr ("getshortpath: res = 0"); + free (shortpath); + set_werrno; + return (char *) longpath; + } +// printf ("shortpath: %s\n", shortpath); + return shortpath; +} + +char *relocaten (const char *ModuleName, const char *path) +{ + char *relative_path, *relocated_path, *relocated_short_path; + int relative_path_len; + + if (!curr_prefix) + set_current_prefix (ModuleName); +// printf ("path: %s\n", path); +// printf ("orig_prefix: %s\n", orig_prefix); +// printf ("curr_prefix: %s\n", curr_prefix); +// if (strncmp (orig_prefix, path, orig_prefix_len)) +// if (strcmp (orig_prefix, path)) +// return (char *) path; + relative_path = (char *) path + orig_prefix_len; +// printf ("relative_path: %s\n", relative_path); + relative_path_len = strlen (relative_path); + relocated_path = malloc (curr_prefix_len + relative_path_len + 1); + strcpy (relocated_path, curr_prefix); + strcat (relocated_path, relative_path); +// printf ("relocated_path: %s\n", relocated_path); + relocated_short_path = getshortpath (relocated_path); +// printf ("relocated_short_path: %s\n", relocated_short_path); + if (relocated_short_path) { + if (relocated_short_path != relocated_path) + free (relocated_path); + return relocated_short_path; + } else + return relocated_path; +} + +#else // __WIN32__ +char *relocaten (const char *ModuleName, const char *path) +{ + // dummy function for Unix/Linux + return (char *)path; +} +#endif + +char *relocaten2 (const char *ModuleName, const char *installdir, const char *path) +{ + set_orig_prefix (installdir); + return relocaten (ModuleName, path); +} + +char *relocatenx (const char *ModuleName, const char *installdir, const char *path) +{ + char *p; + + set_orig_prefix (installdir); + if (access (path, R_OK)) + p = relocaten (ModuleName, path); + else + p = (char *) path; +// printf ("relocatenx: %s\n", p); + return p; +} + +char *relocate2 (const char *installdir, const char *path) +{ + return relocaten2 (NULL, installdir, path); +} + +char *relocatex (const char *installdir, const char *path) +{ + return relocatenx (NULL, installdir, path); +} + +char *relocatepx (const char *cprefix, const char *installdir, const char *path) +{ + if (curr_prefix) + free (curr_prefix); + curr_prefix = strdup (cprefix); + return relocatex (installdir, path); +} + +static char *get_orig_prefix (void) +{ + return orig_prefix; +} + +static char *get_curr_prefix (void) +{ + return curr_prefix; +} + +static char *set_curr_prefix (const char *ModuleName) +{ + if (curr_prefix) + free (curr_prefix); + set_current_prefix (ModuleName); + return curr_prefix; +} diff -udrN gettext-runtime0/intl/relocatex.h gettext-runtime/intl/relocatex.h --- gettext-runtime0/intl/relocatex.h 1970-01-01 03:00:00.000000000 +0300 +++ gettext-runtime/intl/relocatex.h 2020-12-22 12:51:51.885861353 +0200 @@ -0,0 +1,41 @@ +/* + Copyright (C) 2006 Free Software Foundation, Inc. + This file is part of the GnuWin C Library. + + The GnuWin C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GnuWin C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GnuWin32 C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef __RELOCATE_H__ +#define __RELOCATE_H__ 1 + +/* #include */ + +#ifdef __cplusplus +extern "C" { +#endif + +char *relocaten (const char *ModuleName, const char *path); +char *relocaten2 (const char *ModuleName, const char *installdir, const char *path); +char *relocatenx (const char *ModuleName, const char *installdir, const char *path); +char *relocate2 (const char *installdir, const char *path); +char *relocatex (const char *installdir, const char *path); + +#ifdef __cplusplus +} +#endif + +//#endif /* __GW32__ */ + +#endif /* __RELOCATE_H__ */ diff -udrN gettext-runtime0/libasprintf/vasnprintf.c gettext-runtime/libasprintf/vasnprintf.c --- gettext-runtime0/libasprintf/vasnprintf.c 2016-03-20 09:37:53.000000000 +0200 +++ gettext-runtime/libasprintf/vasnprintf.c 2020-12-22 12:51:51.916861353 +0200 @@ -67,7 +67,14 @@ #endif #include /* localeconv() */ +#if defined(__MINGW64_VERSION_MAJOR) && defined(__USE_MINGW_ANSI_STDIO) +# define REMOVED__USE_MINGW_ANSI_STDIO +# undef __USE_MINGW_ANSI_STDIO +#endif #include /* snprintf(), sprintf() */ +#if defined(__MINGW64_VERSION_MAJOR) && defined(REMOVED__USE_MINGW_ANSI_STDIO) +# define __USE_MINGW_ANSI_STDIO +#endif #include /* abort(), malloc(), realloc(), free() */ #include /* memcpy(), strlen() */ #include /* errno */ diff -udrN gettext-runtime0/libasprintf/vasnprintf.h gettext-runtime/libasprintf/vasnprintf.h --- gettext-runtime0/libasprintf/vasnprintf.h 2016-03-20 09:37:53.000000000 +0200 +++ gettext-runtime/libasprintf/vasnprintf.h 2020-12-22 12:51:51.915861353 +0200 @@ -40,6 +40,8 @@ extern "C" { #endif +#if !defined(__USE_MINGW_ANSI_STDIO) && defined(__MINGW64_VERSION_MAJOR) + /* Write formatted output to a string dynamically allocated with malloc(). You can pass a preallocated buffer for the result in RESULTBUF and its size in *LENGTHP; otherwise you pass RESULTBUF = NULL. @@ -64,11 +66,14 @@ free (output); } */ + extern char * asnprintf (char *resultbuf, size_t *lengthp, const char *format, ...) __attribute__ ((__format__ (__printf__, 3, 4))); extern char * vasnprintf (char *resultbuf, size_t *lengthp, const char *format, va_list args) __attribute__ ((__format__ (__printf__, 3, 0))); +#endif /* !defined(__USE_MINGW_ANSI_STDIO) && defined(__MINGW64_VERSION_MAJOR) */ + #ifdef __cplusplus } #endif diff -udrN gettext-runtime0/libasprintf/vasprintf.h gettext-runtime/libasprintf/vasprintf.h --- gettext-runtime0/libasprintf/vasprintf.h 2016-03-20 09:37:53.000000000 +0200 +++ gettext-runtime/libasprintf/vasprintf.h 2020-12-22 12:51:51.915861353 +0200 @@ -37,6 +37,8 @@ extern "C" { #endif +#if !defined(__USE_MINGW_ANSI_STDIO) && defined(__MINGW64_VERSION_MAJOR) + /* Write formatted output to a string dynamically allocated with malloc(). If the memory allocation succeeds, store the address of the string in *RESULT and return the number of resulting bytes, excluding the trailing @@ -46,6 +48,8 @@ extern int vasprintf (char **result, const char *format, va_list args) __attribute__ ((__format__ (__printf__, 2, 0))); +#endif /* !defined(__USE_MINGW_ANSI_STDIO) && defined(__MINGW64_VERSION_MAJOR) */ + #ifdef __cplusplus } #endif diff -udrN gettext-runtime0/src/envsubst.c gettext-runtime/src/envsubst.c --- gettext-runtime0/src/envsubst.c 2016-03-20 09:37:53.000000000 +0200 +++ gettext-runtime/src/envsubst.c 2020-12-22 12:51:51.942861352 +0200 @@ -27,6 +27,11 @@ #include #include +#ifdef _WIN32 +# include /* for _setmode() */ +# include +#endif + #include "closeout.h" #include "error.h" #include "progname.h" @@ -281,8 +286,21 @@ static void print_variable (const char *var_ptr, size_t var_len) { + int oldmode; + fwrite (var_ptr, var_len, 1, stdout); +#if defined(_WIN32) + /* Change to binary mode */ + oldmode = _setmode( _fileno( stdout ), _O_BINARY ); +#endif putchar ('\n'); +#if defined(_WIN32) + fflush(stdout); /* Must flush before changing mode back */ + if ( oldmode != -1 ) + { /* Return to prior mode */ + _setmode( _fileno( stdout ), oldmode ); + } +#endif } /* Print the variables contained in STRING to stdout, each one followed by a mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/gtk/gtk22429_1wj.patch000066400000000000000000000125421471325446300237360ustar00rootroot00000000000000diff -udpr gtk+-2.24.29_/docs/faq/Makefile.am gtk+-2.24.29/docs/faq/Makefile.am --- gtk+-2.24.29_/docs/faq/Makefile.am 2014-09-29 23:02:16.000000000 +0300 +++ gtk+-2.24.29/docs/faq/Makefile.am 2020-12-27 16:40:00.428859219 +0200 @@ -7,7 +7,7 @@ if HAVE_DOCBOOK html: if test -w $(srcdir); then \ (cd $(srcdir); \ - db2html gtk-faq.sgml; \ + db2html -o gtk-faq gtk-faq.sgml; \ test -d html && rm -r html; \ mv gtk-faq html); \ fi diff -udpr gtk+-2.24.29_/docs/faq/Makefile.in gtk+-2.24.29/docs/faq/Makefile.in --- gtk+-2.24.29_/docs/faq/Makefile.in 2015-12-10 22:35:26.000000000 +0200 +++ gtk+-2.24.29/docs/faq/Makefile.in 2020-12-27 16:40:00.428859219 +0200 @@ -645,7 +645,8 @@ check-local: test-cwd @HAVE_DOCBOOK_TRUE@ (cd $(srcdir); \ @HAVE_DOCBOOK_TRUE@ db2html gtk-faq.sgml; \ @HAVE_DOCBOOK_TRUE@ test -d html && rm -r html; \ -@HAVE_DOCBOOK_TRUE@ mv gtk-faq html); \ +@HAVE_DOCBOOK_TRUE@ mkdir html; \ +@HAVE_DOCBOOK_TRUE@ mv *.html html); \ @HAVE_DOCBOOK_TRUE@ fi @HAVE_DOCBOOK_TRUE@pdf: diff -udpr gtk+-2.24.29_/docs/tutorial/Makefile.am gtk+-2.24.29/docs/tutorial/Makefile.am --- gtk+-2.24.29_/docs/tutorial/Makefile.am 2014-09-29 23:02:16.000000000 +0300 +++ gtk+-2.24.29/docs/tutorial/Makefile.am 2020-12-27 16:40:00.428859219 +0200 @@ -40,7 +40,7 @@ if HAVE_DOCBOOK html: gtk-tut.sgml if test -w $(srcdir); then \ (cd $(srcdir); \ - db2html gtk-tut.sgml; \ + db2html -o gtk-tut gtk-tut.sgml; \ test -d html && rm -r html; \ mv gtk-tut html; \ mkdir html/images; \ diff -udpr gtk+-2.24.29_/docs/tutorial/Makefile.in gtk+-2.24.29/docs/tutorial/Makefile.in --- gtk+-2.24.29_/docs/tutorial/Makefile.in 2015-12-10 22:35:26.000000000 +0200 +++ gtk+-2.24.29/docs/tutorial/Makefile.in 2020-12-27 16:40:00.428859219 +0200 @@ -658,7 +658,8 @@ check-local: test-cwd @HAVE_DOCBOOK_TRUE@ (cd $(srcdir); \ @HAVE_DOCBOOK_TRUE@ db2html gtk-tut.sgml; \ @HAVE_DOCBOOK_TRUE@ test -d html && rm -r html; \ -@HAVE_DOCBOOK_TRUE@ mv gtk-tut html; \ +@HAVE_DOCBOOK_TRUE@ mkdir html; \ +@HAVE_DOCBOOK_TRUE@ mv *.html html; \ @HAVE_DOCBOOK_TRUE@ mkdir html/images; \ @HAVE_DOCBOOK_TRUE@ cp images/*.png html/images); \ @HAVE_DOCBOOK_TRUE@ fi diff -udpr gtk+-2.24.29_/gdk/win32/gdkpixmap-win32.c gtk+-2.24.29/gdk/win32/gdkpixmap-win32.c --- gtk+-2.24.29_/gdk/win32/gdkpixmap-win32.c 2014-09-29 23:02:16.000000000 +0300 +++ gtk+-2.24.29/gdk/win32/gdkpixmap-win32.c 2020-12-27 16:30:29.275868082 +0200 @@ -37,6 +37,55 @@ #include "gdkprivate-win32.h" #include +static GHashTable *handle_ht = NULL; + +static guint +gdi_handle_hash (HANDLE *handle) +{ + return (guint) *handle; +} + +static gint +gdi_handle_equal (HANDLE *a, + HANDLE *b) +{ + return (*a == *b); +} + +static void +gdi_handle_table_insert (HANDLE *handle, + gpointer data) +{ + g_return_if_fail (handle != NULL); + + if (!handle_ht) + handle_ht = g_hash_table_new ((GHashFunc) gdi_handle_hash, + (GEqualFunc) gdi_handle_equal); + + g_hash_table_insert (handle_ht, handle, data); +} + +static void +gdi_handle_table_remove (HANDLE handle) +{ + if (!handle_ht) + handle_ht = g_hash_table_new ((GHashFunc) gdi_handle_hash, + (GEqualFunc) gdi_handle_equal); + + g_hash_table_remove (handle_ht, &handle); +} + +static gpointer +gdi_handle_table_lookup (GdkNativeWindow handle) +{ + gpointer data = NULL; + + if (handle_ht) + data = g_hash_table_lookup (handle_ht, &handle); + + return data; +} + static void gdk_pixmap_impl_win32_get_size (GdkDrawable *drawable, gint *width, gint *height); @@ -135,7 +184,7 @@ gdk_pixmap_impl_win32_finalize (GObject _gdk_win32_drawable_finish (GDK_DRAWABLE (object)); - gdk_win32_handle_table_remove (GDK_PIXMAP_HBITMAP (wrapper)); + gdi_handle_table_remove (GDK_PIXMAP_HBITMAP (wrapper)); G_OBJECT_CLASS (parent_class)->finalize (object); } @@ -339,7 +388,7 @@ _gdk_pixmap_new (GdkDrawable *drawable, drawable_impl->handle = hbitmap; pixmap_impl->bits = bits; - gdk_win32_handle_table_insert (&GDK_PIXMAP_HBITMAP (pixmap), pixmap); + gdi_handle_table_insert (&GDK_PIXMAP_HBITMAP (pixmap), pixmap); return pixmap; } @@ -523,7 +572,7 @@ gdk_pixmap_foreign_new (GdkNativeWindow pix_impl->height = size.cy; pix_impl->bits = NULL; - gdk_win32_handle_table_insert (&GDK_PIXMAP_HBITMAP (pixmap), pixmap); + gdi_handle_table_insert (&GDK_PIXMAP_HBITMAP (pixmap), pixmap); return pixmap; } @@ -531,7 +580,7 @@ gdk_pixmap_foreign_new (GdkNativeWindow GdkPixmap* gdk_pixmap_lookup (GdkNativeWindow anid) { - return (GdkPixmap*) gdk_win32_handle_table_lookup (anid); + return (GdkPixmap*) gdi_handle_table_lookup (anid); } GdkPixmap* Только в gtk+-2.24.29/gdk/win32: w32pixnap.patch diff -udpr gtk+-2.24.29_/gtk/gtkfilesel.c gtk+-2.24.29/gtk/gtkfilesel.c --- gtk+-2.24.29_/gtk/gtkfilesel.c 2014-09-29 23:02:17.000000000 +0300 +++ gtk+-2.24.29/gtk/gtkfilesel.c 2020-12-27 14:40:19.926970642 +0200 @@ -1974,7 +1974,8 @@ win32_gtk_add_drives_to_dir_list (GtkLis while (*textPtr != '\0') { /* Ignore floppies (?) */ - if (GetDriveType (textPtr) != DRIVE_REMOVABLE) +// We need to see flash drives too - WJ +// if (GetDriveType (textPtr) != DRIVE_REMOVABLE) { /* Build the actual displayable string */ g_snprintf (formatBuffer, sizeof (formatBuffer), "%c:\\", toupper (textPtr[0])); mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/gtk/gtk267_7wj.patch000066400000000000000000002475101471325446300236050ustar00rootroot00000000000000diff -udpr gtk+-2.6.7_/demos/gtk-demo/geninclude.pl.in gtk+-2.6.7/demos/gtk-demo/geninclude.pl.in --- gtk+-2.6.7_/demos/gtk-demo/geninclude.pl.in 2003-11-09 00:08:04.000000000 +0200 +++ gtk+-2.6.7/demos/gtk-demo/geninclude.pl.in 2020-12-27 16:22:52.529875169 +0200 @@ -40,7 +40,7 @@ foreach $href (@demos) { my $do_next = 0; # parent detected - if (defined @parents) { + if (@parents) { foreach $foo (@parents) { if ($foo eq $parent_name) { $do_next = 1; @@ -54,7 +54,7 @@ foreach $href (@demos) { push @parents, $parent_name; - $tmp = (defined @child_arrays)?($#child_arrays + 1):0; + $tmp = @child_arrays?($#child_arrays + 1):0; push @child_arrays, "child$tmp"; push @demos, {"title" => $parent_name, "file" => "NULL", @@ -62,7 +62,7 @@ foreach $href (@demos) { } } -if (defined @parents) { +if (@parents) { $i = 0; for ($i = 0; $i <= $#parents; $i++) { $first = 1; @@ -105,7 +105,7 @@ if (defined @parents) { } @demos_old; # sort the child arrays -if (defined @child_arrays) { +if (@child_arrays) { for ($i = 0; $i <= $#child_arrays; $i++) { @foo_old = @{$child_arrays[$i]}; @@ -133,7 +133,7 @@ foreach $href (@demos) { print ", \n"; } - if (defined @parents) { + if (@parents) { for ($i = 0; $i <= $#parents; $i++) { if ($parents[$i] eq $href->{title}) { diff -udpr gtk+-2.6.7_/gdk/win32/gdkcursor-win32.c gtk+-2.6.7/gdk/win32/gdkcursor-win32.c --- gtk+-2.6.7_/gdk/win32/gdkcursor-win32.c 2004-03-06 05:37:07.000000000 +0200 +++ gtk+-2.6.7/gdk/win32/gdkcursor-win32.c 2020-12-27 16:22:52.529875169 +0200 @@ -41,6 +41,12 @@ _gdk_win32_data_to_wcursor (GdkCursorTyp if (i >= G_N_ELEMENTS (cursors) || !cursors[i].name) return NULL; + /* use real win32 cursor if possible */ + if (cursors[i].builtin) + { + return LoadCursor (NULL, cursors[i].builtin); + } + w = GetSystemMetrics (SM_CXCURSOR); h = GetSystemMetrics (SM_CYCURSOR); diff -udpr gtk+-2.6.7_/gdk/win32/gdkdnd-win32.c gtk+-2.6.7/gdk/win32/gdkdnd-win32.c --- gtk+-2.6.7_/gdk/win32/gdkdnd-win32.c 2004-12-19 23:00:58.000000000 +0200 +++ gtk+-2.6.7/gdk/win32/gdkdnd-win32.c 2020-12-27 16:22:52.529875169 +0200 @@ -978,6 +978,8 @@ gdk_dropfiles_filter (GdkXEvent *xev, /* WM_DROPFILES drops are always file names */ context->targets = g_list_append (NULL, GUINT_TO_POINTER (_text_uri_list)); + context->actions = GDK_ACTION_COPY; + context->suggested_action = GDK_ACTION_COPY; current_dest_drag = context; event->dnd.type = GDK_DROP_START; @@ -987,8 +989,8 @@ gdk_dropfiles_filter (GdkXEvent *xev, DragQueryPoint (hdrop, &pt); ClientToScreen (msg->hwnd, &pt); - event->dnd.x_root = pt.x; - event->dnd.y_root = pt.y; + event->dnd.x_root = pt.x + _gdk_offset_x; + event->dnd.y_root = pt.y + _gdk_offset_y; event->dnd.time = _gdk_win32_get_next_tick (msg->time); nfiles = DragQueryFile (hdrop, 0xFFFFFFFF, NULL, 0); diff -udpr gtk+-2.6.7_/gdk/win32/gdkdrawable-win32.c gtk+-2.6.7/gdk/win32/gdkdrawable-win32.c --- gtk+-2.6.7_/gdk/win32/gdkdrawable-win32.c 2005-04-03 23:36:39.000000000 +0300 +++ gtk+-2.6.7/gdk/win32/gdkdrawable-win32.c 2020-12-27 16:22:52.530875169 +0200 @@ -1856,6 +1856,16 @@ _gdk_win32_blit (gboolean u xdest, ydest, use_fg_bg)); + /* If blitting from the root window, take the multi-monitor offset + * into account. + */ + if (src == ((GdkWindowObject *)_gdk_parent_root)->impl) + { + GDK_NOTE (MISC, g_print ("... offsetting src coords\n")); + xsrc -= _gdk_offset_x; + ysrc -= _gdk_offset_y; + } + draw_impl = (GdkDrawableImplWin32 *) drawable; if (GDK_IS_DRAWABLE_IMPL_WIN32 (src)) diff -udpr gtk+-2.6.7_/gdk/win32/gdkevents-win32.c gtk+-2.6.7/gdk/win32/gdkevents-win32.c --- gtk+-2.6.7_/gdk/win32/gdkevents-win32.c 2005-04-04 02:40:42.000000000 +0300 +++ gtk+-2.6.7/gdk/win32/gdkevents-win32.c 2020-12-27 16:22:52.530875169 +0200 @@ -162,7 +162,8 @@ static HKL latin_locale = NULL; #endif static gboolean in_ime_composition = FALSE; -static UINT resize_timer; +static UINT modal_timer; +static UINT sync_timer = 0; static int debug_indent = 0; @@ -1841,140 +1842,7 @@ handle_configure_event (MSG *msg, } } -static void -erase_background (GdkWindow *window, - HDC hdc) -{ - HDC bgdc = NULL; - HBRUSH hbr = NULL; - HPALETTE holdpal = NULL; - RECT rect; - COLORREF bg; - GdkColormap *colormap; - GdkColormapPrivateWin32 *colormap_private; - int x, y; - int x_offset, y_offset; - - if (((GdkWindowObject *) window)->input_only || - ((GdkWindowObject *) window)->bg_pixmap == GDK_NO_BG || - GDK_WINDOW_IMPL_WIN32 (((GdkWindowObject *) window)->impl)->position_info.no_bg) - { - return; - } - - colormap = gdk_drawable_get_colormap (window); - - if (colormap && - (colormap->visual->type == GDK_VISUAL_PSEUDO_COLOR || - colormap->visual->type == GDK_VISUAL_STATIC_COLOR)) - { - int k; - - colormap_private = GDK_WIN32_COLORMAP_DATA (colormap); - - if (!(holdpal = SelectPalette (hdc, colormap_private->hpal, FALSE))) - WIN32_GDI_FAILED ("SelectPalette"); - else if ((k = RealizePalette (hdc)) == GDI_ERROR) - WIN32_GDI_FAILED ("RealizePalette"); - else if (k > 0) - GDK_NOTE (COLORMAP, g_print ("erase_background: realized %p: %d colors\n", - colormap_private->hpal, k)); - } - - x_offset = y_offset = 0; - while (window && ((GdkWindowObject *) window)->bg_pixmap == GDK_PARENT_RELATIVE_BG) - { - /* If this window should have the same background as the parent, - * fetch the parent. (And if the same goes for the parent, fetch - * the grandparent, etc.) - */ - x_offset += ((GdkWindowObject *) window)->x; - y_offset += ((GdkWindowObject *) window)->y; - window = GDK_WINDOW (((GdkWindowObject *) window)->parent); - } - - if (GDK_WINDOW_IMPL_WIN32 (((GdkWindowObject *) window)->impl)->position_info.no_bg) - { - /* Improves scolling effect, e.g. main buttons of testgtk */ - return; - } - - GetClipBox (hdc, &rect); - - if (((GdkWindowObject *) window)->bg_pixmap == NULL) - { - bg = _gdk_win32_colormap_color (GDK_DRAWABLE_IMPL_WIN32 (((GdkWindowObject *) window)->impl)->colormap, - ((GdkWindowObject *) window)->bg_color.pixel); - - if (!(hbr = CreateSolidBrush (bg))) - WIN32_GDI_FAILED ("CreateSolidBrush"); - else if (!FillRect (hdc, &rect, hbr)) - WIN32_GDI_FAILED ("FillRect"); - if (hbr != NULL) - DeleteObject (hbr); - } - else if (((GdkWindowObject *) window)->bg_pixmap != GDK_NO_BG) - { - GdkPixmap *pixmap = ((GdkWindowObject *) window)->bg_pixmap; - GdkPixmapImplWin32 *pixmap_impl = GDK_PIXMAP_IMPL_WIN32 (GDK_PIXMAP_OBJECT (pixmap)->impl); - - if (x_offset == 0 && y_offset == 0 && - pixmap_impl->width <= 8 && pixmap_impl->height <= 8) - { - if (!(hbr = CreatePatternBrush (GDK_PIXMAP_HBITMAP (pixmap)))) - WIN32_GDI_FAILED ("CreatePatternBrush"); - else if (!FillRect (hdc, &rect, hbr)) - WIN32_GDI_FAILED ("FillRect"); - if (hbr != NULL) - DeleteObject (hbr); - } - else - { - HGDIOBJ oldbitmap; - - if (!(bgdc = CreateCompatibleDC (hdc))) - { - WIN32_GDI_FAILED ("CreateCompatibleDC"); - return; - } - if (!(oldbitmap = SelectObject (bgdc, GDK_PIXMAP_HBITMAP (pixmap)))) - { - WIN32_GDI_FAILED ("SelectObject"); - DeleteDC (bgdc); - return; - } - x = -x_offset; - while (x < rect.right) - { - if (x + pixmap_impl->width >= rect.left) - { - y = -y_offset; - while (y < rect.bottom) - { - if (y + pixmap_impl->height >= rect.top) - { - if (!BitBlt (hdc, x, y, - pixmap_impl->width, pixmap_impl->height, - bgdc, 0, 0, SRCCOPY)) - { - WIN32_GDI_FAILED ("BitBlt"); - SelectObject (bgdc, oldbitmap); - DeleteDC (bgdc); - return; - } - } - y += pixmap_impl->height; - } - } - x += pixmap_impl->width; - } - SelectObject (bgdc, oldbitmap); - DeleteDC (bgdc); - } - } -} - -static GdkRegion * +GdkRegion * _gdk_win32_hrgn_to_region (HRGN hrgn) { RGNDATA *rgndata; @@ -2043,6 +1911,7 @@ handle_wm_paint (MSG *msg, if (GetUpdateRgn (msg->hwnd, hrgn, FALSE) == ERROR) { WIN32_GDI_FAILED ("GetUpdateRgn"); + DeleteObject (hrgn); return; } @@ -2115,6 +1984,7 @@ handle_wm_paint (MSG *msg, } } + DeleteObject (hrgn); return; } @@ -2138,15 +2008,32 @@ handle_stuff_while_moving_or_resizing (v } static VOID CALLBACK -resize_timer_proc (HWND hwnd, - UINT msg, - UINT id, - DWORD time) +modal_timer_proc (HWND hwnd, + UINT msg, + UINT id, + DWORD time) { if (_sizemove_in_progress) handle_stuff_while_moving_or_resizing (); } +static VOID CALLBACK +sync_timer_proc (HWND hwnd, + UINT msg, + UINT id, + DWORD time) +{ + MSG message; + if (PeekMessageW (&message, hwnd, WM_PAINT, WM_PAINT, PM_REMOVE)) + { + return; + } + + RedrawWindow (hwnd, NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW|RDW_ALLCHILDREN); + + KillTimer (hwnd, sync_timer); +} + static void handle_display_change (void) { @@ -2923,11 +2810,17 @@ gdk_event_translate (GdkDisplay *display if (GDK_WINDOW_DESTROYED (window)) break; - erase_background (window, (HDC) msg->wParam); return_val = TRUE; *ret_valp = 1; break; + case WM_SYNCPAINT: + + sync_timer = SetTimer (GDK_WINDOW_HWND (window), + 1, + 200, sync_timer_proc); + break; + case WM_PAINT: handle_wm_paint (msg, window, FALSE, NULL); break; @@ -3042,15 +2935,31 @@ gdk_event_translate (GdkDisplay *display case WM_ENTERSIZEMOVE: _sizemove_in_progress = TRUE; - resize_timer = SetTimer (NULL, 0, 20, resize_timer_proc); + modal_timer = SetTimer (NULL, 0, 20, modal_timer_proc); break; case WM_EXITSIZEMOVE: _sizemove_in_progress = FALSE; - KillTimer (NULL, resize_timer); + KillTimer (NULL, modal_timer); + break; + + case WM_ENTERMENULOOP: + _sizemove_in_progress = TRUE; + modal_timer = SetTimer (NULL, 0, 20, modal_timer_proc); + break; + + case WM_EXITMENULOOP: + _sizemove_in_progress = FALSE; + KillTimer (NULL, modal_timer); break; case WM_WINDOWPOSCHANGED : + /* If position and size haven't changed, don't do anything */ + if (_sizemove_in_progress && + (((WINDOWPOS *)msg->lParam)->flags & SWP_NOMOVE) && + (((WINDOWPOS *)msg->lParam)->flags & SWP_NOSIZE)) + break; + /* Once we've entered the moving or sizing modal loop, we won't * return to the main loop until we're done sizing or moving. */ @@ -3058,55 +2967,14 @@ gdk_event_translate (GdkDisplay *display GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && !GDK_WINDOW_DESTROYED (window)) { - RECT client_rect; - POINT point; - - GetClientRect (msg->hwnd, &client_rect); - point.x = client_rect.left; /* always 0 */ - point.y = client_rect.top; - /* top level windows need screen coords */ - if (gdk_window_get_parent (window) == _gdk_parent_root) - { - ClientToScreen (msg->hwnd, &point); - point.x += _gdk_offset_x; - point.y += _gdk_offset_y; - } - - GDK_WINDOW_IMPL_WIN32 (((GdkWindowObject *) window)->impl)->width = client_rect.right - client_rect.left; - GDK_WINDOW_IMPL_WIN32 (((GdkWindowObject *) window)->impl)->height = client_rect.bottom - client_rect.top; - - ((GdkWindowObject *) window)->x = point.x; - ((GdkWindowObject *) window)->y = point.y; - if (((GdkWindowObject *) window)->event_mask & GDK_STRUCTURE_MASK) { - GdkEvent *event = gdk_event_new (GDK_CONFIGURE); - - event->configure.window = window; - - event->configure.width = client_rect.right - client_rect.left; - event->configure.height = client_rect.bottom - client_rect.top; - - event->configure.x = point.x; - event->configure.y = point.y; - if (((GdkWindowObject *) window)->resize_count > 1) ((GdkWindowObject *) window)->resize_count -= 1; -#if 0 /* I don't like calling _gdk_event_func() from here, isn't there - * a risk of getting events processed in the wrong order, like - * Owen says in the discussion of bug #99540? - */ - fixup_event (event); - if (_gdk_event_func) - (*_gdk_event_func) (event, _gdk_event_data); - gdk_event_free (event); -#else /* Calling append_event() is slower, but guarantees that events won't - * get reordered, I think. - */ - append_event (display, event); -#endif - + handle_configure_event (msg, window); + g_main_context_iteration (NULL, FALSE); + /* Dispatch main loop - to realize resizes... */ handle_stuff_while_moving_or_resizing (); @@ -3119,6 +2987,7 @@ gdk_event_translate (GdkDisplay *display case WM_SIZING: GetWindowRect (GDK_WINDOW_HWND (window), &rect); + drag = (RECT *) msg->lParam; GDK_NOTE (EVENTS, g_print (" %s curr:%s drag:%s", (msg->wParam == WMSZ_BOTTOM ? "BOTTOM" : (msg->wParam == WMSZ_BOTTOMLEFT ? "BOTTOMLEFT" : @@ -3131,13 +3000,13 @@ gdk_event_translate (GdkDisplay *display (msg->wParam == WMSZ_BOTTOMRIGHT ? "BOTTOMRIGHT" : "???")))))))), _gdk_win32_rect_to_string (&rect), - _gdk_win32_rect_to_string ((RECT *) msg->lParam))); + _gdk_win32_rect_to_string (drag))); impl = GDK_WINDOW_IMPL_WIN32 (((GdkWindowObject *) window)->impl); - drag = (RECT *) msg->lParam; orig_drag = *drag; if (impl->hint_flags & GDK_HINT_RESIZE_INC) { + GDK_NOTE (EVENTS, g_print (" (RESIZE_INC)")); if (impl->hint_flags & GDK_HINT_BASE_SIZE) { /* Resize in increments relative to the base size */ @@ -3166,7 +3035,6 @@ gdk_event_translate (GdkDisplay *display if (drag->bottom == rect.bottom) break; adjust_drag (&drag->bottom, rect.bottom, impl->hints.height_inc); - break; case WMSZ_BOTTOMLEFT: @@ -3221,7 +3089,7 @@ gdk_event_translate (GdkDisplay *display { *ret_valp = TRUE; return_val = TRUE; - GDK_NOTE (EVENTS, g_print (" (handled RESIZE_INC: drag:%s)", + GDK_NOTE (EVENTS, g_print (" (handled RESIZE_INC: %s)", _gdk_win32_rect_to_string (drag))); } } @@ -3230,18 +3098,105 @@ gdk_event_translate (GdkDisplay *display if (impl->hint_flags & GDK_HINT_ASPECT) { - gdouble drag_aspect = (gdouble) (drag->right - drag->left) / (drag->bottom - drag->top); - - GDK_NOTE (EVENTS, g_print (" (aspect:%g)", drag_aspect)); - if (drag_aspect < impl->hints.min_aspect || - drag_aspect > impl->hints.max_aspect) + RECT decorated_rect; + RECT undecorated_drag; + int decoration_width, decoration_height; + gdouble drag_aspect; + int drag_width, drag_height, new_width, new_height; + + GetClientRect (GDK_WINDOW_HWND (window), &rect); + decorated_rect = rect; + _gdk_win32_adjust_client_rect (window, &decorated_rect); + + /* Set undecorated_drag to the client area being dragged + * out, in screen coordinates. + */ + undecorated_drag = *drag; + undecorated_drag.left -= decorated_rect.left - rect.left; + undecorated_drag.right -= decorated_rect.right - rect.right; + undecorated_drag.top -= decorated_rect.top - rect.top; + undecorated_drag.bottom -= decorated_rect.bottom - rect.bottom; + + decoration_width = (decorated_rect.right - decorated_rect.left) - (rect.right - rect.left); + decoration_height = (decorated_rect.bottom - decorated_rect.top) - (rect.bottom - rect.top); + + drag_width = undecorated_drag.right - undecorated_drag.left; + drag_height = undecorated_drag.bottom - undecorated_drag.top; + + drag_aspect = (gdouble) drag_width / drag_height; + + GDK_NOTE (EVENTS, g_print (" (ASPECT:%g--%g curr: %g)", + impl->hints.min_aspect, impl->hints.max_aspect, drag_aspect)); + + if (drag_aspect < impl->hints.min_aspect) { - *drag = rect; - *ret_valp = TRUE; - return_val = TRUE; - GDK_NOTE (EVENTS, g_print (" (handled ASPECT: drag:%s)", - _gdk_win32_rect_to_string (drag))); + /* Aspect is getting too narrow */ + switch (msg->wParam) + { + case WMSZ_BOTTOM: + case WMSZ_TOP: + /* User drags top or bottom edge outward. Keep height, increase width. */ + new_width = impl->hints.min_aspect * drag_height; + drag->left -= (new_width - drag_width) / 2; + drag->right = drag->left + new_width + decoration_width; + break; + case WMSZ_BOTTOMLEFT: + case WMSZ_BOTTOMRIGHT: + /* User drags bottom-left or bottom-right corner down. Adjust height. */ + new_height = drag_width / impl->hints.min_aspect; + drag->bottom = drag->top + new_height + decoration_height; + break; + case WMSZ_LEFT: + case WMSZ_RIGHT: + /* User drags left or right edge inward. Decrease height */ + new_height = drag_width / impl->hints.min_aspect; + drag->top += (drag_height - new_height) / 2; + drag->bottom = drag->top + new_height + decoration_height; + break; + case WMSZ_TOPLEFT: + case WMSZ_TOPRIGHT: + /* User drags top-left or top-right corner up. Adjust height. */ + new_height = drag_width / impl->hints.min_aspect; + drag->top = drag->bottom - new_height - decoration_height; + } + } + else if (drag_aspect > impl->hints.max_aspect) + { + /* Aspect is getting too wide */ + switch (msg->wParam) + { + case WMSZ_BOTTOM: + case WMSZ_TOP: + /* User drags top or bottom edge inward. Decrease width. */ + new_width = impl->hints.max_aspect * drag_height; + drag->left += (drag_width - new_width) / 2; + drag->right = drag->left + new_width + decoration_width; + break; + case WMSZ_BOTTOMLEFT: + case WMSZ_TOPLEFT: + /* User drags bottom-left or top-left corner left. Adjust width. */ + new_width = impl->hints.max_aspect * drag_height; + drag->left = drag->right - new_width - decoration_width; + break; + case WMSZ_BOTTOMRIGHT: + case WMSZ_TOPRIGHT: + /* User drags bottom-right or top-right corner right. Adjust width. */ + new_width = impl->hints.max_aspect * drag_height; + drag->right = drag->left + new_width + decoration_width; + break; + case WMSZ_LEFT: + case WMSZ_RIGHT: + /* User drags left or right edge outward. Increase height. */ + new_height = drag_width / impl->hints.max_aspect; + drag->top -= (new_height - drag_height) / 2; + drag->bottom = drag->top + new_height + decoration_height; + break; + } } + *ret_valp = TRUE; + return_val = TRUE; + GDK_NOTE (EVENTS, g_print (" (handled ASPECT: %s)", + _gdk_win32_rect_to_string (drag))); } break; diff -udpr gtk+-2.6.7_/gdk/win32/gdkgeometry-win32.c gtk+-2.6.7/gdk/win32/gdkgeometry-win32.c --- gtk+-2.6.7_/gdk/win32/gdkgeometry-win32.c 2005-03-13 00:07:34.000000000 +0200 +++ gtk+-2.6.7/gdk/win32/gdkgeometry-win32.c 2020-12-27 16:22:52.531875169 +0200 @@ -108,9 +108,9 @@ gdk_window_scroll (GdkWindow *window, GdkRegion *invalidate_region; GdkWindowImplWin32 *impl; GdkWindowObject *obj; - GdkRectangle dest_rect; GList *tmp_list; GdkWindowParentPos parent_pos; + HRGN native_invalidate_region; g_return_if_fail (GDK_IS_WINDOW (window)); @@ -130,22 +130,6 @@ gdk_window_scroll (GdkWindow *window, if (obj->update_area) gdk_region_offset (obj->update_area, dx, dy); - invalidate_region = gdk_region_rectangle (&impl->position_info.clip_rect); - - dest_rect = impl->position_info.clip_rect; - dest_rect.x += dx; - dest_rect.y += dy; - gdk_rectangle_intersect (&dest_rect, &impl->position_info.clip_rect, &dest_rect); - - if (dest_rect.width > 0 && dest_rect.height > 0) - { - GdkRegion *tmp_region; - - tmp_region = gdk_region_rectangle (&dest_rect); - gdk_region_subtract (invalidate_region, tmp_region); - gdk_region_destroy (tmp_region); - } - gdk_window_compute_parent_pos (impl, &parent_pos); parent_pos.x += obj->x; @@ -156,10 +140,13 @@ gdk_window_scroll (GdkWindow *window, gdk_window_tmp_unset_bg (window); - if (!ScrollWindowEx (GDK_WINDOW_HWND (window), - dx, dy, NULL, NULL, - NULL, NULL, SW_SCROLLCHILDREN)) - WIN32_API_FAILED ("ScrollWindowEx"); + native_invalidate_region = CreateRectRgn (0, 0, 0, 0); + if (native_invalidate_region == NULL) + WIN32_API_FAILED ("CreateRectRgn"); + + API_CALL (ScrollWindowEx, (GDK_WINDOW_HWND (window), + dx, dy, NULL, NULL, + native_invalidate_region, NULL, SW_SCROLLCHILDREN)); if (impl->position_info.no_bg) gdk_window_tmp_reset_bg (window); @@ -173,8 +160,15 @@ gdk_window_scroll (GdkWindow *window, tmp_list = tmp_list->next; } - gdk_window_invalidate_region (window, invalidate_region, TRUE); - gdk_region_destroy (invalidate_region); + if (native_invalidate_region != NULL) + { + invalidate_region = _gdk_win32_hrgn_to_region (native_invalidate_region); + gdk_region_offset (invalidate_region, impl->position_info.x_offset, + impl->position_info.y_offset); + gdk_window_invalidate_region (window, invalidate_region, TRUE); + gdk_region_destroy (invalidate_region); + GDI_CALL (DeleteObject, (native_invalidate_region)); + } } void diff -udpr gtk+-2.6.7_/gdk/win32/gdkinput-win32.c gtk+-2.6.7/gdk/win32/gdkinput-win32.c --- gtk+-2.6.7_/gdk/win32/gdkinput-win32.c 2005-02-25 02:09:52.000000000 +0200 +++ gtk+-2.6.7/gdk/win32/gdkinput-win32.c 2020-12-27 16:22:52.531875169 +0200 @@ -43,16 +43,10 @@ #define PACKETMODE (PK_BUTTONS) #include -/* If USE_SYSCONTEXT is on, we open the Wintab device (hmm, what if - * there are several?) as a system pointing device, i.e. it controls - * the normal Windows cursor. This seems much more natural. - */ -#define USE_SYSCONTEXT 1 /* The code for the other choice is not - * good at all. - */ - #define DEBUG_WINTAB 1 /* Verbose debug messages enabled */ +#define PROXIMITY_OUT_DELAY 200 /* In milliseconds, see set_ignore_core */ + #endif #if defined(HAVE_WINTAB) || defined(HAVE_WHATEVER_OTHER) @@ -63,10 +57,6 @@ /* Forward declarations */ -#if !USE_SYSCONTEXT -static GdkInputWindow *gdk_input_window_find_within (GdkWindow *window); -#endif - #ifdef HAVE_WINTAB static GdkDevicePrivate *gdk_input_find_dev_from_ctx (HCTX hctx, @@ -211,7 +201,6 @@ _gdk_input_wintab_init_check (void) GdkDevicePrivate *gdkdev; GdkWindowAttr wa; WORD specversion; - LOGCONTEXT defcontext; HCTX *hctx; UINT ndevices, ncursors, ncsrtypes, firstcsr, hardware; BOOL active; @@ -219,6 +208,7 @@ _gdk_input_wintab_init_check (void) int i, k; int devix, cursorix; char devname[100], csrname[100]; + BOOL defcontext_done; if (wintab_initialized) return; @@ -233,17 +223,6 @@ _gdk_input_wintab_init_check (void) WTInfo (WTI_INTERFACE, IFC_SPECVERSION, &specversion); GDK_NOTE (INPUT, g_print ("Wintab interface version %d.%d\n", HIBYTE (specversion), LOBYTE (specversion))); -#if USE_SYSCONTEXT - WTInfo (WTI_DEFSYSCTX, 0, &defcontext); -#if DEBUG_WINTAB - GDK_NOTE (INPUT, (g_print("DEFSYSCTX:\n"), print_lc(&defcontext))); -#endif -#else - WTInfo (WTI_DEFCONTEXT, 0, &defcontext); -#if DEBUG_WINTAB - GDK_NOTE (INPUT, (g_print("DEFCONTEXT:\n"), print_lc(&defcontext))); -#endif -#endif WTInfo (WTI_INTERFACE, IFC_NDEVICES, &ndevices); WTInfo (WTI_INTERFACE, IFC_NCURSORS, &ncursors); #if DEBUG_WINTAB @@ -268,6 +247,11 @@ _gdk_input_wintab_init_check (void) for (devix = 0; devix < ndevices; devix++) { LOGCONTEXT lc; + + /* We open the Wintab device (hmm, what if there are several?) as a + * system pointing device, i.e. it controls the normal Windows + * cursor. This seems much more natural. + */ WTInfo (WTI_DEVICES + devix, DVC_NAME, devname); @@ -279,65 +263,39 @@ _gdk_input_wintab_init_check (void) WTInfo (WTI_DEVICES + devix, DVC_NPRESSURE, &axis_npressure); WTInfo (WTI_DEVICES + devix, DVC_ORIENTATION, axis_or); + defcontext_done = FALSE; if (HIBYTE (specversion) > 1 || LOBYTE (specversion) >= 1) { - WTInfo (WTI_DDCTXS + devix, CTX_NAME, lc.lcName); - WTInfo (WTI_DDCTXS + devix, CTX_OPTIONS, &lc.lcOptions); - lc.lcOptions |= CXO_MESSAGES; -#if USE_SYSCONTEXT - lc.lcOptions |= CXO_SYSTEM; + /* Try to get device-specific default context */ + /* Some drivers, e.g. Aiptek, don't provide this info */ + if (WTInfo (WTI_DSCTXS + devix, 0, &lc) > 0) + defcontext_done = TRUE; +#if DEBUG_WINTAB + if (defcontext_done) + GDK_NOTE (INPUT, (g_print("Using device-specific default context\n"))); + else + GDK_NOTE (INPUT, (g_print("Note: Driver did not provide device specific default context info despite claiming to support version 1.1\n"))); #endif - lc.lcStatus = 0; - WTInfo (WTI_DDCTXS + devix, CTX_LOCKS, &lc.lcLocks); - lc.lcMsgBase = WT_DEFBASE; - lc.lcDevice = devix; - lc.lcPktRate = 50; - lc.lcPktData = PACKETDATA; - lc.lcPktMode = PK_BUTTONS; /* We want buttons in relative mode */ - lc.lcMoveMask = PACKETDATA; - lc.lcBtnDnMask = lc.lcBtnUpMask = ~0; - WTInfo (WTI_DDCTXS + devix, CTX_INORGX, &lc.lcInOrgX); - WTInfo (WTI_DDCTXS + devix, CTX_INORGY, &lc.lcInOrgY); - WTInfo (WTI_DDCTXS + devix, CTX_INORGZ, &lc.lcInOrgZ); - WTInfo (WTI_DDCTXS + devix, CTX_INEXTX, &lc.lcInExtX); - WTInfo (WTI_DDCTXS + devix, CTX_INEXTY, &lc.lcInExtY); - WTInfo (WTI_DDCTXS + devix, CTX_INEXTZ, &lc.lcInExtZ); - lc.lcOutOrgX = axis_x.axMin; - lc.lcOutOrgY = axis_y.axMin; - lc.lcOutExtX = axis_x.axMax - axis_x.axMin; - lc.lcOutExtY = axis_y.axMax - axis_y.axMin; - lc.lcOutExtY = -lc.lcOutExtY; /* We want Y growing downward */ - WTInfo (WTI_DDCTXS + devix, CTX_SENSX, &lc.lcSensX); - WTInfo (WTI_DDCTXS + devix, CTX_SENSY, &lc.lcSensY); - WTInfo (WTI_DDCTXS + devix, CTX_SENSZ, &lc.lcSensZ); - WTInfo (WTI_DDCTXS + devix, CTX_SYSMODE, &lc.lcSysMode); - WTInfo (WTI_DDCTXS + devix, CTX_SYSORGX, &lc.lcSysOrgX); - WTInfo (WTI_DDCTXS + devix, CTX_SYSORGY, &lc.lcSysOrgY); - WTInfo (WTI_DDCTXS + devix, CTX_SYSEXTX, &lc.lcSysExtX); - WTInfo (WTI_DDCTXS + devix, CTX_SYSEXTY, &lc.lcSysExtY); - WTInfo (WTI_DDCTXS + devix, CTX_SYSSENSX, &lc.lcSysSensX); - WTInfo (WTI_DDCTXS + devix, CTX_SYSSENSY, &lc.lcSysSensY); } - else - { - lc = defcontext; - lc.lcOptions |= CXO_MESSAGES; - lc.lcMsgBase = WT_DEFBASE; - lc.lcPktRate = 50; - lc.lcPktData = PACKETDATA; - lc.lcPktMode = PACKETMODE; - lc.lcMoveMask = PACKETDATA; - lc.lcBtnUpMask = lc.lcBtnDnMask = ~0; -#if 0 - lc.lcOutExtY = -lc.lcOutExtY; /* Y grows downward */ -#else - lc.lcOutOrgX = axis_x.axMin; - lc.lcOutOrgY = axis_y.axMin; - lc.lcOutExtX = axis_x.axMax - axis_x.axMin; - lc.lcOutExtY = axis_y.axMax - axis_y.axMin; - lc.lcOutExtY = -lc.lcOutExtY; /* We want Y growing downward */ + + if (!defcontext_done) + WTInfo (WTI_DEFSYSCTX, 0, &lc); +#if DEBUG_WINTAB + GDK_NOTE (INPUT, (g_print("Default context:\n"), print_lc(&lc))); #endif - } + lc.lcOptions |= CXO_MESSAGES; + lc.lcStatus = 0; + lc.lcMsgBase = WT_DEFBASE; + lc.lcPktRate = 50; + lc.lcPktData = PACKETDATA; + lc.lcPktMode = PACKETMODE; + lc.lcMoveMask = PACKETDATA; + lc.lcBtnUpMask = lc.lcBtnDnMask = ~0; + lc.lcOutOrgX = axis_x.axMin; + lc.lcOutOrgY = axis_y.axMin; + lc.lcOutExtX = axis_x.axMax - axis_x.axMin; + lc.lcOutExtY = axis_y.axMax - axis_y.axMin; + lc.lcOutExtY = -lc.lcOutExtY; /* We want Y growing downward */ #if DEBUG_WINTAB GDK_NOTE (INPUT, (g_print("context for device %d:\n", devix), print_lc(&lc))); @@ -386,11 +344,7 @@ _gdk_input_wintab_init_check (void) gdkdev->info.name = g_strconcat (devname, " ", csrname, NULL); gdkdev->info.source = GDK_SOURCE_PEN; gdkdev->info.mode = GDK_MODE_SCREEN; -#if USE_SYSCONTEXT gdkdev->info.has_cursor = TRUE; -#else - gdkdev->info.has_cursor = FALSE; -#endif gdkdev->hctx = *hctx; gdkdev->cursor = cursorix; WTInfo (WTI_CURSORS + cursorix, CSR_PKTDATA, &gdkdev->pktdata); @@ -527,32 +481,6 @@ decode_tilt (gint *axis_data, axis_data[1] = sin (az) * cos (el) * 1000; } -#if !USE_SYSCONTEXT - -static GdkInputWindow * -gdk_input_window_find_within (GdkWindow *window) -{ - GList *list; - GdkWindow *tmpw; - GdkInputWindow *candidate = NULL; - - for (list = _gdk_input_windows; list != NULL; list = list->next) - { - tmpw = ((GdkInputWindow *) (tmp_list->data))->window; - if (tmpw == window - || IsChild (GDK_WINDOW_HWND (window), GDK_WINDOW_HWND (tmpw))) - { - if (candidate) - return NULL; /* Multiple hits */ - candidate = (GdkInputWindow *) (list->data); - } - } - - return candidate; -} - -#endif /* USE_SYSCONTEXT */ - #endif /* HAVE_WINTAB */ static void @@ -726,15 +654,53 @@ get_modifier_key_state (void) return state; } +#ifdef HAVE_WINTAB + +static guint ignore_core_timer = 0; + +static gboolean +ignore_core_timefunc (gpointer data) +{ + /* The delay has passed */ + _gdk_input_ignore_core = FALSE; + ignore_core_timer = 0; + + return FALSE; /* remove timeout */ +} + +/* + * Set or unset the _gdk_input_ignore_core variable that tells GDK + * to ignore events for the core pointer when the tablet is in proximity + * The unsetting is delayed slightly so that if a tablet event arrives + * just after proximity out, it does not cause a core pointer event + * which e.g. causes GIMP to switch tools. + */ +static void +set_ignore_core (gboolean ignore) +{ + if (ignore) + { + _gdk_input_ignore_core = TRUE; + /* Remove any pending clear */ + if (ignore_core_timer) + { + g_source_remove (ignore_core_timer); + ignore_core_timer = 0; + } + } + else + if (!ignore_core_timer) + ignore_core_timer = g_timeout_add (PROXIMITY_OUT_DELAY, + ignore_core_timefunc, NULL); +} +#endif /* HAVE_WINTAB */ + gboolean _gdk_input_other_event (GdkEvent *event, MSG *msg, GdkWindow *window) { #ifdef HAVE_WINTAB -#if !USE_SYSCONTEXT - GdkWindow *current_window; -#endif GdkDisplay *display; GdkWindowObject *obj, *grab_obj; GdkInputWindow *input_window; @@ -753,7 +719,6 @@ _gdk_input_other_event (GdkEvent *event return FALSE; } -#if USE_SYSCONTEXT window = gdk_window_at_pointer (&x, &y); if (window == NULL) window = _gdk_parent_root; @@ -765,17 +730,6 @@ _gdk_input_other_event (GdkEvent *event g_print ("gdk_input_win32_other_event: window=%p (%d,%d)\n", GDK_WINDOW_HWND (window), x, y)); -#else - /* ??? This code is pretty bogus */ - current_window = gdk_win32_handle_table_lookup (GetActiveWindow ()); - if (current_window == NULL) - return FALSE; - - input_window = gdk_input_window_find_within (current_window); - if (input_window == NULL) - return FALSE; -#endif - if (msg->message == WT_PACKET) { if (!WTPacket ((HCTX) msg->lParam, msg->wParam, &packet)) @@ -925,13 +879,6 @@ _gdk_input_other_event (GdkEvent *event event->button.time = _gdk_win32_get_next_tick (msg->time); event->button.device = &gdkdev->info; -#if 0 -#if USE_SYSCONTEXT - /* Buttons 1 to 3 will come in as WM_[LMR]BUTTON{DOWN,UP} */ - if (event->button.button <= 3) - return FALSE; -#endif -#endif event->button.axes = g_new(gdouble, gdkdev->info.num_axes); gdk_input_translate_coordinates (gdkdev, input_window, @@ -1030,12 +977,12 @@ _gdk_input_other_event (GdkEvent *event if (LOWORD (msg->lParam) == 0) { event->proximity.type = GDK_PROXIMITY_OUT; - _gdk_input_ignore_core = FALSE; + set_ignore_core (FALSE); } else { event->proximity.type = GDK_PROXIMITY_IN; - _gdk_input_ignore_core = TRUE; + set_ignore_core (TRUE); } event->proximity.time = _gdk_win32_get_next_tick (msg->time); event->proximity.device = &gdkdev->info; diff -udpr gtk+-2.6.7_/gdk/win32/gdkkeys-win32.c gtk+-2.6.7/gdk/win32/gdkkeys-win32.c --- gtk+-2.6.7_/gdk/win32/gdkkeys-win32.c 2005-02-24 00:02:59.000000000 +0200 +++ gtk+-2.6.7/gdk/win32/gdkkeys-win32.c 2020-12-27 16:22:52.531875169 +0200 @@ -265,7 +265,7 @@ reset_after_dead (guchar key_state[256]) } } -static gboolean +static void handle_dead (guint keysym, guint *ksymp) { @@ -306,9 +306,12 @@ handle_dead (guint keysym, case GDK_Greek_accentdieresis: /* 0x7ae */ *ksymp = GDK_Greek_accentdieresis; break; default: - return FALSE; + /* By default use the keysym as such. This takes care of for + * instance the dead U+09CD (BENGALI VIRAMA) on the ekushey + * Bengali layout. + */ + *ksymp = keysym; break; } - return TRUE; } static void @@ -446,14 +449,7 @@ update_keymap (void) reset_after_dead (key_state); /* Use dead keysyms instead of "undead" ones */ - if (!handle_dead (keysym, ksymp)) - GDK_NOTE (EVENTS, - g_print ("Unhandled dead key cp:%d vk:%02x sc:%x ch:%02x wc:%04x keysym:%04x%s%s\n", - _gdk_input_codepage, vk, - scancode, chars[0], - wcs[0], keysym, - (shift&0x1 ? " shift" : ""), - (shift&0x2 ? " altgr" : ""))); + handle_dead (keysym, ksymp); } else if (k == 0) { diff -udpr gtk+-2.6.7_/gdk/win32/gdkpixmap-win32.c gtk+-2.6.7/gdk/win32/gdkpixmap-win32.c --- gtk+-2.6.7_/gdk/win32/gdkpixmap-win32.c 2004-12-01 00:56:35.000000000 +0200 +++ gtk+-2.6.7/gdk/win32/gdkpixmap-win32.c 2020-12-27 16:24:11.140873949 +0200 @@ -35,6 +35,55 @@ #include "gdkprivate-win32.h" +static GHashTable *handle_ht = NULL; + +static guint +gdi_handle_hash (HANDLE *handle) +{ + return (guint) *handle; +} + +static gint +gdi_handle_equal (HANDLE *a, + HANDLE *b) +{ + return (*a == *b); +} + +static void +gdi_handle_table_insert (HANDLE *handle, + gpointer data) +{ + g_return_if_fail (handle != NULL); + + if (!handle_ht) + handle_ht = g_hash_table_new ((GHashFunc) gdi_handle_hash, + (GEqualFunc) gdi_handle_equal); + + g_hash_table_insert (handle_ht, handle, data); +} + +static void +gdi_handle_table_remove (HANDLE handle) +{ + if (!handle_ht) + handle_ht = g_hash_table_new ((GHashFunc) gdi_handle_hash, + (GEqualFunc) gdi_handle_equal); + + g_hash_table_remove (handle_ht, &handle); +} + +static gpointer +gdi_handle_table_lookup (GdkNativeWindow handle) +{ + gpointer data = NULL; + + if (handle_ht) + data = g_hash_table_lookup (handle_ht, &handle); + + return data; +} + static void gdk_pixmap_impl_win32_get_size (GdkDrawable *drawable, gint *width, gint *height); @@ -111,7 +160,7 @@ gdk_pixmap_impl_win32_finalize (GObject if (!DeleteObject (GDK_PIXMAP_HBITMAP (wrapper))) WIN32_GDI_FAILED ("DeleteObject"); - gdk_win32_handle_table_remove (GDK_PIXMAP_HBITMAP (wrapper)); + gdi_handle_table_remove (GDK_PIXMAP_HBITMAP (wrapper)); G_OBJECT_CLASS (parent_class)->finalize (object); } @@ -306,7 +355,7 @@ gdk_pixmap_new (GdkDrawable *drawable, drawable_impl->handle = hbitmap; pixmap_impl->bits = bits; - gdk_win32_handle_table_insert (&GDK_PIXMAP_HBITMAP (pixmap), pixmap); + gdi_handle_table_insert (&GDK_PIXMAP_HBITMAP (pixmap), pixmap); return pixmap; } @@ -478,7 +527,7 @@ gdk_pixmap_foreign_new (GdkNativeWindow pix_impl->height = size.cy; pix_impl->bits = NULL; - gdk_win32_handle_table_insert (&GDK_PIXMAP_HBITMAP (pixmap), pixmap); + gdi_handle_table_insert (&GDK_PIXMAP_HBITMAP (pixmap), pixmap); return pixmap; } @@ -486,7 +535,7 @@ gdk_pixmap_foreign_new (GdkNativeWindow GdkPixmap* gdk_pixmap_lookup (GdkNativeWindow anid) { - return (GdkPixmap*) gdk_win32_handle_table_lookup (anid); + return (GdkPixmap*) gdi_handle_table_lookup (anid); } GdkPixmap* diff -udpr gtk+-2.6.7_/gdk/win32/gdkprivate-win32.h gtk+-2.6.7/gdk/win32/gdkprivate-win32.h --- gtk+-2.6.7_/gdk/win32/gdkprivate-win32.h 2005-04-04 02:40:42.000000000 +0300 +++ gtk+-2.6.7/gdk/win32/gdkprivate-win32.h 2020-12-27 16:22:52.531875169 +0200 @@ -360,6 +360,8 @@ HRGN _gdk_win32_gdkregion_to_hrgn (Gd gint x_origin, gint y_origin); +GdkRegion *_gdk_win32_hrgn_to_region (HRGN hrgn); + void _gdk_win32_adjust_client_rect (GdkWindow *window, RECT *RECT); diff -udpr gtk+-2.6.7_/gdk/win32/gdkproperty-win32.c gtk+-2.6.7/gdk/win32/gdkproperty-win32.c --- gtk+-2.6.7_/gdk/win32/gdkproperty-win32.c 2005-04-04 02:40:42.000000000 +0300 +++ gtk+-2.6.7/gdk/win32/gdkproperty-win32.c 2020-12-27 16:22:52.531875169 +0200 @@ -561,7 +561,7 @@ gdk_screen_get_setting (GdkScreen *scr const gchar *name, GValue *value) { - g_return_val_if_fail (screen == gdk_screen_get_default (), FALSE); + g_return_val_if_fail (GDK_IS_SCREEN (screen), FALSE); /* * XXX : if these values get changed through the Windoze UI the diff -udpr gtk+-2.6.7_/gdk/win32/gdkwindow-win32.c gtk+-2.6.7/gdk/win32/gdkwindow-win32.c --- gtk+-2.6.7_/gdk/win32/gdkwindow-win32.c 2005-03-12 01:45:53.000000000 +0200 +++ gtk+-2.6.7/gdk/win32/gdkwindow-win32.c 2020-12-27 16:22:52.532875169 +0200 @@ -37,7 +37,13 @@ #include "gdkprivate-win32.h" #include "gdkinput-win32.h" -#if defined __MINGW32__ || (WINVER < 0x0500) +#if defined __MINGW32__ +#include +#endif + +#if (defined __W32API_MAJOR_VERSION ? ((__W32API_MAJOR_VERSION < 3) || \ + ((__W32API_MAJOR_VERSION == 3) && (__W32API_MINOR_VERSION < 8))) : \ + (WINVER < 0x0500)) typedef struct { DWORD bV5Size; LONG bV5Width; diff -udpr gtk+-2.6.7_/gdk/win32/xcursors.h gtk+-2.6.7/gdk/win32/xcursors.h --- gtk+-2.6.7_/gdk/win32/xcursors.h 2001-02-23 05:51:40.000000000 +0200 +++ gtk+-2.6.7/gdk/win32/xcursors.h 2020-12-27 16:22:52.532875169 +0200 @@ -1,357 +1,357 @@ -static const struct { const gchar *name; gint type; guchar width; guchar height; guchar hotx; guchar hoty; guchar *data; } cursors[] = { - { "X_cursor", 0, 16, 16, 7, 7, +static const struct { const gchar *name; const gchar *builtin; gint type; guchar width; guchar height; guchar hotx; guchar hoty; guchar *data; } cursors[] = { + { "X_cursor", NULL, 0, 16, 16, 7, 7, "\125\000\000\125\152\100\001\251\152\220\006\251\152\244\032\251" "\032\251\152\244\006\252\252\220\001\252\252\100\000\152\251\000" "\000\152\251\000\001\252\252\100\006\252\252\220\032\251\152\244" "\152\244\032\251\152\220\006\251\152\100\001\251\125\000\000\125" }, - { "arrow", 2, 16, 16, 14, 1, + { "arrow", IDC_ARROW, 2, 16, 16, 14, 1, "\000\000\000\025\000\000\001\151\000\000\026\251\000\001\152\244" "\000\026\252\244\001\152\252\220\006\252\252\220\005\126\252\100" "\000\032\252\100\000\152\151\000\001\251\151\000\006\244\144\000" "\032\220\144\000\152\100\020\000\031\000\000\000\004\000\000\000" }, - { "based_arrow_down", 4, 10, 12, 4, 10, + { "based_arrow_down", NULL, 4, 10, 12, 4, 10, "\125\125\126\252\251\125\125\126\252\251\125\245\120\032\100\001" "\244\001\132\124\031\246\101\152\224\005\245\000\025\100" }, - { "based_arrow_up", 6, 10, 12, 4, 10, + { "based_arrow_up", NULL, 6, 10, 12, 4, 10, "\000\120\000\032\100\026\251\101\232\144\025\245\100\032\100\001" "\244\005\132\125\152\252\225\125\125\152\252\225\125\125" }, - { "boat", 8, 16, 9, 14, 4, + { "boat", NULL, 8, 16, 9, 14, 4, "\000\026\000\000\000\152\240\000\201\225\150\000\252\252\252\252" "\125\125\126\225\125\125\131\125\125\125\145\100\252\252\244\000" "\125\125\120\000" }, - { "bogosity", 10, 15, 16, 7, 7, + { "bogosity", NULL, 10, 15, 16, 7, 7, "\125\105\105\125\251\031\032\225\144\144\145\101\221\221\220\126" "\126\126\125\252\252\252\226\145\145\146\131\221\221\231\146\106" "\106\145\231\131\131\226\252\252\252\125\225\225\225\006\106\106" "\101\131\031\031\126\244\144\152\125\121\121\125" }, - { "bottom_left_corner", 12, 16, 16, 1, 14, + { "bottom_left_corner", IDC_SIZENESW, 12, 16, 16, 1, 14, "\125\000\000\000\151\000\000\000\151\025\000\120\151\031\001\220" "\151\031\006\100\151\031\031\000\151\031\144\000\151\031\220\000" "\151\032\125\120\151\032\252\220\151\025\125\120\151\000\000\000" "\151\125\125\125\152\252\252\251\152\252\252\251\125\125\125\125" }, - { "bottom_right_corner", 14, 16, 16, 14, 14, + { "bottom_right_corner", IDC_SIZENWSE, 14, 16, 16, 14, 14, "\000\000\000\125\000\000\000\151\005\000\124\151\006\100\144\151" "\001\220\144\151\000\144\144\151\000\031\144\151\000\006\144\151" "\005\125\244\151\006\252\244\151\005\125\124\151\000\000\000\151" "\125\125\125\151\152\252\252\251\152\252\252\251\125\125\125\125" }, - { "bottom_side", 16, 15, 16, 7, 14, + { "bottom_side", IDC_SIZENS, 16, 15, 16, 7, 14, "\000\005\100\000\000\031\000\000\000\144\000\000\001\220\000\000" "\006\100\000\000\031\000\000\120\144\024\001\221\221\220\001\226" "\131\000\001\231\220\000\001\251\000\000\001\220\000\125\125\125" "\125\252\252\252\226\252\252\252\125\125\125\125" }, - { "bottom_tee", 18, 16, 12, 8, 10, + { "bottom_tee", NULL, 18, 16, 12, 8, 10, "\000\005\120\000\000\006\220\000\000\006\220\000\000\006\220\000" "\000\006\220\000\000\006\220\000\000\006\220\000\000\006\220\000" "\125\126\225\125\152\252\252\251\152\252\252\251\125\125\125\125" }, - { "box_spiral", 20, 16, 16, 8, 8, + { "box_spiral", NULL, 20, 16, 16, 8, 8, "\252\252\252\251\225\125\125\125\232\252\252\251\231\125\125\131" "\231\252\252\231\231\225\125\231\231\232\251\231\231\231\131\231" "\231\231\231\231\231\232\231\231\231\225\131\231\231\252\251\231" "\231\125\125\231\232\252\252\231\225\125\125\131\252\252\252\251" }, - { "center_ptr", 22, 12, 16, 5, 1, + { "center_ptr", IDC_UPARROW, 22, 12, 16, 5, 1, "\000\125\000\000\151\000\001\151\100\001\252\100\005\252\120\006" "\252\220\026\252\224\032\252\244\132\252\245\151\151\151\145\151" "\131\124\151\025\000\151\000\000\151\000\000\151\000\000\125\000" }, - { "circle", 24, 16, 16, 8, 8, + { "circle", NULL, 24, 16, 16, 8, 8, "\000\025\124\000\001\132\245\100\005\252\252\120\026\252\252\224" "\032\245\132\244\132\220\006\245\152\100\001\251\152\100\001\251" "\152\100\001\251\152\100\001\251\132\220\006\245\032\245\132\244" "\026\252\252\224\005\252\252\120\001\132\245\100\000\025\124\000" }, - { "clock", 26, 15, 16, 6, 3, + { "clock", IDC_APPSTARTING, 26, 15, 16, 6, 3, "\032\252\252\101\241\252\012\112\030\132\112\141\206\222\111\206" "\251\131\046\006\124\220\232\006\251\012\132\252\252\244\142\032" "\110\221\210\151\042\106\041\244\211\030\232\246\044\242\032\110" "\246\250\024\052\232\252\252\252\152\252\252\251" }, - { "coffee_mug", 28, 16, 16, 7, 9, + { "coffee_mug", NULL, 28, 16, 16, 7, 9, "\002\252\252\000\011\125\125\200\051\125\125\151\046\125\126\231" "\145\252\251\131\245\125\125\131\245\125\125\131\145\125\125\131" "\045\125\125\131\046\226\126\231\151\231\231\231\251\232\231\231" "\246\231\226\231\145\125\125\131\045\125\125\131\012\252\252\240" }, - { "cross", 30, 16, 16, 7, 7, - "\000\025\120\000\000\031\220\000\000\031\220\000\000\031\220\000" - "\000\031\220\000\125\131\225\125\125\131\225\125\252\251\252\252" - "\125\125\125\125\252\251\252\252\000\031\220\000\000\031\220\000" - "\000\031\220\000\000\031\220\000\000\031\220\000\000\031\220\000" }, - { "cross_reverse", 32, 16, 15, 7, 7, + { "cross", IDC_CROSS, 30, 16, 15, 7, 7, + "\000\031\220\000\000\031\220\000\000\031\220\000\000\031\220\000" + "\000\031\220\000\125\131\225\125\252\251\252\252\125\125\125\125" + "\252\251\252\252\125\131\225\125\000\031\220\000\000\031\220\000" + "\000\031\220\000\000\031\220\000\000\031\220\000" }, + { "cross_reverse", NULL, 32, 16, 15, 7, 7, "\044\030\220\140\211\030\221\211\142\130\226\044\030\230\230\220" "\006\050\242\100\125\210\211\125\252\240\052\252\000\001\000\000" "\252\240\052\252\125\210\211\125\006\050\242\100\030\230\230\220" "\142\130\226\044\211\030\221\211\044\030\220\140" }, - { "crosshair", 34, 16, 16, 7, 7, - "\000\005\100\000\000\006\100\000\000\006\100\000\000\006\100\000" - "\000\006\100\000\000\006\100\000\125\126\125\125\125\126\125\125" - "\252\251\252\252\000\006\100\000\000\006\100\000\000\006\100\000" - "\000\006\100\000\000\006\100\000\000\006\100\000\000\006\100\000" }, - { "diamond_cross", 36, 16, 16, 7, 7, - "\000\025\120\000\000\131\224\000\001\151\245\000\005\211\211\100" - "\026\011\202\120\130\011\200\224\145\131\225\145\252\250\252\251" - "\125\125\125\125\250\011\200\250\045\011\201\140\011\111\205\200" - "\002\131\226\000\000\231\230\000\000\051\240\000\000\011\200\000" }, - { "dot", 38, 12, 12, 6, 6, + { "crosshair", IDC_CROSS, 34, 16, 15, 7, 7, + "\000\006\100\000\000\006\100\000\000\006\100\000\000\006\100\000" + "\000\006\100\000\000\006\100\000\125\126\125\125\252\251\252\252" + "\125\126\125\125\000\006\100\000\000\006\100\000\000\006\100\000" + "\000\006\100\000\000\006\100\000\000\006\100\000" }, + { "diamond_cross", NULL, 36, 15, 15, 7, 7, + "\000\031\220\000\001\246\220\000\031\231\220\001\222\141\220\031" + "\011\201\221\220\046\001\232\252\232\252\225\125\025\125\252\251" + "\252\251\220\046\001\221\220\230\031\001\222\141\220\001\231\231" + "\000\001\246\220\000\001\231\000\000" }, + { "dot", NULL, 38, 12, 12, 6, 6, "\001\125\100\025\252\124\032\252\244\132\252\245\152\252\251\152" "\252\251\152\252\251\152\252\251\132\252\245\032\252\244\025\252" "\124\001\125\100" }, - { "dotbox", 40, 14, 14, 7, 6, + { "dotbox", NULL, 40, 14, 14, 7, 6, "\125\125\125\126\252\252\251\145\125\125\226\100\000\031\144\000" "\001\226\101\124\031\144\032\101\226\101\244\031\144\025\101\226" "\100\000\031\144\000\001\226\125\125\131\152\252\252\225\125\125" "\125" }, - { "double_arrow", 42, 12, 16, 6, 8, + { "double_arrow", IDC_SIZENS, 42, 12, 16, 6, 8, "\000\125\000\001\151\100\005\252\120\026\252\224\132\151\245\151" "\151\151\125\151\125\000\151\000\000\151\000\125\151\125\151\151" "\151\132\151\245\026\252\224\005\252\120\001\151\100\000\125\000" }, - { "draft_large", 44, 15, 16, 14, 0, - "\000\000\000\024\000\000\005\140\000\001\132\100\000\126\250\000" - "\025\252\200\005\152\252\001\132\252\240\006\252\252\200\000\026" - "\250\000\001\146\240\000\026\032\000\001\140\150\000\026\001\200" - "\001\140\006\000\006\000\000\000\040\000\000\000" }, - { "draft_small", 46, 15, 15, 14, 0, + { "draft_large", NULL, 44, 15, 15, 14, 0, + "\000\000\000\030\000\000\006\220\000\001\252\100\000\152\244\000" + "\032\252\200\006\252\251\001\252\252\240\005\125\252\100\000\031" + "\250\000\001\226\220\000\031\032\000\001\220\144\000\031\001\200" + "\001\220\005\000\011\000\000\000\000" }, + { "draft_small", NULL, 46, 15, 15, 14, 0, "\000\000\000\030\000\000\006\220\000\001\252\000\000\152\244\000" "\032\252\200\000\125\251\000\000\031\240\000\001\226\100\000\031" "\030\000\001\220\100\000\031\000\000\001\220\000\000\031\000\000" "\001\220\000\000\011\000\000\000\000" }, - { "draped_box", 48, 14, 14, 7, 6, + { "draped_box", NULL, 48, 14, 14, 7, 6, "\125\125\125\126\252\252\251\140\145\220\226\032\132\111\146\220" "\151\226\244\121\251\145\032\105\226\121\244\131\152\105\032\226" "\151\006\231\141\245\244\226\006\131\011\152\252\252\225\125\125" "\125" }, - { "exchange", 50, 16, 16, 7, 7, + { "exchange", NULL, 50, 16, 16, 7, 7, "\120\025\124\000\144\152\251\000\151\252\252\100\152\245\126\220" "\145\220\001\220\145\245\000\120\152\251\000\000\125\125\000\000" "\000\000\125\125\000\000\152\251\005\000\032\131\006\100\006\131" "\006\225\132\251\001\252\252\151\000\152\251\031\000\025\124\005" }, - { "fleur", 52, 16, 16, 8, 8, + { "fleur", IDC_SIZEALL, 52, 16, 16, 8, 8, "\000\005\120\000\000\006\224\000\000\032\244\000\000\152\251\000" "\001\026\224\100\006\106\221\220\132\126\225\245\152\252\252\251" "\152\252\252\251\132\126\225\245\006\106\221\220\001\026\224\100" "\000\152\251\000\000\032\244\000\000\006\220\000\000\005\120\000" }, - { "gobbler", 54, 16, 16, 14, 3, - "\000\000\152\220\000\000\152\120\220\000\132\132\226\252\232\125" - "\252\252\252\125\252\251\132\120\252\245\132\120\151\125\132\220" - "\125\125\252\120\126\252\251\120\025\225\125\100\001\225\125\000" - "\001\220\000\000\001\220\000\000\006\251\000\000\005\125\000\000" }, - { "gumby", 56, 16, 16, 2, 0, + { "gobbler", NULL, 54, 16, 16, 14, 2, + "\000\000\125\120\000\000\152\220\120\000\152\125\225\125\132\132" + "\226\252\232\125\252\252\252\120\252\251\132\120\252\245\132\120" + "\151\125\132\220\125\125\252\120\026\252\251\100\001\225\125\000" + "\001\220\000\000\001\220\000\000\005\225\000\000\006\251\000\000" }, + { "gumby", NULL, 56, 16, 16, 2, 0, "\012\252\000\000\122\125\200\000\244\225\140\000\251\231\230\000" "\244\225\130\000\244\232\231\120\252\225\132\244\132\225\132\252" "\005\225\130\152\000\225\130\152\000\226\131\252\000\226\130\152" "\000\226\130\025\002\126\126\000\011\126\125\200\012\250\252\200" }, - { "hand1", 58, 13, 16, 12, 0, + { "hand1", IDC_HAND, 58, 13, 16, 12, 0, "\000\000\006\200\000\032\240\000\152\220\000\152\220\000\152\220" "\000\152\251\001\152\252\221\232\252\224\252\252\251\046\252\252" "\105\132\252\101\126\252\100\226\145\100\051\131\000\006\231\000" "\000\151\000\000" }, - { "hand2", 60, 16, 16, 0, 1, + { "hand2", IDC_HAND, 60, 16, 16, 0, 1, "\025\125\100\000\152\252\220\000\225\125\144\000\152\251\131\000" "\026\125\126\100\001\251\126\100\006\125\126\100\001\251\131\220" "\006\125\145\144\001\245\225\131\000\132\125\144\000\031\145\220" "\000\006\126\100\000\001\231\000\000\000\144\000\000\000\020\000" }, - { "heart", 62, 15, 14, 6, 8, + { "heart", NULL, 62, 15, 14, 6, 8, "\012\250\252\200\245\152\126\212\100\144\006\244\000\100\006\220" "\000\000\032\100\000\000\151\000\104\001\251\000\100\032\051\000" "\001\240\051\000\032\000\051\001\240\000\051\132\000\000\051\240" "\000\000\052\000\000" }, - { "icon", 64, 16, 16, 8, 8, + { "icon", NULL, 64, 16, 16, 8, 8, "\252\252\252\252\246\146\146\146\231\231\231\232\246\146\146\146" "\231\125\125\232\246\125\125\146\231\125\125\232\246\125\125\146" "\231\125\125\232\246\125\125\146\231\125\125\232\246\125\125\146" "\231\231\231\232\246\146\146\146\231\231\231\232\252\252\252\252" }, - { "iron_cross", 66, 16, 16, 8, 7, + { "iron_cross", NULL, 66, 16, 16, 8, 7, "\005\125\125\120\032\252\252\244\026\252\252\224\145\252\252\131" "\151\152\251\151\152\132\245\251\152\226\226\251\152\252\252\251" "\152\252\252\251\152\226\226\251\152\132\245\251\151\152\251\151" "\145\252\252\131\026\252\252\224\032\252\252\244\005\125\125\120" }, - { "left_ptr", 68, 10, 16, 1, 1, + { "left_ptr", IDC_ARROW, 68, 10, 16, 1, 1, "\120\000\006\100\000\151\000\006\244\000\152\220\006\252\100\152" "\251\006\252\244\152\252\226\252\125\151\244\006\106\220\120\151" "\000\001\244\000\032\100\000\120" }, - { "left_side", 70, 16, 15, 1, 7, + { "left_side", IDC_SIZEWE, 70, 16, 15, 1, 7, "\125\000\000\000\151\000\000\000\151\000\120\000\151\001\220\000" "\151\006\100\000\151\031\000\000\151\145\125\125\151\252\252\251" "\151\145\125\125\151\031\000\000\151\006\100\000\151\001\220\000" "\151\000\120\000\151\000\000\000\125\000\000\000" }, - { "left_tee", 72, 12, 16, 1, 8, + { "left_tee", NULL, 72, 12, 16, 1, 8, "\125\000\000\151\000\000\151\000\000\151\000\000\151\000\000\151" "\000\000\151\125\125\152\252\251\152\252\251\151\125\125\151\000" "\000\151\000\000\151\000\000\151\000\000\151\000\000\125\000\000" }, - { "leftbutton", 74, 16, 16, 8, 8, + { "leftbutton", NULL, 74, 16, 16, 8, 8, "\025\125\125\120\152\252\252\244\152\252\252\244\145\145\145\144" "\145\146\146\144\145\146\146\144\145\146\146\144\145\146\146\144" "\145\145\145\144\152\252\252\244\152\252\252\244\152\252\252\244" "\152\252\252\244\152\252\252\244\152\252\252\244\025\125\125\120" }, - { "ll_angle", 76, 12, 12, 1, 10, + { "ll_angle", NULL, 76, 12, 12, 1, 10, "\125\000\000\151\000\000\151\000\000\151\000\000\151\000\000\151" "\000\000\151\000\000\151\000\000\151\125\125\152\252\251\152\252" "\251\125\125\125" }, - { "lr_angle", 78, 12, 12, 10, 10, + { "lr_angle", NULL, 78, 12, 12, 10, 10, "\000\000\125\000\000\151\000\000\151\000\000\151\000\000\151\000" "\000\151\000\000\151\000\000\151\125\125\151\152\252\251\152\252" "\251\125\125\125" }, - { "man", 80, 16, 16, 14, 5, + { "man", NULL, 80, 16, 16, 14, 5, "\001\132\224\000\006\251\252\000\005\131\225\100\220\006\100\004" "\144\032\220\052\031\145\145\232\006\246\152\105\001\146\145\000" "\000\045\144\000\000\031\220\000\000\145\144\000\001\226\131\000" "\006\131\226\100\026\144\146\120\152\220\032\245\252\220\032\252" }, - { "middlebutton", 82, 16, 16, 8, 8, + { "middlebutton", NULL, 82, 16, 16, 8, 8, "\025\125\125\120\152\252\252\244\152\252\252\244\145\145\145\144" "\146\145\146\144\146\145\146\144\146\145\146\144\146\145\146\144" "\145\145\145\144\152\252\252\244\152\252\252\244\152\252\252\244" "\152\252\252\244\152\252\252\244\152\252\252\244\025\125\125\120" }, - { "mouse", 84, 16, 16, 4, 1, + { "mouse", NULL, 84, 16, 16, 4, 1, "\000\125\100\000\001\124\000\000\000\152\000\000\000\045\000\000" "\025\151\125\100\125\132\125\120\152\252\252\225\225\125\125\145" "\232\132\132\151\232\132\132\151\232\132\132\151\225\125\125\151" "\005\125\125\051\001\125\124\000\000\225\140\000\000\052\200\000" }, - { "pencil", 86, 13, 16, 11, 15, + { "pencil", NULL, 86, 13, 16, 11, 15, "\132\220\000\031\131\000\006\126\220\000\145\230\000\012\246\100" "\001\225\140\000\031\131\000\002\125\200\000\145\144\000\012\126" "\000\001\225\220\000\031\131\000\001\252\100\000\032\220\000\001" "\244\000\000\031" }, - { "pirate", 88, 16, 16, 7, 12, + { "pirate", IDC_NO, 88, 16, 16, 7, 12, "\000\152\220\000\001\252\244\000\006\252\251\000\032\132\132\100" "\032\132\132\100\006\252\251\000\001\252\244\000\100\152\220\001" "\200\152\220\045\220\152\220\151\145\032\101\220\032\200\052\100" "\000\052\200\000\026\252\250\011\252\125\132\251\225\000\005\144" }, - { "plus", 90, 12, 12, 5, 6, + { "plus", NULL, 90, 12, 12, 5, 6, "\000\125\000\000\151\000\000\151\000\000\151\000\125\151\125\152" "\252\251\152\252\251\125\151\125\000\151\000\000\151\000\000\151" "\000\000\125\000" }, - { "question_arrow", 92, 11, 16, 5, 8, + { "question_arrow", IDC_HELP, 92, 11, 16, 5, 8, "\002\252\000\052\252\002\245\152\032\125\151\152\001\245\151\012" "\221\124\251\101\152\224\001\251\100\006\144\000\031\220\002\246" "\240\026\232\120\026\245\000\026\120\000\025\000" }, - { "right_ptr", 94, 10, 16, 8, 1, + { "right_ptr", NULL, 94, 10, 16, 8, 1, "\000\000\120\000\031\000\006\220\001\251\000\152\220\032\251\006" "\252\221\252\251\152\252\225\132\251\001\246\220\151\031\006\220" "\121\244\000\032\100\000\120\000" }, - { "right_side", 96, 16, 15, 14, 7, + { "right_side", IDC_SIZEWE, 96, 16, 15, 14, 7, "\000\000\000\125\000\000\000\151\000\005\000\151\000\006\100\151" "\000\001\220\151\000\000\144\151\125\125\131\151\152\252\252\151" "\125\125\131\151\000\000\144\151\000\001\220\151\000\006\100\151" "\000\005\000\151\000\000\000\151\000\000\000\125" }, - { "right_tee", 98, 12, 16, 10, 8, + { "right_tee", NULL, 98, 12, 16, 10, 8, "\000\000\125\000\000\151\000\000\151\000\000\151\000\000\151\000" "\000\151\125\125\151\152\252\251\152\252\251\125\125\151\000\000" "\151\000\000\151\000\000\151\000\000\151\000\000\151\000\000\125" }, - { "rightbutton", 100, 16, 16, 8, 8, + { "rightbutton", NULL, 100, 16, 16, 8, 8, "\025\125\125\120\152\252\252\244\152\252\252\244\145\145\145\144" "\146\146\145\144\146\146\145\144\146\146\145\144\146\146\145\144" "\145\145\145\144\152\252\252\244\152\252\252\244\152\252\252\244" "\152\252\252\244\152\252\252\244\152\252\252\244\025\125\125\120" }, - { "rtl_logo", 102, 16, 16, 7, 7, + { "rtl_logo", NULL, 102, 16, 16, 7, 7, "\125\125\125\125\152\252\252\251\145\125\131\131\144\000\031\031" "\145\125\131\031\152\252\251\031\145\145\131\031\144\144\031\031" "\144\144\031\031\144\145\131\131\144\152\252\251\144\145\125\131" "\144\144\000\031\145\145\125\131\152\252\252\251\125\125\125\125" }, - { "sailboat", 104, 16, 16, 8, 0, + { "sailboat", NULL, 104, 16, 16, 8, 0, "\000\000\120\000\000\000\124\000\000\001\144\000\000\005\145\000" "\000\006\151\000\000\026\151\000\000\032\151\100\000\132\152\100" "\000\152\152\100\001\152\152\120\001\252\152\220\005\252\152\220" "\006\252\152\225\026\252\152\245\132\251\132\200\025\125\124\000" }, - { "sb_down_arrow", 106, 9, 16, 4, 15, + { "sb_down_arrow", NULL, 106, 9, 16, 4, 15, "\005\124\001\231\000\146\100\031\220\006\144\001\231\000\146\100" "\031\220\006\144\001\231\005\146\125\131\225\052\252\002\252\000" "\052\000\002\000" }, - { "sb_h_double_arrow", 108, 15, 9, 7, 4, + { "sb_h_double_arrow", IDC_SIZEWE, 108, 15, 9, 7, 4, "\001\100\005\000\031\000\031\001\245\125\151\032\252\252\251\252" "\125\126\251\252\252\252\221\245\125\151\001\220\001\220\001\100" "\005\000" }, - { "sb_left_arrow", 110, 16, 9, 0, 4, + { "sb_left_arrow", NULL, 110, 16, 9, 0, 4, "\000\120\000\000\001\220\000\000\006\225\125\125\032\252\252\252" "\152\225\125\125\032\252\252\252\006\225\125\125\001\220\000\000" "\000\120\000\000" }, - { "sb_right_arrow", 112, 16, 9, 15, 4, + { "sb_right_arrow", NULL, 112, 16, 9, 15, 4, "\000\000\005\000\000\000\006\100\125\125\126\220\252\252\252\244" "\125\125\126\251\252\252\252\244\125\125\126\220\000\000\006\100" "\000\000\005\000" }, - { "sb_up_arrow", 114, 9, 16, 4, 0, + { "sb_up_arrow", NULL, 114, 9, 16, 4, 0, "\000\200\000\250\000\252\200\252\250\126\145\125\231\120\146\100" "\031\220\006\144\001\231\000\146\100\031\220\006\144\001\231\000" "\146\100\025\120" }, - { "sb_v_double_arrow", 116, 9, 15, 4, 7, + { "sb_v_double_arrow", IDC_SIZENS, 116, 9, 15, 4, 7, "\001\220\001\251\001\252\221\252\251\126\145\101\231\000\146\100" "\031\220\006\144\001\231\005\146\125\252\251\032\251\001\251\000" "\031\000" }, - { "shuttle", 118, 16, 16, 11, 0, + { "shuttle", NULL, 118, 16, 16, 11, 0, "\000\000\006\100\000\000\032\220\000\000\152\244\000\000\251\252" "\000\030\251\252\000\144\251\252\001\224\251\252\001\224\251\252" "\001\224\251\252\001\224\251\252\006\224\251\252\032\224\251\252" "\152\250\251\252\025\244\145\144\000\120\032\244\000\000\006\220" }, - { "sizing", 120, 16, 16, 8, 8, + { "sizing", IDC_SIZENWSE, 120, 16, 16, 8, 8, "\125\125\120\000\152\252\220\000\145\125\120\000\144\000\000\000" "\144\125\125\000\144\152\251\000\144\145\131\025\144\144\031\031" "\144\144\031\031\124\145\131\031\000\152\251\031\000\125\126\131" "\000\000\001\231\000\005\125\151\000\006\252\251\000\005\125\125" }, - { "spider", 122, 16, 16, 6, 7, + { "spider", NULL, 122, 16, 16, 6, 7, "\030\000\002\100\006\000\011\000\002\000\010\000\001\200\044\000" "\100\225\140\001\220\152\220\152\050\152\222\220\006\252\251\000" "\006\252\250\000\050\152\226\200\220\152\220\152\100\225\140\001" "\001\200\040\000\002\100\030\000\006\000\011\000\030\000\002\100" }, - { "spraycan", 124, 12, 16, 10, 2, + { "spraycan", NULL, 124, 12, 16, 10, 2, "\000\000\012\001\100\205\006\230\112\012\244\205\032\144\112\152" "\251\000\145\131\000\152\131\000\146\131\000\152\131\000\146\131" "\000\152\131\000\152\131\000\145\131\000\145\131\000\152\251\000" }, - { "star", 126, 16, 16, 7, 7, + { "star", NULL, 126, 16, 16, 7, 7, "\000\002\000\000\000\011\200\000\000\011\200\000\000\030\220\000" "\000\044\140\000\000\140\044\000\001\140\045\100\132\202\012\224" "\240\000\000\051\132\200\012\224\005\202\011\100\006\011\202\100" "\030\044\140\220\030\220\030\220\032\100\006\220\031\000\001\220" }, - { "target", 128, 16, 14, 7, 7, - "\000\032\220\000\000\252\250\000\002\245\152\000\012\120\026\200" - "\051\000\001\240\244\002\000\150\240\011\200\051\240\024\120\051" - "\140\005\100\045\130\001\000\224\026\000\002\120\005\240\051\100" - "\001\132\225\000\000\025\120\000" }, - { "tcross", 130, 15, 15, 7, 7, + { "target", NULL, 128, 16, 15, 7, 7, + "\000\025\120\000\000\132\224\000\001\252\251\000\006\240\052\100" + "\032\000\002\220\150\001\000\244\240\006\100\051\240\030\220\051" + "\240\006\100\051\150\001\000\244\032\000\002\220\006\240\052\100" + "\001\252\251\000\000\132\224\000\000\025\120\000" }, + { "tcross", IDC_CROSS, 130, 15, 15, 7, 7, "\000\005\100\000\000\031\000\000\000\144\000\000\001\220\000\000" "\006\100\000\000\031\000\005\125\145\125\132\252\252\251\125\126" "\125\124\000\031\000\000\000\144\000\000\001\220\000\000\006\100" "\000\000\031\000\000\000\124\000\000" }, - { "top_left_arrow", 132, 16, 16, 1, 1, + { "top_left_arrow", NULL, 132, 16, 16, 1, 1, "\124\000\000\000\151\100\000\000\152\224\000\000\032\251\100\000" "\032\252\224\000\006\252\251\120\006\252\252\220\001\252\225\120" "\001\252\220\000\000\151\144\000\000\151\031\000\000\031\006\100" "\000\031\001\220\000\025\000\144\000\000\000\031\000\000\000\005" }, - { "top_left_corner", 134, 16, 16, 1, 1, + { "top_left_corner", IDC_SIZENWSE, 134, 16, 16, 1, 1, "\125\125\125\125\152\252\252\251\152\252\252\251\151\125\125\125" "\151\000\000\000\151\025\125\120\151\032\252\220\151\032\125\120" "\151\031\220\000\151\031\144\000\151\031\031\000\151\031\006\100" "\151\031\001\220\151\025\000\120\151\000\000\000\125\000\000\000" }, - { "top_right_corner", 136, 16, 16, 14, 1, + { "top_right_corner", IDC_SIZENESW, 136, 16, 16, 14, 1, "\125\125\125\125\152\252\252\251\152\252\252\251\125\125\125\151" "\000\000\000\151\005\125\124\151\006\252\244\151\005\125\244\151" "\000\006\144\151\000\031\144\151\000\144\144\151\001\220\144\151" "\006\100\144\151\005\000\124\151\000\000\000\151\000\000\000\125" }, - { "top_side", 138, 15, 16, 7, 1, + { "top_side", IDC_SIZENS, 138, 15, 16, 7, 1, "\125\125\125\125\252\252\252\226\252\252\252\125\125\125\125\000" "\006\100\000\000\152\100\000\006\146\100\000\145\226\100\006\106" "\106\100\024\031\005\000\000\144\000\000\001\220\000\000\006\100" "\000\000\031\000\000\000\144\000\000\001\120\000" }, - { "top_tee", 140, 16, 12, 8, 1, + { "top_tee", NULL, 140, 16, 12, 8, 1, "\125\125\125\125\152\252\252\251\152\252\252\251\125\126\225\125" "\000\006\220\000\000\006\220\000\000\006\220\000\000\006\220\000" "\000\006\220\000\000\006\220\000\000\006\220\000\000\005\120\000" }, - { "trek", 142, 9, 16, 4, 0, + { "trek", NULL, 142, 9, 16, 4, 0, "\001\220\000\124\000\152\100\152\244\152\252\132\232\226\252\244" "\152\244\006\244\004\144\106\152\145\246\151\145\226\131\021\226" "\104\145\220\031" }, - { "ul_angle", 144, 12, 12, 1, 1, + { "ul_angle", NULL, 144, 12, 12, 1, 1, "\125\125\125\152\252\251\152\252\251\151\125\125\151\000\000\151" "\000\000\151\000\000\151\000\000\151\000\000\151\000\000\151\000" "\000\125\000\000" }, - { "umbrella", 146, 16, 16, 8, 2, + { "umbrella", NULL, 146, 16, 16, 8, 2, "\001\025\024\124\121\125\125\105\105\225\226\120\025\131\131\225" "\145\226\231\140\131\152\245\225\126\006\102\124\000\006\100\000" "\000\006\100\000\000\006\100\000\000\006\100\000\000\006\124\000" "\000\006\124\000\000\006\144\000\000\006\144\000\000\001\220\000" }, - { "ur_angle", 148, 12, 12, 10, 1, + { "ur_angle", NULL, 148, 12, 12, 10, 1, "\125\125\125\152\252\251\152\252\251\125\125\151\000\000\151\000" "\000\151\000\000\151\000\000\151\000\000\151\000\000\151\000\000" "\151\000\000\125" }, - { "watch", 150, 16, 16, 15, 9, + { "watch", IDC_WAIT, 150, 16, 16, 15, 9, "\006\252\251\000\006\252\251\000\006\252\251\000\032\252\252\100" "\151\126\126\220\245\126\125\245\225\126\125\152\225\132\225\152" "\225\132\225\152\225\145\125\152\245\225\125\245\151\125\126\220" "\032\252\252\100\006\252\251\000\006\252\251\000\006\252\251\000" }, - { "xterm", 152, 9, 16, 4, 8, + { "xterm", IDC_IBEAM, 152, 9, 16, 4, 8, "\125\025\132\232\225\152\124\026\120\001\220\000\144\000\031\000" "\006\100\001\220\000\144\000\031\000\006\100\005\224\025\251\126" "\246\245\124\125" }, diff -udpr gtk+-2.6.7_/gdk-pixbuf/gdk-pixbuf-private.h gtk+-2.6.7/gdk-pixbuf/gdk-pixbuf-private.h --- gtk+-2.6.7_/gdk-pixbuf/gdk-pixbuf-private.h 2004-11-16 05:01:57.000000000 +0200 +++ gtk+-2.6.7/gdk-pixbuf/gdk-pixbuf-private.h 2020-12-27 16:22:52.532875169 +0200 @@ -97,9 +97,9 @@ GdkPixbuf *_gdk_pixbuf_generic_image_loa GdkPixbufFormat *_gdk_pixbuf_get_format (GdkPixbufModule *image_module); #ifdef USE_GMODULE -#define MODULE_ENTRY(type,function) function +#define MODULE_ENTRY(type,function) __declspec(dllexport) function #else -#define MODULE_ENTRY(type,function) _gdk_pixbuf__ ## type ## _ ## function +#define MODULE_ENTRY(type,function) __declspec(dllexport) _gdk_pixbuf__ ## type ## _ ## function #endif #endif /* GDK_PIXBUF_ENABLE_BACKEND */ diff -udpr gtk+-2.6.7_/gdk-pixbuf/io-bmp.c gtk+-2.6.7/gdk-pixbuf/io-bmp.c --- gtk+-2.6.7_/gdk-pixbuf/io-bmp.c 2005-04-10 00:53:39.000000000 +0300 +++ gtk+-2.6.7/gdk-pixbuf/io-bmp.c 2020-12-27 16:22:52.532875169 +0200 @@ -1074,14 +1074,10 @@ gdk_pixbuf__bmp_image_load_increment(gpo gint BytesToCopy; - g_print ("load_inc\n"); if (context->read_state == READ_STATE_DONE) return TRUE; else if (context->read_state == READ_STATE_ERROR) - { - g_print ("ah\n"); return FALSE; - } while (size > 0) { if (context->BufferDone < context->BufferSize) { /* We still @@ -1107,37 +1103,25 @@ gdk_pixbuf__bmp_image_load_increment(gpo if (!DecodeHeader (context->buff, context->buff + 14, context, error)) - { - g_print ("bla\n"); return FALSE; - } break; case READ_STATE_PALETTE: if (!DecodeColormap (context->buff, context, error)) - { - g_print ("bleh\n"); return FALSE; - } break; case READ_STATE_BITMASKS: if (!decode_bitmasks (context->buff, context, error)) - { - g_print ("blurb\n"); return FALSE; - } break; case READ_STATE_DATA: if (context->Compressed == BI_RGB || context->Compressed == BI_BITFIELDS) OneLine (context); else if (!DoCompressed (context, error)) - { - g_print ("blurb\n"); return FALSE; - } break; case READ_STATE_DONE: diff -udpr gtk+-2.6.7_/gdk-pixbuf/io-pnm.c gtk+-2.6.7/gdk-pixbuf/io-pnm.c --- gtk+-2.6.7_/gdk-pixbuf/io-pnm.c 2005-02-16 05:39:27.000000000 +0200 +++ gtk+-2.6.7/gdk-pixbuf/io-pnm.c 2020-12-27 16:22:52.532875169 +0200 @@ -245,7 +245,7 @@ pnm_read_next_value (PnmIOBuffer *inbuf, /* get the value */ result = strtol (buf, &endptr, 10); - if (*endptr != '\0' || result < 0) { + if (*endptr != '\0' || result < 0 || result > G_MAXUINT) { g_set_error (error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_CORRUPT_IMAGE, diff -udpr gtk+-2.6.7_/gdk-pixbuf/io-xpm.c gtk+-2.6.7/gdk-pixbuf/io-xpm.c --- gtk+-2.6.7_/gdk-pixbuf/io-xpm.c 2005-03-03 16:03:53.000000000 +0200 +++ gtk+-2.6.7/gdk-pixbuf/io-xpm.c 2020-12-27 16:22:52.533875169 +0200 @@ -1167,7 +1167,8 @@ file_buffer (enum buf_op op, gpointer ha /* Fall through to the xpm_read_string. */ case op_body: - xpm_read_string (h->infile, &h->buffer, &h->buffer_size); + if(!xpm_read_string (h->infile, &h->buffer, &h->buffer_size)) + return NULL; return h->buffer; default: @@ -1262,7 +1263,9 @@ pixbuf_create_from_xpm (const gchar * (* _("XPM has invalid number of chars per pixel")); return NULL; } - if (n_col <= 0 || n_col >= G_MAXINT / (cpp + 1)) { + if (n_col <= 0 || + n_col >= G_MAXINT / (cpp + 1) || + n_col >= G_MAXINT / sizeof (XPMColor)) { g_set_error (error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_CORRUPT_IMAGE, diff -udpr gtk+-2.6.7_/gtk/gtkcombobox.c gtk+-2.6.7/gtk/gtkcombobox.c --- gtk+-2.6.7_/gtk/gtkcombobox.c 2005-04-09 01:03:53.000000000 +0300 +++ gtk+-2.6.7/gtk/gtkcombobox.c 2020-12-27 16:22:52.533875169 +0200 @@ -103,6 +103,7 @@ struct _GtkComboBoxPrivate guint changed_id; guint popup_idle_id; guint scroll_timer; + guint resize_idle_id; gint width; GSList *cells; @@ -2852,6 +2853,8 @@ list_popup_resize_idle (gpointer user_da gtk_window_move (GTK_WINDOW (combo_box->priv->popup_window), x, y); } + combo_box->priv->resize_idle_id = 0; + GDK_THREADS_LEAVE (); return FALSE; @@ -2860,7 +2863,9 @@ list_popup_resize_idle (gpointer user_da static void gtk_combo_box_list_popup_resize (GtkComboBox *combo_box) { - g_idle_add (list_popup_resize_idle, combo_box); + if (!combo_box->priv->resize_idle_id) + combo_box->priv->resize_idle_id = + g_idle_add (list_popup_resize_idle, combo_box); } static void @@ -3330,6 +3335,12 @@ gtk_combo_box_list_destroy (GtkComboBox combo_box->priv->scroll_timer = 0; } + if (combo_box->priv->resize_idle_id) + { + g_source_remove (combo_box->priv->resize_idle_id); + combo_box->priv->resize_idle_id = 0; + } + gtk_widget_destroy (combo_box->priv->tree_view); combo_box->priv->tree_view = NULL; @@ -3416,7 +3427,8 @@ gtk_combo_box_list_button_released (GtkW if (ewidget != combo_box->priv->tree_view) { - if (ewidget == combo_box->priv->button && + if ((ewidget == combo_box->priv->button || + ewidget == combo_box->priv->box ) && !popup_in_progress && gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (combo_box->priv->button))) { @@ -3425,7 +3437,8 @@ gtk_combo_box_list_button_released (GtkW } /* released outside treeview */ - if (ewidget != combo_box->priv->button) + if (ewidget != combo_box->priv->button && + ewidget != combo_box->priv->box) { gtk_combo_box_popdown (combo_box); @@ -3618,10 +3631,10 @@ gtk_combo_box_list_auto_scroll (GtkCombo value = adj->value - (tree_view->allocation.y - y + 1); gtk_adjustment_set_value (adj, CLAMP (value, adj->lower, adj->upper - adj->page_size)); } - else if (y >= tree_view->allocation.y + tree_view->allocation.height && + else if (y >= tree_view->allocation.height && adj->upper - adj->page_size > adj->value) { - value = adj->value + (y - tree_view->allocation.y - tree_view->allocation.height + 1); + value = adj->value + (y - tree_view->allocation.height + 1); gtk_adjustment_set_value (adj, CLAMP (value, 0.0, adj->upper - adj->page_size)); } } diff -udpr gtk+-2.6.7_/gtk/gtkdnd.c gtk+-2.6.7/gtk/gtkdnd.c --- gtk+-2.6.7_/gtk/gtkdnd.c 2005-03-20 08:25:27.000000000 +0200 +++ gtk+-2.6.7/gtk/gtkdnd.c 2020-12-27 16:22:52.534875169 +0200 @@ -1949,11 +1949,7 @@ gtk_drag_begin_internal (GtkWidget return NULL; } - if (gdk_keyboard_grab (ipc_widget->window, FALSE, time) != 0) - { - gtk_drag_release_ipc_widget (ipc_widget); - return NULL; - } + gdk_keyboard_grab (ipc_widget->window, FALSE, time); /* We use a GTK grab here to override any grabs that the widget * we are dragging from might have held @@ -2145,6 +2141,9 @@ gtk_drag_source_set (GtkWidget g_signal_connect (widget, "button_press_event", G_CALLBACK (gtk_drag_source_event_cb), site); + g_signal_connect (widget, "button_release_event", + G_CALLBACK (gtk_drag_source_event_cb), + site); g_signal_connect (widget, "motion_notify_event", G_CALLBACK (gtk_drag_source_event_cb), site); @@ -2183,9 +2182,6 @@ gtk_drag_source_unset (GtkWidget g_signal_handlers_disconnect_by_func (widget, gtk_drag_source_event_cb, site); - g_signal_handlers_disconnect_by_func (widget, - gtk_drag_source_event_cb, - site); g_object_set_data (G_OBJECT (widget), "gtk-site-data", NULL); } } diff -udpr gtk+-2.6.7_/gtk/gtkentry.c gtk+-2.6.7/gtk/gtkentry.c --- gtk+-2.6.7_/gtk/gtkentry.c 2005-04-07 07:45:30.000000000 +0300 +++ gtk+-2.6.7/gtk/gtkentry.c 2020-12-27 16:22:52.534875169 +0200 @@ -75,6 +75,8 @@ struct _GtkEntryPrivate { gfloat xalign; gint insert_pos; + guint real_changed : 1; + guint change_count : 8; }; enum { @@ -349,6 +351,9 @@ static void disconnect_completio static void connect_completion_signals (GtkEntry *entry, GtkEntryCompletion *completion); +static void begin_change (GtkEntry *entry); +static void end_change (GtkEntry *entry); +static void emit_changed (GtkEntry *entry); static GtkWidgetClass *parent_class = NULL; @@ -1024,6 +1029,46 @@ gtk_entry_init (GtkEntry *entry) G_CALLBACK (gtk_entry_delete_surrounding_cb), entry); } +static void +begin_change (GtkEntry *entry) +{ + GtkEntryPrivate *priv = GTK_ENTRY_GET_PRIVATE (entry); + + priv->change_count++; +} + +static void +end_change (GtkEntry *entry) +{ + GtkEditable *editable = GTK_EDITABLE (entry); + GtkEntryPrivate *priv = GTK_ENTRY_GET_PRIVATE (entry); + + g_return_if_fail (priv->change_count > 0); + + priv->change_count--; + + if (priv->change_count == 0) + { + if (priv->real_changed) + { + g_signal_emit_by_name (editable, "changed"); + priv->real_changed = FALSE; + } + } +} + +static void +emit_changed (GtkEntry *entry) +{ + GtkEditable *editable = GTK_EDITABLE (entry); + GtkEntryPrivate *priv = GTK_ENTRY_GET_PRIVATE (entry); + + if (priv->change_count == 0) + g_signal_emit_by_name (editable, "changed"); + else + priv->real_changed = TRUE; +} + /* * Overwrite a memory that might contain sensitive information. */ @@ -2243,7 +2288,7 @@ gtk_entry_real_insert_text (GtkEditable gtk_entry_recompute (entry); - g_signal_emit_by_name (editable, "changed"); + emit_changed (entry); g_object_notify (G_OBJECT (editable), "text"); } @@ -2293,7 +2338,7 @@ gtk_entry_real_delete_text (GtkEditable gtk_entry_recompute (entry); - g_signal_emit_by_name (editable, "changed"); + emit_changed (entry); g_object_notify (G_OBJECT (editable), "text"); } } @@ -3553,7 +3598,7 @@ gtk_entry_move_forward_word (GtkEntry *e /* Find the next word end */ new_pos++; - while (new_pos < n_attrs && !log_attrs[new_pos].is_word_end) + while (new_pos < n_attrs - 1 && !log_attrs[new_pos].is_word_end) new_pos++; g_free (log_attrs); @@ -3688,12 +3733,16 @@ paste_received (GtkClipboard *clipboard, _gtk_entry_completion_popdown (completion); } + begin_change (entry); + g_object_freeze_notify (G_OBJECT (entry)); if (gtk_editable_get_selection_bounds (editable, &start, &end)) gtk_editable_delete_text (editable, start, end); pos = entry->current_pos; gtk_editable_insert_text (editable, text, -1, &pos); gtk_editable_set_position (editable, pos); + g_object_thaw_notify (G_OBJECT (entry)); + end_change (entry); if (completion) g_signal_handler_unblock (entry, completion->priv->changed_id); @@ -3838,10 +3887,14 @@ gtk_entry_set_text (GtkEntry *entry, if (completion) g_signal_handler_block (entry, completion->priv->changed_id); + begin_change (entry); + g_object_freeze_notify (G_OBJECT (entry)); gtk_editable_delete_text (GTK_EDITABLE (entry), 0, -1); tmp_pos = 0; gtk_editable_insert_text (GTK_EDITABLE (entry), text, strlen (text), &tmp_pos); + g_object_thaw_notify (G_OBJECT (entry)); + end_change (entry); if (completion) g_signal_handler_unblock (entry, completion->priv->changed_id); @@ -4724,8 +4777,12 @@ gtk_entry_drag_data_received (GtkWidget else { /* Replacing selection */ + begin_change (entry); + g_object_freeze_notify (G_OBJECT (entry)); gtk_editable_delete_text (editable, sel1, sel2); gtk_editable_insert_text (editable, str, -1, &sel1); + g_object_thaw_notify (G_OBJECT (entry)); + end_change (entry); } g_free (str); @@ -4790,6 +4847,7 @@ cursor_blinks (GtkEntry *entry) gboolean blink; if (GTK_WIDGET_HAS_FOCUS (entry) && + entry->editable && entry->selection_bound == entry->current_pos) { g_object_get (settings, "gtk-cursor-blink", &blink, NULL); diff -udpr gtk+-2.6.7_/gtk/gtkfilesel.c gtk+-2.6.7/gtk/gtkfilesel.c --- gtk+-2.6.7_/gtk/gtkfilesel.c 2005-04-07 07:45:30.000000000 +0300 +++ gtk+-2.6.7/gtk/gtkfilesel.c 2020-12-27 16:22:52.535875169 +0200 @@ -2070,7 +2070,8 @@ win32_gtk_add_drives_to_dir_list (GtkLis while (*textPtr != '\0') { /* Ignore floppies (?) */ - if (GetDriveType (textPtr) != DRIVE_REMOVABLE) +// We need to see flash drives too - WJ +// if (GetDriveType (textPtr) != DRIVE_REMOVABLE) { /* Build the actual displayable string */ g_snprintf (formatBuffer, sizeof (formatBuffer), "%c:\\", toupper (textPtr[0])); diff -udpr gtk+-2.6.7_/gtk/gtkmain.c gtk+-2.6.7/gtk/gtkmain.c --- gtk+-2.6.7_/gtk/gtkmain.c 2005-03-20 08:25:28.000000000 +0200 +++ gtk+-2.6.7/gtk/gtkmain.c 2020-12-27 16:22:52.535875169 +0200 @@ -290,13 +290,46 @@ _gtk_get_libdir (void) return gtk_libdir; } +/* Lifted from HEAD GLib */ +static gchar * +g_win32_locale_filename_from_utf8 (const gchar *utf8filename) +{ + gchar *retval = g_locale_from_utf8 (utf8filename, -1, NULL, NULL, NULL); + + if (retval == NULL && G_WIN32_HAVE_WIDECHAR_API ()) + { + /* Conversion failed, so convert to wide chars, check if there + * is a 8.3 version, and use that. + */ + wchar_t *wname = g_utf8_to_utf16 (utf8filename, -1, NULL, NULL, NULL); + if (wname != NULL) + { + wchar_t wshortname[MAX_PATH + 1]; + if (GetShortPathNameW (wname, wshortname, G_N_ELEMENTS (wshortname))) + { + gchar *tem = g_utf16_to_utf8 (wshortname, -1, NULL, NULL, NULL); + retval = g_locale_from_utf8 (tem, -1, NULL, NULL, NULL); + g_free (tem); + } + g_free (wname); + } + } + return retval; +} + const gchar * _gtk_get_localedir (void) { static char *gtk_localedir = NULL; if (gtk_localedir == NULL) - gtk_localedir = g_win32_get_package_installation_subdirectory - (GETTEXT_PACKAGE, dll_name, "lib\\locale"); + { + gtk_localedir = g_win32_get_package_installation_subdirectory (GETTEXT_PACKAGE, dll_name, "lib\\locale"); + if (gtk_localedir != NULL) + gtk_localedir = g_win32_locale_filename_from_utf8 (gtk_localedir); + + if (gtk_localedir == NULL) + gtk_localedir = "\\"; /* Punt */ + } return gtk_localedir; } diff -udpr gtk+-2.6.7_/gtk/gtknotebook.c gtk+-2.6.7/gtk/gtknotebook.c --- gtk+-2.6.7_/gtk/gtknotebook.c 2005-04-07 07:45:30.000000000 +0300 +++ gtk+-2.6.7/gtk/gtknotebook.c 2020-12-27 16:22:52.536875169 +0200 @@ -4370,10 +4370,8 @@ gtk_notebook_insert_page_menu (GtkNotebo if (!notebook->first_tab) notebook->first_tab = notebook->children; - if (!notebook->cur_page) - gtk_widget_set_child_visible (child, TRUE); - else - gtk_widget_set_child_visible (child, FALSE); + /* child visible will be turned on by switch_page below */ + gtk_widget_set_child_visible (child, FALSE); if (tab_label) { diff -udpr gtk+-2.6.7_/gtk/gtkradiobutton.c gtk+-2.6.7/gtk/gtkradiobutton.c --- gtk+-2.6.7_/gtk/gtkradiobutton.c 2005-03-20 08:25:28.000000000 +0200 +++ gtk+-2.6.7/gtk/gtkradiobutton.c 2020-12-27 16:22:52.536875169 +0200 @@ -510,7 +510,7 @@ gtk_radio_button_focus (GtkWidget { GtkWidget *child = tmp_list->data; - if (GTK_WIDGET_VISIBLE (child) && GTK_WIDGET_IS_SENSITIVE (child)) + if (GTK_WIDGET_REALIZED (child) && GTK_WIDGET_IS_SENSITIVE (child)) { new_focus = child; break; @@ -528,7 +528,7 @@ gtk_radio_button_focus (GtkWidget { GtkWidget *child = tmp_list->data; - if (GTK_WIDGET_VISIBLE (child) && GTK_WIDGET_IS_SENSITIVE (child)) + if (GTK_WIDGET_REALIZED (child) && GTK_WIDGET_IS_SENSITIVE (child)) { new_focus = child; break; diff -udpr gtk+-2.6.7_/gtk/gtkscale.c gtk+-2.6.7/gtk/gtkscale.c --- gtk+-2.6.7_/gtk/gtkscale.c 2005-04-07 07:45:30.000000000 +0300 +++ gtk+-2.6.7/gtk/gtkscale.c 2020-12-27 16:22:52.536875169 +0200 @@ -265,10 +265,10 @@ gtk_scale_class_init (GtkScaleClass *cla add_slider_binding (binding_set, GDK_KP_Down, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_DOWN); - add_slider_binding (binding_set, GDK_Page_Up, 0, + add_slider_binding (binding_set, GDK_Page_Up, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_LEFT); - add_slider_binding (binding_set, GDK_KP_Page_Up, 0, + add_slider_binding (binding_set, GDK_KP_Page_Up, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_LEFT); add_slider_binding (binding_set, GDK_Page_Up, 0, @@ -277,10 +277,10 @@ gtk_scale_class_init (GtkScaleClass *cla add_slider_binding (binding_set, GDK_KP_Page_Up, 0, GTK_SCROLL_PAGE_UP); - add_slider_binding (binding_set, GDK_Page_Down, 0, + add_slider_binding (binding_set, GDK_Page_Down, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_RIGHT); - add_slider_binding (binding_set, GDK_KP_Page_Down, 0, + add_slider_binding (binding_set, GDK_KP_Page_Down, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_RIGHT); add_slider_binding (binding_set, GDK_Page_Down, 0, diff -udpr gtk+-2.6.7_/gtk/gtkwindow.c gtk+-2.6.7/gtk/gtkwindow.c --- gtk+-2.6.7_/gtk/gtkwindow.c 2005-04-07 08:09:33.000000000 +0300 +++ gtk+-2.6.7/gtk/gtkwindow.c 2020-12-27 16:22:52.537875169 +0200 @@ -4695,16 +4695,20 @@ gtk_window_real_set_focus (GtkWindow *wi { GtkWidget *old_focus = window->focus_widget; gboolean had_default = FALSE; + gboolean focus_had_default = FALSE; + gboolean old_focus_had_default = FALSE; if (old_focus) { g_object_ref (old_focus); g_object_freeze_notify (G_OBJECT (old_focus)); + old_focus_had_default = GTK_WIDGET_HAS_DEFAULT (old_focus); } if (focus) { g_object_ref (focus); g_object_freeze_notify (G_OBJECT (focus)); + focus_had_default = GTK_WIDGET_HAS_DEFAULT (focus); } if (window->default_widget) @@ -4716,10 +4720,11 @@ gtk_window_real_set_focus (GtkWindow *wi (window->focus_widget != window->default_widget)) { GTK_WIDGET_UNSET_FLAGS (window->focus_widget, GTK_HAS_DEFAULT); - + gtk_widget_queue_draw (window->focus_widget); + if (window->default_widget) GTK_WIDGET_SET_FLAGS (window->default_widget, GTK_HAS_DEFAULT); - } + } window->focus_widget = NULL; @@ -4761,14 +4766,20 @@ gtk_window_real_set_focus (GtkWindow *wi if (window->default_widget && (had_default != GTK_WIDGET_HAS_DEFAULT (window->default_widget))) gtk_widget_queue_draw (window->default_widget); - + if (old_focus) { + if (old_focus_had_default != GTK_WIDGET_HAS_DEFAULT (old_focus)) + gtk_widget_queue_draw (old_focus); + g_object_thaw_notify (G_OBJECT (old_focus)); g_object_unref (old_focus); } if (focus) { + if (focus_had_default != GTK_WIDGET_HAS_DEFAULT (focus)) + gtk_widget_queue_draw (focus); + g_object_thaw_notify (G_OBJECT (focus)); g_object_unref (focus); } diff -udpr gtk+-2.6.7_/modules/engines/ms-windows/msw_style.c gtk+-2.6.7/modules/engines/ms-windows/msw_style.c --- gtk+-2.6.7_/modules/engines/ms-windows/msw_style.c 2005-03-21 00:40:58.000000000 +0200 +++ gtk+-2.6.7/modules/engines/ms-windows/msw_style.c 2020-12-27 16:22:52.537875169 +0200 @@ -1448,10 +1448,13 @@ draw_box (GtkStyle *style, } else if (detail && strcmp (detail, "menuitem") == 0) { shadow_type = GTK_SHADOW_NONE; +#if 0 + /* don't work with Vista */ if (xp_theme_draw (window, XP_THEME_ELEMENT_MENU_ITEM, style, x, y, width, height, state_type, area)) { return; } +#endif } else if (detail && !strcmp (detail, "trough")) { mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/gtk/gtkrc000066400000000000000000000011771471325446300220030ustar00rootroot00000000000000gtk-icon-sizes="gtk-menu=14,14:gtk-small-toolbar=16,16:gtk-large-toolbar=24,24:gtk-dnd=32,32" gtk-toolbar-icon-size=large-toolbar #gtk-button-images=0 gtk-alternative-button-order=1 style "msw-default" { GtkWidget::interior_focus = 1 GtkOptionMenu::indicator_size = { 9, 5 } GtkOptionMenu::indicator_spacing = { 7, 5, 2, 2 } GtkToolbar::shadow-type = none GtkHandleBox::shadow-type = etched-in GtkSpinButton::shadow-type = in GtkComboBox::add-tearoffs = false GtkTreeView::allow-rules = 0 GtkTreeView::expander_size = 11 GtkUIManager::add-tearoffs = false engine "wimp" { } } class "*" style "msw-default" mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/gtk/loaders.cache000066400000000000000000000007341471325446300233620ustar00rootroot00000000000000# GdkPixbuf Image Loader Modules file # Automatically generated file, do not edit # Created by gdk-pixbuf-query-loaders.exe from gdk-pixbuf-2.32.3 # "lib/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-svg.dll" "svg" 6 "gdk-pixbuf" "Scalable Vector Graphics" "LGPL" "image/svg+xml" "image/svg" "image/svg-xml" "image/vnd.adobe.svg+xml" "text/xml-svg" "image/svg+xml-compressed" "" "svg" "svgz" "svg.gz" "" " 89?@:;AB<=C8899::;;<<==8899::;;<<==8899::;;<<==8899::;;<<==8899::;;<<==8899::;;<<==8899::;;<<==8899::;;<<==8899::;;<<==8899::;;<<==8899::;;<<==8899::;;<<==8899::;;<<==8899::;;<<==8899::;;<<==8899::;;<<==8899::;;<<==8899::;;<<==8899::;;<<==,-###./01###2345###67!&*#+)%!&*#+)%!&*#+)%&'#()&'#()&'#()!"#$%!"#$%!"#$%   mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/gtk/pango.aliases000066400000000000000000000030511471325446300234060ustar00rootroot00000000000000# Default pango.aliases file used on Windows courier = "courier new" # Segoe UI is the default system font on Vista "segoe ui" = "segoe ui,meiryo,malgun gothic,microsoft jhenghei,microsoft yahei,gisha,leelawadee,arial unicode ms,browallia new,mingliu,simhei,gulimche,ms gothic,sylfaen,kartika,latha,mangal,raavi" # Tahoma on XP tahoma = "tahoma,arial unicode ms,lucida sans unicode,browallia new,mingliu,simhei,gulimche,ms gothic,sylfaen,kartika,latha,mangal,raavi" # The standard pseudo fonts # It sucks to use the same GulimChe, MS Gothic, Sylfaen, Kartika, # Latha, Mangal and Raavi fonts for all three of sans, serif and # mono, but it isn't like there would be much choice. For most # non-Latin scripts that Windows includes any font at all for, it # has ony one. One solution is to install the free DejaVu fonts # that are popular on Linux. They are listed here first. sans = "dejavu sans,tahoma,arial unicode ms,lucida sans unicode,browallia new,mingliu,simhei,gulimche,ms gothic,sylfaen,kartika,latha,mangal,raavi" sans-serif = "dejavu sans,tahoma,arial unicode ms,lucida sans unicode,browallia new,mingliu,simhei,gulimche,ms gothic,sylfaen,kartika,latha,mangal,raavi" serif = "dejavu serif,georgia,angsana new,mingliu,simsun,gulimche,ms gothic,sylfaen,kartika,latha,mangal,raavi" mono = "dejavu sans mono,courier new,lucida console,courier monothai,mingliu,simsun,gulimche,ms gothic,sylfaen,kartika,latha,mangal,raavi" monospace = "dejavu sans mono,courier new,lucida console,courier monothai,mingliu,simsun,gulimche,ms gothic,sylfaen,kartika,latha,mangal,raavi" mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/gtk/pango182_1wj.patch000066400000000000000000000106601471325446300241040ustar00rootroot00000000000000diff -udpr pango-1.8.2_/pango/pango-utils.c pango-1.8.2/pango/pango-utils.c --- pango-1.8.2_/pango/pango-utils.c 2005-06-15 02:35:08.000000000 +0400 +++ pango-1.8.2/pango/pango-utils.c 2010-12-06 02:54:30.000000000 +0300 @@ -1472,6 +1472,120 @@ alias_free (struct PangoAlias *alias) g_free (alias); } +#ifdef G_OS_WIN32 + +static const char *builtin_aliases[] = { + "courier = \"courier new\"", + "\"segoe ui\" = \"segoe ui,arial unicode ms,browallia new,mingliu,simhei,gulimche,ms gothic,sylfaen,kartika,latha,mangal,raavi\"", + "tahoma = \"tahoma,arial unicode ms,browallia new,mingliu,simhei,gulimche,ms gothic,sylfaen,kartika,latha,mangal,raavi\"", + /* It sucks to use the same GulimChe, MS Gothic, Sylfaen, Kartika, + * Latha, Mangal and Raavi fonts for all three of sans, serif and + * mono, but it isn't like there would be much choice. For most + * non-Latin scripts that Windows includes any font at all for, it + * has ony one. One solution is to install the free DejaVu fonts + * that are popular on Linux. They are listed here first. + */ + "sans = \"dejavu sans,tahoma,arial unicode ms,browallia new,mingliu,simhei,gulimche,ms gothic,sylfaen,kartika,latha,mangal,raavi\"", + "sans-serif = \"dejavu sans,tahoma,arial unicode ms,browallia new,mingliu,simhei,gulimche,ms gothic,sylfaen,kartika,latha,mangal,raavi\"", + "serif = \"dejavu serif,georgia,angsana new,mingliu,simsun,gulimche,ms gothic,sylfaen,kartika,latha,mangal,raavi\"", + "mono = \"dejavu sans mono,courier new,courier monothai,mingliu,simsun,gulimche,ms gothic,sylfaen,kartika,latha,mangal,raavi\"", + "monospace = \"dejavu sans mono,courier new,courier monothai,mingliu,simsun,gulimche,ms gothic,sylfaen,kartika,latha,mangal,raavi\"" +}; + +static void +read_builtin_aliases (void) +{ + + GString *line_buffer; + GString *tmp_buffer1; + GString *tmp_buffer2; + const char *pos; + int line; + struct PangoAlias alias_key; + struct PangoAlias *alias; + char **new_families; + int n_new; + int i; + + line_buffer = g_string_new (NULL); + tmp_buffer1 = g_string_new (NULL); + tmp_buffer2 = g_string_new (NULL); + +#define ASSERT(x) if (!(x)) g_error ("Assertion failed: " #x) + + for (line = 0; line < G_N_ELEMENTS (builtin_aliases); line++) + { + g_string_assign (line_buffer, builtin_aliases[line]); + gboolean append = FALSE; + + pos = line_buffer->str; + + ASSERT (pango_scan_string (&pos, tmp_buffer1) && + pango_skip_space (&pos)); + + if (*pos == '+') + { + append = TRUE; + pos++; + } + + ASSERT (*(pos++) == '='); + + ASSERT (pango_scan_string (&pos, tmp_buffer2)); + + ASSERT (!pango_skip_space (&pos)); + + alias_key.alias = g_ascii_strdown (tmp_buffer1->str, -1); + + /* Remove any existing values */ + alias = g_hash_table_lookup (pango_aliases_ht, &alias_key); + + if (!alias) + { + alias = g_new0 (struct PangoAlias, 1); + alias->alias = alias_key.alias; + + g_hash_table_insert (pango_aliases_ht, + alias, alias); + } + else + g_free (alias_key.alias); + + new_families = g_strsplit (tmp_buffer2->str, ",", -1); + + n_new = 0; + while (new_families[n_new]) + n_new++; + + if (alias->families && append) + { + alias->families = g_realloc (alias->families, + sizeof (char *) *(n_new + alias->n_families)); + for (i = 0; i < n_new; i++) + alias->families[alias->n_families + i] = new_families[i]; + g_free (new_families); + alias->n_families += n_new; + } + else + { + for (i = 0; i < alias->n_families; i++) + g_free (alias->families[i]); + g_free (alias->families); + + alias->families = new_families; + alias->n_families = n_new; + } + } + +#undef ASSERT + + g_string_free (line_buffer, TRUE); + g_string_free (tmp_buffer1, TRUE); + g_string_free (tmp_buffer2, TRUE); +} + +#endif + static void read_alias_file (const char *filename) { @@ -1507,7 +1621,7 @@ read_alias_file (const char *filename) if (!pango_skip_space (&pos)) continue; - if (!pango_scan_word (&pos, tmp_buffer1) || + if (!pango_scan_string (&pos, tmp_buffer1) || !pango_skip_space (&pos)) { errstring = g_strdup ("Line is not of the form KEY=VALUE or KEY+=VALUE"); @@ -1615,6 +1729,9 @@ pango_load_aliases (void) (GDestroyNotify)alias_free, NULL); +#ifdef G_OS_WIN32 + read_builtin_aliases (); +#endif filename = g_strconcat (pango_get_sysconf_subdirectory (), G_DIR_SEPARATOR_S "pango.aliases", mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/gtk/screenshot.ico000066400000000000000000000042761471325446300236220ustar00rootroot00000000000000 ¨( @€ÿÿÿmmmIIIÛÛÛ¶¶¶’’’$$$ÿ¶mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/gtk/winbuild.sh000066400000000000000000001046111471325446300231140ustar00rootroot00000000000000#!/bin/sh # winbuild.sh - cross-compile GTK+ and its dependencies for Windows # Copyright (C) 2010,2011,2017,2019,2020,2021 Dmitry Groshev # 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 in the file COPYING. ########################## # CONFIGURATION SETTINGS # ########################## LIBS="zlib xz zstd libjpeg libwebp libpng libtiff freetype openjpeg lcms "\ "libiconv gettext glib atk pango gtk" PROGRAMS="gifsicle mtpaint mtpaint_handbook" PHONY="libs all" TOOLS="dev vars" LOCALES="es cs fr pt pt_BR de pl tr zh_TW sk zh_CN ja ru gl nl it sv tl hu" # Applied only to GTK+ ATM OPTIMIZE="-march=i686 -O2 -fweb -fomit-frame-pointer -fmodulo-sched -Wno-pointer-sign" # Everything works OK with package-relative prefix, for now WPREFIX= SRCDIR=`pwd` TOPDIR="$SRCDIR/zad" # Directories for various parts WRKDIR="$TOPDIR/wrk" # Where sources are compiled INSDIR="$TOPDIR/ins" # Where files get installed PKGDIR="$TOPDIR/pkg" # Where package gets formed DEVDIR="$TOPDIR/dev" # Where dev files get collected # Also "$TOPDIR/bin", "$TOPDIR/include" & "$TOPDIR/lib", with symlinks to actual files UNPDIR="$WRKDIR/_000_" # Where archives are unpacked ######################## # CROSS-COMPILER PATHS # ######################## # SpeedBlue cross-MinGW or similar # http://www.speedblue.org/cross_compilation/ MPREFIX=/usr/i586-mingw32-4.2.4 MTARGET=i586-mingw32 # mingw-cross-env # http://mingw-cross-env.nongnu.org/ #MPREFIX=~/mingw-cross-env-2.18/usr #MTARGET=i686-pc-mingw32 # MXE # http://mxe.cc/ #MPREFIX=~/mxe/usr #MTARGET=i686-w64-mingw32.shared ALLPATHS=' LONGPATH="$TOPDIR:$MPREFIX/bin:$PATH" SHORTPATH="$TOPDIR:$TOPDIR/bin:$PATH" ALLPATH="$TOPDIR:$TOPDIR/bin:$MPREFIX/bin:$PATH" ' eval "$ALLPATHS" ######################## # Initialize vars COMPONENTS=" $LIBS $PROGRAMS $PHONY $TOOLS " for ZAD in $COMPONENTS do eval "DEP_$ZAD=" eval "NEED_$ZAD=" eval "HAVE_$ZAD=" done REBUILD= # Don't recompile by default INNER_DIRS=" bin include lib " # !!! Parameter shouldn't contain directory UNPACK () { local ZAD local CNT local FFILE local FNAME local FCMD # Identify the source archive for ZAD in "$SRCDIR"/$1 do if [ -f "$ZAD" ] then FFILE="$ZAD" break fi done if [ -z "$FFILE" ] then echo "ERROR: $1 not found in $SRCDIR" exit 1 fi # Prepare to unpack FNAME="${FFILE#$SRCDIR/}" case "$FFILE" in *.tar.bz2) FDIR=.tar.bz2 ; FCMD="tar $2 -xf" ;; *.tar.gz) FDIR=.tar.gz ; FCMD="tar $2 -xf" ;; *.tar.xz) FDIR=.tar.xz ; FCMD="tar --use-compress-program xz -xf" ;; *.tar.zst) FDIR=.tar.zst ; FCMD="tar --use-compress-program zstd -xf" ;; *.zip) FDIR=.zip ; FCMD="unzip $2" ;; *) echo "ERROR: $FNAME unknown archive type" ; exit 1 ;; esac FDIR="$WRKDIR/${FNAME%$FDIR}" DESTDIR="$INSDIR/${FDIR##*/}" DEST="$DESTDIR$WPREFIX" [ -d "$DESTDIR" -a ! "$REBUILD" ] && return 1 # Prepare temp dir & unpack rm -rf "$UNPDIR" mkdir -p "$UNPDIR" cd "$UNPDIR" $FCMD "$FFILE" cd "$WRKDIR" # Find out if tarbombing happened CNT=0 for ZAD in "$UNPDIR"/* do CNT=$((CNT+1)) done # Check for unexpanded glob if [ $CNT = 1 ] && [ ! -e "$ZAD" ] then echo "ERROR: empty archive $FNAME" exit 1 fi # Move the files to regular location rm -rf "$FDIR" "$DESTDIR" if [ $CNT = 1 ] && [ -d "$ZAD" ] && \ [ "${INNER_DIRS%${ZAD##*/} *}" = "$INNER_DIRS" ] then # With enclosing directory mv "$ZAD/" "$FDIR" else # Tarbomb mv "$UNPDIR" "$FDIR" fi cd "$FDIR" # On return, source directory is current and FDIR holds it; # DESTDIR holds installation directory; and DEST , installdir+prefix return 0 } # Hardcoded direction - from current directory to DEST COPY_BINARIES () { mkdir -p "$DEST" cp -R ./ "$DEST" chmod -R a-x,a+X "$DEST" } # Hardcoded origin - DEST EXPORT () { cp -sfRT "$DEST/include/" "$TOPDIR/include/" cp -sfRT "$DEST/lib/" "$TOPDIR/lib/" rm -f "$TOPDIR/lib/"*.la # !!! These break some utils' compilation } # Relativize .pc file RELATIVIZE () { if grep 'exec_prefix=\$' "$1" then : else # Relativize pkgconfig file cat <<- PKGFIX > "$1"_ prefix=$WPREFIX exec_prefix=\${prefix} libdir=\${exec_prefix}/lib includedir=\${prefix}/include `sed -e '/^Name:/,$!d' "$1"` PKGFIX cp -fp "$1"_ "$1" fi } # Tools TARGET_STRIP="$MPREFIX/bin/$MTARGET-strip" BUILD_zlib () { UNPACK "zlib-*.tar.*" || return 0 PATH="$SHORTPATH" make -f win32/Makefile.gcc install SHARED_MODE=1 INCLUDE_PATH="$DEST/include" \ LIBRARY_PATH="$DEST/lib" BINARY_PATH="$DEST/bin" LOC=-static-libgcc mkdir -p "$DEST/bin" cp -fp zlib1.dll "$DEST"/bin if [ -e "$DEST"/lib/pkgconfig/zlib.pc ] then # Relativize pkgconfig file of zlib 1.2.6+ cat <<- PKGFIX > zlib.pc_ prefix=$WPREFIX exec_prefix=\${prefix} libdir=\${exec_prefix}/lib sharedlibdir=\${libdir} includedir=\${prefix}/include `sed -e '/^Name:/,$!d' "$DEST"/lib/pkgconfig/zlib.pc` PKGFIX cp -fp zlib.pc_ "$DEST"/lib/pkgconfig/zlib.pc else # Rename import lib of zlib 1.2.5 cp -fp libzdll.a "$DEST"/lib/libz.dll.a fi EXPORT } BUILD_xz () { UNPACK "xz-*.tar.*" || return 0 PATH="$LONGPATH" ./configure --prefix="$WPREFIX" --host=$MTARGET --disable-threads \ --disable-nls --enable-small --disable-scripts LDFLAGS=-static-libgcc make make install-strip DESTDIR="$DESTDIR" RELATIVIZE "$DEST"/lib/pkgconfig/liblzma.pc EXPORT } BUILD_zstd () { UNPACK "zstd-*.tar.*" || return 0 # Stop dragging C++ in by default sed -i '/^project(/ s/)/ C)/' build/cmake/CMakeLists.txt build/cmake/*/CMakeLists.txt patch -p1 <<- 'UNCXX' # Not attempt to mess with C++ cross-compiler --- zstd-1.4.5_/build/cmake/CMakeLists.txt 2020-05-22 08:04:00.000000000 +0300 +++ zstd-1.4.5/build/cmake/CMakeLists.txt 2020-11-08 18:14:22.171222309 +0200 @@ -40,12 +40,10 @@ set(PROJECT_VERSION_PATCH ${zstd_VERSION_PATCH}) set(PROJECT_VERSION "${zstd_VERSION_MAJOR}.${zstd_VERSION_MINOR}.${zstd_VERSION_PATCH}") enable_language(C) # Main library is in C - enable_language(CXX) # Testing contributed code also utilizes CXX else() project(zstd VERSION "${zstd_VERSION_MAJOR}.${zstd_VERSION_MINOR}.${zstd_VERSION_PATCH}" LANGUAGES C # Main library is in C - CXX # Testing contributed code also utilizes CXX ) endif() message(STATUS "ZSTD VERSION: ${zstd_VERSION}") --- zstd-1.4.5_/build/cmake/CMakeModules/AddZstdCompilationFlags.cmake 2020-05-22 08:04:00.000000000 +0300 +++ zstd-1.4.5/build/cmake/CMakeModules/AddZstdCompilationFlags.cmake 2020-11-08 18:17:48.056232126 +0200 @@ -1,4 +1,3 @@ -include(CheckCXXCompilerFlag) include(CheckCCompilerFlag) function(EnableCompilerFlag _flag _C _CXX) @@ -12,18 +11,10 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${_flag}" PARENT_SCOPE) endif () endif () - if (_CXX) - CHECK_CXX_COMPILER_FLAG(${_flag} CXX_FLAG_${varname}) - if (CXX_FLAG_${varname}) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${_flag}" PARENT_SCOPE) - endif () - endif () endfunction() macro(ADD_ZSTD_COMPILATION_FLAGS) - if (CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang" OR MINGW) #Not only UNIX but also WIN32 for MinGW - #Set c++11 by default - EnableCompilerFlag("-std=c++11" false true) + if (CMAKE_C_COMPILER_ID MATCHES "GNU|Clang" OR MINGW) #Not only UNIX but also WIN32 for MinGW #Set c99 by default EnableCompilerFlag("-std=c99" true false) EnableCompilerFlag("-Wall" true true) @@ -56,8 +47,7 @@ # Remove duplicates compilation flags foreach (flag_var CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO - CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE - CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO) + ) if( ${flag_var} ) separate_arguments(${flag_var}) list(REMOVE_DUPLICATES ${flag_var}) UNCXX patch -p1 <<- 'PKGC' # Install .pc --- a/build/cmake/lib/CMakeLists.txt +++ b/build/cmake/lib/CMakeLists.txt @@ -165,7 +165,7 @@ if (ZSTD_BUILD_STATIC) OUTPUT_NAME ${STATIC_LIBRARY_BASE_NAME}) endif () -if (UNIX) +if (UNIX OR MINGW) # pkg-config set(PREFIX "${CMAKE_INSTALL_PREFIX}") set(LIBDIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}") PKGC patch -p1 <<- 'DLLDIR' # Install .dll --- a/build/cmake/lib/CMakeLists.txt +++ b/build/cmake/lib/CMakeLists.txt @@ -163,6 +163,7 @@ install(TARGETS ${library_targets} INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" + RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" ) # uninstall target DLLDIR PATH="$LONGPATH" mkdir tbuild cd tbuild LDFLAGS=-static-libgcc \ cmake -DCMAKE_TOOLCHAIN_FILE="$TOPDIR/toolchain" \ -DZSTD_MULTITHREAD_SUPPORT=OFF -DZSTD_BUILD_STATIC=OFF \ -DZSTD_BUILD_PROGRAMS=OFF -DCMAKE_INSTALL_PREFIX= \ ../build/cmake make make install DESTDIR="$DESTDIR" "$TARGET_STRIP" --strip-unneeded "$DEST"/bin/*.dll RELATIVIZE "$DEST"/lib/pkgconfig/libzstd.pc EXPORT } BUILD_libjpeg () { UNPACK "jpegsrc.*.tar.*" || return 0 PATH="$LONGPATH" ./configure --prefix="$WPREFIX" --host=$MTARGET LDFLAGS=-static-libgcc make make install-strip DESTDIR="$DESTDIR" EXPORT } BUILD_libwebp () { UNPACK "libwebp-*.tar.*" || return 0 PATH="$LONGPATH" NOCONFIGURE=1 ./autogen.sh CPPFLAGS="-isystem $TOPDIR/include" LDFLAGS="-static-libgcc -L$TOPDIR/lib" \ ./configure --prefix="$WPREFIX" --host=$MTARGET --disable-static \ --disable-silent-rules --enable-everything --enable-swap-16bit-csp make make install-strip DESTDIR="$DESTDIR" EXPORT } DEP_libpng="zlib" BUILD_libpng () { UNPACK "libpng-*.tar.*" || return 0 # !!! Binutils 2.20 cannot create proper export libs if given a version # script; so any libpng version before 1.4.4 needs the below fix sed -i 's/have_ld_version_script=yes/have_ld_version_script=no/' ./configure # !!! Make libpng12 default DLL, same as it is default everything else sed -i 's/for ext in a la so sl/for ext in a dll.a la so sl/' ./Makefile.in PATH="$LONGPATH" CPPFLAGS="-isystem $TOPDIR/include" LDFLAGS="-static-libgcc -L$TOPDIR/lib" \ ./configure --prefix="$WPREFIX" --host=$MTARGET --without-libpng-compat make make install-strip DESTDIR="$DESTDIR" EXPORT } DEP_libtiff="zlib xz zstd libjpeg libwebp" BUILD_libtiff () { UNPACK "tiff-*.tar.*" || return 0 PATH="$LONGPATH" CPPFLAGS="-isystem $TOPDIR/include" LDFLAGS="-L$TOPDIR/lib" \ ./configure --prefix="$WPREFIX" --host=$MTARGET --disable-cxx \ --without-x make LDFLAGS="-XCClinker -static-libgcc -L$TOPDIR/lib" make install-strip DESTDIR="$DESTDIR" EXPORT } DEP_freetype="zlib libpng" BUILD_freetype () { UNPACK "freetype-*.tar.*" || return 0 sed -i 's/_pkg_min_version=.*/_pkg_min_version=0.23/' \ builds/unix/configure # Does not need more # !!! Cross-compile breaks down if cross-gcc named "gcc" is present in PATH PATH="$LONGPATH" CPPFLAGS="-isystem $TOPDIR/include" LDFLAGS="-static-libgcc -L$TOPDIR/lib" \ ./configure --prefix="$WPREFIX" --host=$MTARGET make "$TARGET_STRIP" --strip-unneeded objs/.libs/*.dll objs/.libs/*.a make install DESTDIR="$DESTDIR" if grep 'exec_prefix=\$' "$DEST"/lib/pkgconfig/freetype2.pc then : else # Relativize pkgconfig file of FreeType 2.4.12+ cat <<- PKGFIX > freetype2.pc_ prefix=$WPREFIX exec_prefix=\${prefix} libdir=\${exec_prefix}/lib includedir=\${prefix}/include `sed -e '/^Name:/,$!d' "$DEST"/lib/pkgconfig/freetype2.pc` PKGFIX cp -fp freetype2.pc_ "$DEST"/lib/pkgconfig/freetype2.pc fi EXPORT } : << 'COMMENTED_OUT' DEP_jasper="libjpeg" # !!! Versions 2.x not supported yet !!! BUILD_jasper () { UNPACK "jasper-1.*.tar.*" || return 0 sed -i '/libjasper_la_LDFLAGS/ s/=/= -no-undefined/' src/libjasper/Makefile.in patch -p1 <<- 'END' # Fix compilation diff -rup jasper-1.900.1/src/appl/tmrdemo.c jasper-1.900.1.new/src/appl/tmrdemo.c --- jasper-1.900.1/src/appl/tmrdemo.c 2007-01-19 16:43:08.000000000 -0500 +++ jasper-1.900.1.new/src/appl/tmrdemo.c 2008-09-09 09:14:21.000000000 -0400 @@ -1,4 +1,5 @@ #include +#include int main(int argc, char **argv) { @@ -43,7 +44,7 @@ int main(int argc, char **argv) printf("zero time %.3f us\n", t * 1e6); jas_tmr_start(&tmr); - sleep(1); + Sleep(1); jas_tmr_stop(&tmr); t = jas_tmr_get(&tmr); printf("time delay %.8f s\n", t); END PATH="$LONGPATH" CPPFLAGS="-isystem $TOPDIR/include" LDFLAGS="-L$TOPDIR/lib" \ ./configure --prefix="$WPREFIX" --host=$MTARGET --enable-shared \ lt_cv_deplibs_check_method='match_pattern \.dll\.a$' # !!! Otherwise it tests for PE file format, which naturally fails # if no .la file is present to provide redirection make LDFLAGS="-XCClinker -static-libgcc -L$TOPDIR/lib" make install-strip DESTDIR="$DESTDIR" "$TARGET_STRIP" --strip-unneeded "$DEST"/bin/libjasper*.dll EXPORT } COMMENTED_OUT BUILD_openjpeg () { UNPACK "openjpeg-*.tar.*" || return 0 sed -i '/^project(/ s/)/ C)/' CMakeLists.txt PATH="$LONGPATH" mkdir build cd build LDFLAGS=-static-libgcc \ cmake -DCMAKE_TOOLCHAIN_FILE="$TOPDIR/toolchain" \ -DCMAKE_BUILD_TYPE=Release .. make install/strip DESTDIR="$DESTDIR" rm -rf "$DESTDIR"/lib/openjpeg-* # Useless EXPORT } BUILD_lcms () { UNPACK "lcms2-*.tar.*" || return 0 PATH="$LONGPATH" # The '-D...' and 'ax_cv_...' are workarounds for config bugs in 2.9 CPPFLAGS="-isystem $TOPDIR/include -DCMS_RELY_ON_WINDOWS_STATIC_MUTEX_INIT" \ LDFLAGS="-static-libgcc -L$TOPDIR/lib" \ ./configure --prefix="$WPREFIX" --host=$MTARGET \ ax_cv_have_func_attribute_visibility=no \ ax_cv_check_cflags___fvisibility_hidden=no make make install-strip DESTDIR="$DESTDIR" EXPORT } # These were extracting prebuilt packages, instead of compiling from sources : << 'COMMENTED_OUT' BUILD_libiconv () { UNPACK "libiconv-1.9.1.bin.woe32.zip" || return 0 COPY_BINARIES local ZAD local PERED for ZAD in "$DEST"/lib/*.lib do PERED="${ZAD##*/}" mv -f "$ZAD" "${ZAD%$PERED}"lib"${PERED%.lib}".dll.a done EXPORT } BUILD_gettext () { UNPACK "gettext-0.14.5.zip" && COPY_BINARIES UNPACK "gettext-dev-0.14.5.zip" || return 0 mkdir -p "$DEST/include" "$DEST/lib" cp -fp include/libintl.h "$DEST"/include cp -fp lib/libintl.a "$DEST"/lib cp -fp lib/intl.lib "$DEST"/lib/libintl.dll.a chmod -R a-x,a+X "$DEST" EXPORT } BUILD_glib () { UNPACK "glib-2.6.*.zip" && COPY_BINARIES UNPACK "glib-dev-2.6.*.zip" || return 0 COPY_BINARIES rm -f "$DEST"/lib/*.def "$DEST"/lib/*.lib EXPORT } BUILD_atk () { UNPACK "atk-1.9.0.zip" && COPY_BINARIES UNPACK "atk-dev-1.9.0.zip" || return 0 COPY_BINARIES rm -f "$DEST"/lib/*.lib EXPORT } BUILD_pango () { UNPACK "pango-1.8.*.zip" && COPY_BINARIES UNPACK "pango-dev-1.8.*.zip" || return 0 COPY_BINARIES rm -f "$DEST"/lib/*.def "$DEST"/lib/*.lib EXPORT } COMMENTED_OUT BUILD_libiconv () { UNPACK "libiconv-*.tar.*" || return 0 PATH="$LONGPATH" CPPFLAGS="-isystem $TOPDIR/include" LDFLAGS="-static-libgcc -L$TOPDIR/lib" \ ./configure --prefix="$WPREFIX" --host=$MTARGET \ --enable-static make make install DESTDIR="$DESTDIR" "$TARGET_STRIP" --strip-unneeded "$DEST"/bin/* # For libiconv 1.9.2, first ever to have support for MinGW mv "$DEST"/bin/iconv "$DEST"/bin/iconv.exe || true EXPORT } DEP_gettext="libiconv" BUILD_gettext () { UNPACK "gettext-0.14.*.tar.*" || return 0 # git ec56ad8f2bf513a88efc3dba44953edff3909207 # Fix some incorrect SUBLANG_* values that were taken from glib's gwin32.c. patch -p1 <<- 'END' # Is needed to fix build failure with w32api 3.15+ --- a/gettext-runtime/intl/localename.c +++ b/gettext-runtime/intl/localename.c @@ -494,10 +494,10 @@ # define SUBLANG_AZERI_CYRILLIC 0x02 # endif # ifndef SUBLANG_BENGALI_INDIA -# define SUBLANG_BENGALI_INDIA 0x00 +# define SUBLANG_BENGALI_INDIA 0x01 # endif # ifndef SUBLANG_BENGALI_BANGLADESH -# define SUBLANG_BENGALI_BANGLADESH 0x01 +# define SUBLANG_BENGALI_BANGLADESH 0x02 # endif # ifndef SUBLANG_CHINESE_MACAU # define SUBLANG_CHINESE_MACAU 0x05 @@ -590,16 +590,16 @@ # define SUBLANG_NEPALI_INDIA 0x02 # endif # ifndef SUBLANG_PUNJABI_INDIA -# define SUBLANG_PUNJABI_INDIA 0x00 +# define SUBLANG_PUNJABI_INDIA 0x01 # endif # ifndef SUBLANG_PUNJABI_PAKISTAN -# define SUBLANG_PUNJABI_PAKISTAN 0x01 +# define SUBLANG_PUNJABI_PAKISTAN 0x02 # endif # ifndef SUBLANG_ROMANIAN_ROMANIA -# define SUBLANG_ROMANIAN_ROMANIA 0x00 +# define SUBLANG_ROMANIAN_ROMANIA 0x01 # endif # ifndef SUBLANG_ROMANIAN_MOLDOVA -# define SUBLANG_ROMANIAN_MOLDOVA 0x01 +# define SUBLANG_ROMANIAN_MOLDOVA 0x02 # endif # ifndef SUBLANG_SERBIAN_LATIN # define SUBLANG_SERBIAN_LATIN 0x02 @@ -608,10 +608,10 @@ # define SUBLANG_SERBIAN_CYRILLIC 0x03 # endif # ifndef SUBLANG_SINDHI_INDIA -# define SUBLANG_SINDHI_INDIA 0x00 +# define SUBLANG_SINDHI_INDIA 0x01 # endif # ifndef SUBLANG_SINDHI_PAKISTAN -# define SUBLANG_SINDHI_PAKISTAN 0x01 +# define SUBLANG_SINDHI_PAKISTAN 0x02 # endif # ifndef SUBLANG_SPANISH_GUATEMALA # define SUBLANG_SPANISH_GUATEMALA 0x04 @@ -670,14 +670,14 @@ # ifndef SUBLANG_TAMAZIGHT_ARABIC # define SUBLANG_TAMAZIGHT_ARABIC 0x01 # endif -# ifndef SUBLANG_TAMAZIGHT_LATIN -# define SUBLANG_TAMAZIGHT_LATIN 0x02 +# ifndef SUBLANG_TAMAZIGHT_ALGERIA_LATIN +# define SUBLANG_TAMAZIGHT_ALGERIA_LATIN 0x02 # endif # ifndef SUBLANG_TIGRINYA_ETHIOPIA -# define SUBLANG_TIGRINYA_ETHIOPIA 0x00 +# define SUBLANG_TIGRINYA_ETHIOPIA 0x01 # endif # ifndef SUBLANG_TIGRINYA_ERITREA -# define SUBLANG_TIGRINYA_ERITREA 0x01 +# define SUBLANG_TIGRINYA_ERITREA 0x02 # endif # ifndef SUBLANG_URDU_PAKISTAN # define SUBLANG_URDU_PAKISTAN 0x01 @@ -1432,7 +1432,7 @@ _nl_locale_name_default (void) { /* FIXME: Adjust this when Tamazight locales appear on Unix. */ case SUBLANG_TAMAZIGHT_ARABIC: return "ber_MA@arabic"; - case SUBLANG_TAMAZIGHT_LATIN: return "ber_MA@latin"; + case SUBLANG_TAMAZIGHT_ALGERIA_LATIN: return "ber_DZ@latin"; } return "ber_MA"; case LANG_TAMIL: END # !!! Try upgrading to latest version - *this* one dir shouldn't drag in much # (But disable threading then - for use with mtPaint, it's a complete waste) PATH="$LONGPATH" CPPFLAGS="-isystem $TOPDIR/include" LDFLAGS="-static-libgcc -L$TOPDIR/lib" \ ./configure --prefix="$WPREFIX" --host=$MTARGET \ --without-libexpat-prefix make -C gettext-runtime/intl make -C gettext-runtime/intl install DESTDIR="$DESTDIR" "$TARGET_STRIP" --strip-unneeded "$DEST"/bin/*.dll EXPORT } DEP_glib="libiconv gettext" BUILD_glib () { UNPACK "glib-2.6.*.tar.*" || return 0 patch -p1 <<- 'END' # Is needed to fix build failure with gcc 4.3+ diff -udr glib-2.6.6/glib/gutils.h glib-2.6.6_/glib/gutils.h --- glib-2.6.6/glib/gutils.h 2005-04-19 12:06:05.000000000 +0400 +++ glib-2.6.6_/glib/gutils.h 2017-10-10 02:35:44.765808857 +0300 @@ -97,7 +97,7 @@ # define G_INLINE_FUNC # undef G_CAN_INLINE #elif defined (__GNUC__) -# define G_INLINE_FUNC extern inline +# define G_INLINE_FUNC static inline #elif defined (G_CAN_INLINE) # define G_INLINE_FUNC static inline #else /* can't inline */ END # Derived from gettext's git ec56ad8f2bf513a88efc3dba44953edff3909207 # (Chosen instead of the route GLib 2.14+ has taken with svn 5257, to # preserve consistent behaviour across various Windows versions despite # their multiple bugs.) patch -p1 <<- 'END' # Is needed to fix build failure with w32api 3.15+ diff -udpr glib-2.6.6_/glib/gwin32.c glib-2.6.6/glib/gwin32.c --- glib-2.6.6_/glib/gwin32.c 2005-03-14 07:02:07.000000000 +0300 +++ glib-2.6.6/glib/gwin32.c 2011-01-14 00:52:49.000000000 +0300 @@ -416,10 +416,10 @@ g_win32_ftruncate (gint fd, #define SUBLANG_AZERI_CYRILLIC 0x02 #endif #ifndef SUBLANG_BENGALI_INDIA -#define SUBLANG_BENGALI_INDIA 0x00 +#define SUBLANG_BENGALI_INDIA 0x01 #endif #ifndef SUBLANG_BENGALI_BANGLADESH -#define SUBLANG_BENGALI_BANGLADESH 0x01 +#define SUBLANG_BENGALI_BANGLADESH 0x02 #endif #ifndef SUBLANG_CHINESE_MACAU #define SUBLANG_CHINESE_MACAU 0x05 @@ -512,16 +512,16 @@ g_win32_ftruncate (gint fd, #define SUBLANG_NEPALI_INDIA 0x02 #endif #ifndef SUBLANG_PUNJABI_INDIA -#define SUBLANG_PUNJABI_INDIA 0x00 +#define SUBLANG_PUNJABI_INDIA 0x01 #endif #ifndef SUBLANG_PUNJABI_PAKISTAN -#define SUBLANG_PUNJABI_PAKISTAN 0x01 +#define SUBLANG_PUNJABI_PAKISTAN 0x02 #endif #ifndef SUBLANG_ROMANIAN_ROMANIA -#define SUBLANG_ROMANIAN_ROMANIA 0x00 +#define SUBLANG_ROMANIAN_ROMANIA 0x01 #endif #ifndef SUBLANG_ROMANIAN_MOLDOVA -#define SUBLANG_ROMANIAN_MOLDOVA 0x01 +#define SUBLANG_ROMANIAN_MOLDOVA 0x02 #endif #ifndef SUBLANG_SERBIAN_LATIN #define SUBLANG_SERBIAN_LATIN 0x02 @@ -530,10 +530,10 @@ g_win32_ftruncate (gint fd, #define SUBLANG_SERBIAN_CYRILLIC 0x03 #endif #ifndef SUBLANG_SINDHI_INDIA -#define SUBLANG_SINDHI_INDIA 0x00 +#define SUBLANG_SINDHI_INDIA 0x01 #endif #ifndef SUBLANG_SINDHI_PAKISTAN -#define SUBLANG_SINDHI_PAKISTAN 0x01 +#define SUBLANG_SINDHI_PAKISTAN 0x02 #endif #ifndef SUBLANG_SPANISH_GUATEMALA #define SUBLANG_SPANISH_GUATEMALA 0x04 @@ -592,14 +592,14 @@ g_win32_ftruncate (gint fd, #ifndef SUBLANG_TAMAZIGHT_ARABIC #define SUBLANG_TAMAZIGHT_ARABIC 0x01 #endif -#ifndef SUBLANG_TAMAZIGHT_LATIN -#define SUBLANG_TAMAZIGHT_LATIN 0x02 +#ifndef SUBLANG_TAMAZIGHT_ALGERIA_LATIN +#define SUBLANG_TAMAZIGHT_ALGERIA_LATIN 0x02 #endif #ifndef SUBLANG_TIGRINYA_ETHIOPIA -#define SUBLANG_TIGRINYA_ETHIOPIA 0x00 +#define SUBLANG_TIGRINYA_ETHIOPIA 0x01 #endif #ifndef SUBLANG_TIGRINYA_ERITREA -#define SUBLANG_TIGRINYA_ERITREA 0x01 +#define SUBLANG_TIGRINYA_ERITREA 0x02 #endif #ifndef SUBLANG_URDU_PAKISTAN #define SUBLANG_URDU_PAKISTAN 0x01 END # Remove traces of existing install - just to be on the safe side rm -rf "$TOPDIR/include/glib-2.0" "$TOPDIR/lib/glib-2.0" rm -f "$TOPDIR/lib/pkgconfig"/glib*.pc "$TOPDIR/lib/pkgconfig"/gmodule*.pc rm -f "$TOPDIR/lib/pkgconfig"/gobject*.pc "$TOPDIR/lib/pkgconfig"/gthread*.pc rm -f "$TOPDIR/lib"/libglib*.dll.a "$TOPDIR/lib"/libgmodule*.dll.a rm -f "$TOPDIR/lib"/libgobject*.dll.a "$TOPDIR/lib"/libgthread*.dll.a PATH="$ALLPATH" CPPFLAGS="-isystem $TOPDIR/include" LDFLAGS="-L$TOPDIR/lib" \ CFLAGS="-mms-bitfields $OPTIMIZE" \ ./configure --prefix="$WPREFIX" --host=$MTARGET --enable-all-warnings \ --disable-static --disable-gtk-doc --enable-debug=yes \ --enable-explicit-deps=no \ --with-threads=win32 glib_cv_stack_grows=no # !!! See about "-fno-strict-aliasing": is it needed here with GCC 4, or not? make LDFLAGS="-XCClinker -static-libgcc -L$TOPDIR/lib" make install-strip DESTDIR="$DESTDIR" find "$DEST/" -name '*.dll' -exec "$TARGET_STRIP" --strip-unneeded {} + mv "$DEST/share/locale" "$DEST/lib/locale" echo 'PKG="$PKG bin/gspawn-win32-helper.exe"' > "$DESTDIR.install" echo 'DEV="$DEV lib/glib-2.0/"' >> "$DESTDIR.install" EXPORT } DEP_atk="glib gettext" BUILD_atk () { UNPACK "atk-1.9.*.tar.*" || return 0 # Remove traces of existing install - just to be on the safe side rm -rf "$TOPDIR/include/atk-1.0" rm -f "$TOPDIR/lib/pkgconfig"/atk.pc "$TOPDIR/lib"/libatk*.dll.a PATH="$ALLPATH" CPPFLAGS="-isystem $TOPDIR/include" LDFLAGS="-static-libgcc -L$TOPDIR/lib" \ CFLAGS="-mms-bitfields $OPTIMIZE" \ ./configure --prefix="$WPREFIX" --host=$MTARGET --enable-all-warnings \ --disable-static --disable-gtk-doc --enable-debug=yes \ --enable-explicit-deps=no make make install-strip DESTDIR="$DESTDIR" find "$DEST/" -name '*.dll' -exec "$TARGET_STRIP" --strip-unneeded {} + mv "$DEST/share/locale" "$DEST/lib/locale" EXPORT } DEP_pango="glib" BUILD_pango () { UNPACK "pango-1.8.*.tar.*" || return 0 patch -p1 -i "$SRCDIR/pango182_1wj.patch" # !!! Remove traces of existing install - else confusion will result rm -rf "$TOPDIR/include/pango-1.0" rm -f "$TOPDIR/lib/pkgconfig"/pango*.pc "$TOPDIR/lib"/libpango*.dll.a # !!! The only way to disable Fc backend is to report Fontconfig missing rm -f "$TOPDIR/lib/pkgconfig/fontconfig.pc" PATH="$ALLPATH" CPPFLAGS="-isystem $TOPDIR/include" LDFLAGS="-static-libgcc -L$TOPDIR/lib" \ CFLAGS="-mms-bitfields $OPTIMIZE" \ ./configure --prefix="$WPREFIX" --host=$MTARGET --enable-all-warnings \ --disable-static --disable-gtk-doc --enable-debug=yes \ --enable-explicit-deps=no \ --without-x --with-usp10=$TOPDIR/include make make install-strip DESTDIR="$DESTDIR" find "$DEST/" -name '*.dll' -exec "$TARGET_STRIP" --strip-unneeded {} + find "$DEST/lib/pango/1.4.0/" \( -name '*.dll.a' -o -name '*.la' \) -delete mkdir -p "$DEST/etc/pango" cp -p "$SRCDIR/pango.aliases" "$DEST/etc/pango" || true cp -p "$SRCDIR/pango.modules" "$DEST/etc/pango" || true echo 'PKG="$PKG lib/pango/"' > "$DESTDIR.install" EXPORT } DEP_gtk="glib gettext libtiff libpng libjpeg atk pango" BUILD_gtk () { UNPACK "wtkit*.zip" -LL && COPY_BINARIES touch "$DEST.exclude" # Do not package the contents local WTKIT WTKIT="$DEST" UNPACK "gtk+-2.6.7.tar.*" || return 0 patch -p1 -i "$SRCDIR/gtk267_7wj.patch" # !!! Remove traces of existing install - else confusion will result rm -rf "$TOPDIR/include/gtk-2.0" "$TOPDIR/lib/gtk-2.0" rm -f "$TOPDIR/lib/pkgconfig"/g[dt]k*.pc "$TOPDIR/lib"/libg[dt]k*.dll.a PATH="$ALLPATH" CPPFLAGS="-isystem $TOPDIR/include" LDFLAGS="-L$TOPDIR/lib" \ CFLAGS="-mms-bitfields $OPTIMIZE" \ ./configure --prefix="$WPREFIX" --host=$MTARGET --enable-all-warnings \ --disable-static --disable-gtk-doc --enable-debug=yes \ --enable-explicit-deps=no \ --with-gdktarget=win32 --with-wintab="$WTKIT" make LDFLAGS="-XCClinker -static-libgcc -L$TOPDIR/lib" make install-strip DESTDIR="$DESTDIR" find "$DEST/" -name '*.dll' -exec "$TARGET_STRIP" --strip-unneeded {} + find "$DEST/lib/gtk-2.0/2.4.0/" \( -name '*.dll.a' -o -name '*.la' \) -delete mv "$DEST/share/locale" "$DEST/lib/locale" rm -f "$DEST/lib/locale"/*/LC_MESSAGES/gtk20-properties.mo mkdir -p "$DEST/etc/gtk-2.0" cp -p "$SRCDIR/gdk-pixbuf.loaders" "$DEST/etc/gtk-2.0" || true cp -p "$SRCDIR/gtkrc" "$DEST/etc/gtk-2.0" || true printf '%s%s\n' 'PKG="$PKG lib/gtk-2.0/2.4.0/engines/libwimp.dll ' \ 'lib/gtk-2.0/2.4.0/loaders/"' > "$DESTDIR.install" echo 'DEV="$DEV lib/gtk-2.0/include/"' >> "$DESTDIR.install" EXPORT } BUILD_gifsicle () { UNPACK "gifsicle-*.tar.*" || return 0 PATH="$LONGPATH" CPPFLAGS="-isystem $TOPDIR/include" LDFLAGS="-static-libgcc -L$TOPDIR/lib" \ ./configure --prefix="$WPREFIX" --host=$MTARGET \ --without-x make make install-strip DESTDIR="$DESTDIR" echo 'PKG="$PKG bin/gifsicle.exe"' > "$DESTDIR.install" echo 'DEV=' >> "$DESTDIR.install" } DEP_mtpaint="$LIBS gifsicle" BUILD_mtpaint () { UNPACK "mtpaint-*.tar.bz2" || return 0 PATH="$LONGPATH" CPPFLAGS="-isystem $TOPDIR/include" LDFLAGS="-static-libgcc -L$TOPDIR/lib" \ ./configure --prefix="$WPREFIX" --host=$MTARGET \ release intl make make install DESTDIR="$DESTDIR" # Now prepare Windows-specific package parts local ZAD for ZAD in COPYING NEWS README do # Convert to CRLF sed -e 's/$/\x0D/g' ./$ZAD >"$DESTDIR/$ZAD.txt" done cp -a -t "$DESTDIR" "$SRCDIR/"*.ico ZAD="${DESTDIR##*mtpaint-}" # Version number sed -e "s/%VERSION%/$ZAD/g" "$SRCDIR/mtpaint-setup.iss" \ > "$DESTDIR/mtpaint-setup.iss" ZAD='[InternetShortcut]\r\nURL=http://mtpaint.sourceforge.net/\r\n' echo -en "$ZAD" > "$DESTDIR/mtpaint.url" echo 'PKG="./"' > "$DESTDIR.install" echo 'DEV=' >> "$DESTDIR.install" } BUILD_mtpaint_handbook () { UNPACK "mtpaint_handbook-*.zip" || return 0 mkdir -p "$DESTDIR" cp -ar -t "$DESTDIR" docs echo 'PKG="docs/"' > "$DESTDIR.install" echo 'DEV=' >> "$DESTDIR.install" } # Collect compiled files and drop them into runtime and development packages INST_all () { rm -rf "$PKGDIR"/* "$DEVDIR"/* local ZAD local PERED local FILE local DIR local DEST local PKG local DEV # Support locales only of GLib-based libs local LOCALES_SV LOCALES_SV="$LOCALES" LOCALES="" for ZAD in $LOCALES_SV do LOCALES="$LOCALES lib/locale/$ZAD/" done LOCALES="${LOCALES# }" for ZAD in "$INSDIR"/* do [ ! -d "$ZAD" -o -e "$ZAD.exclude" ] && continue echo "$ZAD" # Progress indicator PKG="bin/*.dll etc/ $LOCALES" DEV="include/ lib/*.a lib/pkgconfig/" if [ -f "$ZAD.install" ] then # !!! REMEMBER TO CREATE THESE FOR PACKAGES WITH NONDEFAULT CONTENT . "$ZAD.install" fi DIR="$PKGDIR" while [ -n "$PKG" -o -n "$DEV" ] do PKG="$PKG " while [ -n "$PKG" ] do PERED="${PKG%% *}" PKG="${PKG#$PERED }" [ -z "$PERED" ] && continue for FILE in "$ZAD$WPREFIX"/$PERED do [ -e "$FILE" ] || continue DEST="$DIR/${FILE#$ZAD}" mkdir -p "${DEST%/?*}" cp -fpRT "$FILE" "$DEST" done done DIR="$DEVDIR" PKG="$DEV" DEV= done done LOCALES="$LOCALES_SV" cd "$PKGDIR/bin" if [ ! -f "$PKGDIR/etc/pango/pango.modules" ] then mkdir -p "$PKGDIR/etc/pango" wine "$INSDIR"/pango-*"$WPREFIX"/bin/pango-querymodules.exe | \ sed -e 's|\\\\\?|/|g' \ -e "s|.:.\+\($WPREFIX/lib/pango\)|\1|" > \ "$PKGDIR/etc/pango/pango.modules" fi if [ ! -f "$PKGDIR/etc/gtk-2.0/gdk-pixbuf.loaders" ] then mkdir -p "$PKGDIR/etc/gtk-2.0" wine "$INSDIR"/gtk+-*"$WPREFIX"/bin/gdk-pixbuf-query-loaders.exe | \ sed -e '/:/ s|\\\\\?|/|g' \ -e "s|.:.\+\($WPREFIX/lib/gtk-2\)|\1|" > \ "$PKGDIR/etc/gtk-2.0/gdk-pixbuf.loaders" fi } DEP_libs="$LIBS" BUILD_libs () { INST_all } DEP_all="$LIBS $PROGRAMS" BUILD_all () { INST_all } BUILD_dev () { UNPACK "dev.tar.*" || return 0 touch "$DEST.exclude" # Do not package the contents ln -sf "$FDIR" "$DEST" EXPORT } BUILD_vars () { cat <<- VARS > "$TOPDIR/vars" MPREFIX='$MPREFIX' MTARGET=$MTARGET TOPDIR='$TOPDIR' $ALLPATHS PATH="\$LONGPATH" CPPFLAGS="-isystem \$TOPDIR/include" LDFLAGS="-static-libgcc -L\$TOPDIR/lib" PKG_CONFIG="\$TOPDIR${PKG_CONFIG#$TOPDIR}" VARS } # Ctrl+C terminates script trap exit INT # Parse commandline if [ "$1" = new ] then REBUILD=1 shift fi ZAD= for ZAD in "$@" do case "$ZAD" in only-?* | no-?* ) DEP="${ZAD#*-}";; * ) DEP="$ZAD";; esac if [ "${COMPONENTS#* $DEP }" = "$COMPONENTS" ] then echo "Unknown parameter: '$ZAD'" continue fi if [ "${ZAD%$DEP}" = "no-" ] then # Without component eval "HAVE_$DEP=1" elif [ "${ZAD%$DEP}" = "only-" ] then # Without dependencies eval "NEED_$DEP=2" # Force compile eval "DEPS=\$DEP_$DEP" for DEP in $DEPS do eval "HAVE_$DEP=1" done else # With component eval "NEED_$DEP=2" fi done if [ -z "$ZAD" ] then # Build "all" by default NEED_all=2 fi set -e # "set -eu" feels like overkill # Prepare build directories mkdir -p "$WRKDIR" "$INSDIR" "$PKGDIR" "$DEVDIR" test -d "$TOPDIR/include" || cp -sR "$MPREFIX/$MTARGET/include/" "$TOPDIR/include/" test -d "$TOPDIR/lib" || cp -sR "$MPREFIX/$MTARGET/lib/" "$TOPDIR/lib/" # Create links for what misconfigured cross-compilers fail to provide mkdir -p "$TOPDIR/bin" LONGCC=`PATH="$LONGPATH" which $MTARGET-gcc` for BINARY in ${LONGCC%/*}/$MTARGET-* do ln -sf "$BINARY" "$TOPDIR/bin/${BINARY##*/$MTARGET-}" done # Prepare fake pkg-config OLD_PKGCONFIG=`which pkg-config` PKG_CONFIG="$TOPDIR/pkg-config" export PKG_CONFIG rm -f "$PKG_CONFIG" cat << PKGCONFIG > "$PKG_CONFIG" #!/bin/sh export PKG_CONFIG_LIBDIR="$TOPDIR/lib/pkgconfig" export PKG_CONFIG_PATH= # pkg-config doesn't like --define-variable with these if [ "x\${*#*--atleast-pkgconfig-version}" != "x\${*#*--atleast-version}" ] then exec "$OLD_PKGCONFIG" "\$@" else exec "$OLD_PKGCONFIG" --define-variable=prefix="$TOPDIR" "\$@" fi PKGCONFIG chmod +x "$PKG_CONFIG" # Not actually needed for the packages in here, but why not ln -sf pkg-config "$TOPDIR/$MTARGET-pkg-config" # Prepare cmake toolchain config cat << TOOLCHAIN > "$TOPDIR/toolchain" set(CMAKE_SYSTEM_NAME Windows) set(CMAKE_CROSS_COMPILING ON) set(CMAKE_C_COMPILER "$MPREFIX/bin/$MTARGET-gcc") set(CMAKE_RC_COMPILER "$MPREFIX/bin/$MTARGET-windres") set(CMAKE_FIND_ROOT_PATH "$TOPDIR" "$MPREFIX") set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) set(CMAKE_INSTALL_PREFIX "${WPREFIX:-/}" CACHE PATH "") option(BUILD_PKGCONFIG_FILES "" ON) TOOLCHAIN # Provide glib-genmarshal wrapper GLIB_GENMARSHAL="$TOPDIR/$MTARGET-glib-genmarshal" export GLIB_GENMARSHAL rm -f "$GLIB_GENMARSHAL" cat << GENMARSHAL > "$GLIB_GENMARSHAL" #!/bin/sh glib-genmarshal "\$@" | sed 's/g_value_get_schar/g_value_get_char/' GENMARSHAL chmod +x "$GLIB_GENMARSHAL" # Provide (stripped-down) GLib 2.6.6 scripts for ATK & Pango SCRIPTDIR="$WRKDIR/glib/build/win32" mkdir -p "$SCRIPTDIR" cat << 'END' > "$SCRIPTDIR/compile-resource" #!/bin/sh rcfile=$1 resfile=$2 if [ -f $rcfile ]; then basename=`basename $rcfile .rc` if [ -f $basename-build.stamp ]; then read number <$basename-build.stamp buildnumber=`expr $number + 1` echo Build number $buildnumber echo $buildnumber >$basename-build.stamp else echo Using zero as build number buildnumber=0 fi m4 -DBUILDNUMBER=$buildnumber <$rcfile >$$.rc && ${WINDRES-windres} $$.rc $resfile && rm $$.rc else exit 1 fi END cat << 'END' > "$SCRIPTDIR/lt-compile-resource" #!/bin/sh rcfile=$1 lo=$2 case "$lo" in *.lo) resfile=.libs/`basename $lo .lo`.o ;; *) echo libtool object name should end with .lo exit 1 ;; esac d=`dirname $0` [ ! -d .libs ] && mkdir .libs o_files_in_dotlibs=`echo .libs/*.o` case "$o_files_in_dotlibs" in .libs/\*.o) use_script=false ;; *) use_script=true ;; esac o_files_in_dot=$(echo ./*.o) case "$o_files_in_dot" in ./\*.o) ;; *) use_script=true ;; esac $d/compile-resource $rcfile $resfile && { if [ $use_script = true ]; then (echo "# $lo" echo "# Generated by lt-compile-resource, compatible with libtool" echo "pic_object=$resfile" echo "non_pic_object=none") >$lo else mv $resfile $lo fi exit 0 } exit 1 END chmod +x "$SCRIPTDIR"/* # A little extra safety LIBS= PROGRAMS= PHONY= TOOLS= # Do the build in proper order READY= while [ "$READY" != 2 ] do READY=2 for ZAD in $COMPONENTS do if ((NEED_$ZAD<=HAVE_$ZAD)) then continue fi READY=1 eval "DEPS=\$DEP_$ZAD" for DEP in $DEPS do eval "NEED_$DEP=\${NEED_$DEP:-1}" if ((NEED_$DEP>HAVE_$DEP)) then # echo "$ZAD needs $DEP" READY= fi done if [ $READY ] then echo "Build $ZAD" eval "BUILD_$ZAD" eval "HAVE_$ZAD=\$NEED_$ZAD" fi done done mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/gtk/winbuild64.sh000066400000000000000000001204141471325446300232650ustar00rootroot00000000000000#!/bin/sh # winbuild64.sh - cross-compile GTK+ and its dependencies for Windows 64-bit # Copyright (C) 2010,2011,2017,2019,2020,2021 Dmitry Groshev # 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 in the file COPYING. ########################## # CONFIGURATION SETTINGS # ########################## LIBS="libgcc pthread libcxx zlib xz zstd libjpeg libwebp libpng "\ "libtiff openjpeg lcms bzip2 freetype_base libiconv gettext expat fontconfig "\ "pcre libffi glib pixman cairo icu harfbuzz freetype fribidi pango gdkpixbuf "\ "libxml2 libcroco libgsf librsvg atk gtk" PROGRAMS="gifsicle mtpaint mtpaint_handbook" PHONY="libs all" TOOLS="dev vars" LOCALES="es cs fr pt pt_BR de pl tr zh_TW sk zh_CN ja ru gl nl it sv tl hu" # Applied only to GTK+ ATM #OPTIMIZE="-march=i686 -O2 -fweb -fomit-frame-pointer -fmodulo-sched -Wno-pointer-sign" # Everything works OK with package-relative prefix, for now WPREFIX= SRCDIR=`pwd` TOPDIR="$SRCDIR/zad" # Directories for various parts WRKDIR="$TOPDIR/wrk" # Where sources are compiled INSDIR="$TOPDIR/ins" # Where files get installed PKGDIR="$TOPDIR/pkg" # Where package gets formed DEVDIR="$TOPDIR/dev" # Where dev files get collected # Also "$TOPDIR/bin", "$TOPDIR/include" & "$TOPDIR/lib", with symlinks to actual files UNPDIR="$WRKDIR/_000_" # Where archives are unpacked ######################## # CROSS-COMPILER PATHS # ######################## # SpeedBlue cross-MinGW or similar # http://www.speedblue.org/cross_compilation/ #MPREFIX=/usr/i586-mingw32-4.2.4 #MTARGET=i586-mingw32 # mingw-cross-env # http://mingw-cross-env.nongnu.org/ #MPREFIX=~/mingw-cross-env-2.18/usr #MTARGET=i686-pc-mingw32 # MXE # http://mxe.cc/ #MPREFIX=~/strawberry-mxe-master/usr #MPREFIX=~/mxe/usr #MTARGET=x86_64-w64-mingw32.shared # MinGW-w64, SpeedBlue-like build MPREFIX=/usr/x86_64-w64-mingw32-5.5.0 MTARGET=x86_64-w64-mingw32 ALLPATHS=' DEFPATH="$PATH" LONGPATH="$TOPDIR:$MPREFIX/bin:$PATH" SHORTPATH="$TOPDIR:$TOPDIR/bin:$PATH" ALLPATH="$TOPDIR:$TOPDIR/bin:$MPREFIX/bin:$PATH" ' eval "$ALLPATHS" ######################## # Initialize vars COMPONENTS=" $LIBS $PROGRAMS $PHONY $TOOLS " for ZAD in $COMPONENTS do eval "DEP_$ZAD=" eval "NEED_$ZAD=" eval "HAVE_$ZAD=" done REBUILD= # Don't recompile by default INNER_DIRS=" bin include lib " # !!! Parameter shouldn't contain directory UNPACK () { local ZAD local CNT local FFILE local FNAME local FCMD # Identify the source archive for ZAD in "$SRCDIR"/$1 do if [ -f "$ZAD" ] then FFILE="$ZAD" break fi done if [ -z "$FFILE" ] then echo "ERROR: $1 not found in $SRCDIR" exit 1 fi # Prepare to unpack FNAME="${FFILE#$SRCDIR/}" case "$FFILE" in *.tar.bz2) FDIR=.tar.bz2 ; FCMD="tar -xf" ;; *.tar.gz) FDIR=.tar.gz ; FCMD="tar -xf" ;; *.tar.xz) FDIR=.tar.xz ; FCMD="tar --use-compress-program xz -xf" ;; *.tar.zst) FDIR=.tar.zst ; FCMD="tar --use-compress-program zstd -xf" ;; *.zip) FDIR=.zip ; FCMD="unzip" ;; *) echo "ERROR: $FNAME unknown archive type" ; exit 1 ;; esac FDIR="$WRKDIR/${FNAME%$FDIR}$2" DESTDIR="$INSDIR/${FDIR##*/}" DEST="$DESTDIR$WPREFIX" [ -d "$DESTDIR" -a ! "$REBUILD" ] && return 1 # Prepare temp dir & unpack rm -rf "$UNPDIR" mkdir -p "$UNPDIR" cd "$UNPDIR" $FCMD "$FFILE" cd "$WRKDIR" # Find out if tarbombing happened CNT=0 for ZAD in "$UNPDIR"/* do CNT=$((CNT+1)) done # Check for unexpanded glob if [ $CNT = 1 ] && [ ! -e "$ZAD" ] then echo "ERROR: empty archive $FNAME" exit 1 fi # Move the files to regular location rm -rf "$FDIR" "$DESTDIR" if [ $CNT = 1 ] && [ -d "$ZAD" ] && \ [ "${INNER_DIRS%${ZAD##*/} *}" = "$INNER_DIRS" ] then # With enclosing directory mv "$ZAD/" "$FDIR" else # Tarbomb mv "$UNPDIR" "$FDIR" fi cd "$FDIR" # On return, source directory is current and FDIR holds it; # DESTDIR holds installation directory; and DEST , installdir+prefix return 0 } # Hardcoded direction - from current directory to DEST COPY_BINARIES () { mkdir -p "$DEST" cp -R ./ "$DEST" chmod -R a-x,a+X "$DEST" } # Hardcoded origin - DEST EXPORT () { cp -sfRT "$DEST/include/" "$TOPDIR/include/" cp -sfRT "$DEST/lib/" "$TOPDIR/lib/" rm -f "$TOPDIR/lib/"*.la # !!! These break some utils' compilation } # Relativize .pc files RELATIVIZE () { local ZAD for ZAD in "$@" do grep 'exec_prefix=\$' "$ZAD" && continue # Relativize pkgconfig file cat <<- PKGFIX > "$ZAD"_ prefix=$WPREFIX exec_prefix=\${prefix} libdir=\${exec_prefix}/lib includedir=\${prefix}/include `sed -e '/^Name:/,$!d' "$ZAD"` PKGFIX mv -f "$ZAD"_ "$ZAD" done } # Prepare one of GCC's DLLs for packaging IMPORT_DLL () { DESTDIR="$INSDIR/$1" DEST="$DESTDIR$WPREFIX" [ -d "$DESTDIR" -a ! "$REBUILD" ] && return 0 rm -rf "$DESTDIR" mkdir -p "$DEST/bin" # Check if it can be linked dynamically local LIB LIB=${2:-lib$1.dll.a} LIB=`"$TOPDIR/bin/gcc" --print-file-name=$LIB` [ -f "$LIB" ] || return 0 # Search for DLL in corresponding libdir, then in bindir under prefix local DLL DLL=`"$TOPDIR/bin/dlltool" --identify "$LIB"` LIB="${LIB%/*}/$DLL" [ -f "$LIB" ] || LIB="$MPREFIX/$MTARGET/bin/$DLL" [ -f "$LIB" ] || LIB="$MPREFIX/bin/$DLL" if [ ! -f "$LIB" ] then echo "ERROR: $1 DLL '$DLL' not found" exit 1 fi cp -fp "$LIB" "$DEST/bin" "$TARGET_STRIP" --strip-unneeded "$DEST"/bin/*.dll } # Tools TARGET_STRIP="$MPREFIX/bin/$MTARGET-strip" BUILD_pthread () { # Check if gcc needs the library at all # cd "$WRKDIR" # echo "main() { ; }" > _conf.c # "$TOPDIR/bin/gcc" -pthread _conf.c -o _conf.tmp > /dev/null 2>&1 || return 0 IMPORT_DLL pthread } DEP_libgcc="pthread" BUILD_libgcc () { IMPORT_DLL libgcc libgcc_s.a } DEP_libcxx="libgcc pthread" BUILD_libcxx () { IMPORT_DLL stdc++ } BUILD_zlib () { UNPACK "zlib-*.tar.*" || return 0 PATH="$SHORTPATH" ./configure --prefix="$WPREFIX" -shared -static make -f win32/Makefile.gcc install SHARED_MODE=1 INCLUDE_PATH="$DEST/include" \ LIBRARY_PATH="$DEST/lib" BINARY_PATH="$DEST/bin" LOC=-static-libgcc mkdir -p "$DEST/bin" cp -fp zlib1.dll "$DEST"/bin if [ -e "$DEST"/lib/pkgconfig/zlib.pc ] then # Relativize pkgconfig file of zlib 1.2.6+ cat <<- PKGFIX > zlib.pc_ prefix=$WPREFIX exec_prefix=\${prefix} libdir=\${exec_prefix}/lib sharedlibdir=\${libdir} includedir=\${prefix}/include `sed -e '/^Name:/,$!d' "$DEST"/lib/pkgconfig/zlib.pc` PKGFIX cp -fp zlib.pc_ "$DEST"/lib/pkgconfig/zlib.pc else # Rename import lib of zlib 1.2.5 cp -fp libzdll.a "$DEST"/lib/libz.dll.a fi EXPORT } BUILD_xz () { UNPACK "xz-*.tar.*" || return 0 PATH="$LONGPATH" ./configure --prefix="$WPREFIX" --host=$MTARGET --disable-threads \ --disable-nls --enable-small --disable-scripts LDFLAGS=-static-libgcc make make install-strip DESTDIR="$DESTDIR" RELATIVIZE "$DEST"/lib/pkgconfig/liblzma.pc EXPORT } BUILD_zstd () { UNPACK "zstd-*.tar.*" || return 0 # Stop dragging C++ in by default sed -i '/^project(/ s/)/ C)/' build/cmake/CMakeLists.txt build/cmake/*/CMakeLists.txt patch -p1 <<- 'UNCXX' # Not attempt to mess with C++ cross-compiler --- zstd-1.4.5_/build/cmake/CMakeLists.txt 2020-05-22 08:04:00.000000000 +0300 +++ zstd-1.4.5/build/cmake/CMakeLists.txt 2020-11-08 18:14:22.171222309 +0200 @@ -40,12 +40,10 @@ set(PROJECT_VERSION_PATCH ${zstd_VERSION_PATCH}) set(PROJECT_VERSION "${zstd_VERSION_MAJOR}.${zstd_VERSION_MINOR}.${zstd_VERSION_PATCH}") enable_language(C) # Main library is in C - enable_language(CXX) # Testing contributed code also utilizes CXX else() project(zstd VERSION "${zstd_VERSION_MAJOR}.${zstd_VERSION_MINOR}.${zstd_VERSION_PATCH}" LANGUAGES C # Main library is in C - CXX # Testing contributed code also utilizes CXX ) endif() message(STATUS "ZSTD VERSION: ${zstd_VERSION}") --- zstd-1.4.5_/build/cmake/CMakeModules/AddZstdCompilationFlags.cmake 2020-05-22 08:04:00.000000000 +0300 +++ zstd-1.4.5/build/cmake/CMakeModules/AddZstdCompilationFlags.cmake 2020-11-08 18:17:48.056232126 +0200 @@ -1,4 +1,3 @@ -include(CheckCXXCompilerFlag) include(CheckCCompilerFlag) function(EnableCompilerFlag _flag _C _CXX) @@ -12,18 +11,10 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${_flag}" PARENT_SCOPE) endif () endif () - if (_CXX) - CHECK_CXX_COMPILER_FLAG(${_flag} CXX_FLAG_${varname}) - if (CXX_FLAG_${varname}) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${_flag}" PARENT_SCOPE) - endif () - endif () endfunction() macro(ADD_ZSTD_COMPILATION_FLAGS) - if (CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang" OR MINGW) #Not only UNIX but also WIN32 for MinGW - #Set c++11 by default - EnableCompilerFlag("-std=c++11" false true) + if (CMAKE_C_COMPILER_ID MATCHES "GNU|Clang" OR MINGW) #Not only UNIX but also WIN32 for MinGW #Set c99 by default EnableCompilerFlag("-std=c99" true false) EnableCompilerFlag("-Wall" true true) @@ -56,8 +47,7 @@ # Remove duplicates compilation flags foreach (flag_var CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO - CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE - CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO) + ) if( ${flag_var} ) separate_arguments(${flag_var}) list(REMOVE_DUPLICATES ${flag_var}) UNCXX patch -p1 <<- 'PKGC' # Install .pc --- a/build/cmake/lib/CMakeLists.txt +++ b/build/cmake/lib/CMakeLists.txt @@ -165,7 +165,7 @@ if (ZSTD_BUILD_STATIC) OUTPUT_NAME ${STATIC_LIBRARY_BASE_NAME}) endif () -if (UNIX) +if (UNIX OR MINGW) # pkg-config set(PREFIX "${CMAKE_INSTALL_PREFIX}") set(LIBDIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}") PKGC patch -p1 <<- 'DLLDIR' # Install .dll --- a/build/cmake/lib/CMakeLists.txt +++ b/build/cmake/lib/CMakeLists.txt @@ -163,6 +163,7 @@ install(TARGETS ${library_targets} INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" + RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" ) # uninstall target DLLDIR PATH="$LONGPATH" mkdir tbuild cd tbuild LDFLAGS=-static-libgcc \ cmake -DCMAKE_TOOLCHAIN_FILE="$TOPDIR/toolchain" \ -DZSTD_MULTITHREAD_SUPPORT=OFF -DZSTD_BUILD_STATIC=OFF \ -DZSTD_BUILD_PROGRAMS=OFF -DCMAKE_INSTALL_PREFIX= \ ../build/cmake make make install DESTDIR="$DESTDIR" "$TARGET_STRIP" --strip-unneeded "$DEST"/bin/*.dll RELATIVIZE "$DEST"/lib/pkgconfig/libzstd.pc EXPORT echo 'DEV="$DEV lib/cmake/"' > "$DESTDIR.install" } BUILD_libjpeg () { UNPACK "jpegsrc.*.tar.*" || return 0 PATH="$LONGPATH" ./configure --prefix="$WPREFIX" --host=$MTARGET LDFLAGS=-static-libgcc make make install-strip DESTDIR="$DESTDIR" EXPORT } BUILD_libwebp () { UNPACK "libwebp-*.tar.*" || return 0 PATH="$LONGPATH" NOCONFIGURE=1 ./autogen.sh CPPFLAGS="-isystem $TOPDIR/include" LDFLAGS="-static-libgcc -L$TOPDIR/lib" \ ./configure --prefix="$WPREFIX" --host=$MTARGET --disable-static \ --disable-silent-rules --enable-everything --enable-swap-16bit-csp make make install-strip DESTDIR="$DESTDIR" EXPORT } DEP_libpng="zlib" BUILD_libpng () { UNPACK "libpng-*.tar.*" || return 0 PATH="$LONGPATH" CPPFLAGS="-isystem $TOPDIR/include" LDFLAGS="-static-libgcc -L$TOPDIR/lib" \ ./configure --prefix="$WPREFIX" --host=$MTARGET --disable-static make make install-strip DESTDIR="$DESTDIR" EXPORT # For those stupid things not using pkg-config local ZAD for ZAD in "$DEST"/bin/libpng*-config do ln -sf "${ZAD#$TOPDIR/}" "$TOPDIR/" done echo 'DEV="$DEV bin/libpng*-config"' > "$DESTDIR.install" } DEP_libtiff="zlib xz zstd libjpeg libwebp" BUILD_libtiff () { UNPACK "tiff-*.tar.*" || return 0 PATH="$LONGPATH" CPPFLAGS="-isystem $TOPDIR/include" LDFLAGS="-L$TOPDIR/lib" \ ./configure --prefix="$WPREFIX" --host=$MTARGET --disable-cxx \ --without-x make LDFLAGS="-XCClinker -static-libgcc -L$TOPDIR/lib" make install-strip DESTDIR="$DESTDIR" EXPORT } BUILD_openjpeg () { UNPACK "openjpeg-*.tar.*" || return 0 sed -i '/^project(/ s/)/ C)/' CMakeLists.txt PATH="$LONGPATH" mkdir build cd build LDFLAGS=-static-libgcc \ cmake -DCMAKE_TOOLCHAIN_FILE="$TOPDIR/toolchain" \ -DCMAKE_BUILD_TYPE=Release .. make install/strip DESTDIR="$DESTDIR" rm -rf "$DEST"/lib/openjpeg-* # Useless EXPORT } BUILD_lcms () { UNPACK "lcms2-*.tar.*" || return 0 PATH="$LONGPATH" autoreconf -fi CPPFLAGS="-isystem $TOPDIR/include" \ LDFLAGS="-static-libgcc -L$TOPDIR/lib" \ ./configure --prefix="$WPREFIX" --host=$MTARGET --disable-static make make install-strip DESTDIR="$DESTDIR" EXPORT } BUILD_bzip2 () { UNPACK "bzip2-*.tar.*" || return 0 patch -p1 <<- 'FIX' # Fix the necessary minimum --- a/bzip2.c +++ b/bzip2.c @@ -128,7 +128,7 @@ #if BZ_LCCWIN32 # include # include -# include +# include # define NORETURN /**/ # define PATH_SEP '\\' --- a/bzlib.h +++ b/bzlib.h @@ -75,7 +75,7 @@ typedef #include #endif -#ifdef _WIN32 +#if 0 # include # ifdef small /* windows.h define small to char */ @@ -116,7 +116,7 @@ BZ_EXTERN int BZ_API(BZ2_bzCompressEnd) ( BZ_EXTERN int BZ_API(BZ2_bzDecompressInit) ( bz_stream *strm, int verbosity, - int small + int small_ ); BZ_EXTERN int BZ_API(BZ2_bzDecompress) ( @@ -140,7 +140,7 @@ BZ_EXTERN BZFILE* BZ_API(BZ2_bzReadOpen) ( int* bzerror, FILE* f, int verbosity, - int small, + int small_, void* unused, int nUnused ); @@ -216,7 +216,7 @@ BZ_EXTERN int BZ_API(BZ2_bzBuffToBuffDecompress) ( unsigned int* destLen, char* source, unsigned int sourceLen, - int small, + int small_, int verbosity ); FIX PATH="$SHORTPATH" make libbz2.a cc *.o -shared -o libbz2.dll -Xlinker --out-implib -Xlinker libbz2.dll.a mkdir -p "$DEST/bin" "$DEST/lib" "$DEST/include" cp -a bzlib.h "$DEST/include/" cp -a libbz2*.a "$DEST/lib/" cp -a libbz2.dll "$DEST/bin/" "$TARGET_STRIP" --strip-unneeded "$DEST"/bin/* EXPORT } do_BUILD_freetype () { sed -i 's/_pkg_min_version=.*/_pkg_min_version=0.23/' \ builds/unix/configure # Does not need more # !!! Cross-compile breaks down if cross-gcc named "gcc" is present in PATH PATH="$LONGPATH" CPPFLAGS="-isystem $TOPDIR/include" LDFLAGS="-static-libgcc -L$TOPDIR/lib" \ ./configure --prefix="$WPREFIX" --host=$MTARGET \ --enable-freetype-config --with-harfbuzz=$1 make "$TARGET_STRIP" --strip-unneeded objs/.libs/*.dll objs/.libs/*.a make install DESTDIR="$DESTDIR" RELATIVIZE "$DEST"/lib/pkgconfig/freetype2.pc EXPORT # For those stupid things not using pkg-config ln -sf "${DEST#$TOPDIR/}"/bin/freetype-config "$TOPDIR/" } DEP_freetype_base="zlib libpng bzip2" BUILD_freetype_base () { UNPACK "freetype-*.tar.*" _base || return 0 do_BUILD_freetype no touch "$DESTDIR.exclude" # Do not package the contents } BUILD_libiconv () { UNPACK "libiconv-*.tar.*" || return 0 PATH="$LONGPATH" CPPFLAGS="-isystem $TOPDIR/include" LDFLAGS="-static-libgcc -L$TOPDIR/lib" \ ./configure --prefix="$WPREFIX" --host=$MTARGET \ --enable-static make make install DESTDIR="$DESTDIR" "$TARGET_STRIP" --strip-unneeded "$DEST"/bin/* EXPORT } DEP_gettext="libiconv" BUILD_gettext () { UNPACK "gettext-*.tar.*" || return 0 cd gettext-runtime rm -f intl/canonicalize.[ch] intl/relocatex.[ch] patch -p1 < "$SRCDIR"/gettext1981runtime.patch PATH="$LONGPATH" CPPFLAGS="-isystem $TOPDIR/include" LDFLAGS="-static-libgcc -L$TOPDIR/lib" \ ./configure --prefix="$WPREFIX" --host=$MTARGET \ --enable-threads=win32 --enable-relocatable make -C intl make -C intl install DESTDIR="$DESTDIR" "$TARGET_STRIP" --strip-unneeded "$DEST"/bin/*.dll EXPORT } BUILD_expat () { UNPACK "expat-*.tar.*" || return 0 PATH="$LONGPATH" CPPFLAGS="-isystem $TOPDIR/include" LDFLAGS="-static-libgcc -L$TOPDIR/lib" \ ./configure --prefix="$WPREFIX" --host=$MTARGET \ --without-docbook make make install-strip DESTDIR="$DESTDIR" EXPORT } DEP_fontconfig="freetype_base gettext expat" BUILD_fontconfig () { UNPACK "fontconfig-*.tar.*" || return 0 PATH="$LONGPATH" autoreconf -fi CPPFLAGS="-isystem $TOPDIR/include" LDFLAGS="-static-libgcc -L$TOPDIR/lib" \ ./configure --prefix="$WPREFIX" --host=$MTARGET \ --with-arch=$MTARGET --disable-docs # !!! libtool eats the LDFLAGS, need to force 'em down its throat sed -i -e 's/-static-libgcc/-XCClinker -static-libgcc/' src/Makefile # "noinst_PROGRAMS=" is to avoid making tests, as test-hash.c is broken make noinst_PROGRAMS= make install-strip DESTDIR="$DESTDIR" noinst_PROGRAMS= EXPORT local ZAD for ZAD in "$DEST"/etc/fonts/conf.d/*.conf do rm "$ZAD" cp -a "$DEST/share/fontconfig/conf.avail/${ZAD##*/}" "$ZAD" done mkdir -p "$DEST"/var/cache/fontconfig # Just to be safe echo 'PKG="$PKG etc/ var/ share/fontconfig/"' > "$DESTDIR.install" } BUILD_pcre () { UNPACK "pcre-*.tar.*" || return 0 PATH="$LONGPATH" CPPFLAGS="-isystem $TOPDIR/include" LDFLAGS="-static-libgcc -L$TOPDIR/lib" \ ./configure --prefix="$WPREFIX" --host=$MTARGET \ --enable-utf --enable-unicode-properties \ --enable-pcre16 #--enable-pcre32 --enable-jit make make install-strip DESTDIR="$DESTDIR" EXPORT # For those stupid things not using pkg-config ln -sf "${DEST#$TOPDIR/}"/bin/pcre-config "$TOPDIR/" echo 'DEV="$DEV bin/pcre-config"' > "$DESTDIR.install" } BUILD_libffi () { UNPACK "libffi-*.tar.*" || return 0 PATH="$LONGPATH" CPPFLAGS="-isystem $TOPDIR/include" LDFLAGS="-static-libgcc -L$TOPDIR/lib" \ ./configure --prefix="$WPREFIX" --host=$MTARGET make make install-strip DESTDIR="$DESTDIR" EXPORT } DEP_glib="zlib libiconv gettext pcre libffi" BUILD_glib () { UNPACK "glib-*.tar.*" || return 0 # Remove traces of existing install - just to be on the safe side rm -rf "$TOPDIR/include/glib-2.0" "$TOPDIR/lib/glib-2.0" rm -rf "$TOPDIR/include/"gio*/ "$TOPDIR/lib/gio" local ZAD for ZAD in glib gmodule gobject gthread gio do rm -f "$TOPDIR/lib/pkgconfig"/$ZAD*.pc rm -f "$TOPDIR/lib"/lib$ZAD*.dll.a done PATH="$LONGPATH" NOCONFIGURE=1 ./autogen.sh CPPFLAGS="-fcommon -isystem $TOPDIR/include" LDFLAGS="-static-libgcc -L$TOPDIR/lib" \ ./configure --prefix="$WPREFIX" --host=$MTARGET \ --disable-compile-warnings \ --disable-static --enable-debug=yes \ --disable-gtk-doc-html --disable-man \ --with-threads=win32 --with-pcre=system --with-libiconv=gnu # --disable-fam # "--disable-compile-warnings" as GCC 10 mistakes %I64u for %u make make install-strip DESTDIR="$DESTDIR" sed -i -e '/^Libs.private/s/-L[^ ]*//' "$DEST"/lib/pkgconfig/*.pc mv "$DEST/share/locale" "$DEST/lib/locale" echo 'PKG="$PKG bin/gspawn-win64-helper*.exe"' > "$DESTDIR.install" echo 'DEV="$DEV lib/glib-2.0/"' >> "$DESTDIR.install" EXPORT } DEP_pixman="libpng pthread" BUILD_pixman () { UNPACK "pixman-*.tar.*" || return 0 PATH="$LONGPATH" CPPFLAGS="-isystem $TOPDIR/include" LDFLAGS="-static-libgcc -L$TOPDIR/lib" \ ./configure --prefix="$WPREFIX" --host=$MTARGET # !!! libtool eats the LDFLAGS, need to force 'em down its throat sed -i -e 's/-static-libgcc/-XCClinker -static-libgcc/' pixman/Makefile # Avoiding making tests, which is simply too long make noinst_PROGRAMS= make install-strip DESTDIR="$DESTDIR" noinst_PROGRAMS= EXPORT } DEP_cairo="zlib libpng freetype_base fontconfig glib pixman" BUILD_cairo () { UNPACK "cairo-*.tar.*" || return 0 # _FORTIFY_SOURCE "support" in MinGW-w64 is such that it's much easier to # disable outright, than make behave sed -i -e '/_FORTIFY_SOURCE=2/d' configure PATH="$LONGPATH" CPPFLAGS="-isystem $TOPDIR/include" LDFLAGS="-static-libgcc -L$TOPDIR/lib" \ ./configure --prefix="$WPREFIX" --host=$MTARGET \ --enable-win32 --enable-win32-font \ --disable-xlib --disable-xcb --disable-quartz \ --enable-tee \ --enable-ps --enable-pdf --enable-svg \ --disable-trace \ --disable-gtk-doc --disable-gtk-doc-html # --disable-static # --disable-pthread --disable-atomic # !!! libtool eats the LDFLAGS, need to force 'em down its throat sed -i -e 's/-static-libgcc/-XCClinker -static-libgcc/' src/Makefile # Avoiding making tests & utils, which is simply too long make noinst_PROGRAMS= make install-strip DESTDIR="$DESTDIR" noinst_PROGRAMS= EXPORT } DEP_icu="libcxx" BUILD_icu () { UNPACK "icu*.tar.*" || return 0 local SDIR SDIR="$FDIR"/source [ -d "$SDIR" ] || SDIR="$FDIR"/icu4c/source # A native build is prerequisite for a cross-build local NATDIR NATDIR="$SDIR/zad" mkdir -p "$NATDIR" cd "$NATDIR" PATH="$DEFPATH" "$SDIR"/configure CC=${CC:-gcc} CXX=${CXX:-g++} \ --disable-tests --disable-samples make cd "$SDIR" # Dynamic libstdc++ because static adds a few Mb extra # Dynamic libgcc because libstdc++ DLL will drag it in anyway PATH="$LONGPATH" CPPFLAGS="-isystem $TOPDIR/include" LDFLAGS="-L$TOPDIR/lib" \ ./configure --prefix="$WPREFIX" --host=$MTARGET \ --with-cross-build="$NATDIR" --enable-icu-config=no \ CXXFLAGS='-std=c++11' make SO_TARGET_VERSION_SUFFIX= make install DESTDIR="$DESTDIR" SO_TARGET_VERSION_SUFFIX= # DLL install was into /lib as of v66.1, properly into /bin in 68.2 mv -t "$DEST"/bin/ "$DEST"/lib/*[0-9].dll || true # Actual versioned DLLs rm -f "$DEST"/lib/*.dll # Unversioned symlinks are of no use "$TARGET_STRIP" --strip-unneeded "$DEST"/bin/*.dll EXPORT echo 'DEV="$DEV lib/icu/"' > "$DESTDIR.install" } DEP_harfbuzz="freetype_base glib cairo icu pthread" BUILD_harfbuzz () { UNPACK "harfbuzz-*.tar.*" || return 0 PATH="$LONGPATH" NOCONFIGURE=1 ./autogen.sh CPPFLAGS="-isystem $TOPDIR/include" LDFLAGS="-static-libgcc -L$TOPDIR/lib" \ ./configure --prefix="$WPREFIX" --host=$MTARGET \ ac_cv_header_sys_mman_h=no CXXFLAGS='-std=c++11' # !!! Crazy libtool is crazy, excise shared libgcc from it by hand sed -i -e '/^postdeps=/s/-lgcc_s//g' libtool make noinst_PROGRAMS= make install-strip DESTDIR="$DESTDIR" noinst_PROGRAMS= RELATIVIZE "$DEST"/lib/pkgconfig/*.pc EXPORT echo 'DEV="$DEV lib/cmake/"' > "$DESTDIR.install" } DEP_freetype="$DEP_freetype_base harfbuzz" BUILD_freetype () { UNPACK "freetype-*.tar.*" || return 0 do_BUILD_freetype yes echo 'DEV="$DEV bin/freetype-config"' > "$DESTDIR.install" } # Needs the .xz/.bz2 release package, NOT the (halfbaked) source code .gz one DEP_fribidi="glib" BUILD_fribidi () { UNPACK "fribidi-*.tar.*" || return 0 PATH="$LONGPATH" sed -i 's,__declspec(dllimport),,' lib/fribidi-common.h CPPFLAGS="-isystem $TOPDIR/include" LDFLAGS="-static-libgcc -L$TOPDIR/lib" \ ./configure --prefix="$WPREFIX" --host=$MTARGET \ --disable-debug --disable-deprecated make noinst_PROGRAMS= AM_DEFAULT_VERBOSITY=1 make install-strip DESTDIR="$DESTDIR" noinst_PROGRAMS= EXPORT } # !!! All MXE builds failed; MSYS2's 1.43.0 and Octave's 1.42.1 worked # Maybe worth it to add libthai ? Get rid of fontconfig as in Octave? DEP_pango="glib fontconfig cairo harfbuzz freetype fribidi" BUILD_pango () { UNPACK "pango-*.tar.*" || return 0 patch -p1 <<- 'ORDER' --- pango-1.40.3.orig/pango/Makefile.am 2019-01-25 08:50:50.848933403 -0500 +++ pango-1.40.3/pango/Makefile.am 2019-01-25 08:52:32.440937173 -0500 @@ -389,7 +389,7 @@ libpangowin32_1_0_la_LIBADD = \ libpango-$(PANGO_API_VERSION).la \ $(GLIB_LIBS) \ - -lgdi32 -lusp10 + -lusp10 -lgdi32 libpangowin32_1_0_la_DEPENDENCIES = \ libpango-$(PANGO_API_VERSION).la libpangowin32_1_0_la_SOURCES = \ --- pango-1.40.3.orig/pango/Makefile.in 2019-01-25 08:50:50.852933403 -0500 +++ pango-1.40.3/pango/Makefile.in 2019-01-25 08:55:59.660944864 -0500 @@ -867,7 +867,7 @@ libpangowin32_1_0_la_LIBADD = \ libpango-$(PANGO_API_VERSION).la \ $(GLIB_LIBS) \ - -lgdi32 -lusp10 + -lusp10 -lgdi32 libpangowin32_1_0_la_DEPENDENCIES = libpango-$(PANGO_API_VERSION).la \ $(am__append_33) --- pango-1.40.3.orig/pangowin32.pc.in 2019-01-25 08:50:50.848933403 -0500 +++ pango-1.40.3/pangowin32.pc.in 2019-01-25 08:51:20.696934510 -0500 @@ -8,5 +8,5 @@ Version: @VERSION@ Requires: pango Libs: -L${libdir} -lpangowin32-@PANGO_API_VERSION@ -Libs.private: -lgdi32 -lusp10 +Libs.private: -lusp10 -lgdi32 Cflags: -I${includedir}/pango-1.0 ORDER # !!! Remove traces of existing install - else confusion will result rm -rf "$TOPDIR/include/pango-1.0" rm -f "$TOPDIR/lib/pkgconfig"/pango*.pc "$TOPDIR/lib"/libpango*.dll.a PATH="$LONGPATH" CPPFLAGS="-isystem $TOPDIR/include" LDFLAGS="-static-libgcc -L$TOPDIR/lib" \ ./configure --prefix="$WPREFIX" --host=$MTARGET \ --disable-gtk-doc --disable-gtk-doc-html --disable-static \ --enable-debug=yes # --disable-introspection make noinst_PROGRAMS= make install-strip DESTDIR="$DESTDIR" noinst_PROGRAMS= EXPORT } DEP_gdkpixbuf="libpng libjpeg libtiff libiconv gettext glib" # jasper BUILD_gdkpixbuf () { UNPACK "gdk-pixbuf-*.tar.*" || return 0 # Remove traces of existing install rm -rf "$TOPDIR/include/gdk-pixbuf*" rm -f "$TOPDIR/lib/pkgconfig"/gdk-pixbuf*.pc rm -f "$TOPDIR/lib"/libgdk_pixbuf*.dll.a WANT_JASPER= [ "`echo \"$TOPDIR\"/lib/libjasper*`" != "$TOPDIR/lib/libjasper*" ] && \ WANT_JASPER=--with-libjasper PATH="$LONGPATH" CPPFLAGS="-fcommon -isystem $TOPDIR/include" LDFLAGS="-static-libgcc -L$TOPDIR/lib" \ ./configure --prefix="$WPREFIX" --host=$MTARGET \ --disable-gtk-doc --disable-gtk-doc-html --disable-static \ --with-included-loaders --without-gdiplus $WANT_JASPER \ --enable-relocations # For svg plugin # --disable-introspection make make install-strip DESTDIR="$DESTDIR" mv "$DEST/share/locale" "$DEST/lib/locale" # If at all EXPORT } DEP_libxml2="zlib xz libiconv" BUILD_libxml2 () { UNPACK "libxml2-*.tar.*" || return 0 sed -i 's,`uname`,MinGW,g' xml2-config.in PATH="$LONGPATH" CPPFLAGS="-isystem $TOPDIR/include" LDFLAGS="-static-libgcc -L$TOPDIR/lib" \ ./configure --prefix="$WPREFIX" --host=$MTARGET \ --without-debug --without-python --without-threads # Clean up pkgconfig file sed -i '/^Libs.private:/s/ -L[^ ]\+//g' libxml-2.0.pc make make install-strip DESTDIR="$DESTDIR" EXPORT # For those stupid things not using pkg-config ln -sf "${DEST#$TOPDIR/}"/bin/xml2-config "$TOPDIR/" echo 'DEV="$DEV bin/xml2-config lib/cmake/"' > "$DESTDIR.install" } DEP_libcroco="glib libxml2" BUILD_libcroco () { UNPACK "libcroco-*.tar.*" || return 0 patch -p0 <<- 'LIBTOOL' # Make the outdated thing recognize 64-bit objects --- ltmain.sh0 2008-11-07 23:19:28.000000000 +0200 +++ ltmain.sh 2020-12-22 19:56:21.038466138 +0200 @@ -215,7 +215,7 @@ ;; *ar\ archive*) # could be an import, or static if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | \ - $EGREP -e 'file format pe-i386(.*architecture: i386)?' >/dev/null ; then + $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then win32_nmres=`eval $NM -f posix -A $1 | \ $SED -n -e '1,100{ / I /{ LIBTOOL PATH="$ALLPATH" # Else libtool runs host objdump CPPFLAGS="-isystem $TOPDIR/include" LDFLAGS="-static-libgcc -L$TOPDIR/lib" \ ./configure --prefix="$WPREFIX" --host=$MTARGET \ --disable-gtk-doc make make install-strip DESTDIR="$DESTDIR" "$TARGET_STRIP" --strip-unneeded "$DEST"/bin/*.dll # The install-strip doesn't EXPORT } DEP_libgsf="zlib bzip2 gettext glib libxml2" BUILD_libgsf () { UNPACK "libgsf-*.tar.*" || return 0 # Fix pkgconfig file sed -i 's/^Requires:.*/& gio-2.0/' libgsf-1.pc.in echo 'Libs.private: -lz -lbz2' >> libgsf-1.pc.in PATH="$LONGPATH" CPPFLAGS="-isystem $TOPDIR/include" LDFLAGS="-static-libgcc -L$TOPDIR/lib" \ ./configure --prefix="$WPREFIX" --host=$MTARGET \ --disable-gtk-doc --with-zlib --with-bz2 make -C gsf make -C gsf install-strip DESTDIR="$DESTDIR" make install-pkgconfigDATA DESTDIR="$DESTDIR" rm -f "$DEST"/lib/pkgconfig/libgsf-win32*.pc # No such thing built EXPORT } BROKEN_SVG_PLUGIN=1 # !!! Fails to do its job, for some reason DEP_librsvg="glib libxml2 cairo pango gdkpixbuf libcroco libgsf" BUILD_librsvg () { UNPACK "librsvg-*.tar.*" || return 0 sed -i 's/ gio-unix/ gio-windows/g' configure # Replace dependency patch -p1 <<- 'GIO' # commit 1811f207653e36c301260203866d958e443b2150 --- a/rsvg-convert.c +++ b/rsvg-convert.c @@ -36,7 +36,11 @@ #include #include #include +#ifdef _WIN32 +#include +#else #include +#endif #include "rsvg-css.h" #include "rsvg.h" @@ -213,7 +217,11 @@ main (int argc, char **argv) if (using_stdin) { file = NULL; +#ifdef _WIN32 + stream = g_win32_input_stream_new (STDIN_FILENO, FALSE); +#else stream = g_unix_input_stream_new (STDIN_FILENO, FALSE); +#endif } else { GFileInfo *file_info; gboolean compressed = FALSE; GIO patch -p0 <<- 'REALPATH' # Substitute; adapted from bug #710163 --- rsvg-base.c0 2014-06-18 21:05:08.000000000 +0300 +++ rsvg-base.c 2020-12-22 23:04:56.777290547 +0200 @@ -57,6 +57,8 @@ #include "rsvg-paint-server.h" #include "rsvg-xml.h" +#define realpath(a,b) _fullpath(b,a,_MAX_PATH) + /* * This is configurable at runtime */ REALPATH local gdk_pixbuf_binarydir local gdk_pixbuf_moduledir local gdk_pixbuf_cache_file gdk_pixbuf_binarydir="`$PKG_CONFIG --variable=gdk_pixbuf_binarydir gdk-pixbuf-2.0`" gdk_pixbuf_moduledir="`$PKG_CONFIG --variable gdk_pixbuf_moduledir gdk-pixbuf-2.0`" gdk_pixbuf_cache_file="`$PKG_CONFIG --variable gdk_pixbuf_cache_file gdk-pixbuf-2.0`" # Make configure script use prepared (de-prefixed) values of these sed -i '/gdk_pixbuf_\(binarydir\|moduledir\|cache_file\)=/d' configure PATH="$LONGPATH" gdk_pixbuf_binarydir="${gdk_pixbuf_binarydir#$TOPDIR}" \ gdk_pixbuf_moduledir="${gdk_pixbuf_moduledir#$TOPDIR}" \ gdk_pixbuf_cache_file="${gdk_pixbuf_cache_file#$TOPDIR}" \ CPPFLAGS="-isystem $TOPDIR/include" LDFLAGS="-static-libgcc -L$TOPDIR/lib" \ ./configure --prefix="$WPREFIX" --host=$MTARGET \ --disable-gtk-doc --disable-tools --enable-introspection=no make make install-strip DESTDIR="$DESTDIR" [ "${BROKEN_SVG_PLUGIN:-0}" -ne 0 ] && rm -f "$DEST${gdk_pixbuf_moduledir#$TOPDIR}"/* EXPORT echo 'PKG="$PKG bin/rsvg-convert.exe '"${gdk_pixbuf_moduledir#$TOPDIR/}"'/*.dll"' > "$DESTDIR.install" } DEP_atk="gettext glib" BUILD_atk () { UNPACK "atk-*.tar.*" || return 0 # Remove traces of existing install - just to be on the safe side rm -rf "$TOPDIR/include/atk-1.0" rm -f "$TOPDIR/lib/pkgconfig"/atk.pc "$TOPDIR/lib"/libatk*.dll.a PATH="$LONGPATH" CPPFLAGS="-isystem $TOPDIR/include" LDFLAGS="-static-libgcc -L$TOPDIR/lib" \ ./configure --prefix="$WPREFIX" --host=$MTARGET \ --disable-gtk-doc --disable-gtk-doc-html --disable-static # --disable-introspection make noinst_PROGRAMS= make install-strip DESTDIR="$DESTDIR" noinst_PROGRAMS= mv "$DEST/share/locale" "$DEST/lib/locale" EXPORT } DEP_gtk="gettext glib cairo pango gdkpixbuf atk" BUILD_gtk () { UNPACK "gtk+-2*.tar.*" || return 0 patch -p1 -i "$SRCDIR/gtk22429_1wj.patch" rm gtk/gtk.def # Force it be recreated # !!! Remove traces of existing install - else confusion may result rm -rf "$TOPDIR/include/gtk-2.0" "$TOPDIR/include/gail-1.0" "$TOPDIR/lib/gtk-2.0" rm -f "$TOPDIR/lib/pkgconfig"/gail.pc "$TOPDIR/lib/pkgconfig"/gdk-[2w]*.pc \ "$TOPDIR/lib/pkgconfig"/gtk*.pc \ "$TOPDIR/lib"/libg[dt]k-*.dll.a "$TOPDIR/lib"/libgailutil.dll.a PATH="$LONGPATH" CPPFLAGS="-fcommon -isystem $TOPDIR/include" LDFLAGS="-static-libgcc -L$TOPDIR/lib" \ ./configure --prefix="$WPREFIX" --host=$MTARGET \ --disable-gtk-doc --disable-gtk-doc-html --disable-static \ --enable-debug=yes --with-included-immodules --with-gdktarget=win32 \ --disable-glibtest --disable-modules --disable-cups --disable-papi # --disable-introspection make noinst_PROGRAMS= make install-strip DESTDIR="$DESTDIR" noinst_PROGRAMS= find "$DEST/lib/gtk-2.0/" \( -name '*.dll.a' -o -name '*.la' \) -delete mv "$DEST/share/locale" "$DEST/lib/locale" rm -f "$DEST/lib/locale"/*/LC_MESSAGES/gtk20-properties.mo # cp -p "$SRCDIR/gtkrc" "$DEST/etc/gtk-2.0" || true EXPORT printf '%s%s\n' 'PKG="$PKG lib/gtk-2.0/*/*/*.dll ' \ 'lib/gtk-2.0/*/*.dll share/themes/ etc/"' > "$DESTDIR.install" echo 'DEV="$DEV lib/gtk-2.0/include/"' >> "$DESTDIR.install" } DEP_gifsicle="pthread" BUILD_gifsicle () { UNPACK "gifsicle-*.tar.*" || return 0 PATH="$LONGPATH" # !!! Uncomment the below for buggy GCC 10.2 # CFLAGS="-O2 -fno-ipa-cp" \ CPPFLAGS="-isystem $TOPDIR/include" LDFLAGS="-static-libgcc -L$TOPDIR/lib" \ ./configure --prefix="$WPREFIX" --host=$MTARGET \ --without-x make make install-strip DESTDIR="$DESTDIR" echo 'PKG="$PKG bin/gifsicle.exe"' > "$DESTDIR.install" echo 'DEV=' >> "$DESTDIR.install" } DEP_mtpaint="$LIBS gifsicle" BUILD_mtpaint () { UNPACK "mtpaint-*.tar.*" || return 0 PATH="$LONGPATH" CPPFLAGS="-isystem $TOPDIR/include" LDFLAGS="-static-libgcc -L$TOPDIR/lib" \ ./configure --prefix="$WPREFIX" --host=$MTARGET \ release intl make make install DESTDIR="$DESTDIR" # Now prepare Windows-specific package parts local ZAD for ZAD in COPYING NEWS README do # Convert to CRLF sed -e 's/$/\x0D/g' ./$ZAD >"$DEST/$ZAD.txt" done cp -a -t "$DEST" "$SRCDIR/"*.ico ZAD="${DESTDIR##*mtpaint-}" # Version number sed -e "s/%VERSION%/$ZAD/g" "$SRCDIR/mtpaint-setup64.iss" \ > "$DEST/mtpaint-setup64.iss" ZAD='[InternetShortcut]\r\nURL=http://mtpaint.sourceforge.net/\r\n' echo -en "$ZAD" > "$DEST/mtpaint.url" echo 'PKG="./"' > "$DESTDIR.install" echo 'DEV=' >> "$DESTDIR.install" } BUILD_mtpaint_handbook () { UNPACK "mtpaint_handbook-*.zip" || return 0 mkdir -p "$DEST" cp -ar -t "$DEST" docs echo 'PKG="docs/"' > "$DESTDIR.install" echo 'DEV=' >> "$DESTDIR.install" } # Collect compiled files and drop them into runtime and development packages INST_all () { rm -rf "$PKGDIR"/* "$DEVDIR"/* local ZAD local PERED local FILE local DIR local DEST local PKG local DEV # Support locales only of GLib-based libs local LOCALES_SV LOCALES_SV="$LOCALES" LOCALES="" for ZAD in $LOCALES_SV do LOCALES="$LOCALES lib/locale/$ZAD/" done LOCALES="${LOCALES# }" for ZAD in "$INSDIR"/* do [ ! -d "$ZAD" -o -e "$ZAD.exclude" ] && continue echo "$ZAD" # Progress indicator PKG="bin/*.dll etc/ $LOCALES" DEV="include/ lib/*.a lib/pkgconfig/" if [ -f "$ZAD.install" ] then # !!! REMEMBER TO CREATE THESE FOR PACKAGES WITH NONDEFAULT CONTENT . "$ZAD.install" fi DIR="$PKGDIR" while [ -n "$PKG" -o -n "$DEV" ] do PKG="$PKG " while [ -n "$PKG" ] do PERED="${PKG%% *}" PKG="${PKG#$PERED }" [ -z "$PERED" ] && continue for FILE in "$ZAD$WPREFIX"/$PERED do [ -e "$FILE" ] || continue DEST="$DIR/${FILE#$ZAD}" mkdir -p "${DEST%/?*}" cp -fpRT "$FILE" "$DEST" done done DIR="$DEVDIR" PKG="$DEV" DEV= done done LOCALES="$LOCALES_SV" # Add loader cache file about SVG plugin - IF the plugin is working if [ "${BROKEN_SVG_PLUGIN:-0}" -eq 0 ] then ZAD="`$PKG_CONFIG --variable gdk_pixbuf_cache_file gdk-pixbuf-2.0`" ZAD="$PKGDIR${ZAD#$TOPDIR}" PERED="$SRCDIR/${ZAD##*/}" DIR="`$PKG_CONFIG --variable gdk_pixbuf_moduledir gdk-pixbuf-2.0`" DIR="$PKGDIR${DIR#$TOPDIR}" mkdir -p "${ZAD%/*}" if [ -f "$PERED" ] # Have prepared cache file then cp -p "$PERED" "$ZAD" elif which wine >/dev/null # Can prepare it using Wine then ( cd "$PKGDIR$WPREFIX/bin" && \ wine "$INSDIR"/gdk-pixbuf*"$WPREFIX"/bin/gdk-pixbuf-query-loaders.exe "$DIR"/*.dll \ | sed -e '/\.dll"/s|"'$PKGDIR$WPREFIX/'|"|' > "$ZAD" ) fi fi } DEP_libs="$LIBS" BUILD_libs () { INST_all } DEP_all="$LIBS $PROGRAMS" BUILD_all () { INST_all } BUILD_dev () { UNPACK "dev.tar.*" || return 0 touch "$DESTDIR.exclude" # Do not package the contents ln -sf "$FDIR" "$DEST" EXPORT } BUILD_vars () { cat <<- VARS > "$TOPDIR/vars" MPREFIX='$MPREFIX' MTARGET=$MTARGET TOPDIR='$TOPDIR' $ALLPATHS PATH="\$LONGPATH" CPPFLAGS="-isystem \$TOPDIR/include" LDFLAGS="-static-libgcc -L\$TOPDIR/lib" PKG_CONFIG="\$TOPDIR${PKG_CONFIG#$TOPDIR}" VARS } # Ctrl+C terminates script trap exit INT # Parse commandline if [ "$1" = new ] then REBUILD=1 shift fi ZAD= for ZAD in "$@" do case "$ZAD" in only-?* | no-?* ) DEP="${ZAD#*-}";; * ) DEP="$ZAD";; esac if [ "${COMPONENTS#* $DEP }" = "$COMPONENTS" ] then echo "Unknown parameter: '$ZAD'" continue fi if [ "${ZAD%$DEP}" = "no-" ] then # Without component eval "HAVE_$DEP=1" elif [ "${ZAD%$DEP}" = "only-" ] then # Without dependencies eval "NEED_$DEP=2" # Force compile eval "DEPS=\$DEP_$DEP" for DEP in $DEPS do eval "HAVE_$DEP=1" done else # With component eval "NEED_$DEP=2" fi done if [ -z "$ZAD" ] then # Build "all" by default NEED_all=2 fi set -e # "set -eu" feels like overkill # Prepare build directories mkdir -p "$WRKDIR" "$INSDIR" "$PKGDIR" "$DEVDIR" test -d "$TOPDIR/include" || cp -sR "$MPREFIX/$MTARGET/include/" "$TOPDIR/include/" test -d "$TOPDIR/lib" || cp -sR "$MPREFIX/$MTARGET/lib/" "$TOPDIR/lib/" # Create links for what misconfigured cross-compilers fail to provide mkdir -p "$TOPDIR/bin" LONGCC=`PATH="$LONGPATH" which $MTARGET-gcc` for BINARY in ${LONGCC%/*}/$MTARGET-* do ln -sf "$BINARY" "$TOPDIR/bin/${BINARY##*/$MTARGET-}" done [ -x "$TOPDIR/bin/cc" ] || ln -sf gcc "$TOPDIR/bin/cc" # Fix bad float.h if ! ( cd "$TOPDIR" && bin/cc -isystem include -imacros float.h -dM -E - < /dev/null | \ grep -E '\bDBL_EPSILON\b' > /dev/null ) then cp -p "$TOPDIR/include/float.h" "$TOPDIR/include/float.h.new" patch -d "$TOPDIR/include" -p3 <<- 'FLOATFIX' --- a/mingw-w64-headers/crt/float.h.new +++ b/mingw-w64-headers/crt/float.h.new @@ -114,6 +114,15 @@ #define DBL_MAX_10_EXP __DBL_MAX_10_EXP__ #define LDBL_MAX_10_EXP __LDBL_MAX_10_EXP__ + /* The difference between 1 and the least value greater than 1 that is + representable in the given floating point type, b**1-p. */ + #undef FLT_EPSILON + #undef DBL_EPSILON + #undef LDBL_EPSILON + #define FLT_EPSILON __FLT_EPSILON__ + #define DBL_EPSILON __DBL_EPSILON__ + #define LDBL_EPSILON __LDBL_EPSILON__ + /* Addition rounds to 0: zero, 1: nearest, 2: +inf, 3: -inf, -1: unknown. */ /* ??? This is supposed to change with calls to fesetround in . */ #undef FLT_ROUNDS FLOATFIX ln -sf float.h.new "$TOPDIR/include/float.h" fi # Prepare traps for stupid configure scripts for SCRIPT in libpng-config pcre-config freetype-config xml2-config do [ -x "$TOPDIR/$SCRIPT" ] || ln -s `which false` "$TOPDIR/$SCRIPT" done # Prepare fake pkg-config OLD_PKGCONFIG=`which pkg-config` PKG_CONFIG="$TOPDIR/pkg-config" export PKG_CONFIG rm -f "$PKG_CONFIG" cat << PKGCONFIG > "$PKG_CONFIG" #!/bin/sh export PKG_CONFIG_LIBDIR="$TOPDIR/lib/pkgconfig" export PKG_CONFIG_PATH= # pkg-config doesn't like --define-variable with these if [ "x\${*#*--atleast-pkgconfig-version}" != "x\${*#*--atleast-version}" ] then exec "$OLD_PKGCONFIG" "\$@" else exec "$OLD_PKGCONFIG" --define-variable=prefix="$TOPDIR" "\$@" fi PKGCONFIG chmod +x "$PKG_CONFIG" # Not actually needed for the packages in here, but why not ln -sf pkg-config "$TOPDIR/$MTARGET-pkg-config" # Prepare cmake toolchain config cat << TOOLCHAIN > "$TOPDIR/toolchain" set(CMAKE_SYSTEM_NAME Windows) set(CMAKE_CROSS_COMPILING ON) set(CMAKE_C_COMPILER "$MPREFIX/bin/$MTARGET-gcc") set(CMAKE_RC_COMPILER "$MPREFIX/bin/$MTARGET-windres") set(CMAKE_FIND_ROOT_PATH "$TOPDIR" "$MPREFIX") set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) set(CMAKE_INSTALL_PREFIX "${WPREFIX:-/}" CACHE PATH "") option(BUILD_PKGCONFIG_FILES "" ON) TOOLCHAIN # A little extra safety LIBS= PROGRAMS= PHONY= TOOLS= # Do the build in proper order READY= while [ "$READY" != 2 ] do READY=2 for ZAD in $COMPONENTS do if ((NEED_$ZAD<=HAVE_$ZAD)) then continue fi READY=1 eval "DEPS=\$DEP_$ZAD" for DEP in $DEPS do eval "NEED_$DEP=\${NEED_$DEP:-1}" if ((NEED_$DEP>HAVE_$DEP)) then # echo "$ZAD needs $DEP" READY= fi done if [ $READY ] then echo "Build $ZAD" eval "BUILD_$ZAD" eval "HAVE_$ZAD=\$NEED_$ZAD" fi done done mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/gtk/winbuild_rsvg.sh000066400000000000000000000362231471325446300241600ustar00rootroot00000000000000#!/bin/sh # winbuild_rsvg.sh - cross-compile static rsvg-convert.exe for Windows # Copyright (C) 2016,2017,2020 Dmitry Groshev # 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 in the file COPYING. ########################## # CONFIGURATION SETTINGS # ########################## LIBS="dev glib pixman cairo pango libxml2 libcroco librsvg gdkpixbuf" PHONY="all" # Everything works OK with package-relative prefix, for now WPREFIX= SRCDIR=`pwd` TOPDIR="$SRCDIR/zad" # Directories for various parts WRKDIR="$TOPDIR/wrk" # Where sources are compiled INSDIR="$TOPDIR/ins" # Where files get installed PKGDIR="$TOPDIR/pkg" # Where package gets formed DEVDIR="$TOPDIR/dev" # Where dev files get collected # Also "$TOPDIR/bin", "$TOPDIR/include" & "$TOPDIR/lib", with symlinks to actual files UNPDIR="$WRKDIR/_000_" # Where archives are unpacked ######################## # CROSS-COMPILER PATHS # ######################## # SpeedBlue cross-MinGW or similar # http://www.speedblue.org/cross_compilation/ MPREFIX=/usr/i586-mingw32-4.2.4 MTARGET=i586-mingw32 # mingw-cross-env # http://mingw-cross-env.nongnu.org/ #MPREFIX=~/mingw-cross-env-2.18/usr #MTARGET=i686-pc-mingw32 # MXE # http://mxe.cc/ #MPREFIX=~/mxe/usr #MTARGET=i686-w64-mingw32.shared LONGPATH="$TOPDIR:$MPREFIX/bin:$PATH" SHORTPATH="$TOPDIR:$TOPDIR/bin:$PATH" ALLPATH="$TOPDIR:$TOPDIR/bin:$MPREFIX/bin:$PATH" ######################## # Initialize vars COMPONENTS=" $LIBS $PROGRAMS $PHONY " for ZAD in $COMPONENTS do eval "DEP_$ZAD=" eval "NEED_$ZAD=" eval "HAVE_$ZAD=" done REBUILD= # Don't recompile by default INNER_DIRS=" bin include lib " # !!! Parameter shouldn't contain directory UNPACK () { local ZAD local CNT local FFILE local FNAME local FCMD # Identify the source archive for ZAD in "$SRCDIR"/$1 do if [ -f "$ZAD" ] then FFILE="$ZAD" break fi done if [ -z "$FFILE" ] then echo "ERROR: $1 not found in $SRCDIR" exit 1 fi # Prepare to unpack FNAME="${FFILE#$SRCDIR/}" case "$FFILE" in *.tar.xz) FDIR=.tar.xz ; FCMD="tar $2 --use-compress-program xz -xf" ;; *.tar.bz2) FDIR=.tar.bz2 ; FCMD="tar $2 -xf" ;; *.tar.gz) FDIR=.tar.gz ; FCMD="tar $2 -xf" ;; *.zip) FDIR=.zip ; FCMD="unzip $2" ;; *) echo "ERROR: $FNAME unknown archive type" ; exit 1 ;; esac FDIR="$WRKDIR/${FNAME%$FDIR}" DESTDIR="$INSDIR/${FDIR##*/}" DEST="$DESTDIR$WPREFIX" [ -d "$DESTDIR" -a ! "$REBUILD" ] && return 1 # Prepare temp dir & unpack rm -rf "$UNPDIR" mkdir -p "$UNPDIR" cd "$UNPDIR" $FCMD "$FFILE" cd "$WRKDIR" # Find out if tarbombing happened CNT=0 for ZAD in "$UNPDIR"/* do CNT=$((CNT+1)) done # Check for unexpanded glob if [ $CNT = 1 ] && [ ! -e "$ZAD" ] then echo "ERROR: empty archive $FNAME" exit 1 fi # Move the files to regular location rm -rf "$FDIR" "$DESTDIR" if [ $CNT = 1 ] && [ -d "$ZAD" ] && \ [ "${INNER_DIRS%${ZAD##*/} *}" = "$INNER_DIRS" ] then # With enclosing directory mv "$ZAD/" "$FDIR" else # Tarbomb mv "$UNPDIR" "$FDIR" fi cd "$FDIR" # On return, source directory is current and FDIR holds it; # DESTDIR holds installation directory; and DEST , installdir+prefix return 0 } # Hardcoded direction - from current directory to DEST COPY_BINARIES () { mkdir -p "$DEST" cp -R ./ "$DEST" chmod -R a-x,a+X "$DEST" } # Hardcoded origin - DEST EXPORT () { cp -sfRT "$DEST/include/" "$TOPDIR/include/" cp -sfRT "$DEST/lib/" "$TOPDIR/lib/" rm -f "$TOPDIR/lib/"*.la # !!! These break some utils' compilation } # Tools TARGET_STRIP="$MPREFIX/bin/$MTARGET-strip" BUILD_dev () { UNPACK "dev.tar.*" || return 0 touch "$DEST.exclude" # Do not package the contents ln -sf "$FDIR" "$DEST" EXPORT } DEP_glib="dev" # libiconv gettext BUILD_glib () { UNPACK "glib-*.tar.*" || return 0 # Remove traces of existing install - just to be on the safe side rm -rf "$TOPDIR/include/glib-2.0" "$TOPDIR/lib/glib-2.0" rm -f "$TOPDIR/lib/pkgconfig"/glib*.pc "$TOPDIR/lib/pkgconfig"/gmodule*.pc rm -f "$TOPDIR/lib/pkgconfig"/gobject*.pc "$TOPDIR/lib/pkgconfig"/gthread*.pc rm -f "$TOPDIR/lib"/libglib*.dll.a "$TOPDIR/lib"/libgmodule*.dll.a rm -f "$TOPDIR/lib"/libgobject*.dll.a "$TOPDIR/lib"/libgthread*.dll.a PATH="$ALLPATH" CPPFLAGS="-isystem $TOPDIR/include" LDFLAGS="-L$TOPDIR/lib" \ ./configure --disable-gtk-doc-html --with-threads=win32 \ --disable-shared --enable-static \ --prefix="$WPREFIX" --host=$MTARGET # !!! Try reducing the featureset some more make make install DESTDIR="$DESTDIR" # Fix libs sed -i 's/^Libs:.*/& -lole32 -lws2_32/' "$DEST/lib/pkgconfig/glib-2.0.pc" sed -i 's/^Libs:.*/& -lshlwapi -ldnsapi/' "$DEST/lib/pkgconfig/gio-2.0.pc" EXPORT ln -sf "$DEST/bin/glib-mkenums" "$TOPDIR/glib-mkenums" } DEP_gdkpixbuf="glib dev" # gettext libtiff libpng libjpeg jasper BUILD_gdkpixbuf () { UNPACK "gdk-pixbuf-*.tar.*" || return 0 # Remove traces of existing install - *.dll.a can break static build rm -rf "$TOPDIR/include/gtk-2.0/gdk-pixbuf" "$TOPDIR/lib/pango" rm -f "$TOPDIR/lib/pkgconfig"/gdk-pixbuf*.pc rm -f "$TOPDIR/lib"/libgdk_pixbuf*.dll.a patch <<- 'END' --- configure_ 2010-11-06 02:56:08.000000000 +0300 +++ configure 2016-04-10 10:42:55.000000000 +0300 @@ -4650,19 +4650,6 @@ ;; esac -if test "$os_win32" = "yes"; then - if test x$enable_static = xyes -o x$enable_static = x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Disabling static library build, must build as DLL on Windows." >&5 -$as_echo "$as_me: WARNING: Disabling static library build, must build as DLL on Windows." >&2;} - enable_static=no - fi - if test x$enable_shared = xno; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Enabling shared library build, must build as DLL on Windows." >&5 -$as_echo "$as_me: WARNING: Enabling shared library build, must build as DLL on Windows." >&2;} - fi - enable_shared=yes -fi - case `pwd` in *\ * | *\ *) END WANT_JASPER= [ "`echo \"$TOPDIR\"/lib/libjasper*`" != "$TOPDIR/lib/libjasper*" ] && \ WANT_JASPER=--with-libjasper PATH="$ALLPATH" CPPFLAGS="-isystem $TOPDIR/include" LDFLAGS="-L$TOPDIR/lib" \ ./configure --disable-modules --with-included-loaders $WANT_JASPER \ --disable-gdiplus --disable-shared --enable-static \ --prefix="$WPREFIX" --host=$MTARGET # LIBS="`'$(TARGET)-pkg-config' --libs libtiff-4`" make make install DESTDIR="$DESTDIR" EXPORT } DEP_pixman="glib" BUILD_pixman () { UNPACK "pixman-*.tar.*" || return 0 PATH="$LONGPATH" ./configure --disable-sse2 --disable-shared --enable-static \ --prefix="$WPREFIX" --host=$MTARGET LIBS="`pkg-config gio-2.0 --libs`" make make install DESTDIR="$DESTDIR" EXPORT } # Depends on libpng too, but will match version later - use default one for now DEP_cairo="glib pixman" BUILD_cairo () { UNPACK "cairo-*.tar.*" || return 0 sed -i 's,^\(Libs:.*\),\1 @CAIRO_NONPKGCONFIG_LIBS@,' src/cairo.pc.in sed -i 's/ -flto//' configure # Broken lib if enabled PATH="$ALLPATH" CPPFLAGS="-isystem $TOPDIR/include" LDFLAGS="-L$TOPDIR/lib" \ ./configure --disable-xlib --disable-xlib-xrender --disable-ft \ --disable-atomic --disable-pthread --disable-ps --disable-pdf \ --disable-gtk-doc --disable-shared --enable-static \ --prefix="$WPREFIX" --host=$MTARGET \ CFLAGS="$CFLAGS -DCAIRO_WIN32_STATIC_BUILD" \ LIBS="-lmsimg32 -lgdi32 `pkg-config pixman-1 --libs`" # Is reasonable to try disabling SVG backend too make make install DESTDIR="$DESTDIR" EXPORT } DEP_pango="glib cairo" BUILD_pango () { UNPACK "pango-*.tar.*" || return 0 # Remove traces of existing install - *.dll.a break rsvg-convert link rm -rf "$TOPDIR/include/pango-1.0" "$TOPDIR/lib/pango" rm -f "$TOPDIR/lib/pkgconfig"/pango*.pc rm -f "$TOPDIR/lib"/libpango*.dll.a patch -p1 -l -i "$SRCDIR/pango182_1wj.patch" patch <<- 'END' --- configure0 2007-07-28 01:27:07.000000000 +0400 +++ configure 2016-04-10 04:50:38.000000000 +0300 @@ -4495,19 +4495,6 @@ -if test "$pango_os_win32" = "yes"; then - if test x$enable_static = xyes -o x$enable_static = x; then - { echo "$as_me:$LINENO: WARNING: Disabling static library build, must build as DLL on Windows." >&5 -echo "$as_me: WARNING: Disabling static library build, must build as DLL on Windows." >&2;} - enable_static=no - fi - if test x$enable_shared = xno; then - { echo "$as_me:$LINENO: WARNING: Enabling shared library build, must build as DLL on Windows." >&5 -echo "$as_me: WARNING: Enabling shared library build, must build as DLL on Windows." >&2;} - fi - enable_shared=yes -fi - # Check whether --enable-shared was given. if test "${enable_shared+set}" = set; then enableval=$enable_shared; p=${PACKAGE-default} END PATH="$ALLPATH" ./configure --enable-explicit-deps --with-included-modules \ --without-dynamic-modules --enable-shared=no --enable-static \ --prefix="$WPREFIX" --host=$MTARGET \ LIBS="`pkg-config cairo --libs` -lpng12" #-lws2_32 # libpng's name must match the one Cairo uses (and *can* use!) make make install DESTDIR="$DESTDIR" # Fix libs sed -i 's/^Requires:.*/& pangowin32/' "$DEST/lib/pkgconfig/pangocairo.pc" EXPORT } DEP_libxml2="dev" # zlib libiconv BUILD_libxml2 () { UNPACK "libxml2-*.tar.*" || return 0 PATH="$ALLPATH" CPPFLAGS="-isystem $TOPDIR/include" LDFLAGS="-L$TOPDIR/lib" \ ./configure --without-debug --without-python --without-threads \ --disable-shared --enable-static \ --prefix="$WPREFIX" --host=$MTARGET make make install DESTDIR="$DESTDIR" # Fix libs sed -i 's/^Libs:.*/& -lws2_32 -lz -liconv/' "$DEST/lib/pkgconfig/libxml-2.0.pc" EXPORT } DEP_libcroco="glib libxml2" BUILD_libcroco () { UNPACK "libcroco-*.tar.*" || return 0 PATH="$ALLPATH" CPPFLAGS="-isystem $TOPDIR/include" LDFLAGS="-L$TOPDIR/lib" \ ./configure --disable-gtk-doc --disable-shared --enable-static \ --prefix="$WPREFIX" --host=$MTARGET \ LIBXML2_LIBS="`pkg-config libxml-2.0 --libs --static`" make make install DESTDIR="$DESTDIR" EXPORT } DEP_librsvg="glib libxml2 cairo pango libcroco gdkpixbuf" BUILD_librsvg () { UNPACK "librsvg-*.tar.*" || return 0 patch <<- 'END' --- rsvg-gobject.c0 2012-08-19 21:59:52.000000000 +0400 +++ rsvg-gobject.c 2016-04-10 04:20:18.000000000 +0300 @@ -41,6 +41,23 @@ #include "rsvg-defs.h" #include "rsvg.h" +void +g_clear_object (volatile GObject **object_ptr) +{ + gpointer *ptr = (gpointer) object_ptr; + gpointer old; + + /* This is a little frustrating. + * Would be nice to have an atomic exchange (with no compare). + */ + do + old = g_atomic_pointer_get (ptr); + while G_UNLIKELY (!g_atomic_pointer_compare_and_exchange (ptr, old, NULL)); + + if (old) + g_object_unref (old); +} + enum { PROP_0, PROP_FLAGS, END patch <<- 'END' --- rsvg-base.c0 2012-08-19 21:59:52.000000000 +0400 +++ rsvg-base.c 2017-10-11 03:27:44.063649365 +0300 @@ -1722,6 +1722,8 @@ return rsvg_handle_close_impl (handle, error); } +void +g_clear_object (volatile GObject **object_ptr); /** * rsvg_handle_read_stream_sync: * @handle: a #RsvgHandle END PATH="$ALLPATH" CPPFLAGS="-isystem $TOPDIR/include" LDFLAGS="-L$TOPDIR/lib" \ ./configure --enable-introspection=no --disable-pixbuf-loader \ --disable-gtk-doc --disable-shared --enable-static \ --prefix="$WPREFIX" --host=$MTARGET \ LIBS="`pkg-config libxml-2.0 --libs --static`" make make install DESTDIR="$DESTDIR" "$TARGET_STRIP" --strip-unneeded "$DEST"/bin/*.exe echo 'PKG="$PKG bin/rsvg-convert.exe"' > "$DESTDIR.install" EXPORT } # Collect compiled files and drop them into runtime and development packages INST_all () { rm -rf "$PKGDIR"/* "$DEVDIR"/* local ZAD local PERED local FILE local DIR local DEST local PKG local DEV for ZAD in "$INSDIR"/* do [ ! -d "$ZAD" -o -e "$ZAD.exclude" ] && continue echo "$ZAD" # Progress indicator PKG="bin/*.dll" DEV="include/ lib/*.a lib/pkgconfig/" if [ -f "$ZAD.install" ] then # !!! REMEMBER TO CREATE THESE FOR PACKAGES WITH NONDEFAULT CONTENT . "$ZAD.install" fi DIR="$PKGDIR" while [ -n "$PKG" -o -n "$DEV" ] do PKG="$PKG " while [ -n "$PKG" ] do PERED="${PKG%% *}" PKG="${PKG#$PERED }" [ -z "$PERED" ] && continue for FILE in "$ZAD$WPREFIX"/$PERED do [ -e "$FILE" ] || continue DEST="$DIR/${FILE#$ZAD}" mkdir -p "${DEST%/?*}" cp -fpRT "$FILE" "$DEST" done done DIR="$DEVDIR" PKG="$DEV" DEV= done done } DEP_all="$LIBS" BUILD_all () { INST_all } # Ctrl+C terminates script trap exit INT # Parse commandline if [ "$1" = new ] then REBUILD=1 shift fi ZAD= for ZAD in "$@" do case "$ZAD" in only-?* | no-?* ) DEP="${ZAD#*-}";; * ) DEP="$ZAD";; esac if [ "${COMPONENTS#* $DEP }" = "$COMPONENTS" ] then echo "Unknown parameter: '$ZAD'" continue fi if [ "${ZAD%$DEP}" = "no-" ] then # Without component eval "HAVE_$DEP=1" elif [ "${ZAD%$DEP}" = "only-" ] then # Without dependencies eval "NEED_$DEP=2" # Force compile eval "DEPS=\$DEP_$DEP" for DEP in $DEPS do eval "HAVE_$DEP=1" done else # With component eval "NEED_$DEP=2" fi done if [ -z "$ZAD" ] then # Build "all" by default NEED_all=2 fi set -e # "set -eu" feels like overkill # Prepare build directories mkdir -p "$WRKDIR" "$INSDIR" "$PKGDIR" "$DEVDIR" test -d "$TOPDIR/include" || cp -sR "$MPREFIX/$MTARGET/include/" "$TOPDIR/include/" test -d "$TOPDIR/lib" || cp -sR "$MPREFIX/$MTARGET/lib/" "$TOPDIR/lib/" # Create links for what misconfigured cross-compilers fail to provide mkdir -p "$TOPDIR/bin" LONGCC=`PATH="$LONGPATH" which $MTARGET-gcc` for BINARY in ${LONGCC%/*}/$MTARGET-* do ln -sf "$BINARY" "$TOPDIR/bin/${BINARY##*/$MTARGET-}" done # Prepare fake pkg-config OLD_PKGCONFIG=`which pkg-config` PKG_CONFIG="$TOPDIR/pkg-config" export PKG_CONFIG rm -f "$PKG_CONFIG" cat << PKGCONFIG > "$PKG_CONFIG" #!/bin/sh export PKG_CONFIG_LIBDIR="$TOPDIR/lib/pkgconfig" export PKG_CONFIG_PATH= # pkg-config doesn't like --define-variable with these if [ "x\${*#*--atleast-pkgconfig-version}" != "x\${*#*--atleast-version}" ] then exec "$OLD_PKGCONFIG" "\$@" else exec "$OLD_PKGCONFIG" --define-variable=prefix="$TOPDIR" "\$@" fi PKGCONFIG chmod +x "$PKG_CONFIG" # Not actually needed for the packages in here, but why not ln -sf pkg-config "$TOPDIR/$MTARGET-pkg-config" # Give GLib 2.25+ a fake binary for its fake dependency if ! ( cd "$TOPDIR" && which glib-compile-schemas ) then ln -sf `which true` "$TOPDIR/glib-compile-schemas" fi # A little extra safety LIBS= PROGRAMS= PHONY= # Do the build in proper order READY= while [ "$READY" != 2 ] do READY=2 for ZAD in $COMPONENTS do if ((NEED_$ZAD<=HAVE_$ZAD)) then continue fi READY=1 eval "DEPS=\$DEP_$ZAD" for DEP in $DEPS do eval "NEED_$DEP=\${NEED_$DEP:-1}" if ((NEED_$DEP>HAVE_$DEP)) then # echo "$ZAD needs $DEP" READY= fi done if [ $READY ] then echo "Build $ZAD" eval "BUILD_$ZAD" eval "HAVE_$ZAD=\$NEED_$ZAD" fi done done mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/pkg/000077500000000000000000000000001471325446300207345ustar00rootroot00000000000000mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/pkg/debmaker000077500000000000000000000023351471325446300224370ustar00rootroot00000000000000#!/bin/bash WRKDIR=`pwd` VERSION=3.50 ARCH=i386 tar xf mtpaint-$VERSION.tar.bz2 cd mtpaint-$VERSION || exit 1 ./configure release intl man staticgif --prefix=/usr --fakeroot=$WRKDIR/ubuntulibs make DEST=$WRKDIR/zad make install DESTDIR=$DEST gzip -9 $DEST/usr/share/man/man*/* cd $WRKDIR unzip mtpaint_handbook-$VERSION.zip mkdir -p $DEST/usr/share/doc mv mtpaint_handbook-$VERSION/docs $DEST/usr/share/doc/mtpaint SIZE=`( cd $DEST && du -s)` SIZE=${SIZE%%[!0-9]*} cat > control << CONTROL Package: mtpaint Version: $VERSION Architecture: $ARCH Maintainer: Dmitry Groshev Installed-Size: $SIZE Section: graphics Priority: extra Homepage: http://mtpaint.sourceforge.net/ Description: mtPaint - Mark Tyler's Painting Program mtPaint is a GTK+1/2/3 based painting program designed for creating icons and pixel based artwork. It can edit indexed palette or 24 bit RGB images and offers painting and palette manipulation tools. CONTROL cd $DEST md5sum `find * -type f` > $WRKDIR/md5sums tar cf $WRKDIR/data.tar * cd $WRKDIR tar cf control.tar control md5sums gzip -n -9 control.tar data.tar echo "2.0" > debian-binary bsdtar --format ar -cf mtpaint_${VERSION}_i386.deb debian-binary control.tar.gz data.tar.gz mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/pkg/slackbuild000077500000000000000000000010271471325446300227770ustar00rootroot00000000000000#!/bin/bash WRKDIR=`pwd` VERSION=3.50 ARCH=x86_64 SLACK=14.2 tar xf mtpaint-$VERSION.tar.bz2 cd mtpaint-$VERSION || exit 1 ./configure release intl man nowebp --prefix=/usr --mandir=/usr/man --docdir=/usr/doc #--fakeroot=$WRKDIR/slacklibs make DEST=$WRKDIR/zad make install DESTDIR=$DEST gzip -9 $DEST/usr/man/man*/* cd $WRKDIR unzip mtpaint_handbook-$VERSION.zip mkdir -p $DEST/usr/doc mv mtpaint_handbook-$VERSION/docs $DEST/usr/doc/mtpaint cd $DEST || exit 1 makepkg -l y -c y $WRKDIR/mtpaint-${VERSION}-${ARCH}-1_slack${SLACK}.tgz mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/pkg/slackbuild32000077500000000000000000000010571471325446300231470ustar00rootroot00000000000000#!/bin/bash WRKDIR=`pwd` VERSION=3.50 ARCH=i386 SLACK=14.2 . /etc/profile.d/32dev.sh tar xf mtpaint-$VERSION.tar.bz2 cd mtpaint-$VERSION || exit 1 ./configure release intl man nowebp --prefix=/usr --mandir=/usr/man --docdir=/usr/doc #--fakeroot=$WRKDIR/slacklibs make DEST=$WRKDIR/zad make install DESTDIR=$DEST gzip -9 $DEST/usr/man/man*/* cd $WRKDIR unzip mtpaint_handbook-$VERSION.zip mkdir -p $DEST/usr/doc mv mtpaint_handbook-$VERSION/docs $DEST/usr/doc/mtpaint cd $DEST || exit 1 makepkg -l y -c y $WRKDIR/mtpaint-${VERSION}-${ARCH}-1_slack${SLACK}.tgz mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/po/000077500000000000000000000000001471325446300205715ustar00rootroot00000000000000mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/po/Makefile000066400000000000000000000007631471325446300222370ustar00rootroot00000000000000include ../_conf.txt langs = es cs fr pt pt_BR de pl tr zh_TW sk zh_CN ja ru gl nl it sv tl hu kab all: for iii in $(langs); do echo -n "$$iii = "; msgfmt -v -o $$iii.mo $$iii.po; done install: for iii in $(langs); do mkdir -p $(DESTDIR)$(MT_LANG_DEST)/$$iii/LC_MESSAGES/; done for iii in $(langs); do cp $$iii.mo $(DESTDIR)$(MT_LANG_DEST)/$$iii/LC_MESSAGES/mtpaint.mo; done uninstall: for iii in $(langs); do rm $(DESTDIR)$(MT_LANG_DEST)/$$iii/LC_MESSAGES/mtpaint.mo; done clean: rm *.mo mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/po/README000066400000000000000000000001051471325446300214450ustar00rootroot00000000000000The po files here allow mtPaint to be translated to other languages. mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/po/cs.po000066400000000000000000002752411471325446300215510ustar00rootroot00000000000000# translation of cs.po to Czech # translation of cs.po to # Czech translations for mtpaint package. # Copyright (C) 2005 THE mtpaint'S COPYRIGHT HOLDER # This file is distributed under the same license as the mtpaint package. # # Pavel Ruzicka , 2005, 2006. # Pavel Ruzicka , 2006, 2007. msgid "" msgstr "" "Project-Id-Version: cs\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-01-04 21:31+0200\n" "PO-Revision-Date: 2014-01-01 19:48+0000\n" "Last-Translator: fri \n" "Language-Team: Czech \n" "Language: cs\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Launchpad-Export-Date: 2020-04-05 23:36+0000\n" "X-Generator: Launchpad (build a296f04231dee355be5db73cc878b9e21689a253)\n" #: src/ani.c:647 msgid "Animation Preview" msgstr "Náhled animace" #: src/ani.c:650 src/shifter.c:275 msgid "Play" msgstr "PÅ™ehrát" #: src/ani.c:654 msgid "Fix" msgstr "Fixovat" #: src/ani.c:655 src/ani.c:1005 src/font.c:1624 src/font.c:1643 #: src/shifter.c:286 src/viewer.c:97 msgid "Close" msgstr "Zavřít" #: src/ani.c:709 src/ani.c:812 src/ani.c:1022 src/ani.c:1028 src/canvas.c:356 #: src/canvas.c:708 src/canvas.c:989 src/canvas.c:1353 src/canvas.c:1383 #: src/canvas.c:1470 src/canvas.c:1545 src/canvas.c:1988 src/canvas.c:1994 #: src/canvas.c:2077 src/canvas.c:2217 src/canvas.c:2240 src/font.c:1352 #: src/fpick.c:636 src/fpick.c:754 src/layer.c:524 src/layer.c:815 #: src/layer.c:970 src/mainwindow.c:341 src/mainwindow.c:370 #: src/mainwindow.c:534 src/mainwindow.c:578 src/mainwindow.c:604 #: src/mainwindow.c:3797 src/mainwindow.c:4045 src/otherwindow.c:931 #: src/otherwindow.c:980 src/otherwindow.c:982 src/prefs.c:459 src/spawn.c:924 #: src/spawn.c:978 src/spawn.c:1017 src/thread.c:360 src/vcode.c:9912 #: src/viewer.c:1161 src/viewer.c:1179 msgid "Error" msgstr "Chyba" #: src/ani.c:709 msgid "Unable to create output directory" msgstr "Nelze vytvoÅ™it výstupní adresář" #: src/ani.c:759 msgid "Creating Animation Frames" msgstr "Vytváří se snímky animace" #: src/ani.c:812 msgid "Unable to save image" msgstr "Nelze uložit obrázek" #: src/ani.c:840 src/canvas.c:1171 src/fpick.c:731 src/layer.c:311 #: src/layer.c:379 src/layer.c:826 src/layer.c:840 src/mainwindow.c:375 #: src/mainwindow.c:1026 src/png.c:8794 src/prefs.c:464 msgid "Warning" msgstr "Varování" #: src/ani.c:840 msgid "" "Do you really want to clear all of the position and cycle data for all of " "the layers?" msgstr "" "Opravdu chcete vymazat vÅ¡echna poziÄní a cyklová data pro vÅ¡echny vrstvy?" #: src/ani.c:841 src/fpick.c:731 src/layer.c:311 src/layer.c:842 #: src/mainwindow.c:375 msgid "No" msgstr "Ne" #: src/ani.c:841 src/fpick.c:731 src/layer.c:311 src/layer.c:842 #: src/mainwindow.c:375 msgid "Yes" msgstr "Ano" #: src/ani.c:954 msgid "Set Key Frame" msgstr "Nastavit klíÄový snímek" #: src/ani.c:961 msgid "Configure Animation" msgstr "Konfigurovat animaci" #: src/ani.c:964 msgid "Output Files" msgstr "Výstupní soubory" #: src/ani.c:967 msgid "Start frame" msgstr "První snímek" #: src/ani.c:969 msgid "End frame" msgstr "Poslední snímek" #: src/ani.c:971 src/shifter.c:267 msgid "Delay" msgstr "ZpoždÄ›ní" #: src/ani.c:973 msgid "Output path" msgstr "Výstupní cesta" #: src/ani.c:973 src/font.c:1637 src/spawn.c:664 msgid "Select Directory" msgstr "Vybrat adresář" #: src/ani.c:976 msgid "File prefix" msgstr "PÅ™edpona souboru" #: src/ani.c:978 src/canvas.c:2096 msgid "File Format" msgstr "Typ souboru" #: src/ani.c:982 msgid "Positions" msgstr "Pozice" #: src/ani.c:997 msgid "Cycling" msgstr "Cyklus" #: src/ani.c:1006 msgid "Save" msgstr "Uložit" #: src/ani.c:1007 src/font.c:1577 src/otherwindow.c:868 src/otherwindow.c:1615 #: src/otherwindow.c:1728 src/otherwindow.c:2938 src/otherwindow.c:3071 #: src/otherwindow.c:3170 msgid "Preview" msgstr "Náhled" #: src/ani.c:1008 src/shifter.c:285 msgid "Create Frames" msgstr "VytvoÅ™it snímky" #: src/ani.c:1022 msgid "You must have at least 2 layers to create an animation" msgstr "Musíte mít alespoň 2 vrstvy pro vytvoÅ™ení animace" #: src/ani.c:1028 msgid "You must save your layers file before creating an animation" msgstr "PÅ™ed vytvoÅ™ením animace musíte nejprve uložit soubor vrstev" #: src/canvas.c:357 msgid "The image is too large to transform." msgstr "Obrázek je pro transformaci příliÅ¡ velký." #: src/canvas.c:393 src/canvas.c:430 src/otherwindow.c:1613 #: src/otherwindow.c:2524 src/otherwindow.c:2583 src/otherwindow.c:3179 msgid "Gradient" msgstr "PÅ™echod" #: src/canvas.c:393 src/otherwindow.c:840 src/otherwindow.c:842 #: src/otherwindow.c:2074 src/otherwindow.c:3180 msgid "Palette" msgstr "Paleta" #: src/canvas.c:393 src/info.c:265 src/otherwindow.c:847 src/otherwindow.c:2757 #: src/otherwindow.c:3180 src/png.c:781 src/png.c:995 msgid "Clipboard" msgstr "Schránka" #: src/canvas.c:394 src/cpick.c:831 src/toolbar.c:299 msgid "Value" msgstr "Hodnota" #: src/canvas.c:394 src/cpick.c:811 src/otherwindow.c:575 src/otherwindow.c:859 #: src/otherwindow.c:3053 src/toolbar.c:318 msgid "Red" msgstr "ÄŒervená" #: src/canvas.c:394 src/cpick.c:815 src/otherwindow.c:575 src/otherwindow.c:860 #: src/otherwindow.c:3053 src/toolbar.c:319 msgid "Green" msgstr "Zelená" #: src/canvas.c:394 src/cpick.c:819 src/otherwindow.c:575 src/otherwindow.c:861 #: src/otherwindow.c:3053 src/toolbar.c:320 msgid "Blue" msgstr "Modrá" #: src/canvas.c:399 msgid "From " msgstr "" #: src/canvas.c:403 msgid "To " msgstr "" #: src/canvas.c:410 msgid "Map" msgstr "" #: src/canvas.c:429 msgid "MT" msgstr "MT" #: src/canvas.c:429 msgid "Sobel" msgstr "Sobel" #: src/canvas.c:429 msgid "Prewitt" msgstr "Prewitt" #: src/canvas.c:429 msgid "Kirsch" msgstr "Kirsch" #: src/canvas.c:430 msgid "Roberts" msgstr "Roberts" #: src/canvas.c:430 msgid "Laplace" msgstr "Laplace" #: src/canvas.c:430 msgid "Morphological" msgstr "Morfologické" #: src/canvas.c:442 msgid "Edge Detect" msgstr "Detekce hran" #: src/canvas.c:464 msgid "Edge Sharpen" msgstr "ZaostÅ™ení hran" #: src/canvas.c:472 msgid "Edge Soften" msgstr "ZjemnÄ›ní hran" #: src/canvas.c:521 msgid "Different X/Y" msgstr "Rozdílné X/Y" #: src/canvas.c:522 src/canvas.c:562 src/canvas.c:603 src/canvas.c:637 #: src/canvas.c:722 src/otherwindow.c:1037 src/otherwindow.c:2685 msgid "Gamma corrected" msgstr "S Gamma korekcí" #: src/canvas.c:530 src/memory.c:8219 msgid "Gaussian Blur" msgstr "Gaussovo rozmazání" #: src/canvas.c:558 msgid "Radius" msgstr "PolomÄ›r" #: src/canvas.c:559 msgid "Amount" msgstr "Množství" #: src/canvas.c:560 msgid "Threshold " msgstr "Práh " #: src/canvas.c:570 src/memory.c:8360 msgid "Unsharp Mask" msgstr "ZaostÅ™ovací maska" #: src/canvas.c:599 msgid "Outer radius" msgstr "VnÄ›jší polomÄ›r" #: src/canvas.c:600 msgid "Inner radius" msgstr "VnitÅ™ní polomÄ›r" #: src/canvas.c:602 src/info.c:280 msgid "Normalize" msgstr "Normalizovat" #: src/canvas.c:611 src/memory.c:8512 msgid "Difference of Gaussians" msgstr "Rozdíl gausiánů" #: src/canvas.c:636 msgid "Protect details" msgstr "Chránit podrobnosti" #: src/canvas.c:645 msgid "Kuwahara-Nagao Blur" msgstr "RozostÅ™ení Kuwahara-Nagao" #: src/canvas.c:709 msgid "The image is too large for this rotation." msgstr "Obrázek je moc velký pro tuto rotaci." #: src/canvas.c:723 msgid "Smooth" msgstr "Vyhladit" #: src/canvas.c:732 msgid "Free Rotate" msgstr "Libovolná rotace" #: src/canvas.c:989 src/viewer.c:1161 msgid "Not enough memory to create clipboard" msgstr "Nedostatek pamÄ›ti pro vytvoÅ™ení schránky" #: src/canvas.c:1172 msgid "" "You have not allocated enough memory in the Preferences window to undo this " "action." msgstr "" #: src/canvas.c:1353 msgid "Invalid palette file" msgstr "Neplatný soubor palety" #: src/canvas.c:1383 msgid "Invalid channel file." msgstr "Neplatný soubor kanálů." #: src/canvas.c:1401 msgid "Raw frames" msgstr "Nezpracované snímky" #: src/canvas.c:1401 msgid "Composited frames" msgstr "Složené snímky" #: src/canvas.c:1402 msgid "Composited frames with nonzero delay" msgstr "Složené snímky s nenulovým zpoždÄ›ním" #: src/canvas.c:1406 msgid "Load Frames" msgstr "Nahrát snímky" #: src/canvas.c:1409 msgid "Load into Layers" msgstr "Nahrát do vrstev" #: src/canvas.c:1415 msgid "Load First Frame" msgstr "Nahrát první snímek" #: src/canvas.c:1416 msgid "Explode Frames" msgstr "Rozbalit snímky" #: src/canvas.c:1418 msgid "View Animation" msgstr "Zobrazit animaci" #: src/canvas.c:1434 #, c-format msgid "This is an animated %s file." msgstr "Toto je animovaný %s." #: src/canvas.c:1435 #, c-format msgid "This is a multipage %s file." msgstr "Toto je vícestránkový %s soubor." #: src/canvas.c:1459 #, c-format msgid "File is too big, must be <= to width=%i height=%i" msgstr "Soubor je příliÅ¡ velký, musí být <= šířka=%i výška=%i" #: src/canvas.c:1461 msgid "Unable to explode frames" msgstr "Nelze rozbalit snímky" #: src/canvas.c:1463 msgid "Unable to load file" msgstr "Nelze naÄíst soubor" #: src/canvas.c:1465 msgid "" "The file import library had to terminate due to a problem with the file " "(possibly corrupt image data or a truncated file). I have managed to load " "some data as the header seemed fine, but I would suggest you save this image " "to a new file to ensure this does not happen again." msgstr "" "Knihovna pro import souborů skonÄila z důvodu problémů se souborem (možná " "poÅ¡kozená obrazová data, nebo zkrácený soubor) PodaÅ™ilo se naÄíst nÄ›jaká " "data, jelikož hlaviÄka se zdá být v pořádku, ale doporuÄuji uložit tento " "obrázek do nového souboru, aby se situace již neopakovala." #: src/canvas.c:1467 msgid "The animation is too long to load all of it into layers." msgstr "" "Animace je příliÅ¡ dlouhá na to, aby vÅ¡e z ní mohlo být nahráno do vrstev." #: src/canvas.c:1469 msgid "Could not explode all the frames in the animation." msgstr "Nelze rozbalit vÅ¡echny snímky v animaci." #: src/canvas.c:1481 src/font.c:1556 src/fpick.c:937 src/otherwindow.c:2765 #: src/prefs.c:321 src/toolbar.c:451 msgid "Size" msgstr "Velikost" #: src/canvas.c:1484 src/otherwindow.c:244 msgid "Width" msgstr "Šířka" #: src/canvas.c:1485 src/otherwindow.c:245 msgid "Height" msgstr "Výška" #: src/canvas.c:1489 src/channels.c:253 src/channels.c:317 src/fpick.c:666 #: src/fpick.c:957 src/mainwindow.c:3990 src/otherwindow.c:255 #: src/otherwindow.c:517 src/otherwindow.c:591 src/otherwindow.c:867 #: src/otherwindow.c:1058 src/otherwindow.c:1727 src/otherwindow.c:2101 #: src/otherwindow.c:2336 src/otherwindow.c:2538 src/otherwindow.c:2691 #: src/otherwindow.c:2776 src/otherwindow.c:2937 src/otherwindow.c:3070 #: src/otherwindow.c:3169 src/prefs.c:338 src/prefs.c:464 src/prefs.c:538 #: src/spawn.c:666 src/viewer.c:1258 msgid "Cancel" msgstr "Storno" #: src/canvas.c:1490 src/channels.c:253 src/channels.c:317 src/fpick.c:956 #: src/info.c:297 src/mainwindow.c:3992 src/mygtk.c:233 src/mygtk.c:535 #: src/otherwindow.c:591 src/otherwindow.c:871 src/otherwindow.c:1058 #: src/otherwindow.c:1729 src/otherwindow.c:2101 src/otherwindow.c:2336 #: src/otherwindow.c:2538 src/otherwindow.c:2691 src/otherwindow.c:2776 #: src/otherwindow.c:3072 src/otherwindow.c:3171 src/prefs.c:338 #: src/prefs.c:538 src/spawn.c:666 msgid "OK" msgstr "OK" #: src/canvas.c:1504 #, c-format msgid "This is a scalable %s file." msgstr "" #: src/canvas.c:1545 msgid "Cannot open file" msgstr "Nelze otevřít soubor" #: src/canvas.c:1546 msgid "Unsupported file format" msgstr "Nepodporovaný typ souboru" #: src/canvas.c:1673 #, c-format msgid "File: %s already exists. Do you want to overwrite it?" msgstr "Soubor: %s již existuje. Chcete ho pÅ™epsat?" #: src/canvas.c:1674 msgid "File Found" msgstr "Soubor nalezen" #: src/canvas.c:1674 src/mainwindow.c:1095 msgid "NO" msgstr "NE" #: src/canvas.c:1674 src/mainwindow.c:1095 msgid "YES" msgstr "ANO" #: src/canvas.c:1988 msgid "Unable to export undo images" msgstr "Nelze exportovat obrázky historie" #: src/canvas.c:1994 msgid "Unable to export ASCII file" msgstr "Nelze exportovat do ASCII souboru" #: src/canvas.c:2076 src/layer.c:814 src/mainwindow.c:529 #, c-format msgid "Unable to save file: %s" msgstr "Nelze uložit soubor: %s" #: src/canvas.c:2101 src/prefs.c:222 msgid "Transparency index" msgstr "Index průhlednosti" #: src/canvas.c:2103 msgid "TIFF Compression" msgstr "" #: src/canvas.c:2105 src/prefs.c:225 msgid "JPEG Save Quality (100=High)" msgstr "Kvalita ukládání JPEGu (100=Vysoká)" #: src/canvas.c:2107 msgid "ZIP Compression (0=None)" msgstr "" #: src/canvas.c:2108 src/prefs.c:227 msgid "PNG Compression (0=None)" msgstr "PNG komprese (0=žádná)" #: src/canvas.c:2111 src/prefs.c:249 msgid "LZMA2 Compression (0=None)" msgstr "" #: src/canvas.c:2113 src/prefs.c:252 msgid "ZSTD Compression Level" msgstr "" #: src/canvas.c:2115 src/prefs.c:231 msgid "TGA RLE Compression" msgstr "TGA RLE komprese" #: src/canvas.c:2117 msgid "LBM PackBits Compression" msgstr "" #: src/canvas.c:2118 src/prefs.c:226 msgid "JPEG2000 Compression (0=Lossless)" msgstr "JPEG2000 komprese (0=bezeztrátová)" #: src/canvas.c:2120 msgid "WebP Compression" msgstr "" #: src/canvas.c:2122 msgid "WebP Save Quality (100=High)" msgstr "" #: src/canvas.c:2123 src/prefs.c:263 msgid "V8 Save Quality (100=High)" msgstr "" #: src/canvas.c:2125 src/prefs.c:264 msgid "V8L Compression (0=None)" msgstr "" #: src/canvas.c:2127 msgid "Hotspot at X =" msgstr "Aktivní bod na X =" #: src/canvas.c:2129 msgid "Y =" msgstr "Y =" #: src/canvas.c:2133 msgid "Animation delay" msgstr "ZpoždÄ›ní animace" #: src/canvas.c:2136 src/otherwindow.c:253 msgid "Undoable" msgstr "Vratitelné" #: src/canvas.c:2138 src/prefs.c:236 msgid "Apply colour profile" msgstr "Použít barevný profil" #: src/canvas.c:2176 src/toolbar.c:543 msgid "Load Image File" msgstr "NaÄtení obrázku" #: src/canvas.c:2191 src/toolbar.c:544 msgid "Save Image File" msgstr "Uložení obrázku" #: src/canvas.c:2196 msgid "Load Palette File" msgstr "NaÄtení palety" #: src/canvas.c:2202 msgid "Save Palette File" msgstr "Uložení palety" #: src/canvas.c:2207 msgid "Export Undo Images" msgstr "Export obrázků historie" #: src/canvas.c:2212 msgid "Export Undo Images (reversed)" msgstr "Export obrázků historie (reverznÄ›)" #: src/canvas.c:2217 msgid "You must have 16 or fewer palette colours to export ASCII art." msgstr "Pokud chcete exportovat ASCII kresbu, musíte mít maximálnÄ› 16 barev." #: src/canvas.c:2220 msgid "Export ASCII Art" msgstr "Exportovat jako ASCII kresbu" #: src/canvas.c:2224 msgid "Save Layer Files" msgstr "Uložení souborů vrstev" #: src/canvas.c:2234 msgid "Choose frames directory" msgstr "Vyberte adresář snímků" #: src/canvas.c:2240 msgid "You must save at least one frame to create an animated GIF." msgstr "Abyste vytvoÅ™ili animovaný GIF, musíte uložit alespoň jeden snímek." #: src/canvas.c:2243 msgid "Export GIF animation" msgstr "Exportovat GIF animaci" #: src/canvas.c:2247 msgid "Load Channel" msgstr "Otevřít kanálový soubor" #: src/canvas.c:2255 msgid "Save Channel" msgstr "Uložit kanálový soubor" #: src/canvas.c:2260 msgid "Save Composite Image" msgstr "Uložit kompozitní obrázek" #: src/channels.c:243 msgid "Create Channel" msgstr "VytvoÅ™it kanál" #: src/channels.c:244 msgid "Channel Type" msgstr "Typ kanálu" #: src/channels.c:247 msgid "Initial Channel State" msgstr "PoÄáteÄní stav kanálu" #: src/channels.c:251 msgid "Inverted" msgstr "Invertovaný" #: src/channels.c:265 msgid "Cleared" msgstr "Nenastaven" #: src/channels.c:266 msgid "Set" msgstr "Nastavený" #: src/channels.c:267 msgid "Set colour A radius B" msgstr "Nastavena barva A radius B" #: src/channels.c:268 msgid "Set blend A to B" msgstr "Nastaveno smíchání A do B" #: src/channels.c:269 msgid "Image Red" msgstr "ÄŒervená obrázku" #: src/channels.c:270 msgid "Image Green" msgstr "Zelená obrázku" #: src/channels.c:271 msgid "Image Blue" msgstr "Modrá obrázku" #: src/channels.c:273 src/channels.c:313 src/mainwindow.c:67 #: src/otherwindow.c:1679 msgid "Alpha" msgstr "Alpha" #: src/channels.c:274 src/channels.c:314 src/mainwindow.c:67 #: src/otherwindow.c:1683 msgid "Selection" msgstr "VýbÄ›r" #: src/channels.c:275 src/channels.c:315 src/mainwindow.c:67 #: src/otherwindow.c:1687 msgid "Mask" msgstr "Maska" #: src/channels.c:312 msgid "Delete Channels" msgstr "Smazat kanály" #: src/channels.c:367 msgid "Threshold Channel" msgstr "Práh kanálu" #: src/cpick.c:823 src/otherwindow.c:573 src/otherwindow.c:820 #: src/toolbar.c:299 msgid "Hue" msgstr "Odstín" #: src/cpick.c:827 src/otherwindow.c:573 src/otherwindow.c:818 #: src/toolbar.c:299 msgid "Saturation" msgstr "Saturace" #: src/cpick.c:835 msgid "Hex" msgstr "" #: src/cpick.c:840 src/layer.c:1109 src/otherwindow.c:2530 src/prefs.c:323 #: src/toolbar.c:457 msgid "Opacity" msgstr "Neprůsvitnost" #: src/font.c:982 msgid "Creating Font Index" msgstr "Vytváří se seznam písem" #: src/font.c:1353 msgid "You must select at least one directory to search for fonts." msgstr "Musíte vybrat alespoň jeden adresář, ve kterém se bude hledat písmo." #: src/font.c:1529 src/font.c:1624 src/toolbar.c:609 src/viewer.c:1213 #: src/viewer.c:1258 msgid "Paste Text" msgstr "Vložit text" #: src/font.c:1533 src/font.c:1572 src/png.c:3578 msgid "Text" msgstr "Text" #: src/font.c:1540 msgid "Font" msgstr "Písmo" #: src/font.c:1548 msgid "Style" msgstr "Styl" #: src/font.c:1566 msgid "Filename" msgstr "Název souboru" #: src/font.c:1567 msgid "Face" msgstr "" #: src/font.c:1587 src/viewer.c:1222 msgid "Antialias" msgstr "Vyhlazení" #: src/font.c:1590 src/viewer.c:1224 msgid "Invert" msgstr "Invertovat" #: src/font.c:1593 src/viewer.c:1226 msgid "Background colour =" msgstr "Barva pozadí =" #: src/font.c:1601 src/viewer.c:1233 msgid "DPI =" msgstr "" #: src/font.c:1610 msgid "Oblique" msgstr "SklonÄ›né" #: src/font.c:1612 src/viewer.c:1244 msgid "Angle of rotation =" msgstr "Úhel rotace =" #: src/font.c:1617 src/viewer.c:1248 msgid "Align" msgstr "" #: src/font.c:1620 src/viewer.c:1253 msgid "Spacing" msgstr "" #: src/font.c:1629 msgid "Font Directories" msgstr "Adresáře s fonty" #: src/font.c:1634 src/spawn.c:664 msgid "Directory" msgstr "Adresář" #: src/font.c:1637 msgid "New Directory" msgstr "Nový adresář" #: src/font.c:1644 src/prefs.c:532 msgid "Add" msgstr "PÅ™idat" #: src/font.c:1645 src/prefs.c:533 msgid "Remove" msgstr "Odstranit" #: src/font.c:1646 msgid "Create Index" msgstr "VytvoÅ™it index" #: src/font.c:1660 src/viewer.c:1267 msgid "Enter Text Here" msgstr "Zadejte text" #: src/fpick.c:635 #, c-format msgid "Could not access directory %s" msgstr "Nemohu pÅ™istoupit do složky %s" #: src/fpick.c:668 src/fpick.c:698 msgid "Delete" msgstr "Smazat" #: src/fpick.c:669 src/fpick.c:698 msgid "Rename" msgstr "PÅ™ejmenovat" #: src/fpick.c:672 src/otherwindow.c:255 src/otherwindow.c:1666 msgid "Create" msgstr "VytvoÅ™it" #: src/fpick.c:699 msgid "Enter the new filename" msgstr "Zadejte nové jméno souboru" #: src/fpick.c:704 msgid "Create Directory" msgstr "VytvoÅ™it adresář" #: src/fpick.c:705 msgid "Enter the name of the new directory" msgstr "Zadejte jméno nového adresáře" #: src/fpick.c:729 #, c-format msgid "Do you really want to delete \"%s\" ?" msgstr "Opravdu chcete smazat \"%s\" ?" #: src/fpick.c:735 msgid "Unable to delete" msgstr "Nelze smazat" #: src/fpick.c:741 msgid "Unable to rename" msgstr "Nelze pÅ™ejmenovat" #: src/fpick.c:750 msgid "Unable to create directory" msgstr "Nelze vytvoÅ™it adresář" #: src/fpick.c:924 msgid "Up" msgstr "Nahoru" #: src/fpick.c:925 msgid "Home" msgstr "Domovský adresář" #: src/fpick.c:926 msgid "Create New Directory" msgstr "VytvoÅ™it nový adresář" #: src/fpick.c:927 msgid "Show Hidden Files" msgstr "Zobrazit skryté soubory" #: src/fpick.c:929 msgid "Case Insensitive Sort" msgstr "TřídÄ›ní bez rozliÅ¡ení velikosti písmen" #: src/fpick.c:936 msgid "Name" msgstr "Jméno" #: src/fpick.c:938 msgid "Type" msgstr "Typ" #: src/fpick.c:939 msgid "Modified" msgstr "ZmÄ›nÄ›no" #: src/help.c:25 src/prefs.c:160 msgid "General" msgstr "Obecné" #: src/help.c:26 msgid "Keyboard shortcuts" msgstr "Klávesové zkratky" #: src/help.c:27 msgid "Mouse shortcuts" msgstr "Zkratky myÅ¡i" #: src/help.c:28 msgid "Credits" msgstr "PodÄ›kování" #: src/help.c:32 msgid "mtPaint 3.51 - Copyright (C) 2004-2021 The Authors\n" msgstr "mtPaint 3.51 - Copyright (C) 2004-2021 AutoÅ™i\n" #: src/help.c:33 msgid "See 'Credits' section for a list of the authors.\n" msgstr "Seznam autorů naleznete v záložce PodÄ›kování.\n" #: src/help.c:34 msgid "" "mtPaint 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.\n" msgstr "" "mtPaint je svobodný software; můžete ho šířit a/nebo modifikovat v souladu s " "GNU General Public Licencí jak byla publikována Free Software Foundation; " "buÄ verzí 3, nebo( dle vaÅ¡eho zvážení) jakoukoliv další verzí.\n" #: src/help.c:35 msgid "" "mtPaint 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.\n" msgstr "" "mtPaint je distribuován v nadÄ›ji, že bude používán, ale BEZ JAKÉKOLIV " "ZÃRUKY; a také bez samozÅ™ejmé záruky PRODEJNOSTI, nebo SCHOPNOSTI PLNIT " "SPECIÃLNà ÚČELY. Pro více detailů si pÅ™eÄtÄ›te GNU General Public Licenci.\n" #: src/help.c:36 msgid "" "mtPaint is a simple GTK+1/2/3 painting program designed for creating icons " "and pixel based artwork. It can edit indexed palette or 24 bit RGB images " "and offers basic painting and palette manipulation tools. It also has " "several other more powerful features such as channels, layers and animation. " "Due to its simplicity and lack of dependencies it runs well on GNU/Linux, " "Windows and older PC hardware.\n" msgstr "" "mtPaint je jednoduchý GTK+1/2/3 kreslící program navržený pro vytváření ikon " "a kreseb tvoÅ™ených pixely. Může upravovat obrázky s indexovanou, nebo 24 bit " "RGB paletou a nabídnout základní kreslicí a manipulaÄní nástroje. Má také " "mnoho dalších mocných nástrojů, jako kanály, vrstvy a animace. Vzhledem ke " "své jednoduchosti a bez závislostí běží dobÅ™e na GNU/ Linuxu, Windows a " "starším PC hardware.\n" #: src/help.c:37 msgid "" "There is full documentation of mtPaint's features contained in a handbook. " "If you don't already have this, you can download it from the mtPaint " "website.\n" msgstr "" "Kompletní dokumentace funkcí mtPaintu je k dispozici v příruÄce. Jestliže " "ji jeÅ¡tÄ› nemáte, můžete si ji stáhnout z webových stránek mtPaintu.\n" #: src/help.c:38 msgid "" "If you like mtPaint and you want to keep up to date with new releases, or " "you want to give some feedback, then the mailing lists may be of interest to " "you:\n" msgstr "" "Pokud se vám mtPaint líbí a chcete mít vždy nejnovÄ›jší verzi, nebo chcete " "sdÄ›lit nÄ›jaké názory, může být pro vás zajímavá tato poÅ¡tovní konference:\n" #: src/help.c:39 msgid "http://sourceforge.net/mail/?group_id=155874" msgstr "http://sourceforge.net/mail/?group_id=155874" #: src/help.c:42 msgid " Ctrl-N Create new image" msgstr " Ctrl-N VytvoÅ™it nový obrázek" #: src/help.c:43 msgid " Ctrl-O Open Image" msgstr " Ctrl-O Otevřít obrázek" #: src/help.c:44 msgid " Ctrl-S Save Image" msgstr " Ctrl-S Uložit obrázek" #: src/help.c:45 msgid " Ctrl-Shift-S Save layers file" msgstr " Ctrl-Shift-S Uložit soubor s vrstvami" #: src/help.c:46 msgid " Ctrl-Q Quit program\n" msgstr " Ctrl-Q UkonÄit program\n" #: src/help.c:47 msgid " Ctrl-A Select whole image" msgstr " Ctrl-A Vybrat celý obrázek" #: src/help.c:48 msgid " Escape Select nothing, cancel paste box" msgstr " Escape ZruÅ¡it výbÄ›r, vkládání" #: src/help.c:49 msgid " J Lasso selection\n" msgstr " J VýbÄ›r lasa\n" #: src/help.c:50 msgid " Ctrl-C Copy selection to clipboard" msgstr " Ctrl-C Zkopírovat výbÄ›r do schránky" #: src/help.c:51 msgid "" " Ctrl-X Copy selection to clipboard, and then paint current " "pattern to selection area" msgstr "" " Ctrl-X Zkopírovat výbÄ›r do schránky, a potom vyplnit oblast " "výbÄ›ru aktuálním vzorem" #: src/help.c:52 msgid " Ctrl-V Paste clipboard to centre of current view" msgstr " Ctrl-V Vložit schránku do stÅ™edu obrázku" #: src/help.c:53 msgid " Ctrl-K Paste clipboard to location it was copied from" msgstr " Ctrl-K Vložit schránku do míst, odkud byla kopírována" #: src/help.c:54 msgid " Ctrl-Shift-V Paste clipboard to new layer" msgstr " Ctrl-Shift-V Vložit obsah schránky do nové vrstvy" #: src/help.c:55 msgid " Enter/Return Commit paste to canvas" msgstr " Enter/Return Potvrdit vložení na plátno" #: src/help.c:56 msgid " Shift+Enter/Return Commit paste and swap canvas into the clipboard\n" msgstr " Shift+Enter/Return Odeslat vložit a vymÄ›nit plátno do schránky\n" #: src/help.c:57 msgid " Arrow keys Paint Mode - Move the mouse pointer" msgstr " Klávesy Å¡ipek Režim kreslení - ZmÄ›na barvy A, nebo B" #: src/help.c:58 msgid "" " Arrow keys Selection Mode - Nudge selection box or paste box by one " "pixel" msgstr "" " Klávesy Å¡ipek Režim výbÄ›ru - Posun oblasti výbÄ›ru, nebo vkládání o " "jeden pixel" #: src/help.c:59 msgid "" " Shift+Arrow keys Nudge mouse pointer, selection box or paste box by x " "pixels - x is defined by the Preferences window" msgstr "" " Shift+Å¡ipky Posun oblasti výbÄ›ru, vkládání o x pixelů - x je definováno v " "oknÄ› voleb" #: src/help.c:60 msgid " Ctrl+Arrows Move layer or resize selection box" msgstr "" " Ctrl+Å¡ipky PÅ™esunout vrstvu, nebo zmÄ›nit velikost oblasti výbÄ›ru" #: src/help.c:61 msgid " Ctrl+Shift+Arrows Move layer or resize selection box by x pixels\n" msgstr "" " Ctrl+Shift+Å¡ipky Posunout vrstvu nebo zmÄ›nit velikost oblasti výbÄ›ru o x " "obrazových bodů\n" #: src/help.c:62 msgid " Enter/Return Paint Mode - Simulate left click" msgstr "" " Enter/Return Režim kreslení - napodobit klepnutí levým tlaÄítkem myÅ¡i" #: src/help.c:63 msgid " Backspace Paint Mode - Simulate right click\n" msgstr "" " Backspace Režim kreslení - napodobit klepnutí pravým tlaÄítkem " "myÅ¡i\n" #: src/help.c:64 msgid "" " [ or ] Change colour A to the next or previous palette item" msgstr "" " [ or ] ZmÄ›nit barvu A na další, nebo pÅ™edchozí položku palety" #: src/help.c:65 msgid "" " Shift+[ or ] Change colour B to the next or previous palette item\n" msgstr "" " Shift+[ or ] ZmÄ›nit barvu B na další, nebo pÅ™edchozí položku palety\n" #: src/help.c:66 msgid " Delete Crop image to selection" msgstr " Delete Oříznout obrázek dle výbÄ›ru" #: src/help.c:67 msgid "" " Insert Transform colours - i.e. Brightness, Contrast, " "Saturation, Posterize, Gamma" msgstr "" " Insert Transformovat barvy - jako Jas, Kontrast, Saturace, bity " "na barvu, Gamma" #: src/help.c:68 msgid " Ctrl-G Greyscale the image" msgstr " Ctrl-G PÅ™evést na Å¡kálu Å¡edi" #: src/help.c:69 msgid " Shift-Ctrl-G Greyscale the image (Gamma corrected)" msgstr " Shift-Ctrl-G PÅ™evést na Å¡kálu Å¡edi (S Gamma korekcí)" #: src/help.c:70 msgid " Ctrl+M Mirror the image" msgstr " Ctrl+M Zrcadlit obrázek" #: src/help.c:71 msgid " Shift-Ctrl-I Invert the image\n" msgstr " Shift-Ctrl-I Obrátit obrázek\n" #: src/help.c:72 msgid "" " Ctrl-T Draw a rectangle around the selection area with the " "current fill" msgstr "" " Ctrl-T Nakreslit obdélník okolo oblasti výbÄ›ru aktuální výplní" #: src/help.c:73 msgid " Ctrl-Shift-T Fill in the selection area with the current fill" msgstr " Ctrl-Shift-T Vyplnit oblast výbÄ›ru aktuální výplní" #: src/help.c:74 msgid " Ctrl-L Draw an ellipse spanning the selection area" msgstr " Ctrl-L Nakreslit elipsu uvnitÅ™ oblasti výbÄ›ru" #: src/help.c:75 msgid " Ctrl-Shift-L Draw a filled ellipse spanning the selection area\n" msgstr " Ctrl-Shift-L Nakreslit vyplnÄ›nou elipsu uvnitÅ™ oblasti výbÄ›ru\n" #: src/help.c:76 msgid " Ctrl-E Edit the RGB values for colours A & B" msgstr " Ctrl-E Upravit RGB hodnoty pro barvy A a B" #: src/help.c:77 msgid " Ctrl-W Edit all palette colours\n" msgstr " Ctrl-W Upravit vÅ¡echny barvy palety\n" #: src/help.c:78 msgid " Ctrl-P Preferences" msgstr " Ctrl-P Volby" #: src/help.c:79 msgid " Ctrl-I Information\n" msgstr " Ctrl-I Informace\n" #: src/help.c:80 msgid " Ctrl-Z Undo last action" msgstr " Ctrl-Z Vrátit poslední akci" #: src/help.c:81 msgid " Ctrl-R Redo an undone action\n" msgstr " Ctrl-R Znovu provést vrácenou akci\n" #: src/help.c:82 msgid " Shift-T Text Tool (GTK+)" msgstr " Shift-T Textový nástroj (GTK+)" #: src/help.c:83 msgid " T Text Tool (FreeType)\n" msgstr " T Textový nástro (FreeType)\n" #: src/help.c:84 msgid " V View Window" msgstr " V Okno zobrazení" #: src/help.c:85 msgid " L Layers Window\n" msgstr " L Okno vrstev\n" #: src/help.c:86 msgid " Ctrl-H Toggle Hide Image mode" msgstr "" #: src/help.c:87 msgid " B Toggle Snap to Tile Grid mode\n" msgstr " B PÅ™epnout režim PÅ™ichytit k mřížce\n" #: src/help.c:88 msgid " X Swap Colours A & B" msgstr " X VymÄ›nit barvy A & B" #: src/help.c:89 msgid " E Choose Colour\n" msgstr " E Vybrat barvu\n" #: src/help.c:90 msgid "" " A Draw open arrow head when using the line tool (size set " "by flow setting)" msgstr "" " A Kreslit otevÅ™enou hlaviÄku Å¡ipky pÅ™i používání nástroje " "Äáry (velikost nastavena pomocí nastavení toku)" #: src/help.c:91 msgid "" " S Draw closed arrow head when using the line tool (size " "set by flow setting)\n" msgstr "" " S Kreslit zavÅ™enou hlaviÄku Å¡ipky pÅ™i používání nástroje " "Äáry (velikost nastavena pomocí nastavení toku)\n" #: src/help.c:92 msgid " D Line Tool" msgstr " D Nástroj Äáry" #: src/help.c:93 msgid " F Flood Fill Tool\n" msgstr " F Nástroj pro vyplnÄ›ní barvou\n" #: src/help.c:94 msgid " +,= Main edit window - Zoom in" msgstr " +,= Hlavní editaÄní okno - PÅ™iblížit" #: src/help.c:95 msgid " - Main edit window - Zoom out" msgstr " - Hlavní editaÄní okno - Vzdálit" #: src/help.c:96 msgid " Shift +,= View window - Zoom in" msgstr " Shift +,= Okno zobrazení - PÅ™iblížit" #: src/help.c:97 msgid " Shift - View window - Zoom out\n" msgstr " Shift - Okno zobrazení - Vzdálit\n" #: src/help.c:98 #, c-format msgid " 1 10% zoom" msgstr " 1 10% zoom" #: src/help.c:99 #, c-format msgid " 2 25% zoom" msgstr " 2 25% zoom" #: src/help.c:100 #, c-format msgid " 3 50% zoom" msgstr " 3 50% zoom" #: src/help.c:101 #, c-format msgid " 4 100% zoom" msgstr " 4 100% zoom" #: src/help.c:102 #, c-format msgid " 5 400% zoom" msgstr " 5 400% zoom" #: src/help.c:103 #, c-format msgid " 6 800% zoom" msgstr " 6 800% zoom" #: src/help.c:104 #, c-format msgid " 7 1200% zoom" msgstr " 7 1200% zoom" #: src/help.c:105 #, c-format msgid " 8 1600% zoom" msgstr " 8 1600% zoom" #: src/help.c:106 #, c-format msgid " 9 2000% zoom\n" msgstr " 9 2000% zoom\n" #: src/help.c:107 msgid " Shift + 1 Edit image channel" msgstr " Shift + 1 Upravit kanál obrázku" #: src/help.c:108 msgid " Shift + 2 Edit alpha channel" msgstr " Shift + 2 Upravit alfa kanál" #: src/help.c:109 msgid " Shift + 3 Edit selection channel" msgstr " Shift + 3 Upravit kanál výbÄ›ru" #: src/help.c:110 msgid " Shift + 4 Edit mask channel\n" msgstr " Shift + 4 Upravit kanál masky\n" #: src/help.c:111 msgid " F1 Help" msgstr " F1 Pomoc" #: src/help.c:112 msgid " F2 Choose Pattern" msgstr " F2 Vybrat vzor" #: src/help.c:113 msgid " F3 Choose Brush" msgstr " F3 Vybrat Å¡tÄ›tec" #: src/help.c:114 msgid " F4 Paint Tool" msgstr " F4 Nástroj malování" #: src/help.c:115 msgid " F5 Toggle Main Toolbar" msgstr " F5 Hlavní liÅ¡ta" #: src/help.c:116 msgid " F6 Toggle Tools Toolbar" msgstr " F6 Nástrojová liÅ¡ta" #: src/help.c:117 msgid " F7 Toggle Settings Toolbar" msgstr " F7 LiÅ¡ta nastavení" #: src/help.c:118 msgid " F8 Toggle Palette" msgstr " F8 Paleta" #: src/help.c:119 msgid " F9 Selection Tool" msgstr " F9 Nástroj výbÄ›ru" #: src/help.c:120 msgid " F12 Toggle Dock Area\n" msgstr " F12 PÅ™epnout oblast ukotvení\n" #: src/help.c:121 msgid " Ctrl + F1 - F12 Save current clipboard to file 1-12" msgstr " Ctrl + F1 - F12 Uloží aktuální schránku do souboru 1-12" #: src/help.c:122 msgid " Shift + F1 - F12 Load clipboard from file 1-12\n" msgstr " Shift + F1 - F12 NaÄte soubor 1-12 do schránky\n" #: src/help.c:123 msgid "" " Ctrl + 1, 2, ... , 0 Set opacity to 10%, 20%, ... , 100% (main or keypad " "numbers)" msgstr "" " Ctrl + 1, 2, ... , 0 Nastaví neprůsvitnost na 10%, 20%, ... , 100% " "(hlavní i numerická klávesnice)" #: src/help.c:124 msgid " Ctrl + + or = Increase opacity by 1" msgstr " Ctrl + + or = Zvýší neprůsvitnost o 1" #: src/help.c:125 msgid " Ctrl + - Decrease opacity by 1\n" msgstr " Ctrl + - Sníží neprůsvitnost o 1\n" #: src/help.c:126 msgid "" " Home Show or hide main window menu/toolbar/status bar/palette" msgstr "" " Home Zobrazí, nebo skryje hlavní nabídku, panely, nástroje a " "paletu" #: src/help.c:127 msgid " Page Up Scale Image" msgstr " Page Up ZmÄ›na měřítka plátna" #: src/help.c:128 msgid " Page Down Resize Image canvas" msgstr " Page Down ZmÄ›na velikosti plátna" #: src/help.c:129 msgid " End Pan Window" msgstr " End PÅ™ehledové okno" #: src/help.c:132 msgid " Left button Paint to canvas using the current tool" msgstr " Levé tlaÄítko Maluje na plátno pomocí vybraného nástroje" #: src/help.c:133 msgid "" " Middle button Selects the point which will be the centre of the " "image after the next zoom" msgstr "" " StÅ™ední tlaÄítko Nastaví bod, který bude stÅ™edem obrázku pÅ™i další " "zmÄ›nÄ› zoomu" #: src/help.c:134 msgid "" " Right button Commit paste to canvas / Stop drawing current line / " "Cancel selection\n" msgstr "" " Pravé tlaÄítko Potvrdí vložení na plátno / PÅ™eruší kreslení Äáry / " "Zruší výbÄ›r oblasti\n" #: src/help.c:135 msgid "" " Scroll Wheel In GTK+2/3 the user can have the scroll wheel zoom in " "or out via the Preferences window\n" msgstr "" " KoleÄko myÅ¡i V GTK+2/3 může mít uživatel koleÄko pro pÅ™iblížení " "nebo oddálení nastavením v oknÄ› voleb\n" #: src/help.c:136 msgid " Ctrl+Left button Choose colour A from under mouse pointer" msgstr " Ctrl+Levé tlaÄítko VýbÄ›r barvy A z pod ukazatele myÅ¡i" #: src/help.c:137 msgid " Ctrl+Left button Clone tool - Select source" msgstr "" #: src/help.c:138 msgid "" " Ctrl+Middle button Create colour A/B and pattern based on the RGB colour " "in A (RGB images only)" msgstr "" #: src/help.c:139 msgid " Ctrl+Right button Choose colour B from under mouse pointer" msgstr " Ctrl+Pravé tlaÄítko VýbÄ›r barvy B z pod ukazatele myÅ¡i" #: src/help.c:140 msgid "" " Ctrl+Right button Polygon tool - Delete last point / Delete nearest " "point" msgstr "" #: src/help.c:141 msgid " Ctrl+Scroll Wheel Scroll the main edit window left or right\n" msgstr " Ctrl+koleÄko Posouvá hlavní editaÄní okno doleva, nebo doprava\n" #: src/help.c:142 msgid "" " Ctrl+Double click Set colour A or B to average colour under brush " "square or selection marquee (RGB only)\n" msgstr "" #: src/help.c:143 msgid "" " Shift+Right button Selects the point which will be the centre of the " "image after the next zoom\n" "\n" msgstr "" " Shift+Pravé tlaÄítko Nastaví bod, který bude stÅ™edem obrázku pÅ™i další " "zmÄ›nÄ› zoomu\n" "\n" #: src/help.c:144 msgid "You can fixate the X/Y co-ordinates while moving the mouse:\n" msgstr "PÅ™i posouvání myÅ¡i můžete zablokovat osy X/Y takto:\n" #: src/help.c:145 msgid " Shift Constrain mouse movements to vertical line" msgstr " Shift Omezí posuny myší na vertikální osu" #: src/help.c:146 msgid " Shift+Ctrl Constrain mouse movements to horizontal line" msgstr " Shift+Ctrl Omezí posuny myší na horizontální osu" #: src/help.c:149 msgid "mtPaint is maintained by Dmitry Groshev.\n" msgstr "mtPaint aktuálnÄ› spravuje Dmitry Groshev.\n" #: src/help.c:150 msgid "wjaguar@users.sourceforge.net" msgstr "wjaguar@users.sourceforge.net" #: src/help.c:151 msgid "http://mtpaint.sourceforge.net/\n" msgstr "http://mtpaint.sourceforge.net/\n" #: src/help.c:152 msgid "" "The following people (in alphabetical order) have contributed directly to " "the project, and are therefore worthy of gracious thanks for their " "generosity and hard work:\n" "\n" msgstr "" "Následující lidé (v abecedním poÅ™adí) se přímo podílejí na projektu, a proto " "jim patří velké díky za jejich velkorysost a těžkou práci:\n" "\n" #: src/help.c:153 msgid "Authors\n" msgstr "AutoÅ™i\n" #: src/help.c:154 msgid "" "Dmitry Groshev - Contributing developer for version 2.30. Lead developer and " "maintainer from version 3.00 to the present." msgstr "" "Dmitry Groshev - PÅ™ispívající vývojář pro verzi 2.30. Vedoucí vývojář a " "správce od verze 3.00 do souÄasnosti." #: src/help.c:155 msgid "" "Mark Tyler - Original author and maintainer up to version 3.00, occasional " "contributor thereafter." msgstr "" "Mark Tyler - Původní autor a správce do verze 3.00 a od té doby obÄasný " "pÅ™ispÄ›vatel." #: src/help.c:156 msgid "" "Xiaolin Wu - Wrote the Wu quantizing method - see wu.c for more " "information.\n" "\n" msgstr "" "Xiaolin Wu - Napsal Wu quantovací metodu - více informací v souboru wu.c\n" "\n" #: src/help.c:157 msgid "" "General Contributions (Feedback and Ideas for improvements unless otherwise " "stated)\n" msgstr "" "Základní pÅ™ispÄ›vatelé (ZpÄ›tná vazba a nápady na vylepÅ¡ení, pokud není " "uvedeno jinak)\n" #: src/help.c:158 msgid "Abdulla Al Muhairi - Website redesign April 2005" msgstr "Abdulla Al Muhairi - Redesign stránek - Duben 2005" #: src/help.c:159 msgid "Alan Horkan" msgstr "Alan Horkan" #: src/help.c:160 msgid "Alexandre Prokoudine" msgstr "Alexandre Prokoudine" #: src/help.c:161 msgid "Antonio Andrea Bianco" msgstr "Antonio Andrea Bianco" #: src/help.c:162 msgid "Charlie Ledocq" msgstr "" #: src/help.c:163 msgid "Dennis Lee" msgstr "Dennis Lee" #: src/help.c:164 msgid "Donald White" msgstr "" #: src/help.c:165 msgid "Ed Jason" msgstr "Ed Jason" #: src/help.c:166 msgid "" "Eddie Kohler - Created Gifsicle which is needed for the creation and viewing " "of animated GIF files http://www.lcdf.org/gifsicle/" msgstr "" "Eddie Kohler - VytvoÅ™il Gifsicle, který je potÅ™eba pro vytvoÅ™ení a " "prohlížení animovaných GIFů http://www.lcdf.org/gifsicle/" #: src/help.c:167 msgid "" "Guadalinex Team (Junta de Andalucia) - man page, Launchpad/Rosetta " "registration" msgstr "" "Guadalinex Team (Junta de Andalucia) - manuálová stránka, Launchpad/ Rosetta " "registrace" #: src/help.c:168 msgid "Lou Afonso" msgstr "Lou Afonso" #: src/help.c:169 msgid "Magnus Hjorth" msgstr "Magnus Hjorth" #: src/help.c:170 msgid "Martin Zelaia" msgstr "Martin Zelaia" #: src/help.c:171 msgid "Pasi Kallinen" msgstr "" #: src/help.c:172 msgid "Pavel Ruzicka" msgstr "Pavel Ruzicka" #: src/help.c:173 msgid "Puppy Linux (Barry Kauler)" msgstr "Puppy Linux (Barry Kauler)" #: src/help.c:174 msgid "Victor Copovi" msgstr "" #: src/help.c:175 msgid "Vlastimil Krejcir" msgstr "Vlastimil Krejcir" #: src/help.c:176 msgid "" "William Kern\n" "\n" msgstr "" "William Kern\n" "\n" #: src/help.c:177 msgid "Translations\n" msgstr "PÅ™eklady\n" #: src/help.c:178 msgid "Brazilian Portuguese - Paulo Trevizan, Valter Nazianzeno" msgstr "Brazilská PortugalÅ¡tina - Paulo Trevizan, Valter Nazianzeno" #: src/help.c:179 msgid "Czech - Pavel Ruzicka, Martin Petricek, Roman Hornik, Pavel Fric" msgstr "ÄŒeÅ¡tina - Pavel Ruzicka, Martin Petricek, Roman Horník, Pavel Fric" #: src/help.c:180 msgid "Dutch - Hans Strijards, Pjotr" msgstr "HolandÅ¡tina - Hans Strijards, Pjotr" #: src/help.c:181 msgid "" "French - Nicolas Velin, Pascal Billard, Sylvain Cresto, Johan Serre, " "Philippe Etienne, Victor Copovi" msgstr "" "FrancouzÅ¡tina - Nicolas Velin, Pascal Billard, Sylvain Cresto, Johan Serre, " "Philippe Etienne, Victor Copovi" #: src/help.c:182 msgid "Galician - Miguel Anxo Bouzada" msgstr "Galicijsky - Miguel Anxo Bouzada" #: src/help.c:183 msgid "German - Oliver Frommel, B. Clausius, Ulrich Ringel, Simon Brixel" msgstr "NÄ›mÄina - Oliver Frommel, B. Clausius, Ulrich Ringel, Simon Brixel" #: src/help.c:184 msgid "Hungarian - Ur Balazs" msgstr "MaÄarÅ¡tina - Ur Balazs" #: src/help.c:185 msgid "Italian - Angelo Gemmi" msgstr "Italisky - Angelo Gemmi" #: src/help.c:186 msgid "Japanese - Norihiro YONEDA" msgstr "JaponÅ¡tina - Norihiro YONEDA" #: src/help.c:187 msgid "Kabyle - Yacine Bouklif" msgstr "" #: src/help.c:188 msgid "Polish - Bartosz Kaszubowski, LucaS" msgstr "PolÅ¡tina - Bartosz Kaszubowski, LucaS" #: src/help.c:189 msgid "Portuguese - Israel G. Lugo, Tiago Silva" msgstr "PortugalÅ¡tina - Israel G. Lugo, Tiago Silva" #: src/help.c:190 msgid "Russian - Sergey Irupin, Dmitry Groshev" msgstr "RuÅ¡tina - Sergey Irupin, Dmitry Groshev" #: src/help.c:191 msgid "Simplified Chinese - Cecc" msgstr "ZjednoduÅ¡ená ÄínÅ¡tina - Cecc" #: src/help.c:192 msgid "Slovak - Jozef Riha" msgstr "SlovenÅ¡tina - Jozef Riha" #: src/help.c:193 msgid "" "Spanish - Guadalinex Team (Junta de Andalucia), Antonio Sanchez Leon, Miguel " "Anxo Bouzada, Francisco Jose Rey, Adolfo Jayme" msgstr "" "Å panÄ›lÅ¡tina - Guadalinex Team (Junta de Andalucia), Antonio Sanchez Leon, " "Miguel Anxo Bouzada, Francisco Jose Rey, Adolfo Jayme" #: src/help.c:194 msgid "Swedish - Daniel Nylander, Daniel Eriksson" msgstr "Å védsky - Daniel Nylander, Daniel Eriksson" #: src/help.c:195 msgid "Tagalog - Anjelo delCarmen" msgstr "FilipínÅ¡tina - Anjelo delCarmen" #: src/help.c:196 msgid "Taiwanese Chinese - Wei-Lun Chao" msgstr "Taiwanská ČínÅ¡tina - Wei-Lun Chao" #: src/help.c:197 msgid "Turkish - Muhammet Kara, Tutku Dalmaz" msgstr "TureÄtina - Muhammet Kara, Tutku Dalmaz" #: src/info.c:258 msgid "Information" msgstr "Informace" #: src/info.c:260 msgid "Memory" msgstr "Paměť" #: src/info.c:261 msgid "Total memory for main + undo images" msgstr "Celková paměť pro hlavní obrázky a historii" #: src/info.c:263 msgid "Undo / Redo / Max levels used" msgstr "ZpÄ›t / VpÅ™ed / Max poÄet úrovní" #: src/info.c:265 msgid "Unused" msgstr "Nepoužito" #: src/info.c:269 msgid "Unique RGB pixels" msgstr "Unikátních RGB pixelů" #: src/info.c:272 src/layer.c:121 msgid "Layers" msgstr "Vrstvy" #: src/info.c:273 msgid "Total layer memory usage" msgstr "SpotÅ™eba pamÄ›ti vÅ¡ech vrstev" #: src/info.c:277 msgid "Colour Histogram" msgstr "Histogram barev" #: src/info.c:289 src/otherwindow.c:1614 msgid "Index" msgstr "Index" #: src/info.c:290 msgid "Canvas pixels" msgstr "Pixelů na plátnÄ›" #: src/info.c:328 #, c-format msgid "Clipboard = %i x %i" msgstr "Schránka = %i x %i" #: src/info.c:328 #, c-format msgid "Clipboard = %i x %i x RGB" msgstr "Schránka = %i x %i x RGB" #: src/info.c:377 msgid "Orphans" msgstr "Sirotků" #: src/info.c:383 #, c-format msgid "Colour index totals - %i of %i used" msgstr "Barevný index celkovÄ› - použito %i z %i" #: src/inifile.c:966 msgid "" "Could not find home directory. Using current directory as home directory." msgstr "Nelze nalézt domovský adresář. Použiji aktuální adresář jako domovský." #: src/layer.c:63 msgid "Background" msgstr "Pozadí" #: src/layer.c:122 src/mainwindow.c:5931 msgid "(Modified)" msgstr "(ZmÄ›nÄ›no)" #: src/layer.c:123 src/mainwindow.c:5932 msgid "Untitled" msgstr "Nenazvan" #: src/layer.c:308 #, c-format msgid "Do you really want to delete layer %i (%s) ?" msgstr "Opravdu chcete smazat vrstvu %i (%s) ?" #: src/layer.c:380 msgid "" "One or more of the layers contains changes that have not been saved. Do you " "really want to lose these changes?" msgstr "" "Jedna, nebo více vrstev obsahuje zmÄ›ny, které nebyly uloženy. Opravdu je " "chcete ztratit?" #: src/layer.c:381 src/mainwindow.c:1028 msgid "Cancel Operation" msgstr "Storno" #: src/layer.c:381 src/mainwindow.c:1028 msgid "Lose Changes" msgstr "Budiž" #: src/layer.c:523 #, c-format msgid "%d layers failed to load" msgstr "%d vrstev se nepodaÅ™ilo nahrát" #: src/layer.c:826 msgid "" "One or more of the image layers has not been saved. You must save each " "image individually before saving the layers text file in order to load this " "composite image in the future." msgstr "" "Jedna, nebo více vrstev nebyla uložena. Musíte uložit každý obrázek zvlášť," "než uložíte textový soubor s vrstvami, abyste mohli v budoucnosti otevřít " "tento kompozitní obrázek." #: src/layer.c:841 msgid "Do you really want to delete all of the layers?" msgstr "Opravdu chcete smazat vÅ¡echny vrstvy?" #: src/layer.c:970 msgid "You cannot add any more layers." msgstr "Nemůžete již pÅ™idat žádné další vrstvy." #: src/layer.c:1083 src/otherwindow.c:241 msgid "New Layer" msgstr "Nová vrstva" #: src/layer.c:1085 msgid "Raise" msgstr "Nahoru" #: src/layer.c:1087 msgid "Lower" msgstr "Dolů" #: src/layer.c:1089 msgid "Duplicate Layer" msgstr "Zduplikovat vrstvu" #: src/layer.c:1091 msgid "Centralise Layer" msgstr "Vycentrovat vrstvu" #: src/layer.c:1093 msgid "Delete Layer" msgstr "Smazat vrstvu" #: src/layer.c:1095 msgid "Close Layers Window" msgstr "Zavřít okno vrstev" #: src/layer.c:1101 msgid "Layer Name" msgstr "Název vrstvy" #: src/layer.c:1104 src/toolbar.c:209 msgid "Position" msgstr "Pozice" #: src/layer.c:1112 msgid "Transparent Colour" msgstr "Průhledná barva" #: src/layer.c:1117 msgid "Show all layers in main window" msgstr "Zobrazit vÅ¡echny vrstvy v hlavním oknÄ›" #: src/mainwindow.c:67 src/otherwindow.c:844 src/otherwindow.c:2756 #: src/toolbar.c:342 msgid "Image" msgstr "Obrázek" #: src/mainwindow.c:69 src/mainwindow.c:489 src/otherwindow.c:1613 #: src/otherwindow.c:2302 msgid "RGB" msgstr "RGB" #: src/mainwindow.c:69 src/otherwindow.c:1613 src/otherwindow.c:2302 msgid "sRGB" msgstr "" #: src/mainwindow.c:342 msgid "There were no unused colours to remove!" msgstr "Nejsou žádné nepoužité barvy na odstranÄ›ní!" #: src/mainwindow.c:371 msgid "The palette does not contain 2 colours that have identical RGB values" msgstr "Paleta neobsahuje žádné barvy s identickými RGB hodnotami" #: src/mainwindow.c:374 #, c-format msgid "" "The palette contains %i colours that have identical RGB values. Do you " "really want to merge them into one index and realign the canvas?" msgstr "" "Paleta obsahuje %i barev se stejnými RGB hodnotami. Opravdu je chcete " "slouÄit do jedné a upravit plátno?" #: src/mainwindow.c:492 msgid "indexed" msgstr "indexováno" #: src/mainwindow.c:498 #, c-format msgid "" "You are trying to save an %s image to an %s file which is not possible. I " "would suggest you save with a PNG extension." msgstr "" "Pokoušíte se uložit obrázek %s do %s souboru. Toto není možné, nejlepší je " "uložit jej s příponou PNG." #: src/mainwindow.c:500 #, c-format msgid "" "You are trying to save an %s file with a palette of more than %d colours. " "Either use another format or reduce the palette to %d colours." msgstr "" "Pokoušíte se uložit soubor %s s paletu obsahující více než %d barev. BuÄ " "použijte jiný formát, nebo snížte poÄet barev maximálnÄ› na %d." #: src/mainwindow.c:578 msgid "Unable to load clipboard" msgstr "Nelze naÄíst schránku" #: src/mainwindow.c:604 msgid "Unable to save clipboard" msgstr "Nelze uložit schránku" #: src/mainwindow.c:775 msgid "Zoom in" msgstr "" #: src/mainwindow.c:777 msgid "Zoom out" msgstr "" #: src/mainwindow.c:779 #, c-format msgid "10% zoom" msgstr "" #: src/mainwindow.c:781 #, c-format msgid "25% zoom" msgstr "" #: src/mainwindow.c:783 #, c-format msgid "50% zoom" msgstr "" #: src/mainwindow.c:785 #, c-format msgid "100% zoom" msgstr "" #: src/mainwindow.c:787 #, c-format msgid "400% zoom" msgstr "" #: src/mainwindow.c:789 #, c-format msgid "600% zoom" msgstr "" #: src/mainwindow.c:791 #, c-format msgid "800% zoom" msgstr "" #: src/mainwindow.c:793 #, c-format msgid "1000% zoom" msgstr "" #: src/mainwindow.c:795 #, c-format msgid "1200% zoom" msgstr "" #: src/mainwindow.c:797 #, c-format msgid "1600% zoom" msgstr "" #: src/mainwindow.c:799 #, c-format msgid "2000% zoom" msgstr "" #: src/mainwindow.c:801 #, c-format msgid "4000% zoom" msgstr "" #: src/mainwindow.c:803 #, c-format msgid "8000% zoom" msgstr "" #: src/mainwindow.c:805 #, c-format msgid "10% opacity" msgstr "" #: src/mainwindow.c:807 #, c-format msgid "20% opacity" msgstr "" #: src/mainwindow.c:809 #, c-format msgid "30% opacity" msgstr "" #: src/mainwindow.c:811 #, c-format msgid "40% opacity" msgstr "" #: src/mainwindow.c:813 #, c-format msgid "50% opacity" msgstr "" #: src/mainwindow.c:815 #, c-format msgid "60% opacity" msgstr "" #: src/mainwindow.c:817 #, c-format msgid "70% opacity" msgstr "" #: src/mainwindow.c:819 #, c-format msgid "80% opacity" msgstr "" #: src/mainwindow.c:821 #, c-format msgid "90% opacity" msgstr "" #: src/mainwindow.c:823 #, c-format msgid "100% opacity" msgstr "" #: src/mainwindow.c:825 msgid "Increase opacity" msgstr "" #: src/mainwindow.c:827 msgid "Decrease opacity" msgstr "" #: src/mainwindow.c:829 msgid "Draw open arrow head" msgstr "" #: src/mainwindow.c:831 msgid "Draw closed arrow head" msgstr "" #: src/mainwindow.c:833 msgid "Previous colour A" msgstr "" #: src/mainwindow.c:835 msgid "Next colour A" msgstr "" #: src/mainwindow.c:837 msgid "Previous colour B" msgstr "" #: src/mainwindow.c:839 msgid "Next colour B" msgstr "" #: src/mainwindow.c:841 msgid "Previous pattern" msgstr "" #: src/mainwindow.c:843 msgid "Next pattern" msgstr "" #: src/mainwindow.c:845 msgid "Larger brush" msgstr "" #: src/mainwindow.c:847 msgid "Smaller brush" msgstr "" #: src/mainwindow.c:849 msgid "View window - Zoom in" msgstr "" #: src/mainwindow.c:851 msgid "View window - Zoom out" msgstr "" #: src/mainwindow.c:1027 msgid "" "This canvas/palette contains changes that have not been saved. Do you " "really want to lose these changes?" msgstr "Plátno / paleta obsahuje neuložené zmÄ›ny. Opravdu je chcete ztratit?" #: src/mainwindow.c:1094 msgid "Do you really want to quit?" msgstr "Opravdu chcete skonÄit?" #: src/mainwindow.c:3754 msgid "Empty string or broken quoting" msgstr "" #: src/mainwindow.c:3755 msgid "Script must begin with a command" msgstr "" #: src/mainwindow.c:3756 msgid "Script nesting limit exceeded" msgstr "" #: src/mainwindow.c:3765 #, c-format msgid "'%s' does not match any item" msgstr "" #: src/mainwindow.c:3767 #, c-format msgid "'%s' matches a non-scriptable item" msgstr "" #: src/mainwindow.c:3769 #, c-format msgid "'%s' matches a disabled item" msgstr "" #: src/mainwindow.c:3788 #, c-format msgid "'%s' value does not fit item" msgstr "" #: src/mainwindow.c:3969 msgid "Script" msgstr "" #: src/mainwindow.c:3982 src/spawn.c:656 src/spawn.c:662 msgid "Action" msgstr "Akce" #: src/mainwindow.c:3991 src/spawn.c:666 msgid "Execute" msgstr "Spustit" #: src/mainwindow.c:4045 msgid "Unable to load script" msgstr "" #: src/mainwindow.c:5182 msgid "/_File" msgstr "/_Soubor" #: src/mainwindow.c:5184 msgid "//New" msgstr "//Nový" #: src/mainwindow.c:5186 msgid "//Open ..." msgstr "//Otevřít ..." #: src/mainwindow.c:5188 src/mainwindow.c:5669 msgid "//Save" msgstr "//Uložit" #: src/mainwindow.c:5190 src/mainwindow.c:5549 src/mainwindow.c:5627 #: src/mainwindow.c:5671 msgid "//Save As ..." msgstr "//Uložit jako ..." #: src/mainwindow.c:5192 msgid "//Export Undo Images ..." msgstr "//Export obrázků historie ..." #: src/mainwindow.c:5194 msgid "//Export Undo Images (reversed) ..." msgstr "//Export obrázků historie (reverznÄ›) ..." #: src/mainwindow.c:5196 msgid "//Export ASCII Art ..." msgstr "//Exportovat jako ASCII kresbu ..." #: src/mainwindow.c:5198 msgid "//Export Animated GIF ..." msgstr "//Exportovat jako animovaný GIF ..." #: src/mainwindow.c:5201 msgid "//Actions" msgstr "//ÄŒinnosti" #: src/mainwindow.c:5235 src/mainwindow.c:5488 msgid "///Configure" msgstr "///Nastavit" #: src/mainwindow.c:5290 msgid "//Quit" msgstr "//Konec" #: src/mainwindow.c:5293 msgid "/_Edit" msgstr "/_Upravit" #: src/mainwindow.c:5295 msgid "//Undo" msgstr "//ZpÄ›t" #: src/mainwindow.c:5297 msgid "//Redo" msgstr "//VpÅ™ed" #: src/mainwindow.c:5300 msgid "//Cut" msgstr "//Vyjmout" #: src/mainwindow.c:5302 msgid "//Copy" msgstr "//Kopírovat" #: src/mainwindow.c:5304 msgid "//Copy To Palette" msgstr "//Kopírovat do palety" #: src/mainwindow.c:5306 msgid "//Paste To Centre" msgstr "//Vložit doprostÅ™ed" #: src/mainwindow.c:5308 msgid "//Paste To New Layer" msgstr "//Vložit do nové vrstvy" #: src/mainwindow.c:5310 msgid "//Paste" msgstr "//Vložit" #: src/mainwindow.c:5312 msgid "//Paste Text" msgstr "//Vložit text" #: src/mainwindow.c:5318 msgid "//Paste Text (FreeType)" msgstr "//Vložit text (FreeType)" #: src/mainwindow.c:5321 msgid "//Paste Palette" msgstr "//Vložit paletu" #: src/mainwindow.c:5323 msgid "//Load Clipboard" msgstr "//NaÄíst schránku" #: src/mainwindow.c:5350 msgid "//Save Clipboard" msgstr "//Uložit schránku" #: src/mainwindow.c:5377 msgid "//Import Clipboard from System" msgstr "//Zavést schránku ze systému" #: src/mainwindow.c:5378 msgid "//Export Clipboard to System" msgstr "//Vyvést schránku do systému" #: src/mainwindow.c:5381 msgid "//Choose Pattern ..." msgstr "//Vybrat vzor ..." #: src/mainwindow.c:5383 msgid "//Choose Brush ..." msgstr "//Vybrat Å¡tÄ›tec ..." #: src/mainwindow.c:5385 msgid "//Choose Colour ..." msgstr "//Vybrat barvu..." #: src/mainwindow.c:5392 msgid "/_View" msgstr "/_Zobrazit" #: src/mainwindow.c:5394 msgid "//Show Main Toolbar" msgstr "//Hlavní liÅ¡ta" #: src/mainwindow.c:5396 msgid "//Show Tools Toolbar" msgstr "//Nástrojová liÅ¡ta" #: src/mainwindow.c:5399 msgid "//Show Settings Toolbar" msgstr "//LiÅ¡ta nastavení" #: src/mainwindow.c:5402 msgid "//Show Dock" msgstr "//Ukázat panel" #: src/mainwindow.c:5404 msgid "//Show Palette" msgstr "//Paleta" #: src/mainwindow.c:5406 msgid "//Show Status Bar" msgstr "//Stavová liÅ¡ta" #: src/mainwindow.c:5409 msgid "//Toggle Image View" msgstr "//PÅ™epnout zobrazení" #: src/mainwindow.c:5413 msgid "//Centralize Image" msgstr "//Vycentrovat obrázek" #: src/mainwindow.c:5414 msgid "//Show Zoom Grid" msgstr "//Rastr pÅ™i zvÄ›tÅ¡ení" #: src/mainwindow.c:5415 msgid "//Snap To Tile Grid" msgstr "//PÅ™ichytit k mřížce dlaždic" #: src/mainwindow.c:5417 msgid "//Configure Grid ..." msgstr "//Nastavit mřížku..." #: src/mainwindow.c:5418 msgid "//Tracing Image ..." msgstr "//Obkreslit obrázek..." #: src/mainwindow.c:5421 msgid "//View Window" msgstr "//Okno zobrazení" #: src/mainwindow.c:5423 msgid "//Horizontal Split" msgstr "//Horizontální dÄ›lení" #: src/mainwindow.c:5425 msgid "//Focus View Window" msgstr "//Okno pÅ™iblížení" #: src/mainwindow.c:5427 msgid "//Pan Window" msgstr "//PÅ™ehledové okno" #: src/mainwindow.c:5430 msgid "//Layers Window" msgstr "//Okno vrstev" #: src/mainwindow.c:5433 msgid "/_Image" msgstr "/_Obrázek" #: src/mainwindow.c:5436 msgid "//Convert To RGB" msgstr "//PÅ™evést na RGB" #: src/mainwindow.c:5438 msgid "//Convert To Indexed ..." msgstr "//PÅ™evést na indexovaný ..." #: src/mainwindow.c:5441 msgid "//Scale Canvas ..." msgstr "//ZmÄ›nit měřítko plátna ..." #: src/mainwindow.c:5443 msgid "//Resize Canvas ..." msgstr "//ZmÄ›nit velikost plátna ..." #: src/mainwindow.c:5445 msgid "//Crop" msgstr "//Oříznout" #: src/mainwindow.c:5448 src/mainwindow.c:5517 msgid "//Flip Vertically" msgstr "//OtoÄit vertikálnÄ›" #: src/mainwindow.c:5449 src/mainwindow.c:5519 msgid "//Flip Horizontally" msgstr "//OtoÄit horizontálnÄ›" #: src/mainwindow.c:5452 src/mainwindow.c:5521 msgid "//Rotate Clockwise" msgstr "//OtoÄit po smÄ›ru ruÄiÄek" #: src/mainwindow.c:5453 src/mainwindow.c:5523 msgid "//Rotate Anti-Clockwise" msgstr "//OtoÄit proti smÄ›ru ruÄiÄek" #: src/mainwindow.c:5454 msgid "//Free Rotate ..." msgstr "//OtoÄit libovolnÄ› ..." #: src/mainwindow.c:5455 msgid "//Skew ..." msgstr "//Zkreslit..." #: src/mainwindow.c:5458 msgid "//Segment ..." msgstr "//RozdÄ›lit na Äásti..." #: src/mainwindow.c:5462 msgid "//Script ..." msgstr "" #: src/mainwindow.c:5464 msgid "//Scripts" msgstr "" #: src/mainwindow.c:5491 msgid "//Information ..." msgstr "//Informace ..." #: src/mainwindow.c:5494 msgid "//Preferences ..." msgstr "//Volby ..." #: src/mainwindow.c:5497 msgid "/_Selection" msgstr "/_VýbÄ›r" #: src/mainwindow.c:5499 msgid "//Select All" msgstr "//Vybrat vÅ¡e" #: src/mainwindow.c:5501 msgid "//Select None (Esc)" msgstr "//ZruÅ¡it výbÄ›r (Esc)" #: src/mainwindow.c:5503 msgid "//Lasso Selection" msgstr "//VýbÄ›r lasem" #: src/mainwindow.c:5505 msgid "//Lasso Selection Cut" msgstr "//Vyjmout lasem" #: src/mainwindow.c:5508 msgid "//Outline Selection" msgstr "//Orámovat výbÄ›r" #: src/mainwindow.c:5510 msgid "//Fill Selection" msgstr "//Vyplnit výbÄ›r" #: src/mainwindow.c:5512 msgid "//Outline Ellipse" msgstr "//Orámovat elipsu" #: src/mainwindow.c:5514 msgid "//Fill Ellipse" msgstr "//Vyplnit elipsu" #: src/mainwindow.c:5526 msgid "//Horizontal Ramp" msgstr "//Vodorovná rampa" #: src/mainwindow.c:5528 msgid "//Vertical Ramp" msgstr "//Svislá rampa" #: src/mainwindow.c:5531 msgid "//Alpha Blend A,B" msgstr "//Alfa pÅ™echod mezi A,B" #: src/mainwindow.c:5533 msgid "//Move Alpha to Mask" msgstr "//PÅ™esun Alfa do masky" #: src/mainwindow.c:5535 msgid "//Mask Colour A,B" msgstr "//Maskovat barvy A,B" #: src/mainwindow.c:5537 msgid "//Unmask Colour A,B" msgstr "//Odmaskovat barvy A,B" #: src/mainwindow.c:5539 msgid "//Mask All Colours" msgstr "//Maskovat vÅ¡echny barvy" #: src/mainwindow.c:5541 msgid "//Clear Mask" msgstr "//ZruÅ¡it masku" #: src/mainwindow.c:5544 msgid "/_Palette" msgstr "/_Paleta" #: src/mainwindow.c:5548 src/mainwindow.c:5626 msgid "//Load ..." msgstr "//Otevřít ..." #: src/mainwindow.c:5550 msgid "//Load Default" msgstr "//NaÄíst výchozí" #: src/mainwindow.c:5552 msgid "//Mask All" msgstr "//Maskovat vÅ¡echny barvy" #: src/mainwindow.c:5553 msgid "//Mask None" msgstr "//Nemaskovat žádnou barvu" #: src/mainwindow.c:5555 msgid "//Swap A & B" msgstr "//Prohodit A a B" #: src/mainwindow.c:5557 msgid "//Edit Colour A & B ..." msgstr "//Upravit barvy A a B ..." #: src/mainwindow.c:5559 msgid "//Dither A" msgstr "//Rastr A" #: src/mainwindow.c:5561 msgid "//Palette Editor ..." msgstr "//Editor barev ..." #: src/mainwindow.c:5563 msgid "//Set Palette Size ..." msgstr "//Nastavit poÄet barev ..." #: src/mainwindow.c:5564 msgid "//Merge Duplicate Colours" msgstr "//SlouÄit duplicitní barvy" #: src/mainwindow.c:5566 msgid "//Remove Unused Colours" msgstr "//Odstranit nepoužité barvy" #: src/mainwindow.c:5569 msgid "//Create Quantized ..." msgstr "//VytvoÅ™it kvantované ..." #: src/mainwindow.c:5572 msgid "//Sort Colours ..." msgstr "//Uspořádat barvy ..." #: src/mainwindow.c:5573 msgid "//Palette Shifter ..." msgstr "//PosunovaÄ palety ..." #: src/mainwindow.c:5574 msgid "//Pick Gradient ..." msgstr "//Zvolit pÅ™echod..." #: src/mainwindow.c:5576 msgid "/Effe_cts" msgstr "/_Efekty" #: src/mainwindow.c:5578 msgid "//Transform Colour ..." msgstr "//Transformovat barvy ..." #: src/mainwindow.c:5580 msgid "//Invert" msgstr "//Invertovat" #: src/mainwindow.c:5582 msgid "//Greyscale" msgstr "//Å edá Å¡kála" #: src/mainwindow.c:5584 msgid "//Greyscale (Gamma corrected)" msgstr "//Å edá Å¡kála (s Gamma korekcí)" #: src/mainwindow.c:5586 msgid "//Normalize" msgstr "" #: src/mainwindow.c:5587 src/mainwindow.c:5658 msgid "//Threshold ..." msgstr "//Práh ..." #: src/mainwindow.c:5588 msgid "//Map ..." msgstr "" #: src/mainwindow.c:5590 msgid "//Isometric Transformation" msgstr "//Isometrické transformace" #: src/mainwindow.c:5592 msgid "///Left Side Down" msgstr "///Levá strana dolů" #: src/mainwindow.c:5593 msgid "///Right Side Down" msgstr "///Pravá strana dolů" #: src/mainwindow.c:5594 msgid "///Top Side Right" msgstr "///Horní strana vpravo" #: src/mainwindow.c:5595 msgid "///Bottom Side Right" msgstr "///Dolní strana vpravo" #: src/mainwindow.c:5598 msgid "//Edge Detect ..." msgstr "//Detekce hran ..." #: src/mainwindow.c:5600 msgid "//Difference of Gaussians ..." msgstr "//Gaussův rozdíl..." #: src/mainwindow.c:5602 msgid "//Sharpen ..." msgstr "//ZaostÅ™it ..." #: src/mainwindow.c:5604 msgid "//Unsharp Mask ..." msgstr "//ZaostÅ™ovací maska ..." #: src/mainwindow.c:5606 msgid "//Soften ..." msgstr "//Zjemnit ..." #: src/mainwindow.c:5608 msgid "//Gaussian Blur ..." msgstr "//Gaussovo rozmazání ..." #: src/mainwindow.c:5610 msgid "//Kuwahara-Nagao Blur ..." msgstr "//Rozmazání Kuwahara-Nagao..." #: src/mainwindow.c:5612 msgid "//Emboss" msgstr "//Reliéfy" #: src/mainwindow.c:5614 msgid "//Dilate" msgstr "//Roztáhnout" #: src/mainwindow.c:5616 msgid "//Erode" msgstr "//RozruÅ¡it" #: src/mainwindow.c:5619 msgid "//Solid Noise ..." msgstr "" #: src/mainwindow.c:5620 msgid "//Bacteria ..." msgstr "//Baktérie ..." #: src/mainwindow.c:5623 msgid "/Cha_nnels" msgstr "/Kanály" #: src/mainwindow.c:5625 msgid "//New ..." msgstr "//Nový ..." #: src/mainwindow.c:5628 msgid "//Delete ..." msgstr "//Smazat ..." #: src/mainwindow.c:5632 msgid "//Edit Image" msgstr "//Upravit obrázek" #: src/mainwindow.c:5635 msgid "//Edit Alpha" msgstr "//Upravit alfakanál" #: src/mainwindow.c:5638 msgid "//Edit Selection" msgstr "//Upravit výbÄ›r" #: src/mainwindow.c:5641 msgid "//Edit Mask" msgstr "//Upravit masku" #: src/mainwindow.c:5645 msgid "//Hide Image" msgstr "//Skrýt obrázek" #: src/mainwindow.c:5648 msgid "//Disable Alpha" msgstr "//Vypnout alfakanál" #: src/mainwindow.c:5651 msgid "//Disable Selection" msgstr "//Vypnout výbÄ›r" #: src/mainwindow.c:5654 msgid "//Disable Mask" msgstr "//Vypnout masku" #: src/mainwindow.c:5657 msgid "//Couple RGBA Operations" msgstr "//Párovat RGBA operace" #: src/mainwindow.c:5659 msgid "//Unassociate Alpha" msgstr "//Nespojitá alfa" #: src/mainwindow.c:5663 msgid "//View Alpha as an Overlay" msgstr "//Zobrazit alfakanál jako overlay" #: src/mainwindow.c:5664 msgid "//Configure Overlays ..." msgstr "//Konfigurovat overlaye ..." #: src/mainwindow.c:5666 msgid "/_Layers" msgstr "/Vrstvy" #: src/mainwindow.c:5668 msgid "//New Layer" msgstr "//Nová vrstva" #: src/mainwindow.c:5672 msgid "//Save Composite Image ..." msgstr "//Uložit kompozitní obrázek ..." #: src/mainwindow.c:5673 msgid "//Composite to New Layer" msgstr "//Spojit do nové vrstvy" #: src/mainwindow.c:5674 msgid "//Remove All Layers" msgstr "//Odstranit vÅ¡echny vrstvy" #: src/mainwindow.c:5676 msgid "//Configure Animation ..." msgstr "//Konfigurovat animaci ..." #: src/mainwindow.c:5677 msgid "//Preview Animation ..." msgstr "//Náhled animace ..." #: src/mainwindow.c:5678 msgid "//Set Key Frame ..." msgstr "//Nastavit klíÄový snímek ..." #: src/mainwindow.c:5679 msgid "//Remove All Key Frames ..." msgstr "//Odstranit vÅ¡echny klíÄové snímky ..." #: src/mainwindow.c:5681 msgid "/More..." msgstr "/Více..." #: src/mainwindow.c:5683 msgid "/_Help" msgstr "/Po_moc" #: src/mainwindow.c:5684 msgid "//Documentation" msgstr "//Dokumentace" #: src/mainwindow.c:5686 msgid "//About" msgstr "//O aplikaci" #: src/mainwindow.c:5689 msgid "//Keyboard Shortcuts ..." msgstr "" #: src/mainwindow.c:5690 msgid "//Rebind Shortcut Keycodes" msgstr "//PÅ™evázat klávesové zkratky" #: src/memory.c:2800 msgid "Quantize Pass 1" msgstr "" #: src/memory.c:2854 msgid "Quantize Pass 2" msgstr "Průchod kvantizace 2" #: src/memory.c:3073 src/memory.c:3458 msgid "Converting to Indexed Palette" msgstr "PÅ™evádím na indexovou paletu" #: src/memory.c:5135 src/otherwindow.c:540 msgid "Bacteria Effect" msgstr "Efekt baktérie" #: src/memory.c:5170 msgid "Rotating" msgstr "OtáÄím" #: src/memory.c:5511 msgid "Free Rotation" msgstr "Volné otáÄení" #: src/memory.c:6096 msgid "Scaling Image" msgstr "MÄ›ním měřítko obrázku" #: src/memory.c:7560 msgid "Counting Unique RGB Pixels" msgstr "PoÄítám poÄet unikátních RGB pixelů" #: src/memory.c:7608 msgid "Applying Effect" msgstr "Aplikuji efekt" #: src/memory.c:8792 msgid "Kuwahara-Nagao Filter" msgstr "Kuwahara-Nagaův filtr" #: src/memory.c:10456 src/otherwindow.c:2665 msgid "Skew" msgstr "ZeÅ¡ikmit" #: src/memory.c:10630 msgid "Segmentation Pass 1" msgstr "Průchod rozdÄ›lení na Äásti 1" #: src/memory.c:10757 msgid "Segmentation Pass 2" msgstr "Průchod rozdÄ›lení na Äásti 2" #: src/memory.c:11019 src/otherwindow.c:3156 msgid "Solid Noise" msgstr "" #: src/mygtk.c:134 src/mygtk.c:163 msgid "Please Wait ..." msgstr "Prosím Äekejte ..." #: src/mygtk.c:141 msgid "STOP" msgstr "STOP" #: src/mygtk.c:504 msgid "Disabled" msgstr "" #: src/mygtk.c:504 src/toolbar.c:301 msgid "Screen" msgstr "Závoj" #: src/mygtk.c:504 msgid "Window" msgstr "" #: src/mygtk.c:508 msgid "Input" msgstr "" #: src/mygtk.c:512 msgid "Device:" msgstr "" #: src/mygtk.c:514 msgid "Mode:" msgstr "" #: src/mygtk.c:519 msgid "Axes" msgstr "" #: src/mygtk.c:524 msgid "X:" msgstr "" #: src/mygtk.c:525 msgid "Y:" msgstr "" #: src/mygtk.c:526 msgid "Pressure:" msgstr "" #: src/mygtk.c:527 msgid "X tilt:" msgstr "" #: src/mygtk.c:528 msgid "Y tilt:" msgstr "" #: src/mygtk.c:529 msgid "Wheel:" msgstr "" #: src/mygtk.c:579 msgid "none" msgstr "" #: src/otherwindow.c:236 msgid "24 bit RGB" msgstr "24 bit RGB" #: src/otherwindow.c:236 src/otherwindow.c:3179 msgid "Greyscale" msgstr "Å kála Å¡edi" #: src/otherwindow.c:237 msgid "Indexed Palette" msgstr "Indexovaná paleta" #: src/otherwindow.c:237 msgid "From Clipboard" msgstr "Ze schránky" #: src/otherwindow.c:237 msgid "Grab Screenshot" msgstr "Sejmout obrazovku" #: src/otherwindow.c:242 src/toolbar.c:542 msgid "New Image" msgstr "Nový obrázek" #: src/otherwindow.c:246 src/otherwindow.c:3164 msgid "Colours" msgstr "Barev" #: src/otherwindow.c:409 msgid "Pattern Chooser" msgstr "VýbÄ›r vzoru" #: src/otherwindow.c:497 msgid "Set Palette Size" msgstr "Nastavit poÄet barev" #: src/otherwindow.c:517 src/otherwindow.c:591 src/otherwindow.c:870 #: src/otherwindow.c:2538 src/otherwindow.c:2776 src/otherwindow.c:2939 #: src/prefs.c:338 src/prefs.c:538 msgid "Apply" msgstr "Provést" #: src/otherwindow.c:573 msgid "Luminance" msgstr "Jas" #: src/otherwindow.c:573 src/otherwindow.c:814 msgid "Brightness" msgstr "Jas" #: src/otherwindow.c:574 msgid "Distance to A" msgstr "Vzdálenost k A" #: src/otherwindow.c:575 msgid "Projection to A->B" msgstr "Projekce do A->B" #: src/otherwindow.c:576 msgid "Frequency" msgstr "Frekvence" #: src/otherwindow.c:580 msgid "Sort Palette Colours" msgstr "SeÅ™adit barvy v paletÄ›" #: src/otherwindow.c:582 msgid "Start Index" msgstr "Od indexu" #: src/otherwindow.c:583 msgid "End Index" msgstr "Do indexu" #: src/otherwindow.c:589 msgid "Reverse Order" msgstr "OpaÄné Å™azení" #: src/otherwindow.c:805 msgid "Bitwise" msgstr "" #: src/otherwindow.c:805 msgid "Truncated" msgstr "Zkrácený" #: src/otherwindow.c:805 msgid "Rounded" msgstr "Zakulacený" #: src/otherwindow.c:809 src/toolbar.c:311 src/toolbar.c:558 msgid "Transform Colour" msgstr "Transformace barev" #: src/otherwindow.c:812 msgid "Gamma" msgstr "Gamma" #: src/otherwindow.c:816 msgid "Contrast" msgstr "Kontrast" #: src/otherwindow.c:822 src/otherwindow.c:1674 msgid "Posterize" msgstr "bitů na barvu" #: src/otherwindow.c:831 msgid "Show Detail" msgstr "Zobrazit detaily" #: src/otherwindow.c:836 msgid "Posterize type" msgstr "Typ posterizace" #: src/otherwindow.c:857 msgid "Auto-Preview" msgstr "Automatický náhled" #: src/otherwindow.c:869 msgid "Reset" msgstr "Reset" #: src/otherwindow.c:931 msgid "New geometry is the same as now - nothing to do." msgstr "Nové rozmÄ›ry jsou stejné jako původní - nic se neprovede." #: src/otherwindow.c:980 msgid "The operating system cannot allocate the memory for this operation." msgstr "OperaÄní systém nemůže alokovat paměť pro tuto operaci." #: src/otherwindow.c:982 msgid "" "You have not allocated enough memory in the Preferences window for this " "operation." msgstr "Pro tuto operaci jste nealokovali dostatek pamÄ›ti v oknÄ› Volby." #: src/otherwindow.c:993 src/otherwindow.c:2495 msgid "Mirror" msgstr "ZrcadlovÄ›" #: src/otherwindow.c:993 src/otherwindow.c:994 msgid "Tile" msgstr "Dlaždice" #: src/otherwindow.c:993 msgid "Void" msgstr "Prázdný" #: src/otherwindow.c:994 src/shifter.c:283 msgid "Clear" msgstr "VyÄistit" #: src/otherwindow.c:994 msgid "Mirror tile" msgstr "Zrcadlová dlaždice" #: src/otherwindow.c:996 msgid "Nearest Neighbour" msgstr "Nejbližší okolí" #: src/otherwindow.c:997 msgid "Bilinear / Area Mapping" msgstr "Bilineární / mapování oblasti" #: src/otherwindow.c:998 msgid "Bicubic" msgstr "Bikubické" #: src/otherwindow.c:999 msgid "Bicubic edged" msgstr "Bikubické s hranami" #: src/otherwindow.c:1000 msgid "Bicubic better" msgstr "Lepší bikubické" #: src/otherwindow.c:1001 msgid "Bicubic sharper" msgstr "Bikubické ostÅ™ejší" #: src/otherwindow.c:1002 msgid "Blackman-Harris" msgstr "Blackman-Harris" #: src/otherwindow.c:1008 msgid "Scale Canvas" msgstr "ZmÄ›na měřítka plátna" #: src/otherwindow.c:1009 msgid "Resize Canvas" msgstr "ZmÄ›na velikosti plátna" #: src/otherwindow.c:1012 msgid "Original " msgstr "Originál " #: src/otherwindow.c:1013 msgid "New" msgstr "Nový" #: src/otherwindow.c:1014 msgid "Width " msgstr "Šířka " #: src/otherwindow.c:1018 msgid "Height " msgstr "Výška " #: src/otherwindow.c:1023 src/otherwindow.c:2514 src/otherwindow.c:2672 #: src/toolbar.c:212 msgid "Offset" msgstr "Posun" #: src/otherwindow.c:1026 src/otherwindow.c:1615 src/viewer.c:1209 msgid "Centre" msgstr "Vycentrovat" #: src/otherwindow.c:1033 src/otherwindow.c:1052 msgid "Fix Aspect Ratio" msgstr "Dodržet pomÄ›r stran" #: src/otherwindow.c:1039 src/otherwindow.c:2070 src/toolbar.c:312 msgid "Settings" msgstr "Nastavení" #: src/otherwindow.c:1046 msgid "Sharper image reduction" msgstr "ÄŒisté zmenÅ¡ení obrázku" #: src/otherwindow.c:1047 msgid "Boundary extension" msgstr "Rozšíření hranic" #: src/otherwindow.c:1613 src/otherwindow.c:2302 msgid "HSV" msgstr "HSV" #: src/otherwindow.c:1614 msgid "Highlight" msgstr "" #: src/otherwindow.c:1615 msgid "Limit" msgstr "Limit" #: src/otherwindow.c:1616 msgid "Sphere" msgstr "Koule" #: src/otherwindow.c:1616 src/otherwindow.c:2670 msgid "Angle" msgstr "Úhel" #: src/otherwindow.c:1616 msgid "Cube" msgstr "Krychle" #: src/otherwindow.c:1617 msgid "Opaque" msgstr "Neprůhledné" #: src/otherwindow.c:1617 msgid "Border" msgstr "Okraj" #: src/otherwindow.c:1618 msgid "Transparent" msgstr "Průhledné" #: src/otherwindow.c:1618 msgid "Tile " msgstr "Název " #: src/otherwindow.c:1618 msgid "Segment" msgstr "RozdÄ›lit na Äásti" #: src/otherwindow.c:1656 msgid "Scale" msgstr "Měřítko" #: src/otherwindow.c:1657 src/otherwindow.c:3059 msgid "From" msgstr "Od" #: src/otherwindow.c:1659 src/otherwindow.c:3061 msgid "To" msgstr "Do" #: src/otherwindow.c:1699 msgid "Range" msgstr "Rozsah" #: src/otherwindow.c:1702 msgid "Inverse" msgstr "Inverze" #: src/otherwindow.c:1710 msgid "Smart grid" msgstr "Chytrá mřížka" #: src/otherwindow.c:1712 msgid "Tile grid" msgstr "Mřížka dlaždice" #: src/otherwindow.c:1714 msgid "Minimum grid zoom" msgstr "Rastr pÅ™i zoomu alespoň" #: src/otherwindow.c:1717 msgid "Tile width" msgstr "Šířka dlaždice" #: src/otherwindow.c:1720 msgid "Tile height" msgstr "Výška dlaždice" #: src/otherwindow.c:1744 msgid "Palette Editor" msgstr "Editor barev" #: src/otherwindow.c:1763 msgid "Configure Overlays" msgstr "Konfigurovat overlaye" #: src/otherwindow.c:1782 msgid "Colour Editor" msgstr "Editor barev" #: src/otherwindow.c:1818 src/toolbar.c:430 msgid "Colour-Selective Mode" msgstr "Režim výbÄ›ru barvy" #: src/otherwindow.c:1843 msgid "Configure Grid" msgstr "Nastavit mřížku" #: src/otherwindow.c:2045 msgid "Exact Conversion" msgstr "PÅ™esná konverze" #: src/otherwindow.c:2045 msgid "Use Current Palette" msgstr "Použít aktuální paletu" #: src/otherwindow.c:2046 msgid "PNN Quantize (slow, better quality)" msgstr "PNN kvantizace (pomalejší, ale kvalitnÄ›jší)" #: src/otherwindow.c:2047 msgid "Wu Quantize (fast)" msgstr "Wu kvantizace (rychlá)" #: src/otherwindow.c:2048 msgid "Max-Min Quantize (best for small palettes and dithering)" msgstr "" "Max-Min kvantizace (nejlepší pro palety s malým poÄtem barev a dithering)" #: src/otherwindow.c:2049 src/otherwindow.c:2495 src/otherwindow.c:2756 #: src/png.c:2794 src/prefs.c:377 msgid "None" msgstr "Žádný" #: src/otherwindow.c:2049 msgid "Floyd-Steinberg" msgstr "Floyd-Steinberg" #: src/otherwindow.c:2049 msgid "Stucki" msgstr "Stucki" #: src/otherwindow.c:2052 msgid "Floyd-Steinberg (quick)" msgstr "Floyd-Steinberg (rychlý)" #: src/otherwindow.c:2052 msgid "Dithered (effect)" msgstr "RozechvÄ›lý (efekt)" #: src/otherwindow.c:2053 msgid "Scattered (effect)" msgstr "Rozptýlený (efekt)" #: src/otherwindow.c:2054 msgid "Gamut" msgstr "Gamut" #: src/otherwindow.c:2054 msgid "Weakly" msgstr "SlabÄ›" #: src/otherwindow.c:2054 msgid "Strongly" msgstr "SilnÄ›" #: src/otherwindow.c:2055 msgid "Off" msgstr "Vypnuto" #: src/otherwindow.c:2055 msgid "Separate/Sum" msgstr "Separovat/SeÄíst" #: src/otherwindow.c:2055 msgid "Separate/Split" msgstr "Separovat/RozdÄ›lit" #: src/otherwindow.c:2056 msgid "Length/Sum" msgstr "Délka/SeÄíst" #: src/otherwindow.c:2056 msgid "Length/Split" msgstr "Délka/RozdÄ›lit" #: src/otherwindow.c:2057 msgid "Largest (Linf)" msgstr "NejvÄ›tší (Linf)" #: src/otherwindow.c:2057 msgid "Sum (L1)" msgstr "Suma (L1)" #: src/otherwindow.c:2057 msgid "Euclidean (L2)" msgstr "Euclidean (L2)" #: src/otherwindow.c:2061 msgid "Create Quantized" msgstr "VytvoÅ™it kvantované" #: src/otherwindow.c:2062 msgid "Convert To Indexed" msgstr "PÅ™evod na indexovaný" #: src/otherwindow.c:2065 msgid "Indexed Colours To Use" msgstr "PoÄet indexovaných barev" #: src/otherwindow.c:2078 msgid "Truncate palette" msgstr "Zkrácená paleta" #: src/otherwindow.c:2079 msgid "Diameter based weighting" msgstr "Váha založená na průmÄ›ru" #: src/otherwindow.c:2084 msgid "Dither" msgstr "RozechvÄ›t" #: src/otherwindow.c:2087 src/otherwindow.c:2584 src/otherwindow.c:2928 msgid "Colour space" msgstr "Barevný prostor" #: src/otherwindow.c:2088 src/otherwindow.c:2929 msgid "Difference measure" msgstr "Rozdíl měření" #: src/otherwindow.c:2089 msgid "Reduce colour bleed" msgstr "Redukovat plýtvání barvami" #: src/otherwindow.c:2090 msgid "Serpentine scan" msgstr "Serpentinový scan" #: src/otherwindow.c:2092 msgid "Error propagation, %" msgstr "Chyba propagace, %" #: src/otherwindow.c:2093 msgid "Selective error propagation" msgstr "Selektivní chyba propagace" #: src/otherwindow.c:2097 msgid "Full error precision" msgstr "Plná chybová pÅ™esnost" #: src/otherwindow.c:2302 msgid "Backward HSV" msgstr "ZpÄ›tný HSV" #: src/otherwindow.c:2303 src/otherwindow.c:2326 msgid "Constant" msgstr "Konstantní" #: src/otherwindow.c:2307 msgid "Edit Gradient" msgstr "Upravit gradient" #: src/otherwindow.c:2329 msgid "Points:" msgstr "Bodů:" #: src/otherwindow.c:2493 msgid "Linear" msgstr "Lineární" #: src/otherwindow.c:2493 src/otherwindow.c:2703 msgid "Bilinear" msgstr "Bilineární" #: src/otherwindow.c:2493 msgid "Radial" msgstr "Radiální" #: src/otherwindow.c:2494 msgid "Square" msgstr "ÄŒtvercový" #: src/otherwindow.c:2494 msgid "Angular" msgstr "Úhlové" #: src/otherwindow.c:2494 msgid "Conical" msgstr "Kuželové" #: src/otherwindow.c:2495 msgid "Level " msgstr "" #: src/otherwindow.c:2495 msgid "Repeat" msgstr "Opakovat" #: src/otherwindow.c:2496 msgid "A to B" msgstr "A do B" #: src/otherwindow.c:2496 msgid "A to B (RGB)" msgstr "A do B (RGB)" #: src/otherwindow.c:2497 msgid "A to B (sRGB)" msgstr "A do B (sRGB)" #: src/otherwindow.c:2497 msgid "A to B (HSV)" msgstr "A do B (HSV)" #: src/otherwindow.c:2497 msgid "A to B (backward HSV)" msgstr "A do B (zpÄ›tnÄ› HSV)" #: src/otherwindow.c:2498 msgid "A only" msgstr "Pouze A" #: src/otherwindow.c:2498 src/otherwindow.c:2500 msgid "Custom" msgstr "Vlastní" #: src/otherwindow.c:2499 msgid "Current to 0" msgstr "Aktuální do 0" #: src/otherwindow.c:2499 msgid "Current only" msgstr "Pouze aktuální" #: src/otherwindow.c:2504 msgid "Configure Gradient" msgstr "Nastavení gradientu" #: src/otherwindow.c:2507 src/png.c:1001 msgid "Channel" msgstr "Kanál" #: src/otherwindow.c:2512 msgid "Length" msgstr "Délka" #: src/otherwindow.c:2513 msgid "Repeat length" msgstr "Délka opakování" #: src/otherwindow.c:2515 msgid "Gradient type" msgstr "Typ gradientu" #: src/otherwindow.c:2516 msgid "Extension type" msgstr "Typ rozšíření" #: src/otherwindow.c:2517 msgid "Distance type" msgstr "" #: src/otherwindow.c:2518 msgid "Preview opacity" msgstr "Neprůhlednost náhledu" #: src/otherwindow.c:2527 src/otherwindow.c:2533 src/toolbar.c:309 msgid "Reverse" msgstr "ObrácenÄ›" #: src/otherwindow.c:2528 src/otherwindow.c:2534 msgid "Edit Custom" msgstr "Upravit Vlastní" #: src/otherwindow.c:2592 msgid "Pick Gradient" msgstr "Zvolit pÅ™echod" #: src/otherwindow.c:2668 msgid "Horizontal " msgstr "Horizontální " #: src/otherwindow.c:2674 msgid "At distance" msgstr "Ve vzdálenosti" #: src/otherwindow.c:2675 msgid "Vertical" msgstr "Vertikální" #: src/otherwindow.c:2756 msgid "Unchanged" msgstr "NepozmÄ›nÄ›no" #: src/otherwindow.c:2761 msgid "Tracing Image" msgstr "Obkreslit obrázek" #: src/otherwindow.c:2763 src/toolbar.c:315 msgid "Source" msgstr "Zdroj" #: src/otherwindow.c:2768 msgid "Origin" msgstr "Původ" #: src/otherwindow.c:2771 msgid "Relative scale" msgstr "Relativní měřítko" #: src/otherwindow.c:2774 msgid "Display" msgstr "Zobrazit" #: src/otherwindow.c:2926 msgid "Segment Image" msgstr "RozdÄ›lit obrázek na Äásti" #: src/otherwindow.c:2931 src/toolbar.c:304 msgid "Threshold" msgstr "Práh" #: src/otherwindow.c:2933 msgid "Level" msgstr "Úroveň" #: src/otherwindow.c:2934 msgid "Minimum size" msgstr "Nejmenší velikost" #: src/otherwindow.c:3053 msgid "Max" msgstr "" #: src/otherwindow.c:3053 msgid "Min" msgstr "" #: src/otherwindow.c:3057 msgid "Threshold Image" msgstr "" #: src/otherwindow.c:3158 msgid "Seed" msgstr "" #: src/otherwindow.c:3160 msgid "X span" msgstr "" #: src/otherwindow.c:3161 msgid "Y span" msgstr "" #: src/otherwindow.c:3162 msgid "Octaves" msgstr "" #: src/png.c:620 #, c-format msgid "Saving %s image" msgstr "Ukládám %s obrázek" #: src/png.c:620 #, c-format msgid "Loading %s image" msgstr "Nahrávám %s obrázek" #: src/png.c:998 msgid "Layer" msgstr "Vrstva" #: src/png.c:3577 msgid "Lossless" msgstr "" #: src/png.c:3577 msgid "Default" msgstr "" #: src/png.c:3577 msgid "Picture" msgstr "" #: src/png.c:3577 msgid "Photo" msgstr "" #: src/png.c:3578 msgid "Drawing" msgstr "" #: src/png.c:3578 msgid "Icon" msgstr "" #: src/png.c:8370 msgid "Applying colour profile" msgstr "Používá se barevný profil" #: src/png.c:8792 #, c-format msgid "%d out of %d frames could not be saved as %s - saved as PNG instead" msgstr "" "%d z %d snímků nemohly být uloženy jako %s - místo toho uloženy jako PNG" #: src/png.c:8809 msgid "Explode frames" msgstr "Rozbalit snímky" #: src/prefs.c:56 msgid "Default System Language" msgstr "Výchozí jazyk systému" #: src/prefs.c:57 msgid "Chinese (Simplified)" msgstr "ČínÅ¡tina (zjednoduÅ¡ená)" #: src/prefs.c:57 msgid "Chinese (Taiwanese)" msgstr "Čínsky (Taiwansky)" #: src/prefs.c:57 msgid "Czech" msgstr "ÄŒesky" #: src/prefs.c:58 msgid "Dutch" msgstr "Holandsky" #: src/prefs.c:58 msgid "English (UK)" msgstr "Anglicky (UK)" #: src/prefs.c:58 msgid "French" msgstr "Francouzsky" #: src/prefs.c:58 msgid "Galician" msgstr "Galicijsky" #: src/prefs.c:58 msgid "German" msgstr "NÄ›mecky" #: src/prefs.c:59 msgid "Hungarian" msgstr "MaÄarÅ¡tina" #: src/prefs.c:59 msgid "Italian" msgstr "Italsky" #: src/prefs.c:59 msgid "Japanese" msgstr "Japonsky" #: src/prefs.c:59 msgid "Kabyle" msgstr "" #: src/prefs.c:59 msgid "Polish" msgstr "Polsky" #: src/prefs.c:60 msgid "Portuguese" msgstr "Portugalsky" #: src/prefs.c:60 msgid "Portuguese (Brazilian)" msgstr "Portugalsky (Brazílie)" #: src/prefs.c:60 msgid "Russian" msgstr "Rusky" #: src/prefs.c:60 msgid "Slovak" msgstr "Slovensky" #: src/prefs.c:61 msgid "Spanish" msgstr "Å panÄ›lsky" #: src/prefs.c:61 msgid "Swedish" msgstr "Å védsky" #: src/prefs.c:61 msgid "Tagalog" msgstr "FilipínÅ¡tina" #: src/prefs.c:61 msgid "Turkish" msgstr "Turecky" #: src/prefs.c:81 msgid "Current Device" msgstr "Aktuální zařízení" #: src/prefs.c:135 msgid "Pressure" msgstr "Tlak" #: src/prefs.c:149 msgid "Preferences" msgstr "Volby" #: src/prefs.c:163 msgid "Max threads (0 to autodetect)" msgstr "NejvÄ›tší poÄet vláken (0 pro automatické zjiÅ¡tÄ›ní)" #: src/prefs.c:164 msgid "Min kpixels per render thread" msgstr "" #: src/prefs.c:171 msgid "Max memory used for undo (MB)" msgstr "Max pamÄ›ti použité pro historii (MB)" #: src/prefs.c:172 msgid "Max undo levels" msgstr "NejvÄ›tší poÄet kroků zpÄ›t" #: src/prefs.c:173 msgid "Communal layer undo space (%)" msgstr "Vrátitelný prostor spoleÄné vrstvy (%)" #: src/prefs.c:175 msgid "Bayer master pattern" msgstr "" #: src/prefs.c:178 msgid "Use gamma correction by default" msgstr "Použít gamma korekci jako výchozí" #: src/prefs.c:179 msgid "Use gamma correction when painting" msgstr "" #: src/prefs.c:180 msgid "Separate patterns for A & B" msgstr "" #: src/prefs.c:183 msgid "Optimize alpha chequers" msgstr "Optimalizovat Å¡achovnici alfa kanálu" #: src/prefs.c:184 msgid "Disable view window transparencies" msgstr "Vypnout průhlednost v oknÄ› zobrazení" #: src/prefs.c:185 msgid "Enable overlays by layer" msgstr "" #: src/prefs.c:189 msgid "Language" msgstr "Jazyk" #: src/prefs.c:191 msgid "" "Select preferred language translation\n" "\n" "You will need to restart mtPaint\n" "for this to take full effect" msgstr "" "Vyberte váš oblíbený jazyk\n" "\n" "Aby se projevily vÅ¡echny zmÄ›ny,\n" "je tÅ™eba mtPaint restartovat." #: src/prefs.c:198 msgid "Interface" msgstr "Rozhraní" #: src/prefs.c:200 msgid "Greyscale backdrop" msgstr "Odstín Å¡edivého pozadí" #: src/prefs.c:201 msgid "Selection nudge pixels" msgstr "Posun pixelů výbÄ›ru" #: src/prefs.c:202 msgid "Max Pan Window Size" msgstr "Velikost pÅ™ehledového okna" #: src/prefs.c:204 msgid "Display clipboard while pasting" msgstr "Zobrazovat schránku pÅ™i vkládání" #: src/prefs.c:205 msgid "Mouse cursor = Tool" msgstr "Kurzor myÅ¡i = Nástroj" #: src/prefs.c:206 msgid "Confirm Exit" msgstr "Potvrdit konec" #: src/prefs.c:207 msgid "Q key quits mtPaint" msgstr "Klávesa Q ukonÄí mtPaint" #: src/prefs.c:208 msgid "Arrow keys scroll canvas" msgstr "" #: src/prefs.c:209 msgid "Changing tool commits paste" msgstr "ZmÄ›na nástroje potvrdí vložení" #: src/prefs.c:210 msgid "Centre tool settings dialogs" msgstr "Centrovat dialogy nastavení nástrojů" #: src/prefs.c:211 msgid "New image sets zoom to 100%" msgstr "Nový obrázek nastaví zoom na 100%" #: src/prefs.c:212 msgid "Zoom on cursor position" msgstr "" #: src/prefs.c:214 msgid "Mouse Scroll Wheel = Zoom" msgstr "KoleÄko na myÅ¡i = Zoom" #: src/prefs.c:215 msgid "Use menu icons" msgstr "Použít ikony menu" #: src/prefs.c:220 msgid "Files" msgstr "Soubory" #: src/prefs.c:223 msgid "XBM X hotspot" msgstr "XBM X aktivní bod" #: src/prefs.c:224 msgid "XBM Y hotspot" msgstr "XBM Y aktivní bod" #: src/prefs.c:228 msgid "Recently Used Files" msgstr "Naposledy použité soubory" #: src/prefs.c:229 msgid "Progress bar silence limit" msgstr "Tichý limit ukazatele postupu" #: src/prefs.c:232 msgid "Read 16-bit TGAs as 5:6:5 BGR" msgstr "NaÄíst 16-bitové obrázky TGA jako 5:6:5 BGR" #: src/prefs.c:233 msgid "Write TGAs in bottom-up row order" msgstr "Zapsat TGA s řádkováním odspoda nahoru" #: src/prefs.c:234 msgid "Undoable image loading" msgstr "Vrátitelné nahrávání obrázku" #: src/prefs.c:245 msgid "Compression (RGB)" msgstr "" #: src/prefs.c:246 msgid "Compression (indexed)" msgstr "" #: src/prefs.c:247 msgid "Compression (monochrome)" msgstr "" #: src/prefs.c:255 msgid "Enable predictor" msgstr "" #: src/prefs.c:262 msgid "Compression mode" msgstr "" #: src/prefs.c:271 msgid "Channel for Mask Plane" msgstr "" #: src/prefs.c:273 msgid "Ignore Transparent Colour" msgstr "" #: src/prefs.c:274 msgid "PackBits Compression" msgstr "" #: src/prefs.c:275 msgid "Write Indexed as Planar Bitmap (PBM)" msgstr "" #: src/prefs.c:280 msgid "Paths" msgstr "Cesty" #: src/prefs.c:281 msgid "Clipboard Files" msgstr "Soubory schránky" #: src/prefs.c:281 msgid "Select Clipboard File" msgstr "VýbÄ›r souboru schránky" #: src/prefs.c:283 msgid "HTML Browser Program" msgstr "HTML ProhlížeÄ" #: src/prefs.c:283 msgid "Select Browser Program" msgstr "Vyberte webový prohlížeÄ" #: src/prefs.c:285 msgid "Location of Handbook index" msgstr "UmístÄ›ní indexu příruÄky" #: src/prefs.c:285 msgid "Select Handbook Index File" msgstr "Vyberte Index soubor příruÄky" #: src/prefs.c:287 msgid "Default Palette" msgstr "Výchozí paleta" #: src/prefs.c:287 msgid "Select Default Palette" msgstr "Vybrat výchozí paletu" #: src/prefs.c:289 msgid "Default Patterns" msgstr "Výchozí vzory" #: src/prefs.c:289 msgid "Select Default Patterns File" msgstr "Vybrat soubor s výchozími vzory" #: src/prefs.c:292 msgid "Default CSS" msgstr "" #: src/prefs.c:292 msgid "Select Default CSS File" msgstr "" #: src/prefs.c:295 msgid "Default Theme" msgstr "Výchozí téma" #: src/prefs.c:295 msgid "Select Default Theme File" msgstr "Vybrat soubor s výchozím tématem" #: src/prefs.c:300 msgid "Status Bar" msgstr "Stavová liÅ¡ta" #: src/prefs.c:301 msgid "Canvas Geometry" msgstr "Geometrie plátna" #: src/prefs.c:302 msgid "Cursor X,Y" msgstr "Kurzor X,Y" #: src/prefs.c:303 msgid "Pixel [I] {RGB}" msgstr "Pixel [I] {RGB}" #: src/prefs.c:304 msgid "Selection Geometry" msgstr "Geometrie VýbÄ›ru" #: src/prefs.c:305 msgid "Undo / Redo" msgstr "ZpÄ›t / Znovu" #: src/prefs.c:308 msgid "Tablet" msgstr "Tablet" #: src/prefs.c:309 msgid "Device Settings" msgstr "Nastavení zařízení" #: src/prefs.c:313 msgid "Configure Device" msgstr "Konfigurace zařízení" #: src/prefs.c:319 msgid "Tool Variable" msgstr "Variabilita nástroje" #: src/prefs.c:322 src/toolbar.c:454 msgid "Flow" msgstr "Tok" #: src/prefs.c:330 msgid "Test Area" msgstr "Testovací plocha" #: src/prefs.c:373 msgid "Factor" msgstr "Faktor" #: src/prefs.c:459 msgid "This key is builtin" msgstr "" #: src/prefs.c:462 #, c-format msgid "" "This key is mapped to:\n" "\"%s\"" msgstr "" #: src/prefs.c:465 msgid "Remap" msgstr "" #: src/prefs.c:510 msgid "Keyboard Shortcuts" msgstr "" #: src/shifter.c:147 msgid "Frames" msgstr "Snímků" #: src/shifter.c:258 msgid "Palette Shifter" msgstr "PosunovaÄ palety" #: src/shifter.c:263 msgid "Start" msgstr "Start" #: src/shifter.c:265 msgid "Finish" msgstr "Konec" #: src/shifter.c:284 msgid "Fix Palette" msgstr "Upravit paletu" #: src/spawn.c:651 msgid "Configure File Actions" msgstr "Nastavit Äinnosti pro práci se souborem" #: src/spawn.c:657 src/spawn.c:663 msgid "Command" msgstr "Příkaz" #: src/spawn.c:922 #, c-format msgid "Error %i reported when trying to run %s" msgstr "Nastala chyba %i pÅ™i pokusu o spuÅ¡tÄ›ní %s" #: src/spawn.c:979 msgid "" "I am unable to find the documentation. Either you need to download the " "mtPaint Handbook from the web site and install it, or you need to set the " "correct location in the Preferences window." msgstr "" "Nelze nalézt dokumentaci. BuÄ potÅ™ebujete stáhnout příruÄku mtPaintu z webu " "a nainstalovat ji, nebo musíte nastavit správnou cestu v oknÄ› voleb." #: src/spawn.c:1018 msgid "" "There was a problem running the HTML browser. You need to set the correct " "program name in the Preferences window." msgstr "" "Objevil se problém se spuÅ¡tÄ›ním HTML prohlížeÄe. Musíte nastavit správný " "název programu v oknÄ› voleb." #: src/thread.c:361 msgid "Helper thread is not responding. Save your work and exit the program." msgstr "Vlákno pomocníka neodpovídá. Uložte práci a ukonÄete program." #: src/toolbar.c:147 msgid "RGB Cube" msgstr "RGB krychle" #: src/toolbar.c:148 msgid "By image channel" msgstr "Kanálem obrázku" #: src/toolbar.c:149 msgid "Gradient-driven" msgstr "Gradientem" #: src/toolbar.c:157 msgid "Fill settings" msgstr "Nastavení výplnÄ›" #: src/toolbar.c:170 msgid "Respect opacity mode" msgstr "Respektovat režim neprůhlednosti" #: src/toolbar.c:176 msgid "Smudge settings" msgstr "Nastavení rozmazání" #: src/toolbar.c:215 msgid "Aligned" msgstr "" #: src/toolbar.c:222 msgid "Clone settings" msgstr "" #: src/toolbar.c:228 msgid "By selection channel" msgstr "" #: src/toolbar.c:234 msgid "Lasso settings" msgstr "" #: src/toolbar.c:252 msgid "Brush spacing" msgstr "" #: src/toolbar.c:299 src/toolbar.c:341 msgid "Normal" msgstr "Normální" #: src/toolbar.c:300 msgid "Colour" msgstr "Barva" #: src/toolbar.c:300 msgid "Saturate More" msgstr "Více nasytit" #: src/toolbar.c:301 msgid "Multiply" msgstr "Násobení" #: src/toolbar.c:301 msgid "Divide" msgstr "DÄ›lení" #: src/toolbar.c:301 msgid "Dodge" msgstr "ZesvÄ›tlení" #: src/toolbar.c:302 msgid "Burn" msgstr "Ztmavení" #: src/toolbar.c:302 msgid "Hard Light" msgstr "Tvrdé svÄ›tlo" #: src/toolbar.c:302 msgid "Soft Light" msgstr "MÄ›kké svÄ›tlo" #: src/toolbar.c:302 msgid "Difference" msgstr "Rozdíl" #: src/toolbar.c:303 msgid "Darken" msgstr "Ztmavit" #: src/toolbar.c:303 msgid "Lighten" msgstr "ZesvÄ›tlit" #: src/toolbar.c:303 msgid "Grain Extract" msgstr "Extrakce zrnitosti" #: src/toolbar.c:304 msgid "Grain Merge" msgstr "SlouÄení zrnitosti" #: src/toolbar.c:330 msgid "Blend mode" msgstr "Režim míchání" #: src/toolbar.c:417 msgid "Continuous Mode" msgstr "Spojitý režim" #: src/toolbar.c:421 msgid "Opacity Mode" msgstr "Režim neprůsvitnosti" #: src/toolbar.c:424 msgid "Tint Mode" msgstr "Režim kolorování" #: src/toolbar.c:427 msgid "Tint +-" msgstr "Kolorování +-" #: src/toolbar.c:434 msgid "Blend Mode" msgstr "Režim míchání" #: src/toolbar.c:438 msgid "Disable All Masks" msgstr "Vypnout vÅ¡echny masky" #: src/toolbar.c:441 msgid "Gradient Mode" msgstr "Režim Gradientu" #: src/toolbar.c:486 msgid "Settings Toolbar" msgstr "LiÅ¡ta nastavení" #: src/toolbar.c:546 msgid "Cut" msgstr "Vyjmout" #: src/toolbar.c:548 msgid "Copy" msgstr "Kopírovat" #: src/toolbar.c:550 msgid "Paste" msgstr "Vložit" #: src/toolbar.c:553 msgid "Undo" msgstr "ZpÄ›t" #: src/toolbar.c:555 msgid "Redo" msgstr "VpÅ™ed" #: src/toolbar.c:559 src/viewer.c:328 msgid "Pan Window" msgstr "PÅ™ehledové okno" #: src/toolbar.c:560 src/toolbar.c:640 msgid "More..." msgstr "" #: src/toolbar.c:574 msgid "Paint" msgstr "Malování" #: src/toolbar.c:580 msgid "Shuffle" msgstr "PÅ™eházení" #: src/toolbar.c:583 msgid "Flood Fill" msgstr "VyplnÄ›ní" #: src/toolbar.c:587 msgid "Straight Line" msgstr "Rovná Äára" #: src/toolbar.c:590 msgid "Smudge" msgstr "Rozmazat" #: src/toolbar.c:594 msgid "Clone" msgstr "Klonovat" #: src/toolbar.c:597 msgid "Make Selection" msgstr "OznaÄit výbÄ›r" #: src/toolbar.c:600 msgid "Polygon Selection" msgstr "VýbÄ›r polygonem" #: src/toolbar.c:603 msgid "Place Gradient" msgstr "Vložit Gradient" #: src/toolbar.c:606 msgid "Lasso Selection" msgstr "VýbÄ›r lasem" #: src/toolbar.c:614 msgid "Ellipse Outline" msgstr "Prázdná elipsa" #: src/toolbar.c:617 msgid "Filled Ellipse" msgstr "VyplnÄ›ná elipsa" #: src/toolbar.c:620 msgid "Outline Selection" msgstr "Orámovat výbÄ›r" #: src/toolbar.c:623 msgid "Fill Selection" msgstr "Vyplnit výbÄ›r" #: src/toolbar.c:627 msgid "Flip Selection Vertically" msgstr "OtoÄit výbÄ›r vertikálnÄ›" #: src/toolbar.c:630 msgid "Flip Selection Horizontally" msgstr "OtoÄit výbÄ›r horizontálnÄ›" #: src/toolbar.c:633 msgid "Rotate Selection Clockwise" msgstr "OtoÄit výbÄ›r po smÄ›ru ruÄiÄek" #: src/toolbar.c:636 msgid "Rotate Selection Anti-Clockwise" msgstr "OtoÄit výbÄ›r proti smÄ›ru ruÄiÄek" #: src/vcode.c:5201 msgid "Browse" msgstr "Procházet" #: src/vcode.c:7886 msgid "New key ..." msgstr "" #: src/vcode.c:9909 #, c-format msgid "'%s' does not match any widget" msgstr "" #: src/vcode.c:9910 #, c-format msgid "'%s' value does not fit '%s' widget" msgstr "" #: src/viewer.c:115 msgid "About" msgstr "O aplikaci" #: src/viewer.c:1179 msgid "No font selected" msgstr "" #: src/viewer.c:1209 msgid "Left" msgstr "" #: src/viewer.c:1209 msgid "Right" msgstr "" #~ msgid "Create GIF frames" #~ msgstr "VytvoÅ™it snímky GIF" #~ msgid "" #~ "You are trying to save an XPM file with more than 4096 colours. Either " #~ "use another format or posterize the image to 4 bits, or otherwise reduce " #~ "the number of colours." #~ msgstr "" #~ "Pokoušíte se uložit XPM soubor s více než 4096 barvami. BuÄ použijte jiný " #~ "formát, posterizujete obrázek na 4 bity na kanál, nebo jinak snížte poÄet " #~ "barev." #~ msgid "Store Values" #~ msgstr "Zachovat hodnoty" #~ msgid "File: %s invalid - palette not updated" #~ msgstr "Soubor: %s je neplatný - paleta nebyla aktualizována" #~ msgid "Distance to A+B" #~ msgstr "Vzdálenost k A+B" #~ msgid "Edit Frames" #~ msgstr "Upravit snímky" mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/po/de.po000066400000000000000000003070431471325446300215300ustar00rootroot00000000000000# German translation for mtpaint # This file is distributed under the same license as the mtpaint package. # Oliver Frommel , 2006. # Simon Brixel yahoo.com>, 2012 msgid "" msgstr "" "Project-Id-Version: mtpaint\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-01-04 21:31+0200\n" "PO-Revision-Date: 2012-03-22 14:03+0000\n" "Last-Translator: Achim Behrens, Simon Brixel ,\n" "Language-Team: German \n" "Language: de\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Launchpad-Export-Date: 2011-09-03 18:36+0000\n" "X-Generator: Launchpad (build 13830)\n" #: src/ani.c:647 msgid "Animation Preview" msgstr "Animationsvorschau" #: src/ani.c:650 src/shifter.c:275 msgid "Play" msgstr "Wiedergabe" #: src/ani.c:654 msgid "Fix" msgstr "Fixieren" #: src/ani.c:655 src/ani.c:1005 src/font.c:1624 src/font.c:1643 #: src/shifter.c:286 src/viewer.c:97 msgid "Close" msgstr "Schließen" #: src/ani.c:709 src/ani.c:812 src/ani.c:1022 src/ani.c:1028 src/canvas.c:356 #: src/canvas.c:708 src/canvas.c:989 src/canvas.c:1353 src/canvas.c:1383 #: src/canvas.c:1470 src/canvas.c:1545 src/canvas.c:1988 src/canvas.c:1994 #: src/canvas.c:2077 src/canvas.c:2217 src/canvas.c:2240 src/font.c:1352 #: src/fpick.c:636 src/fpick.c:754 src/layer.c:524 src/layer.c:815 #: src/layer.c:970 src/mainwindow.c:341 src/mainwindow.c:370 #: src/mainwindow.c:534 src/mainwindow.c:578 src/mainwindow.c:604 #: src/mainwindow.c:3797 src/mainwindow.c:4045 src/otherwindow.c:931 #: src/otherwindow.c:980 src/otherwindow.c:982 src/prefs.c:459 src/spawn.c:924 #: src/spawn.c:978 src/spawn.c:1017 src/thread.c:360 src/vcode.c:9912 #: src/viewer.c:1161 src/viewer.c:1179 msgid "Error" msgstr "Fehler" #: src/ani.c:709 msgid "Unable to create output directory" msgstr "Kann Ausgabeverzeichnis nicht anlegen" #: src/ani.c:759 msgid "Creating Animation Frames" msgstr "Animationsrahmen erstellen" #: src/ani.c:812 msgid "Unable to save image" msgstr "Kann Bild nicht speichern" #: src/ani.c:840 src/canvas.c:1171 src/fpick.c:731 src/layer.c:311 #: src/layer.c:379 src/layer.c:826 src/layer.c:840 src/mainwindow.c:375 #: src/mainwindow.c:1026 src/png.c:8794 src/prefs.c:464 msgid "Warning" msgstr "Warnung" #: src/ani.c:840 msgid "" "Do you really want to clear all of the position and cycle data for all of " "the layers?" msgstr "" "Wollen Sie wirklich die Positions- und Zyklusdaten aller Ebenen löschen?" #: src/ani.c:841 src/fpick.c:731 src/layer.c:311 src/layer.c:842 #: src/mainwindow.c:375 msgid "No" msgstr "Nein" #: src/ani.c:841 src/fpick.c:731 src/layer.c:311 src/layer.c:842 #: src/mainwindow.c:375 msgid "Yes" msgstr "Ja" #: src/ani.c:954 msgid "Set Key Frame" msgstr "Keyframe setzen" #: src/ani.c:961 msgid "Configure Animation" msgstr "Animation zusammenfügen" # msgstr "Animation einstellen" #: src/ani.c:964 msgid "Output Files" msgstr "Ausgabedateien" #: src/ani.c:967 msgid "Start frame" msgstr "Start-Frame" #: src/ani.c:969 msgid "End frame" msgstr "End-Frame" #: src/ani.c:971 src/shifter.c:267 msgid "Delay" msgstr "Verzögerung" #: src/ani.c:973 msgid "Output path" msgstr "Ausgabepfad" #: src/ani.c:973 src/font.c:1637 src/spawn.c:664 msgid "Select Directory" msgstr "Verzeichnis wählen" #: src/ani.c:976 msgid "File prefix" msgstr "Dateipräfix" #: src/ani.c:978 src/canvas.c:2096 msgid "File Format" msgstr "Dateiformat" #: src/ani.c:982 msgid "Positions" msgstr "Positionen" #: src/ani.c:997 msgid "Cycling" msgstr "Periodisches Durchlaufen" #: src/ani.c:1006 msgid "Save" msgstr "Speichern" #: src/ani.c:1007 src/font.c:1577 src/otherwindow.c:868 src/otherwindow.c:1615 #: src/otherwindow.c:1728 src/otherwindow.c:2938 src/otherwindow.c:3071 #: src/otherwindow.c:3170 msgid "Preview" msgstr "Vorschau" #: src/ani.c:1008 src/shifter.c:285 msgid "Create Frames" msgstr "Erzeuge Einzelbilder" #: src/ani.c:1022 msgid "You must have at least 2 layers to create an animation" msgstr "Für eine Animation müssen mindestens zwei Ebenen existieren." #: src/ani.c:1028 msgid "You must save your layers file before creating an animation" msgstr "Für eine Animation müssen Sie Ihre Ebenen-Datei vorher speichern" #: src/canvas.c:357 msgid "The image is too large to transform." msgstr "Das Bild ist zu groß zur Umwandlung" #: src/canvas.c:393 src/canvas.c:430 src/otherwindow.c:1613 #: src/otherwindow.c:2524 src/otherwindow.c:2583 src/otherwindow.c:3179 msgid "Gradient" msgstr "Farbverlauf" #: src/canvas.c:393 src/otherwindow.c:840 src/otherwindow.c:842 #: src/otherwindow.c:2074 src/otherwindow.c:3180 msgid "Palette" msgstr "Palette" #: src/canvas.c:393 src/info.c:265 src/otherwindow.c:847 src/otherwindow.c:2757 #: src/otherwindow.c:3180 src/png.c:781 src/png.c:995 msgid "Clipboard" msgstr "Zwischenablage" #: src/canvas.c:394 src/cpick.c:831 src/toolbar.c:299 msgid "Value" msgstr "Wert" #: src/canvas.c:394 src/cpick.c:811 src/otherwindow.c:575 src/otherwindow.c:859 #: src/otherwindow.c:3053 src/toolbar.c:318 msgid "Red" msgstr "Rot" #: src/canvas.c:394 src/cpick.c:815 src/otherwindow.c:575 src/otherwindow.c:860 #: src/otherwindow.c:3053 src/toolbar.c:319 msgid "Green" msgstr "Grün" #: src/canvas.c:394 src/cpick.c:819 src/otherwindow.c:575 src/otherwindow.c:861 #: src/otherwindow.c:3053 src/toolbar.c:320 msgid "Blue" msgstr "Blau" #: src/canvas.c:399 msgid "From " msgstr "" #: src/canvas.c:403 msgid "To " msgstr "" #: src/canvas.c:410 msgid "Map" msgstr "" #: src/canvas.c:429 msgid "MT" msgstr "MT" #: src/canvas.c:429 msgid "Sobel" msgstr "Sobel" #: src/canvas.c:429 msgid "Prewitt" msgstr "Prewitt" #: src/canvas.c:429 msgid "Kirsch" msgstr "Kirsch" #: src/canvas.c:430 msgid "Roberts" msgstr "Roberts" #: src/canvas.c:430 msgid "Laplace" msgstr "Laplace" #: src/canvas.c:430 msgid "Morphological" msgstr "Morphologisch" #: src/canvas.c:442 msgid "Edge Detect" msgstr "Kanten finden" #: src/canvas.c:464 msgid "Edge Sharpen" msgstr "Kanten schärfen" #: src/canvas.c:472 msgid "Edge Soften" msgstr "Kanten aufweichen" #: src/canvas.c:521 msgid "Different X/Y" msgstr "Unterschiedliche X/Y Radien anwenden" #: src/canvas.c:522 src/canvas.c:562 src/canvas.c:603 src/canvas.c:637 #: src/canvas.c:722 src/otherwindow.c:1037 src/otherwindow.c:2685 msgid "Gamma corrected" msgstr "Gamma korrigiert" #: src/canvas.c:530 src/memory.c:8219 msgid "Gaussian Blur" msgstr "Gaußscher Weichzeichner" #: src/canvas.c:558 msgid "Radius" msgstr "Radius" #: src/canvas.c:559 msgid "Amount" msgstr "Betrag" #: src/canvas.c:560 msgid "Threshold " msgstr "Grenzwert " #: src/canvas.c:570 src/memory.c:8360 msgid "Unsharp Mask" msgstr "Unscharf maskieren" #: src/canvas.c:599 msgid "Outer radius" msgstr "Außenradius" #: src/canvas.c:600 msgid "Inner radius" msgstr "Innenradius" #: src/canvas.c:602 src/info.c:280 msgid "Normalize" msgstr "Normalisieren" #: src/canvas.c:611 src/memory.c:8512 msgid "Difference of Gaussians" msgstr "Differenz der Normalverteilung" # msgstr "Differenz der Mittelwerte" # Unterschied von Gaussians, Gaussian Difference # auch in deutschen Fachtexten in Internet fand ich keinen deutschen Begriff dafür, Simon #: src/canvas.c:636 msgid "Protect details" msgstr "Details bewahren" #: src/canvas.c:645 msgid "Kuwahara-Nagao Blur" msgstr "Kuwahara-Nagao Glättungsfilter" #: src/canvas.c:709 msgid "The image is too large for this rotation." msgstr "Das Bild ist zu groß zum Rotieren" # fuzzy #: src/canvas.c:723 msgid "Smooth" msgstr "Weich" # msgstr "Sanft" # weich, geglättet? #: src/canvas.c:732 msgid "Free Rotate" msgstr "Frei drehen" #: src/canvas.c:989 src/viewer.c:1161 msgid "Not enough memory to create clipboard" msgstr "Nicht genug Speicher für die Zwischenablage" # msgstr "Nicht genug Speicher, um Ablage zu erstellen" #: src/canvas.c:1172 msgid "" "You have not allocated enough memory in the Preferences window to undo this " "action." msgstr "" #: src/canvas.c:1353 msgid "Invalid palette file" msgstr "Ungültige Palettendatei" #: src/canvas.c:1383 msgid "Invalid channel file." msgstr "Ungültige Kanaldatei." #: src/canvas.c:1401 msgid "Raw frames" msgstr "Rohe Einzelbilder" #: src/canvas.c:1401 msgid "Composited frames" msgstr "Zusammengefügte Einzelbilder" # msgstr "Verbundene Einzelbilder" # msgstr "Zusammengesetzte Bilder" # Composited: is this word correct English, composite is an adjective #: src/canvas.c:1402 msgid "Composited frames with nonzero delay" msgstr "Zusammengefügte Einzelbilder mit Verzögerung > 0" # msgstr "Zusammengefügte Bilder ohne Verzögerung" #: src/canvas.c:1406 msgid "Load Frames" msgstr "Einzelbilder laden" #: src/canvas.c:1409 msgid "Load into Layers" msgstr "In Ebenen laden" #: src/canvas.c:1415 msgid "Load First Frame" msgstr "Erstes Bild laden" #: src/canvas.c:1416 msgid "Explode Frames" msgstr "Einzelbilder exportieren" #: src/canvas.c:1418 msgid "View Animation" msgstr "Animation ansehen" #: src/canvas.c:1434 #, c-format msgid "This is an animated %s file." msgstr "Das ist eine animierte %s Datei." #: src/canvas.c:1435 #, c-format msgid "This is a multipage %s file." msgstr "Diese %s Datei enthält mehrere Bilder." #: src/canvas.c:1459 #, c-format msgid "File is too big, must be <= to width=%i height=%i" msgstr "Die Datei ist zu groß, sie sollte höchstens %i breit und %i hoch sein." #: src/canvas.c:1461 msgid "Unable to explode frames" msgstr "Kann Einzelbilder nicht extrahieren" # fuzzy #: src/canvas.c:1463 msgid "Unable to load file" msgstr "Kann Datei nicht laden" #: src/canvas.c:1465 msgid "" "The file import library had to terminate due to a problem with the file " "(possibly corrupt image data or a truncated file). I have managed to load " "some data as the header seemed fine, but I would suggest you save this image " "to a new file to ensure this does not happen again." msgstr "" "Die Datei-Importbibliothek musste wegen eines Problems abbrechen (vermutlich " "kaputte Bilddaten oder eine abgeschnittene Datei). Einige Daten konnten " "geladen werden, weil der Datei-Header in Ordnung schien. Sie sollten das " "Bild in eine neue Datei speichern, damit sich das Problem nicht wiederholt." #: src/canvas.c:1467 msgid "The animation is too long to load all of it into layers." msgstr "Die Animation ist zu lang, um sie vollständig in Ebenen zu laden" #: src/canvas.c:1469 msgid "Could not explode all the frames in the animation." msgstr "Konnte nicht alle Einzelbilder der Animation exportieren." #: src/canvas.c:1481 src/font.c:1556 src/fpick.c:937 src/otherwindow.c:2765 #: src/prefs.c:321 src/toolbar.c:451 msgid "Size" msgstr "Größe" #: src/canvas.c:1484 src/otherwindow.c:244 msgid "Width" msgstr "Breite" #: src/canvas.c:1485 src/otherwindow.c:245 msgid "Height" msgstr "Höhe" #: src/canvas.c:1489 src/channels.c:253 src/channels.c:317 src/fpick.c:666 #: src/fpick.c:957 src/mainwindow.c:3990 src/otherwindow.c:255 #: src/otherwindow.c:517 src/otherwindow.c:591 src/otherwindow.c:867 #: src/otherwindow.c:1058 src/otherwindow.c:1727 src/otherwindow.c:2101 #: src/otherwindow.c:2336 src/otherwindow.c:2538 src/otherwindow.c:2691 #: src/otherwindow.c:2776 src/otherwindow.c:2937 src/otherwindow.c:3070 #: src/otherwindow.c:3169 src/prefs.c:338 src/prefs.c:464 src/prefs.c:538 #: src/spawn.c:666 src/viewer.c:1258 msgid "Cancel" msgstr "Abbrechen" #: src/canvas.c:1490 src/channels.c:253 src/channels.c:317 src/fpick.c:956 #: src/info.c:297 src/mainwindow.c:3992 src/mygtk.c:233 src/mygtk.c:535 #: src/otherwindow.c:591 src/otherwindow.c:871 src/otherwindow.c:1058 #: src/otherwindow.c:1729 src/otherwindow.c:2101 src/otherwindow.c:2336 #: src/otherwindow.c:2538 src/otherwindow.c:2691 src/otherwindow.c:2776 #: src/otherwindow.c:3072 src/otherwindow.c:3171 src/prefs.c:338 #: src/prefs.c:538 src/spawn.c:666 msgid "OK" msgstr "OK" #: src/canvas.c:1504 #, c-format msgid "This is a scalable %s file." msgstr "" #: src/canvas.c:1545 msgid "Cannot open file" msgstr "Die Datei kann nicht geöffnet werden." #: src/canvas.c:1546 msgid "Unsupported file format" msgstr "Nicht unterstütztes Dateiformat" #: src/canvas.c:1673 #, c-format msgid "File: %s already exists. Do you want to overwrite it?" msgstr "Datei %s existiert bereits. Überschreiben?" #: src/canvas.c:1674 msgid "File Found" msgstr "Datei gefunden" #: src/canvas.c:1674 src/mainwindow.c:1095 msgid "NO" msgstr "NEIN" #: src/canvas.c:1674 src/mainwindow.c:1095 msgid "YES" msgstr "JA" #: src/canvas.c:1988 msgid "Unable to export undo images" msgstr "Kann Chronikbilder nicht exportieren" # msgstr "Kann Undo-Bilder nicht exportieren" #: src/canvas.c:1994 msgid "Unable to export ASCII file" msgstr "Kann ASCII-Datei nicht speichern" #: src/canvas.c:2076 src/layer.c:814 src/mainwindow.c:529 #, c-format msgid "Unable to save file: %s" msgstr "Kann Datei nicht speichern: %s" #: src/canvas.c:2101 src/prefs.c:222 msgid "Transparency index" msgstr "Transparenz-Index" #: src/canvas.c:2103 msgid "TIFF Compression" msgstr "TIFF Kompression" #: src/canvas.c:2105 src/prefs.c:225 msgid "JPEG Save Quality (100=High)" msgstr "JPEG-Qualität (100=Hoch)" #: src/canvas.c:2107 msgid "ZIP Compression (0=None)" msgstr "ZIP Kompression (0=Keine)" #: src/canvas.c:2108 src/prefs.c:227 msgid "PNG Compression (0=None)" msgstr "PNG Kompression (0=Keine)" #: src/canvas.c:2111 src/prefs.c:249 msgid "LZMA2 Compression (0=None)" msgstr "LZMA2 Kompression (0=Keine)" #: src/canvas.c:2113 src/prefs.c:252 msgid "ZSTD Compression Level" msgstr "" #: src/canvas.c:2115 src/prefs.c:231 msgid "TGA RLE Compression" msgstr "TGA RLE Kompression" #: src/canvas.c:2117 msgid "LBM PackBits Compression" msgstr "LBM PackBits Kompression" #: src/canvas.c:2118 src/prefs.c:226 msgid "JPEG2000 Compression (0=Lossless)" msgstr "JPEG2000 Kompression (0=verlustfrei)" #: src/canvas.c:2120 msgid "WebP Compression" msgstr "WebP Kompression" #: src/canvas.c:2122 msgid "WebP Save Quality (100=High)" msgstr "WebP-Qualität (100=Hoch)" #: src/canvas.c:2123 src/prefs.c:263 msgid "V8 Save Quality (100=High)" msgstr "V8-Qualität (100=Hoch)" #: src/canvas.c:2125 src/prefs.c:264 msgid "V8L Compression (0=None)" msgstr "V8L Kompression (0=Keine)" #: src/canvas.c:2127 msgid "Hotspot at X =" msgstr "Hotspot bei X =" #: src/canvas.c:2129 msgid "Y =" msgstr "" #: src/canvas.c:2133 msgid "Animation delay" msgstr "Animations-Verzögerung" #: src/canvas.c:2136 src/otherwindow.c:253 msgid "Undoable" msgstr "Widerrufbar" # rücknehmbar, widerrufbar, annullierbar, zurücknehmbar # fuzzy #: src/canvas.c:2138 src/prefs.c:236 msgid "Apply colour profile" msgstr "Farbprofil verwenden" #: src/canvas.c:2176 src/toolbar.c:543 msgid "Load Image File" msgstr "Bild laden" #: src/canvas.c:2191 src/toolbar.c:544 msgid "Save Image File" msgstr "Bild speichern" #: src/canvas.c:2196 msgid "Load Palette File" msgstr "Palette laden" #: src/canvas.c:2202 msgid "Save Palette File" msgstr "Palette speichern" #: src/canvas.c:2207 msgid "Export Undo Images" msgstr "Chronikbilder exportieren" # msgstr "Undo-Bilder exportieren" #: src/canvas.c:2212 msgid "Export Undo Images (reversed)" msgstr "Chronikbilder exportieren (umgekehrt)" # msgstr "Undo-Bilder exportieren (umgekehrt)" #: src/canvas.c:2217 msgid "You must have 16 or fewer palette colours to export ASCII art." msgstr "Das Bild darf zum Export als ASCII-Grafik maximal 16 Farben enthalten." #: src/canvas.c:2220 msgid "Export ASCII Art" msgstr "Als ASCII-Grafik exportieren" #: src/canvas.c:2224 msgid "Save Layer Files" msgstr "Ebenen-Textdatei speichern" #: src/canvas.c:2234 msgid "Choose frames directory" msgstr "Verzeichnis für die Einzelbilder wählen" #: src/canvas.c:2240 msgid "You must save at least one frame to create an animated GIF." msgstr "Für ein animiertes GIF müssen Sie mindestens ein Einzelbild speichern." #: src/canvas.c:2243 msgid "Export GIF animation" msgstr "GIF-Animation exportieren" #: src/canvas.c:2247 msgid "Load Channel" msgstr "Kanal laden" #: src/canvas.c:2255 msgid "Save Channel" msgstr "Kanal speichern" #: src/canvas.c:2260 msgid "Save Composite Image" msgstr "Kompositbild speichern" #: src/channels.c:243 msgid "Create Channel" msgstr "Kanal anlegen" #: src/channels.c:244 msgid "Channel Type" msgstr "Kanaltyp" #: src/channels.c:247 msgid "Initial Channel State" msgstr "Anfänglicher Kanalstatus" # msgstr "Anfangsstatus des Kanals" ??? #: src/channels.c:251 msgid "Inverted" msgstr "Invertiert" #: src/channels.c:265 msgid "Cleared" msgstr "Gelöscht" #: src/channels.c:266 msgid "Set" msgstr "Festlegen" #: src/channels.c:267 msgid "Set colour A radius B" msgstr "Farbe A, Radius B festlegen" #: src/channels.c:268 msgid "Set blend A to B" msgstr "Mischung A nach B festlegen" #: src/channels.c:269 msgid "Image Red" msgstr "Bild Rot" #: src/channels.c:270 msgid "Image Green" msgstr "Bild Grün" #: src/channels.c:271 msgid "Image Blue" msgstr "Bild Blau" #: src/channels.c:273 src/channels.c:313 src/mainwindow.c:67 #: src/otherwindow.c:1679 msgid "Alpha" msgstr "Alpha" #: src/channels.c:274 src/channels.c:314 src/mainwindow.c:67 #: src/otherwindow.c:1683 msgid "Selection" msgstr "Auswahl" #: src/channels.c:275 src/channels.c:315 src/mainwindow.c:67 #: src/otherwindow.c:1687 msgid "Mask" msgstr "Maske" #: src/channels.c:312 msgid "Delete Channels" msgstr "Kanäle löschen" #: src/channels.c:367 msgid "Threshold Channel" msgstr "Schwellwert-Kanal" #: src/cpick.c:823 src/otherwindow.c:573 src/otherwindow.c:820 #: src/toolbar.c:299 msgid "Hue" msgstr "Farbton" # msgstr "Tonwert" #: src/cpick.c:827 src/otherwindow.c:573 src/otherwindow.c:818 #: src/toolbar.c:299 msgid "Saturation" msgstr "Sättigung" #: src/cpick.c:835 msgid "Hex" msgstr "Hex" #: src/cpick.c:840 src/layer.c:1109 src/otherwindow.c:2530 src/prefs.c:323 #: src/toolbar.c:457 msgid "Opacity" msgstr "Deckkraft" #: src/font.c:982 msgid "Creating Font Index" msgstr "Erstelle Index der Schriftarten" #: src/font.c:1353 msgid "You must select at least one directory to search for fonts." msgstr "" "Zur Suche nach Schriftarten muss mindestens ein Verzeichnis ausgewählt sein." #: src/font.c:1529 src/font.c:1624 src/toolbar.c:609 src/viewer.c:1213 #: src/viewer.c:1258 msgid "Paste Text" msgstr "Text einfügen" #: src/font.c:1533 src/font.c:1572 src/png.c:3578 msgid "Text" msgstr "Text" #: src/font.c:1540 msgid "Font" msgstr "Schriftart" #: src/font.c:1548 msgid "Style" msgstr "Stil" #: src/font.c:1566 msgid "Filename" msgstr "Dateiname" #: src/font.c:1567 msgid "Face" msgstr "Fläche" #: src/font.c:1587 src/viewer.c:1222 msgid "Antialias" msgstr "Antialias" #: src/font.c:1590 src/viewer.c:1224 msgid "Invert" msgstr "Invertieren" #: src/font.c:1593 src/viewer.c:1226 msgid "Background colour =" msgstr "Hintergrundfarbe =" #: src/font.c:1601 src/viewer.c:1233 msgid "DPI =" msgstr "" #: src/font.c:1610 msgid "Oblique" msgstr "Kursiv (Oblique)" #: src/font.c:1612 src/viewer.c:1244 msgid "Angle of rotation =" msgstr "Rotationswinkel =" #: src/font.c:1617 src/viewer.c:1248 msgid "Align" msgstr "Ausrichten" #: src/font.c:1620 src/viewer.c:1253 msgid "Spacing" msgstr "Zeichenabstand" #: src/font.c:1629 msgid "Font Directories" msgstr "Schriftverzeichnisse" #: src/font.c:1634 src/spawn.c:664 msgid "Directory" msgstr "Verzeichnis" #: src/font.c:1637 msgid "New Directory" msgstr "Neues Verzeichnis" #: src/font.c:1644 src/prefs.c:532 msgid "Add" msgstr "Hinzufügen" #: src/font.c:1645 src/prefs.c:533 msgid "Remove" msgstr "Entfernen" #: src/font.c:1646 msgid "Create Index" msgstr "Erzeuge Index" #: src/font.c:1660 src/viewer.c:1267 msgid "Enter Text Here" msgstr "Text eingeben" #: src/fpick.c:635 #, c-format msgid "Could not access directory %s" msgstr "Auf das Verzeichnis %s kann nicht zugegriffen werden" #: src/fpick.c:668 src/fpick.c:698 msgid "Delete" msgstr "Löschen" #: src/fpick.c:669 src/fpick.c:698 msgid "Rename" msgstr "Umbenennen" #: src/fpick.c:672 src/otherwindow.c:255 src/otherwindow.c:1666 msgid "Create" msgstr "Anlegen" #: src/fpick.c:699 msgid "Enter the new filename" msgstr "Neuen Dateinamen eingeben" #: src/fpick.c:704 msgid "Create Directory" msgstr "Verzeichnis erstellen" #: src/fpick.c:705 msgid "Enter the name of the new directory" msgstr "Name des neuen Verzeichnisses eingeben" #: src/fpick.c:729 #, c-format msgid "Do you really want to delete \"%s\" ?" msgstr "Soll \"%s\" wirklich gelöscht werden?" #: src/fpick.c:735 msgid "Unable to delete" msgstr "Kann nicht löschen" #: src/fpick.c:741 msgid "Unable to rename" msgstr "Kann nicht umbenennen" #: src/fpick.c:750 msgid "Unable to create directory" msgstr "Kann Verzeichnis nicht anlegen" #: src/fpick.c:924 msgid "Up" msgstr "Rauf" # msgstr "Ein Verzeichnis nach oben" #: src/fpick.c:925 msgid "Home" msgstr "Home" #: src/fpick.c:926 msgid "Create New Directory" msgstr "Neues Verzeichnis anlegen" #: src/fpick.c:927 msgid "Show Hidden Files" msgstr "Verborgene Dateien anzeigen" #: src/fpick.c:929 msgid "Case Insensitive Sort" msgstr "Sortieren (ohne Groß-/Kleinschreibung zu beachten)" #: src/fpick.c:936 msgid "Name" msgstr "Name" #: src/fpick.c:938 msgid "Type" msgstr "Typ" #: src/fpick.c:939 msgid "Modified" msgstr "Geändert" #: src/help.c:25 src/prefs.c:160 msgid "General" msgstr "Allgemein" #: src/help.c:26 msgid "Keyboard shortcuts" msgstr "Tastenkürzel" #: src/help.c:27 msgid "Mouse shortcuts" msgstr "Mauskürzel" #: src/help.c:28 msgid "Credits" msgstr "Danksagung" #: src/help.c:32 msgid "mtPaint 3.51 - Copyright (C) 2004-2021 The Authors\n" msgstr "mtPaint 3.51 - Copyright (C) 2004-2021 Die Autoren\n" #: src/help.c:33 msgid "See 'Credits' section for a list of the authors.\n" msgstr "Eine Liste der Autoren finden Sie in der Rubrik 'Danksagung'.\n" #: src/help.c:34 msgid "" "mtPaint 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.\n" msgstr "" "mtPaint ist freie Software. Sie dürfen es weitergeben und/oder modifizieren " "gemäß den Bestimmungen der GNU General Public License, die von Free Software " "Foundation herausgegeben wird, entweder in Version 3 oder wenn Sie wollen, " "auch in einer späteren Version.\n" #: src/help.c:35 msgid "" "mtPaint 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.\n" msgstr "" "mtPaint wird in der Hoffnung verteilt, dass es nützlich ist, jedoch OHNE " "JEGLICHE GARANTIE; nicht einmal mit einer implizierten Garantie der " "VERKEHRSFÄHIGKEIT (MERCHANTABILITY) oder EIGNUNG FÜR EINEN BESTIMMTEN ZWECK. " "Siehe die GNU General Public License für weitere Details.\n" #: src/help.c:36 msgid "" "mtPaint is a simple GTK+1/2/3 painting program designed for creating icons " "and pixel based artwork. It can edit indexed palette or 24 bit RGB images " "and offers basic painting and palette manipulation tools. It also has " "several other more powerful features such as channels, layers and animation. " "Due to its simplicity and lack of dependencies it runs well on GNU/Linux, " "Windows and older PC hardware.\n" msgstr "" "mtPaint ist ein einfaches GTK+1/2/3 Zeichenprogramm zum Bearbeiten von " "Symbolen und Pixelbildern. Es kann Bilder mit indizierter Palette oder 24-" "Bit RGB-Bilder bearbeiten und bietet grundlegende Werkzeuge zum Malen und " "zur Bearbeitung von Paletten. Es bietet auch einige leistungsfähige " "Fähigkeiten wie Kanäle, Ebenen und Animation. Wegen seiner Einfachheit und " "wenigen Abhängigkeiten läuft es gut unter GNU/Linux, Windows und älterer PC-" "Hardware.\n" #: src/help.c:37 msgid "" "There is full documentation of mtPaint's features contained in a handbook. " "If you don't already have this, you can download it from the mtPaint " "website.\n" msgstr "" "Alle Funktionen von mtPaint sind ausführlich in einem Handbuch dokumentiert. " "Falls Sie dieses noch nicht besitzen, können Sie es auf der Webseite von " "mtPaint herunterladen.\n" #: src/help.c:38 msgid "" "If you like mtPaint and you want to keep up to date with new releases, or " "you want to give some feedback, then the mailing lists may be of interest to " "you:\n" msgstr "" "Wenn Ihnen mtPaint gefällt und Sie über neue Versionen benachrichtigt " "werden, oder Rückmeldungen geben wollen, dann dürften die Mailinglisten für " "Sie interessant sein:\n" #: src/help.c:39 msgid "http://sourceforge.net/mail/?group_id=155874" msgstr "" #: src/help.c:42 msgid " Ctrl-N Create new image" msgstr " Strg-N Neues Bild erstellen" #: src/help.c:43 msgid " Ctrl-O Open Image" msgstr " Strg-O Bild öffnen" #: src/help.c:44 msgid " Ctrl-S Save Image" msgstr " Strg-S Bild speichern" #: src/help.c:45 msgid " Ctrl-Shift-S Save layers file" msgstr " Strg-Umschalt-S Speichere Ebenen-Textdatei" #: src/help.c:46 msgid " Ctrl-Q Quit program\n" msgstr " Strg-Q Programm beenden\n" #: src/help.c:47 msgid " Ctrl-A Select whole image" msgstr " Strg-A Alles auswählen" #: src/help.c:48 msgid " Escape Select nothing, cancel paste box" msgstr " Escape Nichts auswählen, Einfügen Vorgang (Box) abbrechen" #: src/help.c:49 msgid " J Lasso selection\n" msgstr " J Lasso Auswahl\n" #: src/help.c:50 msgid " Ctrl-C Copy selection to clipboard" msgstr " Strg-C Auswahl in die Zwischenablage kopieren" #: src/help.c:51 msgid "" " Ctrl-X Copy selection to clipboard, and then paint current " "pattern to selection area" msgstr "" " Strg-X Auswahl in die Zwischenablage kopieren und dann " "aktuelles Muster ins Auswahlfeld zeichnen" #: src/help.c:52 msgid " Ctrl-V Paste clipboard to centre of current view" msgstr " Strg+V Zwischenablage in die Bildmitte einfügen" #: src/help.c:53 msgid " Ctrl-K Paste clipboard to location it was copied from" msgstr " Strg-K Zwischenablage an Ursprungsort einfügen" #: src/help.c:54 msgid " Ctrl-Shift-V Paste clipboard to new layer" msgstr " Strg-Umschalt-V Zwischenablage in neue Ebene einfügen" #: src/help.c:55 msgid " Enter/Return Commit paste to canvas" msgstr " Enter/Return Einfügen in die Zeichenfläche ausführen" #: src/help.c:56 msgid " Shift+Enter/Return Commit paste and swap canvas into the clipboard\n" msgstr "" " Umschalt-Enter/Return Einf. ausführen, verdeckten Bildteil in Ablage\n" #: src/help.c:57 msgid " Arrow keys Paint Mode - Move the mouse pointer" msgstr " Pfeiltasten Im Zeichenmodus - Mauszeiger bewegen" #: src/help.c:58 msgid "" " Arrow keys Selection Mode - Nudge selection box or paste box by one " "pixel" msgstr "" " Pfeiltasten Auswahlmodus - Auswahl-Box bzw. Einfügen-Box pixelweise " "verschieben" #: src/help.c:59 msgid "" " Shift+Arrow keys Nudge mouse pointer, selection box or paste box by x " "pixels - x is defined by the Preferences window" msgstr "" " Umschalt+Pfeiltasten Mauszeiger, Auswahl- bzw. Einfügen-Box um x Pixel " "verschieben - x wird im Einstellungen-Dialog festgelegt" #: src/help.c:60 msgid " Ctrl+Arrows Move layer or resize selection box" msgstr "" " Strg+Pfeiltasten Ebene verschieben bzw. Größe der Auswahl-Box verändern" #: src/help.c:61 msgid " Ctrl+Shift+Arrows Move layer or resize selection box by x pixels\n" msgstr "" " Strg+Umschalt+Pfeiltasten Ebene verschieben bzw. Größe der Auswahl-Box um " "x Pixel verändern\n" #: src/help.c:62 msgid " Enter/Return Paint Mode - Simulate left click" msgstr " Enter/Eingabe Zeichenmodus - simuliert linken Mausklick" #: src/help.c:63 msgid " Backspace Paint Mode - Simulate right click\n" msgstr " Rücktaste (Backspace) Zeichenmodus - simuliert rechten Mausklick\n" #: src/help.c:64 msgid "" " [ or ] Change colour A to the next or previous palette item" msgstr "" " [ bzw. ]\t Farbe A zur nächsten bzw. vorigen Farbein der Palette " "wechseln" #: src/help.c:65 msgid "" " Shift+[ or ] Change colour B to the next or previous palette item\n" msgstr "" " Umschalt+[ bzw. ]\t Farbe B zur nächsten bzw. vorigen Farbe in der Palette " "wechseln\n" #: src/help.c:66 msgid " Delete Crop image to selection" msgstr " Entf Bild auf Größe des Auswahlfelds zuschneiden" #: src/help.c:67 msgid "" " Insert Transform colours - i.e. Brightness, Contrast, " "Saturation, Posterize, Gamma" msgstr "" " Einfg Farben transformieren - z.B.: Helligkeit, Kontrast, " "Sättigung, Posterisieren, Gamma" #: src/help.c:68 msgid " Ctrl-G Greyscale the image" msgstr " Strg-G Bild in Graustufen umwandeln" #: src/help.c:69 msgid " Shift-Ctrl-G Greyscale the image (Gamma corrected)" msgstr " Umschalt-Strg-G Bild in Graustufen umwandeln (Gamma korrigiert)" #: src/help.c:70 msgid " Ctrl+M Mirror the image" msgstr " Strg-M Bild spiegeln" #: src/help.c:71 msgid " Shift-Ctrl-I Invert the image\n" msgstr " Umschalt-Strg-I Bild invertieren\n" #: src/help.c:72 msgid "" " Ctrl-T Draw a rectangle around the selection area with the " "current fill" msgstr "" " Strg-T Zeichne leeres Rechteck um Auswahl mit aktuellem Muster" #: src/help.c:73 msgid " Ctrl-Shift-T Fill in the selection area with the current fill" msgstr " Strg-Umschalt-T Fülle Auswahl mit aktuellem (Füll)Muster" #: src/help.c:74 msgid " Ctrl-L Draw an ellipse spanning the selection area" msgstr " Strg-L Zeichne leere Ellipse in die Auswahl" #: src/help.c:75 msgid " Ctrl-Shift-L Draw a filled ellipse spanning the selection area\n" msgstr " Strg-Umschalt-L Zeichne gefüllte Ellipse in die Auswahl\n" #: src/help.c:76 msgid " Ctrl-E Edit the RGB values for colours A & B" msgstr " Strg-E Farbeditor aufrufen zum Einstellen von Farbe A & B" #: src/help.c:77 msgid " Ctrl-W Edit all palette colours\n" msgstr "" " Strg-W Paletten-Editor aufrufen: Ganze Palette editieren\n" #: src/help.c:78 msgid " Ctrl-P Preferences" msgstr " Strg-P Einstellungen-Dialog aufrufen" #: src/help.c:79 msgid " Ctrl-I Information\n" msgstr " Strg-I Informationen anzeigen\n" #: src/help.c:80 msgid " Ctrl-Z Undo last action" msgstr " Strg-Z Letzten Bearbeitungsschritt zurücknehmen (Undo)" #: src/help.c:81 msgid " Ctrl-R Redo an undone action\n" msgstr "" " Strg-R Zurückgenommenen Bearbeitungsschritt wiederherstellen\n" #: src/help.c:82 msgid " Shift-T Text Tool (GTK+)" msgstr " Umschalt-T\t Text Werkzeug (GTK+)" #: src/help.c:83 msgid " T Text Tool (FreeType)\n" msgstr " T Text Werkzeug (FreeType)\n" #: src/help.c:84 msgid " V View Window" msgstr " V Ansichtsfenster" #: src/help.c:85 msgid " L Layers Window\n" msgstr " L Ebenen Fenster\n" #: src/help.c:86 msgid " Ctrl-H Toggle Hide Image mode" msgstr "" #: src/help.c:87 msgid " B Toggle Snap to Tile Grid mode\n" msgstr " B Maus zu Gitterpunkten springen ein/aus\n" #: src/help.c:88 msgid " X Swap Colours A & B" msgstr " X Farben A & B vertauschen" #: src/help.c:89 msgid " E Choose Colour\n" msgstr " E Farbe wählen\n" #: src/help.c:90 msgid "" " A Draw open arrow head when using the line tool (size set " "by flow setting)" msgstr "" " A Zeichne offene Pfeilspitze während Sie das Linien-" "Werkzeug verwenden. Die Größe wird durch 'Stärke' festgelegt." #: src/help.c:91 msgid "" " S Draw closed arrow head when using the line tool (size " "set by flow setting)\n" msgstr "" " S Zeichne geschlossene Pfeilspitze während Sie das Linien-" "Werkzeug verwenden. Die Größe wird durch 'Stärke' festgelegt.\n" #: src/help.c:92 msgid " D Line Tool" msgstr " D Linien-Werkzeug" #: src/help.c:93 msgid " F Flood Fill Tool\n" msgstr " F Füll-Werkzeug\n" #: src/help.c:94 msgid " +,= Main edit window - Zoom in" msgstr " +,= Hauptarbeitsfenster - Hineinzoomen" #: src/help.c:95 msgid " - Main edit window - Zoom out" msgstr " - Hauptarbeitsfenster - Herauszoomen" #: src/help.c:96 msgid " Shift +,= View window - Zoom in" msgstr " Umschalt +,= Ansichtsfenster - Hineinzoomen" #: src/help.c:97 msgid " Shift - View window - Zoom out\n" msgstr " Umschalt -,= Ansichtsfenster - Herauszoomen\n" #: src/help.c:98 #, c-format msgid " 1 10% zoom" msgstr " 1 10% Zoom" #: src/help.c:99 #, c-format msgid " 2 25% zoom" msgstr " 2 25% Zoom" #: src/help.c:100 #, c-format msgid " 3 50% zoom" msgstr " 3 50% Zoom" #: src/help.c:101 #, c-format msgid " 4 100% zoom" msgstr " 4 100% Zoom" #: src/help.c:102 #, c-format msgid " 5 400% zoom" msgstr " 4 400% Zoom" #: src/help.c:103 #, c-format msgid " 6 800% zoom" msgstr " 6 800% Zoom" #: src/help.c:104 #, c-format msgid " 7 1200% zoom" msgstr " 7 1200% Zoom" #: src/help.c:105 #, c-format msgid " 8 1600% zoom" msgstr " 8 1600% Zoom" #: src/help.c:106 #, c-format msgid " 9 2000% zoom\n" msgstr " 9 2000% Zoom\n" #: src/help.c:107 msgid " Shift + 1 Edit image channel" msgstr " Umschalt + 1 Bildkanal bearbeiten" #: src/help.c:108 msgid " Shift + 2 Edit alpha channel" msgstr " Umschalt + 2 Alphakanal bearbeiten" #: src/help.c:109 msgid " Shift + 3 Edit selection channel" msgstr " Umschalt + 3 Auswahlkanal bearbeiten" #: src/help.c:110 msgid " Shift + 4 Edit mask channel\n" msgstr " Umschalt + 4 Maskenkanal bearbeiten\n" #: src/help.c:111 msgid " F1 Help" msgstr " F1 Hilfe" #: src/help.c:112 msgid " F2 Choose Pattern" msgstr " F2 Muster auswählen" #: src/help.c:113 msgid " F3 Choose Brush" msgstr " F3 Pinsel auswählen" #: src/help.c:114 msgid " F4 Paint Tool" msgstr " F4 Malwerkzeug" #: src/help.c:115 msgid " F5 Toggle Main Toolbar" msgstr " F5 Hauptleiste ein/aus" #: src/help.c:116 msgid " F6 Toggle Tools Toolbar" msgstr " F6 Werkzeugleiste ein/aus" #: src/help.c:117 msgid " F7 Toggle Settings Toolbar" msgstr " F7 Einstellungsleiste ein/aus" #: src/help.c:118 msgid " F8 Toggle Palette" msgstr " F8 Palette ein/aus" #: src/help.c:119 msgid " F9 Selection Tool" msgstr " F9 Auswahlwerkzeug" #: src/help.c:120 msgid " F12 Toggle Dock Area\n" msgstr " F12 Andockfenster ein/aus\n" #: src/help.c:121 msgid " Ctrl + F1 - F12 Save current clipboard to file 1-12" msgstr " Strg + F1 - F12 Speichere aktuelle Zwischenablage in Datei 1-12" #: src/help.c:122 msgid " Shift + F1 - F12 Load clipboard from file 1-12\n" msgstr " Umschalt + F1 - F12 Lade Datei 1-12 in die Zwischenablage\n" #: src/help.c:123 msgid "" " Ctrl + 1, 2, ... , 0 Set opacity to 10%, 20%, ... , 100% (main or keypad " "numbers)" msgstr "" " Strg + 1, 2, ... , 0 Setze Deckkraft auf 10%, 20%, ... , 100% (auch " "Tasten vom Zahlenblock)" #: src/help.c:124 msgid " Ctrl + + or = Increase opacity by 1" msgstr " Strg + + oder = Erhöhe Deckkraft um 1" #: src/help.c:125 msgid " Ctrl + - Decrease opacity by 1\n" msgstr " Strg + - Reduziere Deckkraft um 1\n" #: src/help.c:126 msgid "" " Home Show or hide main window menu/toolbar/status bar/palette" msgstr " Pos1 Vollbild (alle Bedienelemente ein/ausblenden)" #: src/help.c:127 msgid " Page Up Scale Image" msgstr " Bild hoch Bild skalieren (Vergrößern/Verkleinern)" #: src/help.c:128 msgid " Page Down Resize Image canvas" msgstr " Bild runter Größe der Zeichenfläche ändern" #: src/help.c:129 msgid " End Pan Window" msgstr " Ende Verschieben-Fenster (Pan)" #: src/help.c:132 msgid " Left button Paint to canvas using the current tool" msgstr "" " Linke Maustaste Male mit aktuellem Werkzeug in die Zeichenfläche" #: src/help.c:133 msgid "" " Middle button Selects the point which will be the centre of the " "image after the next zoom" msgstr "" " Mittlere Maustaste Wähle den Punkt, der nach dem nächsten Zoom in der " "Bildmitte sein soll" #: src/help.c:134 msgid "" " Right button Commit paste to canvas / Stop drawing current line / " "Cancel selection\n" msgstr "" " Rechte Maustaste Führe 'Einfügen in die Zeichenfläche' durch / " "Verlasse 'Linie zeichnen' / Hebe Auswahl auf\n" #: src/help.c:135 msgid "" " Scroll Wheel In GTK+2/3 the user can have the scroll wheel zoom in " "or out via the Preferences window\n" msgstr "" " Mausrad Mit GTK+2/3 haben Sie die Möglichkeit, im " "Einstellungen-Fenster zoomen mit dem Mausrad zu aktivieren\n" #: src/help.c:136 msgid " Ctrl+Left button Choose colour A from under mouse pointer" msgstr " Strg+Linksklick Farbe unter dem Mauszeiger als Farbe A wählen" #: src/help.c:137 msgid " Ctrl+Left button Clone tool - Select source" msgstr "" # fuzzy #: src/help.c:138 msgid "" " Ctrl+Middle button Create colour A/B and pattern based on the RGB colour " "in A (RGB images only)" msgstr "" " Strg+Mittlere Maustaste Erstelle Farbe A/B und Muster ausgehend von der " "RGB-Farbe in A (nur RGB-Bilder)" #: src/help.c:139 msgid " Ctrl+Right button Choose colour B from under mouse pointer" msgstr " Strg+Rechtsklick Wähle Farbe unter Mauszeiger als Farbe B" #: src/help.c:140 msgid "" " Ctrl+Right button Polygon tool - Delete last point / Delete nearest " "point" msgstr "" #: src/help.c:141 msgid " Ctrl+Scroll Wheel Scroll the main edit window left or right\n" msgstr "" " Strg+Mausrad Das Arbeitsfenster nach rechts oder links scrollen\n" #: src/help.c:142 msgid "" " Ctrl+Double click Set colour A or B to average colour under brush " "square or selection marquee (RGB only)\n" msgstr "" " Strg+Doppelklick Setze Farbe A bzw. B als Farbmittelwert unter " "Pinselquadrat oder Auswahlmarkierung (nur RGB)\n" #: src/help.c:143 msgid "" " Shift+Right button Selects the point which will be the centre of the " "image after the next zoom\n" "\n" msgstr "" " Umschalt+Rechtsklick wählt den Punkt, der nach dem nächsten Mal Zoomen in " "der Mitte sein soll\n" "\n" #: src/help.c:144 msgid "You can fixate the X/Y co-ordinates while moving the mouse:\n" msgstr "Sie können die X/Y Koordinate fixieren während Sie die Maus bewegen:\n" #: src/help.c:145 msgid " Shift Constrain mouse movements to vertical line" msgstr " Umschalt Mausbewegungen nur auf vertikaler Linie" #: src/help.c:146 msgid " Shift+Ctrl Constrain mouse movements to horizontal line" msgstr " Umschalt+Strg Mausbewegungen nur auf horizontaler Linie" #: src/help.c:149 msgid "mtPaint is maintained by Dmitry Groshev.\n" msgstr "mtPaint wird von Dmitry Groshev gepflegt.\n" #: src/help.c:150 msgid "wjaguar@users.sourceforge.net" msgstr "" #: src/help.c:151 msgid "http://mtpaint.sourceforge.net/\n" msgstr "" #: src/help.c:152 msgid "" "The following people (in alphabetical order) have contributed directly to " "the project, and are therefore worthy of gracious thanks for their " "generosity and hard work:\n" "\n" msgstr "" "Folgende Personen (in alphabetischer Reihenfolge) haben direkt zu dem " "Projekt beigetragen und verdienen deshalb aufrichtigen Dank für ihre " "Großzügigkeit und harte Arbeit:\n" #: src/help.c:153 msgid "Authors\n" msgstr "Autoren\n" #: src/help.c:154 msgid "" "Dmitry Groshev - Contributing developer for version 2.30. Lead developer and " "maintainer from version 3.00 to the present." msgstr "" "Dmitry Groshev - Beitragender Entwickler für Version 2.30. Leitender " "Entwickler und Maintainer von Version 3.00 an bis jetzt." #: src/help.c:155 msgid "" "Mark Tyler - Original author and maintainer up to version 3.00, occasional " "contributor thereafter." msgstr "" "Mark Tyler - Originalautor und Maintainer bis Version 3.00, danach " "gelegentlich Beitragender." #: src/help.c:156 msgid "" "Xiaolin Wu - Wrote the Wu quantizing method - see wu.c for more " "information.\n" "\n" msgstr "" "Xiaolin Wu - Schrieb die Methode zur Wu Quantisierung - Siehe wu.c für " "weitere Informationen.\n" "\n" #: src/help.c:157 msgid "" "General Contributions (Feedback and Ideas for improvements unless otherwise " "stated)\n" msgstr "" "Allgemein Beitragende (Rückmeldungen und Ideen für Verbesserungen sofern " "nicht anderweitig genannt):\n" #: src/help.c:158 msgid "Abdulla Al Muhairi - Website redesign April 2005" msgstr "Abdulla Al Muhairi - Neues Design für die Website April 2005" #: src/help.c:159 msgid "Alan Horkan" msgstr "" #: src/help.c:160 msgid "Alexandre Prokoudine" msgstr "" #: src/help.c:161 msgid "Antonio Andrea Bianco" msgstr "" #: src/help.c:162 msgid "Charlie Ledocq" msgstr "" #: src/help.c:163 msgid "Dennis Lee" msgstr "" #: src/help.c:164 msgid "Donald White" msgstr "" #: src/help.c:165 msgid "Ed Jason" msgstr "" #: src/help.c:166 msgid "" "Eddie Kohler - Created Gifsicle which is needed for the creation and viewing " "of animated GIF files http://www.lcdf.org/gifsicle/" msgstr "" "Eddie Kohler - Entwickelte Gifsicle welches zum Erzeugen und Betrachten " "animierter GIF-Dateien verwendet wird http://www.lcdf.org/gifsicle/" #: src/help.c:167 msgid "" "Guadalinex Team (Junta de Andalucia) - man page, Launchpad/Rosetta " "registration" msgstr "" "Guadalinex Team (Junta de Andalucia) - man page, Launchpad/Rosetta " "Registrierung" #: src/help.c:168 msgid "Lou Afonso" msgstr "" #: src/help.c:169 msgid "Magnus Hjorth" msgstr "" #: src/help.c:170 msgid "Martin Zelaia" msgstr "" #: src/help.c:171 msgid "Pasi Kallinen" msgstr "" #: src/help.c:172 msgid "Pavel Ruzicka" msgstr "" #: src/help.c:173 msgid "Puppy Linux (Barry Kauler)" msgstr "" #: src/help.c:174 msgid "Victor Copovi" msgstr "" #: src/help.c:175 msgid "Vlastimil Krejcir" msgstr "" #: src/help.c:176 msgid "" "William Kern\n" "\n" msgstr "" #: src/help.c:177 msgid "Translations\n" msgstr "Übersetzungen\n" #: src/help.c:178 msgid "Brazilian Portuguese - Paulo Trevizan, Valter Nazianzeno" msgstr "Brasilianisches Portugiesisch - Paulo Trevizan, Valter Nazianzeno" #: src/help.c:179 msgid "Czech - Pavel Ruzicka, Martin Petricek, Roman Hornik, Pavel Fric" msgstr "Tschechisch - Pavel Ruzicka, Martin Petricek, Roman Hornik, Pavel Fric" #: src/help.c:180 msgid "Dutch - Hans Strijards, Pjotr" msgstr "Niederländisch - Hans Strijards, Pjotr" #: src/help.c:181 msgid "" "French - Nicolas Velin, Pascal Billard, Sylvain Cresto, Johan Serre, " "Philippe Etienne, Victor Copovi" msgstr "" "Französisch - Nicolas Velin, Pascal Billard, Sylvain Cresto, Johan Serre, " "Philippe Etienne, Victor Copovi" #: src/help.c:182 msgid "Galician - Miguel Anxo Bouzada" msgstr "Galicisch - Miguel Anxo Bouzada" #: src/help.c:183 msgid "German - Oliver Frommel, B. Clausius, Ulrich Ringel, Simon Brixel" msgstr "Deutsch - Oliver Frommel, B. Clausius, Ulrich Ringel, Simon Brixel" #: src/help.c:184 msgid "Hungarian - Ur Balazs" msgstr "Ungarisch - Ur Balazs" #: src/help.c:185 msgid "Italian - Angelo Gemmi" msgstr "Italienisch - Angelo Gemmi" #: src/help.c:186 msgid "Japanese - Norihiro YONEDA" msgstr "Japanisch - Norihiro YONEDA" #: src/help.c:187 msgid "Kabyle - Yacine Bouklif" msgstr "" #: src/help.c:188 msgid "Polish - Bartosz Kaszubowski, LucaS" msgstr "Polnisch - Bartosz Kaszubowski, LucaS" #: src/help.c:189 msgid "Portuguese - Israel G. Lugo, Tiago Silva" msgstr "Portugiesisch - Israel G. Lugo, Tiago Silva" #: src/help.c:190 msgid "Russian - Sergey Irupin, Dmitry Groshev" msgstr "Russisch - Sergey Irupin, Dmitry Groshev" #: src/help.c:191 msgid "Simplified Chinese - Cecc" msgstr "Chinesisch (vereinfacht) - Cecc" #: src/help.c:192 msgid "Slovak - Jozef Riha" msgstr "Slowakisch - Jozef Riha" #: src/help.c:193 msgid "" "Spanish - Guadalinex Team (Junta de Andalucia), Antonio Sanchez Leon, Miguel " "Anxo Bouzada, Francisco Jose Rey, Adolfo Jayme" msgstr "" "Spanisch - Guadalinex Team (Junta de Andalucia), Antonio Sanchez Leon, " "Miguel Anxo Bouzada, Francisco Jose Rey, Adolfo Jayme" #: src/help.c:194 msgid "Swedish - Daniel Nylander, Daniel Eriksson" msgstr "Schwedisch - Daniel Nylander, Daniel Eriksson" #: src/help.c:195 msgid "Tagalog - Anjelo delCarmen" msgstr "Tagalog - Anjelo delCarmen" #: src/help.c:196 msgid "Taiwanese Chinese - Wei-Lun Chao" msgstr "Taiwanesisches Chinesisch - Wei-Lun Chao" #: src/help.c:197 msgid "Turkish - Muhammet Kara, Tutku Dalmaz" msgstr "Türkisch - Muhammet Kara, Tutku Dalmaz" #: src/info.c:258 msgid "Information" msgstr "Informationen" #: src/info.c:260 msgid "Memory" msgstr "Speicher" #: src/info.c:261 msgid "Total memory for main + undo images" msgstr "Gesamtspeicher für Bild und Chronik" #: src/info.c:263 msgid "Undo / Redo / Max levels used" msgstr "Rückgängig / Wiederherstellen / Max ausgeführte Schritte" #: src/info.c:265 msgid "Unused" msgstr "Unbenutzt" #: src/info.c:269 msgid "Unique RGB pixels" msgstr "Anzahl verwendeter RGB Farben" #: src/info.c:272 src/layer.c:121 msgid "Layers" msgstr "Ebenen" #: src/info.c:273 msgid "Total layer memory usage" msgstr "Insgesamt genutzter Ebenenspeicher" #: src/info.c:277 msgid "Colour Histogram" msgstr "Farbhistogramm" #: src/info.c:289 src/otherwindow.c:1614 msgid "Index" msgstr "Index" #: src/info.c:290 msgid "Canvas pixels" msgstr "Pixel der Zeichenfläche" #: src/info.c:328 #, c-format msgid "Clipboard = %i x %i" msgstr "Zwischenablage = %i x %i" #: src/info.c:328 #, c-format msgid "Clipboard = %i x %i x RGB" msgstr "Zwischenablage = %i x %i x RGB" #: src/info.c:377 msgid "Orphans" msgstr "Verwaiste " #: src/info.c:383 #, c-format msgid "Colour index totals - %i of %i used" msgstr "Farbindex-Statistik - %i von %i benutzt" #: src/inifile.c:966 msgid "" "Could not find home directory. Using current directory as home directory." msgstr "" "Konnte das Home-Verzeichnis nicht finden. Benutze das aktuelle Verzeichnis." #: src/layer.c:63 msgid "Background" msgstr "Hintergrund" #: src/layer.c:122 src/mainwindow.c:5931 msgid "(Modified)" msgstr "(Verändert)" #: src/layer.c:123 src/mainwindow.c:5932 msgid "Untitled" msgstr "Unbenannt" #: src/layer.c:308 #, c-format msgid "Do you really want to delete layer %i (%s) ?" msgstr "Wollen Sie Ebene %i (%s) wirklich löschen?" #: src/layer.c:380 msgid "" "One or more of the layers contains changes that have not been saved. Do you " "really want to lose these changes?" msgstr "" "Eine oder mehrere Ebenen enthalten nicht gespeicherte Änderungen. Wollen Sie " "diese wirklich verlieren?" #: src/layer.c:381 src/mainwindow.c:1028 msgid "Cancel Operation" msgstr "Aktion abbrechen" #: src/layer.c:381 src/mainwindow.c:1028 msgid "Lose Changes" msgstr "Änderungen verlieren" #: src/layer.c:523 #, c-format msgid "%d layers failed to load" msgstr "%d Ebenen konnten nicht geladen werden" #: src/layer.c:826 msgid "" "One or more of the image layers has not been saved. You must save each " "image individually before saving the layers text file in order to load this " "composite image in the future." msgstr "" "Eine oder mehrere Ebenen sind nicht gespeichert. Sie müssen vor dem " "Speichern der Ebenen-Textdatei jedes Bild einzeln speichern, um später das " "Kompositbild öffnen zu können." #: src/layer.c:841 msgid "Do you really want to delete all of the layers?" msgstr "Wollen Sie wirklich alle Ebenen löschen?" #: src/layer.c:970 msgid "You cannot add any more layers." msgstr "Sie können keine weiteren Ebenen mehr hinzufügen." #: src/layer.c:1083 src/otherwindow.c:241 msgid "New Layer" msgstr "Neue Ebene" #: src/layer.c:1085 msgid "Raise" msgstr "Höher" #: src/layer.c:1087 msgid "Lower" msgstr "Tiefer" #: src/layer.c:1089 msgid "Duplicate Layer" msgstr "Ebene duplizieren" #: src/layer.c:1091 msgid "Centralise Layer" msgstr "Ebene ausmitteln" #: src/layer.c:1093 msgid "Delete Layer" msgstr "Ebene löschen" #: src/layer.c:1095 msgid "Close Layers Window" msgstr "Ebenenfenster schließen" #: src/layer.c:1101 msgid "Layer Name" msgstr "Ebenenname" #: src/layer.c:1104 src/toolbar.c:209 msgid "Position" msgstr "Position" #: src/layer.c:1112 msgid "Transparent Colour" msgstr "Transparente Farbe" #: src/layer.c:1117 msgid "Show all layers in main window" msgstr "Zeige alle Ebenen im Hauptfenster" #: src/mainwindow.c:67 src/otherwindow.c:844 src/otherwindow.c:2756 #: src/toolbar.c:342 msgid "Image" msgstr "Bild" #: src/mainwindow.c:69 src/mainwindow.c:489 src/otherwindow.c:1613 #: src/otherwindow.c:2302 msgid "RGB" msgstr "RGB" #: src/mainwindow.c:69 src/otherwindow.c:1613 src/otherwindow.c:2302 msgid "sRGB" msgstr "sRGB" #: src/mainwindow.c:342 msgid "There were no unused colours to remove!" msgstr "Es gibt keine unbenutzten Farben, die entfernt werden könnten!" #: src/mainwindow.c:371 msgid "The palette does not contain 2 colours that have identical RGB values" msgstr "Die Palette enthält keine zwei Farben mit identischem RGB-Wert." # fuzzy #: src/mainwindow.c:374 #, c-format msgid "" "The palette contains %i colours that have identical RGB values. Do you " "really want to merge them into one index and realign the canvas?" msgstr "" "Die Palette enthält %i Farben mit identischen RGB-Werten. Wollen Sie diese " "tatsächlich zu einem Index vereinen und die Zeichenfläche neu anordnen?" #: src/mainwindow.c:492 msgid "indexed" msgstr "indiziert" # indiziert/indexiert: Beide Begriffe werden im Internet dafür verwendet, # indiziert führt zu genaueren Suchergebnissen in g* # de.wikipedia.org hat einen Artikel 'indizierte Farben', Suche nach 'indexierter # Palette bringt kein Ergebnis, 'indizierte Palette' das richtige #: src/mainwindow.c:498 #, c-format msgid "" "You are trying to save an %s image to an %s file which is not possible. I " "would suggest you save with a PNG extension." msgstr "" "Ein %s-Bild kann nicht in einer %s-Datei gespeichert werden. Empfohlen wird " "das Speichern mit der Erweiterung PNG." #: src/mainwindow.c:500 #, c-format msgid "" "You are trying to save an %s file with a palette of more than %d colours. " "Either use another format or reduce the palette to %d colours." msgstr "" "Eine %s-Datei kann nicht mit einer Palette gespeichert werden, die mehr als " "%d Farben enthält. Verwenden Sie ein anderes Format oder reduzieren Sie die " "Palette auf %d Farben." #: src/mainwindow.c:578 msgid "Unable to load clipboard" msgstr "Kann Zwischenablage nicht laden." #: src/mainwindow.c:604 msgid "Unable to save clipboard" msgstr "Kann Zwischenablage nicht speichern." #: src/mainwindow.c:775 msgid "Zoom in" msgstr "Hineinzoomen" #: src/mainwindow.c:777 msgid "Zoom out" msgstr "Herauszoomen" #: src/mainwindow.c:779 #, c-format msgid "10% zoom" msgstr "10% Zoom" #: src/mainwindow.c:781 #, c-format msgid "25% zoom" msgstr "25% Zoom" #: src/mainwindow.c:783 #, c-format msgid "50% zoom" msgstr "50% Zoom" #: src/mainwindow.c:785 #, c-format msgid "100% zoom" msgstr "100% Zoom" #: src/mainwindow.c:787 #, c-format msgid "400% zoom" msgstr "400% Zoom" #: src/mainwindow.c:789 #, c-format msgid "600% zoom" msgstr "600% Zoom" #: src/mainwindow.c:791 #, c-format msgid "800% zoom" msgstr "800% Zoom" #: src/mainwindow.c:793 #, c-format msgid "1000% zoom" msgstr "1000% Zoom" #: src/mainwindow.c:795 #, c-format msgid "1200% zoom" msgstr "1200% Zoom" #: src/mainwindow.c:797 #, c-format msgid "1600% zoom" msgstr "1600% Zoom" #: src/mainwindow.c:799 #, c-format msgid "2000% zoom" msgstr "2000% Zoom" #: src/mainwindow.c:801 #, c-format msgid "4000% zoom" msgstr "4000% Zoom" #: src/mainwindow.c:803 #, c-format msgid "8000% zoom" msgstr "8000% Zoom" #: src/mainwindow.c:805 #, c-format msgid "10% opacity" msgstr "10% Deckkraft" #: src/mainwindow.c:807 #, c-format msgid "20% opacity" msgstr "20% Deckkraft" #: src/mainwindow.c:809 #, c-format msgid "30% opacity" msgstr "30% Deckkraft" #: src/mainwindow.c:811 #, c-format msgid "40% opacity" msgstr "40% Deckkraft" #: src/mainwindow.c:813 #, c-format msgid "50% opacity" msgstr "50% Deckkraft" #: src/mainwindow.c:815 #, c-format msgid "60% opacity" msgstr "60% Deckkraft" #: src/mainwindow.c:817 #, c-format msgid "70% opacity" msgstr "70% Deckkraft" #: src/mainwindow.c:819 #, c-format msgid "80% opacity" msgstr "80% Deckkraft" #: src/mainwindow.c:821 #, c-format msgid "90% opacity" msgstr "90% Deckkraft" #: src/mainwindow.c:823 #, c-format msgid "100% opacity" msgstr "100% Deckkraft" #: src/mainwindow.c:825 msgid "Increase opacity" msgstr "Erhöhe Deckkraft" #: src/mainwindow.c:827 msgid "Decrease opacity" msgstr "Reduziere Deckkraft" #: src/mainwindow.c:829 msgid "Draw open arrow head" msgstr "Offene Pfeilspitze zeichnen" #: src/mainwindow.c:831 msgid "Draw closed arrow head" msgstr "Geschlossene Pfeilspitze zeichnen" #: src/mainwindow.c:833 msgid "Previous colour A" msgstr "Vorherige Farbe A" #: src/mainwindow.c:835 msgid "Next colour A" msgstr "Nächste Farbe A" #: src/mainwindow.c:837 msgid "Previous colour B" msgstr "Vorherige Farbe B" #: src/mainwindow.c:839 msgid "Next colour B" msgstr "Nächste Farbe B" #: src/mainwindow.c:841 msgid "Previous pattern" msgstr "Vorheriges Muster" #: src/mainwindow.c:843 msgid "Next pattern" msgstr "Nächstes Muster" #: src/mainwindow.c:845 msgid "Larger brush" msgstr "Größerer Pinsel" #: src/mainwindow.c:847 msgid "Smaller brush" msgstr "Kleinerer Pinsel" #: src/mainwindow.c:849 msgid "View window - Zoom in" msgstr "Ansichtsfenster - Hineinzoomen" #: src/mainwindow.c:851 msgid "View window - Zoom out" msgstr "Ansichtsfenster - Herauszoomen" #: src/mainwindow.c:1027 msgid "" "This canvas/palette contains changes that have not been saved. Do you " "really want to lose these changes?" msgstr "" "Die Zeichnung/Palette enthält nicht gespeicherte Änderungen. Wollen Sie " "diese wirklich verwerfen?" #: src/mainwindow.c:1094 msgid "Do you really want to quit?" msgstr "Wirklich beenden?" #: src/mainwindow.c:3754 msgid "Empty string or broken quoting" msgstr "" #: src/mainwindow.c:3755 msgid "Script must begin with a command" msgstr "" #: src/mainwindow.c:3756 msgid "Script nesting limit exceeded" msgstr "" #: src/mainwindow.c:3765 #, c-format msgid "'%s' does not match any item" msgstr "" #: src/mainwindow.c:3767 #, c-format msgid "'%s' matches a non-scriptable item" msgstr "" #: src/mainwindow.c:3769 #, c-format msgid "'%s' matches a disabled item" msgstr "" #: src/mainwindow.c:3788 #, c-format msgid "'%s' value does not fit item" msgstr "" #: src/mainwindow.c:3969 msgid "Script" msgstr "" #: src/mainwindow.c:3982 src/spawn.c:656 src/spawn.c:662 msgid "Action" msgstr "Funktion" # msgstr "Aktion" #: src/mainwindow.c:3991 src/spawn.c:666 msgid "Execute" msgstr "Ausführen" #: src/mainwindow.c:4045 msgid "Unable to load script" msgstr "" #: src/mainwindow.c:5182 msgid "/_File" msgstr "/_Datei" #: src/mainwindow.c:5184 msgid "//New" msgstr "//Neu" #: src/mainwindow.c:5186 msgid "//Open ..." msgstr "//Öffnen ..." #: src/mainwindow.c:5188 src/mainwindow.c:5669 msgid "//Save" msgstr "//Speichern" #: src/mainwindow.c:5190 src/mainwindow.c:5549 src/mainwindow.c:5627 #: src/mainwindow.c:5671 msgid "//Save As ..." msgstr "//Speichern als ..." #: src/mainwindow.c:5192 msgid "//Export Undo Images ..." msgstr "//Chronikbilder exportieren ..." #: src/mainwindow.c:5194 msgid "//Export Undo Images (reversed) ..." msgstr "//Chronikbilder exportieren (umgekehrt) ..." # msgstr "//Undo-Bilder exportieren (umgekehrt) ..." #: src/mainwindow.c:5196 msgid "//Export ASCII Art ..." msgstr "//Als ASCII-Grafik exportieren ..." #: src/mainwindow.c:5198 msgid "//Export Animated GIF ..." msgstr "//GIF-Animation exportieren ..." #: src/mainwindow.c:5201 msgid "//Actions" msgstr "//Externe Befehle" #: src/mainwindow.c:5235 src/mainwindow.c:5488 msgid "///Configure" msgstr "///Einstellen" #: src/mainwindow.c:5290 msgid "//Quit" msgstr "//Beenden" #: src/mainwindow.c:5293 msgid "/_Edit" msgstr "/_Bearbeiten" #: src/mainwindow.c:5295 msgid "//Undo" msgstr "//Rückgängig" #: src/mainwindow.c:5297 msgid "//Redo" msgstr "//Wiederherstellen" #: src/mainwindow.c:5300 msgid "//Cut" msgstr "//Ausschneiden" #: src/mainwindow.c:5302 msgid "//Copy" msgstr "//Kopieren" #: src/mainwindow.c:5304 msgid "//Copy To Palette" msgstr "//Farben in die Palette kopieren" #: src/mainwindow.c:5306 msgid "//Paste To Centre" msgstr "//Mittig einfügen" #: src/mainwindow.c:5308 msgid "//Paste To New Layer" msgstr "//In neue Ebene einfügen" #: src/mainwindow.c:5310 msgid "//Paste" msgstr "//Einfügen" #: src/mainwindow.c:5312 msgid "//Paste Text" msgstr "//Text einfügen" #: src/mainwindow.c:5318 msgid "//Paste Text (FreeType)" msgstr "//Text einfügen (FreeType)" #: src/mainwindow.c:5321 msgid "//Paste Palette" msgstr "//Palette einfügen" #: src/mainwindow.c:5323 msgid "//Load Clipboard" msgstr "//Zwischenablage laden" #: src/mainwindow.c:5350 msgid "//Save Clipboard" msgstr "//Zwischenablage speichern" #: src/mainwindow.c:5377 msgid "//Import Clipboard from System" msgstr "//Importiere aus System-Zwischenablage" #: src/mainwindow.c:5378 msgid "//Export Clipboard to System" msgstr "//Exportiere in System-Zwischenablage" #: src/mainwindow.c:5381 msgid "//Choose Pattern ..." msgstr "//Muster wählen ..." #: src/mainwindow.c:5383 msgid "//Choose Brush ..." msgstr "//Pinsel wählen ..." #: src/mainwindow.c:5385 msgid "//Choose Colour ..." msgstr "//Farbe wählen ..." #: src/mainwindow.c:5392 msgid "/_View" msgstr "/_Ansicht" #: src/mainwindow.c:5394 msgid "//Show Main Toolbar" msgstr "//Hauptleiste anzeigen" #: src/mainwindow.c:5396 msgid "//Show Tools Toolbar" msgstr "//Werkzeugleiste anzeigen" #: src/mainwindow.c:5399 msgid "//Show Settings Toolbar" msgstr "//Einstellungsleiste anzeigen" #: src/mainwindow.c:5402 msgid "//Show Dock" msgstr "//Dock anzeigen" #: src/mainwindow.c:5404 msgid "//Show Palette" msgstr "//Palette anzeigen" #: src/mainwindow.c:5406 msgid "//Show Status Bar" msgstr "//Statusleiste anzeigen" #: src/mainwindow.c:5409 msgid "//Toggle Image View" msgstr "//Bildansicht umschalten" #: src/mainwindow.c:5413 msgid "//Centralize Image" msgstr "//Bild zentrieren" #: src/mainwindow.c:5414 msgid "//Show Zoom Grid" msgstr "//Zoomgitter anzeigen" #: src/mainwindow.c:5415 msgid "//Snap To Tile Grid" msgstr "//An Gitterpunkten einrasten" #: src/mainwindow.c:5417 msgid "//Configure Grid ..." msgstr "//Gitter konfigurieren ..." #: src/mainwindow.c:5418 msgid "//Tracing Image ..." msgstr "//Bild durchpausen ..." #: src/mainwindow.c:5421 msgid "//View Window" msgstr "//Ansichtsfenster" #: src/mainwindow.c:5423 msgid "//Horizontal Split" msgstr "//Horizontal teilen" #: src/mainwindow.c:5425 msgid "//Focus View Window" msgstr "//Ansichtsfenster fokussieren" #: src/mainwindow.c:5427 msgid "//Pan Window" msgstr "//Ausschnitt verschieben" #: src/mainwindow.c:5430 msgid "//Layers Window" msgstr "//Ebenenfenster" #: src/mainwindow.c:5433 msgid "/_Image" msgstr "/B_ild" #: src/mainwindow.c:5436 msgid "//Convert To RGB" msgstr "//Umwandeln in RGB-Farbe" #: src/mainwindow.c:5438 msgid "//Convert To Indexed ..." msgstr "//Umwandeln in indizierte Farben ..." #: src/mainwindow.c:5441 msgid "//Scale Canvas ..." msgstr "//Zeichenfläche skalieren ..." #: src/mainwindow.c:5443 msgid "//Resize Canvas ..." msgstr "//Größe der Zeichenfläche ändern ..." # msgstr "Neue Größe" #: src/mainwindow.c:5445 msgid "//Crop" msgstr "//Zuschneiden" #: src/mainwindow.c:5448 src/mainwindow.c:5517 msgid "//Flip Vertically" msgstr "//Vertikal spiegeln" #: src/mainwindow.c:5449 src/mainwindow.c:5519 msgid "//Flip Horizontally" msgstr "//Horizontal spiegeln" #: src/mainwindow.c:5452 src/mainwindow.c:5521 msgid "//Rotate Clockwise" msgstr "//Im Uhrzeigersinn drehen" #: src/mainwindow.c:5453 src/mainwindow.c:5523 msgid "//Rotate Anti-Clockwise" msgstr "//Gegen Uhrzeigersinn drehen" #: src/mainwindow.c:5454 msgid "//Free Rotate ..." msgstr "//Frei drehen ..." #: src/mainwindow.c:5455 msgid "//Skew ..." msgstr "//Scheren ..." #: src/mainwindow.c:5458 msgid "//Segment ..." msgstr "//Segmentieren ..." #: src/mainwindow.c:5462 msgid "//Script ..." msgstr "" #: src/mainwindow.c:5464 msgid "//Scripts" msgstr "" #: src/mainwindow.c:5491 msgid "//Information ..." msgstr "//Informationen ..." #: src/mainwindow.c:5494 msgid "//Preferences ..." msgstr "//Einstellungen ..." #: src/mainwindow.c:5497 msgid "/_Selection" msgstr "/Au_swahl" #: src/mainwindow.c:5499 msgid "//Select All" msgstr "//Alles auswählen" #: src/mainwindow.c:5501 msgid "//Select None (Esc)" msgstr "//Nichts auswählen (Esc)" #: src/mainwindow.c:5503 msgid "//Lasso Selection" msgstr "//Lasso Auswahl" #: src/mainwindow.c:5505 msgid "//Lasso Selection Cut" msgstr "//Lasso Auswahl ausschneiden" #: src/mainwindow.c:5508 msgid "//Outline Selection" msgstr "//Auswahl umreißen" #: src/mainwindow.c:5510 msgid "//Fill Selection" msgstr "//Auswahl füllen" #: src/mainwindow.c:5512 msgid "//Outline Ellipse" msgstr "//Ellipse umreißen" #: src/mainwindow.c:5514 msgid "//Fill Ellipse" msgstr "//Ellipse füllen" #: src/mainwindow.c:5526 msgid "//Horizontal Ramp" msgstr "//Horizontaler Farbverlauf" #: src/mainwindow.c:5528 msgid "//Vertical Ramp" msgstr "//Vertikaler Farbverlauf" #: src/mainwindow.c:5531 msgid "//Alpha Blend A,B" msgstr "//Alpha mischen A,B" #: src/mainwindow.c:5533 msgid "//Move Alpha to Mask" msgstr "//Alpha in die Maske verschieben" #: src/mainwindow.c:5535 msgid "//Mask Colour A,B" msgstr "//Farbe maskieren A,B" #: src/mainwindow.c:5537 msgid "//Unmask Colour A,B" msgstr "//Farbmaske entfernen A,B" #: src/mainwindow.c:5539 msgid "//Mask All Colours" msgstr "//Alle Farben maskieren" #: src/mainwindow.c:5541 msgid "//Clear Mask" msgstr "//Maske entfernen" #: src/mainwindow.c:5544 msgid "/_Palette" msgstr "/_Palette" #: src/mainwindow.c:5548 src/mainwindow.c:5626 msgid "//Load ..." msgstr "//Laden ..." #: src/mainwindow.c:5550 msgid "//Load Default" msgstr "//Standardpalette laden" #: src/mainwindow.c:5552 msgid "//Mask All" msgstr "//Alles maskieren" #: src/mainwindow.c:5553 msgid "//Mask None" msgstr "//Nichts maskieren" #: src/mainwindow.c:5555 msgid "//Swap A & B" msgstr "//Farben A und B vertauschen" #: src/mainwindow.c:5557 msgid "//Edit Colour A & B ..." msgstr "//Farben A und B ändern ..." #: src/mainwindow.c:5559 msgid "//Dither A" msgstr "//Farbraster (Dither) A" #: src/mainwindow.c:5561 msgid "//Palette Editor ..." msgstr "//Paletteneditor ..." #: src/mainwindow.c:5563 msgid "//Set Palette Size ..." msgstr "//Palettengröße festlegen ..." #: src/mainwindow.c:5564 msgid "//Merge Duplicate Colours" msgstr "//Doppelte Farben vereinigen" # msgstr "//Doppelte Farben vereinen" #: src/mainwindow.c:5566 msgid "//Remove Unused Colours" msgstr "//Nicht benutzte Farben entfernen" # fuzzy #: src/mainwindow.c:5569 msgid "//Create Quantized ..." msgstr "//Quantisiert ..." # msgstr "//Farbreduzierte Palette berechnen ..." # msgstr "//Anzahl Farben reduzieren ..." # msgstr "//Farbreduktion berechnen ...." #: src/mainwindow.c:5572 msgid "//Sort Colours ..." msgstr "//Farben sortieren ..." # fuzzy #: src/mainwindow.c:5573 msgid "//Palette Shifter ..." msgstr "//Animation durch Farbrotation ..." # fuzzy #: src/mainwindow.c:5574 msgid "//Pick Gradient ..." msgstr "//Gradient sammeln ..." # pick: aussuchen, nehmen, sammeln #: src/mainwindow.c:5576 msgid "/Effe_cts" msgstr "/Effe_kte" #: src/mainwindow.c:5578 msgid "//Transform Colour ..." msgstr "//Farbe transformieren ..." #: src/mainwindow.c:5580 msgid "//Invert" msgstr "//Invertieren" #: src/mainwindow.c:5582 msgid "//Greyscale" msgstr "//Graustufen" #: src/mainwindow.c:5584 msgid "//Greyscale (Gamma corrected)" msgstr "//Graustufen (Gamma korrigiert)" #: src/mainwindow.c:5586 msgid "//Normalize" msgstr "//Normalisieren" #: src/mainwindow.c:5587 src/mainwindow.c:5658 msgid "//Threshold ..." msgstr "//Schwellwert ..." #: src/mainwindow.c:5588 msgid "//Map ..." msgstr "" #: src/mainwindow.c:5590 msgid "//Isometric Transformation" msgstr "//Isometrische Transformation" #: src/mainwindow.c:5592 msgid "///Left Side Down" msgstr "///Linke Seite unten" #: src/mainwindow.c:5593 msgid "///Right Side Down" msgstr "///Rechte Seite unten" #: src/mainwindow.c:5594 msgid "///Top Side Right" msgstr "///Obere Seite rechts" #: src/mainwindow.c:5595 msgid "///Bottom Side Right" msgstr "///Untere Seite rechts" #: src/mainwindow.c:5598 msgid "//Edge Detect ..." msgstr "//Kanten finden ..." #: src/mainwindow.c:5600 msgid "//Difference of Gaussians ..." msgstr "//Differenz der Normalverteilung ..." #: src/mainwindow.c:5602 msgid "//Sharpen ..." msgstr "//Schärfen ..." #: src/mainwindow.c:5604 msgid "//Unsharp Mask ..." msgstr "//Unscharf maskieren ..." #: src/mainwindow.c:5606 msgid "//Soften ..." msgstr "//Weichzeichnen ..." # msgstr "//Aufweichen ..." #: src/mainwindow.c:5608 msgid "//Gaussian Blur ..." msgstr "//Gaußscher Weichzeichner ..." #: src/mainwindow.c:5610 msgid "//Kuwahara-Nagao Blur ..." msgstr "//Kuwahara-Nagao Glättungsfilter ..." #: src/mainwindow.c:5612 msgid "//Emboss" msgstr "//Relief" #: src/mainwindow.c:5614 msgid "//Dilate" msgstr "//Erweitern" #: src/mainwindow.c:5616 msgid "//Erode" msgstr "//Erodieren" #: src/mainwindow.c:5619 msgid "//Solid Noise ..." msgstr "//Plastisches Rauschen ..." #: src/mainwindow.c:5620 msgid "//Bacteria ..." msgstr "//Bakterien ..." #: src/mainwindow.c:5623 msgid "/Cha_nnels" msgstr "/_Kanäle" #: src/mainwindow.c:5625 msgid "//New ..." msgstr "//Neu ..." #: src/mainwindow.c:5628 msgid "//Delete ..." msgstr "//Löschen ..." #: src/mainwindow.c:5632 msgid "//Edit Image" msgstr "//Bild bearbeiten" #: src/mainwindow.c:5635 msgid "//Edit Alpha" msgstr "//Alpha bearbeiten" #: src/mainwindow.c:5638 msgid "//Edit Selection" msgstr "//Auswahl bearbeiten" #: src/mainwindow.c:5641 msgid "//Edit Mask" msgstr "//Maske bearbeiten" #: src/mainwindow.c:5645 msgid "//Hide Image" msgstr "//Bild verbergen" #: src/mainwindow.c:5648 msgid "//Disable Alpha" msgstr "//Alpha ausschalten" #: src/mainwindow.c:5651 msgid "//Disable Selection" msgstr "//Auswahl ausschalten" #: src/mainwindow.c:5654 msgid "//Disable Mask" msgstr "//Maske ausschalten" #: src/mainwindow.c:5657 msgid "//Couple RGBA Operations" msgstr "//RGBA-Aktionen verbinden" #: src/mainwindow.c:5659 msgid "//Unassociate Alpha" msgstr "//Alpha Verbindung lösen" #: src/mainwindow.c:5663 msgid "//View Alpha as an Overlay" msgstr "//Alpha als Overlay anzeigen" #: src/mainwindow.c:5664 msgid "//Configure Overlays ..." msgstr "//Overlays einstellen ..." #: src/mainwindow.c:5666 msgid "/_Layers" msgstr "/_Ebenen" #: src/mainwindow.c:5668 msgid "//New Layer" msgstr "//Neue Ebene" #: src/mainwindow.c:5672 msgid "//Save Composite Image ..." msgstr "//Kompositbild speichern ..." #: src/mainwindow.c:5673 msgid "//Composite to New Layer" msgstr "//Kompositbild in neue Ebene" #: src/mainwindow.c:5674 msgid "//Remove All Layers" msgstr "//Alle Ebenen entfernen" #: src/mainwindow.c:5676 msgid "//Configure Animation ..." msgstr "//Animation zusammenfügen ..." # msgstr "//Animation einstellen ..." #: src/mainwindow.c:5677 msgid "//Preview Animation ..." msgstr "//Animationsvorschau ..." #: src/mainwindow.c:5678 msgid "//Set Key Frame ..." msgstr "//Setze Keyframe ..." #: src/mainwindow.c:5679 msgid "//Remove All Key Frames ..." msgstr "//Entferne alle Keyframes ..." #: src/mainwindow.c:5681 msgid "/More..." msgstr "/Weitere..." #: src/mainwindow.c:5683 msgid "/_Help" msgstr "/_Hilfe" #: src/mainwindow.c:5684 msgid "//Documentation" msgstr "//Dokumentation" #: src/mainwindow.c:5686 msgid "//About" msgstr "//Über" #: src/mainwindow.c:5689 msgid "//Keyboard Shortcuts ..." msgstr "//Tastenkürzel ..." #: src/mainwindow.c:5690 msgid "//Rebind Shortcut Keycodes" msgstr "//Tastenkürzel neu binden" #: src/memory.c:2800 msgid "Quantize Pass 1" msgstr "Quantisieren 1. Durchgang" #: src/memory.c:2854 msgid "Quantize Pass 2" msgstr "Quantisieren 2. Durchgang" #: src/memory.c:3073 src/memory.c:3458 msgid "Converting to Indexed Palette" msgstr "In indiziertes Bild umwandeln" #: src/memory.c:5135 src/otherwindow.c:540 msgid "Bacteria Effect" msgstr "Bakterieneffekt" #: src/memory.c:5170 msgid "Rotating" msgstr "Drehen" #: src/memory.c:5511 msgid "Free Rotation" msgstr "Frei Drehen" #: src/memory.c:6096 msgid "Scaling Image" msgstr "Bildgröße verändern" #: src/memory.c:7560 msgid "Counting Unique RGB Pixels" msgstr "Zähle verwendete RGB Farben" #: src/memory.c:7608 msgid "Applying Effect" msgstr "Wende Effekt an" #: src/memory.c:8792 msgid "Kuwahara-Nagao Filter" msgstr "Kuwahara-Nagao Filter" #: src/memory.c:10456 src/otherwindow.c:2665 msgid "Skew" msgstr "Scheren" #: src/memory.c:10630 msgid "Segmentation Pass 1" msgstr "Segmentieren 1. Durchgang" #: src/memory.c:10757 msgid "Segmentation Pass 2" msgstr "Segmentieren 2. Durchgang" #: src/memory.c:11019 src/otherwindow.c:3156 msgid "Solid Noise" msgstr "Plastisches Rauschen" #: src/mygtk.c:134 src/mygtk.c:163 msgid "Please Wait ..." msgstr "Bitte warten ..." #: src/mygtk.c:141 msgid "STOP" msgstr "STOP" #: src/mygtk.c:504 msgid "Disabled" msgstr "Deaktiviert" #: src/mygtk.c:504 src/toolbar.c:301 msgid "Screen" msgstr "Bildschirm" #: src/mygtk.c:504 msgid "Window" msgstr "Fenster" #: src/mygtk.c:508 msgid "Input" msgstr "Eingabe" #: src/mygtk.c:512 msgid "Device:" msgstr "Gerät:" #: src/mygtk.c:514 msgid "Mode:" msgstr "Modus:" #: src/mygtk.c:519 msgid "Axes" msgstr "Achsen" #: src/mygtk.c:524 msgid "X:" msgstr "" #: src/mygtk.c:525 msgid "Y:" msgstr "" #: src/mygtk.c:526 msgid "Pressure:" msgstr "Druck:" #: src/mygtk.c:527 msgid "X tilt:" msgstr "X-Neigung:" #: src/mygtk.c:528 msgid "Y tilt:" msgstr "Y-Neigung:" #: src/mygtk.c:529 msgid "Wheel:" msgstr "Rad:" #: src/mygtk.c:579 msgid "none" msgstr "keine" #: src/otherwindow.c:236 msgid "24 bit RGB" msgstr "24-Bit RGB" #: src/otherwindow.c:236 src/otherwindow.c:3179 msgid "Greyscale" msgstr "Graustufen" #: src/otherwindow.c:237 msgid "Indexed Palette" msgstr "Indizierte Palette" #: src/otherwindow.c:237 msgid "From Clipboard" msgstr "Aus der Zwischenablage" #: src/otherwindow.c:237 msgid "Grab Screenshot" msgstr "Bildschirmfoto erstellen" #: src/otherwindow.c:242 src/toolbar.c:542 msgid "New Image" msgstr "Neues Bild" #: src/otherwindow.c:246 src/otherwindow.c:3164 msgid "Colours" msgstr "Farben" #: src/otherwindow.c:409 msgid "Pattern Chooser" msgstr "Musterauswahl" #: src/otherwindow.c:497 msgid "Set Palette Size" msgstr "Palettengröße festlegen" #: src/otherwindow.c:517 src/otherwindow.c:591 src/otherwindow.c:870 #: src/otherwindow.c:2538 src/otherwindow.c:2776 src/otherwindow.c:2939 #: src/prefs.c:338 src/prefs.c:538 msgid "Apply" msgstr "Anwenden" #: src/otherwindow.c:573 msgid "Luminance" msgstr "Luminanz" #: src/otherwindow.c:573 src/otherwindow.c:814 msgid "Brightness" msgstr "Helligkeit" #: src/otherwindow.c:574 msgid "Distance to A" msgstr "Abstand zu A" #: src/otherwindow.c:575 msgid "Projection to A->B" msgstr "Projektion von A->B" #: src/otherwindow.c:576 msgid "Frequency" msgstr "Frequenz" #: src/otherwindow.c:580 msgid "Sort Palette Colours" msgstr "Palettenfarben sortieren" #: src/otherwindow.c:582 msgid "Start Index" msgstr "Startindex" #: src/otherwindow.c:583 msgid "End Index" msgstr "Endindex" #: src/otherwindow.c:589 msgid "Reverse Order" msgstr "Umgekehrte Reihenfolge" #: src/otherwindow.c:805 msgid "Bitwise" msgstr "Bitweise" #: src/otherwindow.c:805 msgid "Truncated" msgstr "Gekürzt" #: src/otherwindow.c:805 msgid "Rounded" msgstr "Gerundet" #: src/otherwindow.c:809 src/toolbar.c:311 src/toolbar.c:558 msgid "Transform Colour" msgstr "Farbe transformieren" #: src/otherwindow.c:812 msgid "Gamma" msgstr "Gamma" #: src/otherwindow.c:816 msgid "Contrast" msgstr "Kontrast" # fuzzy #: src/otherwindow.c:822 src/otherwindow.c:1674 msgid "Posterize" msgstr "Posterisieren" # msgstr "Tontrennung" # msgstr "Farbreduktion" #: src/otherwindow.c:831 msgid "Show Detail" msgstr "Zeige Details" # fuzzy #: src/otherwindow.c:836 msgid "Posterize type" msgstr "Posterisierungstyp" # msgstr "Tontrennungsmethode" # msgstr "Farbreduktionsart" #: src/otherwindow.c:857 msgid "Auto-Preview" msgstr "Auto-Vorschau" #: src/otherwindow.c:869 msgid "Reset" msgstr "Zurücksetzen" #: src/otherwindow.c:931 msgid "New geometry is the same as now - nothing to do." msgstr "Neue Geometrie entspricht der aktuellen: Nichts zu tun." #: src/otherwindow.c:980 msgid "The operating system cannot allocate the memory for this operation." msgstr "" "Das Betriebssystem kann nicht genug Speicher für diese Aktion bereitstellen." #: src/otherwindow.c:982 msgid "" "You have not allocated enough memory in the Preferences window for this " "operation." msgstr "" "Sie haben in den Einstellungen nicht genug Speicher für diese Aktion " "reserviert." #: src/otherwindow.c:993 src/otherwindow.c:2495 msgid "Mirror" msgstr "Spiegeln" #: src/otherwindow.c:993 src/otherwindow.c:994 msgid "Tile" msgstr "Kacheln" #: src/otherwindow.c:993 msgid "Void" msgstr "Leer" #: src/otherwindow.c:994 src/shifter.c:283 msgid "Clear" msgstr "Leeren" #: src/otherwindow.c:994 msgid "Mirror tile" msgstr "Gespiegelt kacheln" #: src/otherwindow.c:996 msgid "Nearest Neighbour" msgstr "Nächster Nachbar" #: src/otherwindow.c:997 msgid "Bilinear / Area Mapping" msgstr "Bilinear / Flächenzuordnung" #: src/otherwindow.c:998 msgid "Bicubic" msgstr "Bikubisch" #: src/otherwindow.c:999 msgid "Bicubic edged" msgstr "Bikubisch geschärft" #: src/otherwindow.c:1000 msgid "Bicubic better" msgstr "Bikubisch besser" #: src/otherwindow.c:1001 msgid "Bicubic sharper" msgstr "Bikubisch schärfer" #: src/otherwindow.c:1002 msgid "Blackman-Harris" msgstr "Blackman-Harris" #: src/otherwindow.c:1008 msgid "Scale Canvas" msgstr "Zeichenfläche skalieren" #: src/otherwindow.c:1009 msgid "Resize Canvas" msgstr "Größe der Zeichenfläche ändern" #: src/otherwindow.c:1012 msgid "Original " msgstr "Original " #: src/otherwindow.c:1013 msgid "New" msgstr "Neu" #: src/otherwindow.c:1014 msgid "Width " msgstr "Breite " #: src/otherwindow.c:1018 msgid "Height " msgstr "Höhe " #: src/otherwindow.c:1023 src/otherwindow.c:2514 src/otherwindow.c:2672 #: src/toolbar.c:212 msgid "Offset" msgstr "Versatz" #: src/otherwindow.c:1026 src/otherwindow.c:1615 src/viewer.c:1209 msgid "Centre" msgstr "Mitte" #: src/otherwindow.c:1033 src/otherwindow.c:1052 msgid "Fix Aspect Ratio" msgstr "Festes Seitenverhältnis" #: src/otherwindow.c:1039 src/otherwindow.c:2070 src/toolbar.c:312 msgid "Settings" msgstr "Einstellungen" #: src/otherwindow.c:1046 msgid "Sharper image reduction" msgstr "Schärferes Verkleinern" #: src/otherwindow.c:1047 msgid "Boundary extension" msgstr "Bereichserweiterung" #: src/otherwindow.c:1613 src/otherwindow.c:2302 msgid "HSV" msgstr "HSV" #: src/otherwindow.c:1614 msgid "Highlight" msgstr "Hervorheben" #: src/otherwindow.c:1615 msgid "Limit" msgstr "Grenze" #: src/otherwindow.c:1616 msgid "Sphere" msgstr "Kugel" #: src/otherwindow.c:1616 src/otherwindow.c:2670 msgid "Angle" msgstr "Winkel" #: src/otherwindow.c:1616 msgid "Cube" msgstr "Würfel" #: src/otherwindow.c:1617 msgid "Opaque" msgstr "Undurchsichtig" #: src/otherwindow.c:1617 msgid "Border" msgstr "Rand" #: src/otherwindow.c:1618 msgid "Transparent" msgstr "Transparent" #: src/otherwindow.c:1618 msgid "Tile " msgstr "Kachel" # fuzzy #: src/otherwindow.c:1618 msgid "Segment" msgstr "Segment" #: src/otherwindow.c:1656 msgid "Scale" msgstr "Skalieren" #: src/otherwindow.c:1657 src/otherwindow.c:3059 msgid "From" msgstr "Von" #: src/otherwindow.c:1659 src/otherwindow.c:3061 msgid "To" msgstr "Bis" #: src/otherwindow.c:1699 msgid "Range" msgstr "Bereich" #: src/otherwindow.c:1702 msgid "Inverse" msgstr "Invertiert" #: src/otherwindow.c:1710 msgid "Smart grid" msgstr "Aktives Gitter" #: src/otherwindow.c:1712 msgid "Tile grid" msgstr "Kachel Gitter" #: src/otherwindow.c:1714 msgid "Minimum grid zoom" msgstr "Minimaler Zoom mit Gitter" #: src/otherwindow.c:1717 msgid "Tile width" msgstr "Kachelbreite" #: src/otherwindow.c:1720 msgid "Tile height" msgstr "Kachelhöhe" #: src/otherwindow.c:1744 msgid "Palette Editor" msgstr "Paletteneditor" #: src/otherwindow.c:1763 msgid "Configure Overlays" msgstr "Overlays einstellen" #: src/otherwindow.c:1782 msgid "Colour Editor" msgstr "Farbeditor" #: src/otherwindow.c:1818 src/toolbar.c:430 msgid "Colour-Selective Mode" msgstr "Farbselektiver Modus" #: src/otherwindow.c:1843 msgid "Configure Grid" msgstr "Gitter konfigurieren" #: src/otherwindow.c:2045 msgid "Exact Conversion" msgstr "Genaue Umwandlung" #: src/otherwindow.c:2045 msgid "Use Current Palette" msgstr "Benutze aktuelle Palette" #: src/otherwindow.c:2046 msgid "PNN Quantize (slow, better quality)" msgstr "PNN Quantisierung (langsam, bessere Qualität)" #: src/otherwindow.c:2047 msgid "Wu Quantize (fast)" msgstr "Wu Quantisierung (schnell)" #: src/otherwindow.c:2048 msgid "Max-Min Quantize (best for small palettes and dithering)" msgstr "Max-Min Quantisierung (am besten für kleine Paletten und Dithering)" #: src/otherwindow.c:2049 src/otherwindow.c:2495 src/otherwindow.c:2756 #: src/png.c:2794 src/prefs.c:377 msgid "None" msgstr "Kein" #: src/otherwindow.c:2049 msgid "Floyd-Steinberg" msgstr "Floyd-Steinberg" #: src/otherwindow.c:2049 msgid "Stucki" msgstr "Stucki" #: src/otherwindow.c:2052 msgid "Floyd-Steinberg (quick)" msgstr "Floyd-Steinberg (schnell)" #: src/otherwindow.c:2052 msgid "Dithered (effect)" msgstr "Gerastert (Effekt)" #: src/otherwindow.c:2053 msgid "Scattered (effect)" msgstr "Gestreut (Effekt)" #: src/otherwindow.c:2054 msgid "Gamut" msgstr "Gamut" # de.wikipedia.org/wiki/Gamut: Tonleiter, Skala, Farbpalette; dict.cc: color garmut: Farbumfang # dict.cc Farbumfang #: src/otherwindow.c:2054 msgid "Weakly" msgstr "Schwach" #: src/otherwindow.c:2054 msgid "Strongly" msgstr "Stark" #: src/otherwindow.c:2055 msgid "Off" msgstr "Aus" #: src/otherwindow.c:2055 msgid "Separate/Sum" msgstr "Getrennt/Summe" #: src/otherwindow.c:2055 msgid "Separate/Split" msgstr "Getrennt/Aufgeteilt" #: src/otherwindow.c:2056 msgid "Length/Sum" msgstr "Länge/Summe" #: src/otherwindow.c:2056 msgid "Length/Split" msgstr "Länge/Aufgeteilt" #: src/otherwindow.c:2057 msgid "Largest (Linf)" msgstr "Größte (Linf)" # msgstr "Größte Koordinate (Linf)" #: src/otherwindow.c:2057 msgid "Sum (L1)" msgstr "Summe (L1)" #: src/otherwindow.c:2057 msgid "Euclidean (L2)" msgstr "Euklidisch (L2)" # fuzzy #: src/otherwindow.c:2061 msgid "Create Quantized" msgstr "Quantisieren" # msgstr "Farbreduzierte Palette berechnen" # msgstr "Farbreduzierte Palette erstellen" #: src/otherwindow.c:2062 msgid "Convert To Indexed" msgstr "Umwandeln in indiziertes Palettenbild" # msgstr "Bild in indizierte Farben umwandeln" # msgstr "Nach Indexed umwandeln" # Gimp: Indizierte Farbumwandlung # Photoshop: indiziert... # Corel: Palettenbild # gutes Deutsch? Kann man ein Bild in Farbe umwandeln? #: src/otherwindow.c:2065 msgid "Indexed Colours To Use" msgstr "Anzahl Palettenfarben" # "Neue Anzahl Farben" "Verwendete indexierte Farben" #: src/otherwindow.c:2078 msgid "Truncate palette" msgstr "Palette abschneiden" #: src/otherwindow.c:2079 msgid "Diameter based weighting" msgstr "Durchmesserbasierte Gewichtung" #: src/otherwindow.c:2084 msgid "Dither" msgstr "Farbrasterung (Dithering)" # Der Begriff Dithering sollte stehen bleiben weil er genau ist und für Fachleute wiedererkennbar # rastern: http://www.uni-regensburg.de/EDV/Misc/CompGrafik/Script_6.html #: src/otherwindow.c:2087 src/otherwindow.c:2584 src/otherwindow.c:2928 msgid "Colour space" msgstr "Farbraum" #: src/otherwindow.c:2088 src/otherwindow.c:2929 msgid "Difference measure" msgstr "Bestimmung des Farbunterschieds" #: src/otherwindow.c:2089 msgid "Reduce colour bleed" msgstr "Farbenüberlauf vermindern" #: src/otherwindow.c:2090 msgid "Serpentine scan" msgstr "Bild in Schlangenlinie abtasten" # msgstr "Bild im Zickzack abtasten" #: src/otherwindow.c:2092 msgid "Error propagation, %" msgstr "Fehlerfortsetzung, %" #: src/otherwindow.c:2093 msgid "Selective error propagation" msgstr "Selektive Fehlerfortsetzung" #: src/otherwindow.c:2097 msgid "Full error precision" msgstr "Volle Fehlergenauigkeit" #: src/otherwindow.c:2302 msgid "Backward HSV" msgstr "HSV umgekehrt" #: src/otherwindow.c:2303 src/otherwindow.c:2326 msgid "Constant" msgstr "Konstant" #: src/otherwindow.c:2307 msgid "Edit Gradient" msgstr "Gradient erstellen" #: src/otherwindow.c:2329 msgid "Points:" msgstr "Punkte:" #: src/otherwindow.c:2493 msgid "Linear" msgstr "Linear" #: src/otherwindow.c:2493 src/otherwindow.c:2703 msgid "Bilinear" msgstr "Bilinear" #: src/otherwindow.c:2493 msgid "Radial" msgstr "Radial" #: src/otherwindow.c:2494 msgid "Square" msgstr "Quadrat" #: src/otherwindow.c:2494 msgid "Angular" msgstr "Angular" #: src/otherwindow.c:2494 msgid "Conical" msgstr "Konisch" #: src/otherwindow.c:2495 msgid "Level " msgstr "Ebnen" #: src/otherwindow.c:2495 msgid "Repeat" msgstr "Wiederholen" #: src/otherwindow.c:2496 msgid "A to B" msgstr "A nach B" #: src/otherwindow.c:2496 msgid "A to B (RGB)" msgstr "A nach B (RGB)" #: src/otherwindow.c:2497 msgid "A to B (sRGB)" msgstr "A nach B (sRGB)" #: src/otherwindow.c:2497 msgid "A to B (HSV)" msgstr "A nach B (HSV)" #: src/otherwindow.c:2497 msgid "A to B (backward HSV)" msgstr "A nach B (HSV umgekehrt)" #: src/otherwindow.c:2498 msgid "A only" msgstr "Nur A" #: src/otherwindow.c:2498 src/otherwindow.c:2500 msgid "Custom" msgstr "Benutzerdefiniert" #: src/otherwindow.c:2499 msgid "Current to 0" msgstr "Derzeitig eingestellte bis 0" #: src/otherwindow.c:2499 msgid "Current only" msgstr "Nur derzeitig eingestellte" #: src/otherwindow.c:2504 msgid "Configure Gradient" msgstr "Gradient konfigurieren" #: src/otherwindow.c:2507 src/png.c:1001 msgid "Channel" msgstr "Farbkanal" #: src/otherwindow.c:2512 msgid "Length" msgstr "Länge" #: src/otherwindow.c:2513 msgid "Repeat length" msgstr "Wiederholungslänge" #: src/otherwindow.c:2515 msgid "Gradient type" msgstr "Gradienttyp" #: src/otherwindow.c:2516 msgid "Extension type" msgstr "Fortsetzungsart" #: src/otherwindow.c:2517 msgid "Distance type" msgstr "Abstandstyp" #: src/otherwindow.c:2518 msgid "Preview opacity" msgstr "Deckkraft der Vorschau" #: src/otherwindow.c:2527 src/otherwindow.c:2533 src/toolbar.c:309 msgid "Reverse" msgstr "Umgekehrt" #: src/otherwindow.c:2528 src/otherwindow.c:2534 msgid "Edit Custom" msgstr "Selbst erstellen" # gemeint ist so etwas wie: benutzerdefiniert bearbeiten # übersetzen: nach Maß? Eigener festlegen, bearbeiten, eigenen erstellen, Selbst festlegen #: src/otherwindow.c:2592 msgid "Pick Gradient" msgstr "Gradient auswählen" #: src/otherwindow.c:2668 msgid "Horizontal " msgstr "Horizontal " # fuzzy #: src/otherwindow.c:2674 msgid "At distance" msgstr "Im Abstand" #: src/otherwindow.c:2675 msgid "Vertical" msgstr "Vertikal" #: src/otherwindow.c:2756 msgid "Unchanged" msgstr "Unverändert" #: src/otherwindow.c:2761 msgid "Tracing Image" msgstr "Vorlage zum Pausen" #: src/otherwindow.c:2763 src/toolbar.c:315 msgid "Source" msgstr "Quelle" #: src/otherwindow.c:2768 msgid "Origin" msgstr "Ursprung" #: src/otherwindow.c:2771 msgid "Relative scale" msgstr "Relativer Maßstab" #: src/otherwindow.c:2774 msgid "Display" msgstr "Anzeigen" #: src/otherwindow.c:2926 msgid "Segment Image" msgstr "Bild segmentieren" #: src/otherwindow.c:2931 src/toolbar.c:304 msgid "Threshold" msgstr "Schwellwert" #: src/otherwindow.c:2933 msgid "Level" msgstr "Stufe" # Stufe, Grad, Niveau (Ebene?) #: src/otherwindow.c:2934 msgid "Minimum size" msgstr "Minimale Größe" #: src/otherwindow.c:3053 msgid "Max" msgstr "" #: src/otherwindow.c:3053 msgid "Min" msgstr "" #: src/otherwindow.c:3057 msgid "Threshold Image" msgstr "" #: src/otherwindow.c:3158 msgid "Seed" msgstr "" #: src/otherwindow.c:3160 msgid "X span" msgstr "" #: src/otherwindow.c:3161 msgid "Y span" msgstr "" #: src/otherwindow.c:3162 msgid "Octaves" msgstr "" #: src/png.c:620 #, c-format msgid "Saving %s image" msgstr "Speichere %s Datei" #: src/png.c:620 #, c-format msgid "Loading %s image" msgstr "Lade %s Datei" #: src/png.c:998 msgid "Layer" msgstr "Ebene" #: src/png.c:3577 msgid "Lossless" msgstr "Verlustlos" #: src/png.c:3577 msgid "Default" msgstr "" #: src/png.c:3577 msgid "Picture" msgstr "" #: src/png.c:3577 msgid "Photo" msgstr "" #: src/png.c:3578 msgid "Drawing" msgstr "" #: src/png.c:3578 msgid "Icon" msgstr "" #: src/png.c:8370 msgid "Applying colour profile" msgstr "Farbprofil wird angewendet" #: src/png.c:8792 #, c-format msgid "%d out of %d frames could not be saved as %s - saved as PNG instead" msgstr "" "%d von %d Einzelbilder konnten nicht gespeichert werden als %s - stattdessen " "als PNG gespeichert" #: src/png.c:8809 msgid "Explode frames" msgstr "In Einzelbilder zerlegen" #: src/prefs.c:56 msgid "Default System Language" msgstr "Standardsprache" #: src/prefs.c:57 msgid "Chinese (Simplified)" msgstr "Chinesisch (vereinfacht)" #: src/prefs.c:57 msgid "Chinese (Taiwanese)" msgstr "Chinesisch (Taiwan)" #: src/prefs.c:57 msgid "Czech" msgstr "Tschechisch" #: src/prefs.c:58 msgid "Dutch" msgstr "Niederländisch" #: src/prefs.c:58 msgid "English (UK)" msgstr "Englisch (UK)" #: src/prefs.c:58 msgid "French" msgstr "Französisch" #: src/prefs.c:58 msgid "Galician" msgstr "Galizisch" #: src/prefs.c:58 msgid "German" msgstr "Deutsch" #: src/prefs.c:59 msgid "Hungarian" msgstr "Ungarisch" #: src/prefs.c:59 msgid "Italian" msgstr "Italienisch" #: src/prefs.c:59 msgid "Japanese" msgstr "Japanisch" #: src/prefs.c:59 msgid "Kabyle" msgstr "" #: src/prefs.c:59 msgid "Polish" msgstr "Polnisch" #: src/prefs.c:60 msgid "Portuguese" msgstr "Portugiesisch" #: src/prefs.c:60 msgid "Portuguese (Brazilian)" msgstr "Portugiesisch (Brasilien)" #: src/prefs.c:60 msgid "Russian" msgstr "Russisch" #: src/prefs.c:60 msgid "Slovak" msgstr "Slowakisch" #: src/prefs.c:61 msgid "Spanish" msgstr "Spanisch" #: src/prefs.c:61 msgid "Swedish" msgstr "Schwedisch" #: src/prefs.c:61 msgid "Tagalog" msgstr "Tagalog" #: src/prefs.c:61 msgid "Turkish" msgstr "Türkisch" #: src/prefs.c:81 msgid "Current Device" msgstr "Aktuelles Gerät" #: src/prefs.c:135 msgid "Pressure" msgstr "Druck" #: src/prefs.c:149 msgid "Preferences" msgstr "Einstellungen" #: src/prefs.c:163 msgid "Max threads (0 to autodetect)" msgstr "Max Threads (0 für autodetect)" #: src/prefs.c:164 msgid "Min kpixels per render thread" msgstr "Min. Kilopixel pro Render-Thread" #: src/prefs.c:171 msgid "Max memory used for undo (MB)" msgstr "Max Speicher für die Chronik (MB)" # msgstr "Max Speicher f. Rückgängig Schritte (MB)" # msgstr "Max. reservierter Speicher für Undo (MB)" #: src/prefs.c:172 msgid "Max undo levels" msgstr "Max Anzahl Schritte rückgängig" #: src/prefs.c:173 msgid "Communal layer undo space (%)" msgstr "Gemeinsamer Chronikspeicher der Ebenen (%)" #: src/prefs.c:175 msgid "Bayer master pattern" msgstr "" #: src/prefs.c:178 msgid "Use gamma correction by default" msgstr "Gammakorrektur standardmäßig verwenden" #: src/prefs.c:179 msgid "Use gamma correction when painting" msgstr "Gammakorrektur beim Malen" #: src/prefs.c:180 msgid "Separate patterns for A & B" msgstr "" #: src/prefs.c:183 msgid "Optimize alpha chequers" msgstr "Alpha-Karos optimieren" #: src/prefs.c:184 msgid "Disable view window transparencies" msgstr "Transparenzen im Ansichtsfenster ausschalten" #: src/prefs.c:185 msgid "Enable overlays by layer" msgstr "Overlays für jede Ebene separat aktivieren" #: src/prefs.c:189 msgid "Language" msgstr "Sprache" #: src/prefs.c:191 msgid "" "Select preferred language translation\n" "\n" "You will need to restart mtPaint\n" "for this to take full effect" msgstr "" "Wählen Sie die Sprache\n" "\n" "Sie müssen mtPaint neu starten,\n" "damit die Änderung wirksam wird." #: src/prefs.c:198 msgid "Interface" msgstr "Benutzeroberfläche" #: src/prefs.c:200 msgid "Greyscale backdrop" msgstr "Grauwert des Hintergrunds" # msgstr "Grauwert des Hintergrunds (255=weiß)" # msgstr "Graustufen-Hintergrund" #: src/prefs.c:201 msgid "Selection nudge pixels" msgstr "Schrittweite Auswahlbox bewegen" #: src/prefs.c:202 msgid "Max Pan Window Size" msgstr "Max Breite des Verschiebefensters" # msgstr "Max Breite des Pan-Fensters" # msgstr "Maximale Größe Verschiebefenster" #: src/prefs.c:204 msgid "Display clipboard while pasting" msgstr "Zeige Zwischenablage beim Einfügen" #: src/prefs.c:205 msgid "Mouse cursor = Tool" msgstr "Mauszeiger = Werkzeugsymbol" #: src/prefs.c:206 msgid "Confirm Exit" msgstr "Beenden bestätigen" #: src/prefs.c:207 msgid "Q key quits mtPaint" msgstr "Q-Taste beendet mtPaint" #: src/prefs.c:208 msgid "Arrow keys scroll canvas" msgstr "" #: src/prefs.c:209 msgid "Changing tool commits paste" msgstr "Werkzeugwechsel bestätigt Einfügen" #: src/prefs.c:210 msgid "Centre tool settings dialogs" msgstr "Dialoge zur Werkzeugeinstellung zentrieren" #: src/prefs.c:211 msgid "New image sets zoom to 100%" msgstr "Neues Bild setzt Zoom auf 100%" #: src/prefs.c:212 msgid "Zoom on cursor position" msgstr "Zoomen an der Cursorposition" #: src/prefs.c:214 msgid "Mouse Scroll Wheel = Zoom" msgstr "Mausrad = Zoom" #: src/prefs.c:215 msgid "Use menu icons" msgstr "Verwende Piktogramme im Menü" #: src/prefs.c:220 msgid "Files" msgstr "Dateien" #: src/prefs.c:223 msgid "XBM X hotspot" msgstr "XBM Dateiformat X Hotspot" #: src/prefs.c:224 msgid "XBM Y hotspot" msgstr "XBM Dateiformat Y Hotspot" #: src/prefs.c:228 msgid "Recently Used Files" msgstr "Zuletzt benutzte Dateien" #: src/prefs.c:229 msgid "Progress bar silence limit" msgstr "Fortschrittsbalken nicht anzeigen Limit" #: src/prefs.c:232 msgid "Read 16-bit TGAs as 5:6:5 BGR" msgstr "Lese 16-Bit TGA-Dateien als 5:6:5 BGR" #: src/prefs.c:233 msgid "Write TGAs in bottom-up row order" msgstr "Schreibe TGAs mit Reihenfolge der Zeilen von unten nach oben" #: src/prefs.c:234 msgid "Undoable image loading" msgstr "Möglichkeit das Laden von Bildern rückgängig zu machen" #: src/prefs.c:245 msgid "Compression (RGB)" msgstr "Kompression (RGB)" #: src/prefs.c:246 msgid "Compression (indexed)" msgstr "Kompression (indiziert)" #: src/prefs.c:247 msgid "Compression (monochrome)" msgstr "Kompression (monochrom)" #: src/prefs.c:255 msgid "Enable predictor" msgstr "Prädiktor aktivieren" #: src/prefs.c:262 msgid "Compression mode" msgstr "" #: src/prefs.c:271 msgid "Channel for Mask Plane" msgstr "" #: src/prefs.c:273 msgid "Ignore Transparent Colour" msgstr "" #: src/prefs.c:274 msgid "PackBits Compression" msgstr "PackBits Kompression" #: src/prefs.c:275 msgid "Write Indexed as Planar Bitmap (PBM)" msgstr "" #: src/prefs.c:280 msgid "Paths" msgstr "Dateipfade" #: src/prefs.c:281 msgid "Clipboard Files" msgstr "Dateien in Zwischenablage" #: src/prefs.c:281 msgid "Select Clipboard File" msgstr "Zwischenablage speichern" #: src/prefs.c:283 msgid "HTML Browser Program" msgstr "Browser (Programm zur Anzeige von HTML)" #: src/prefs.c:283 msgid "Select Browser Program" msgstr "Browser zur Anzeige von HTML wählen" # msgstr "Programm zur Anzeige von HTML wählen (Browser) " #: src/prefs.c:285 msgid "Location of Handbook index" msgstr "Pfad für Handbuch Index" # msgstr "Ordner für Handbuch Index" #: src/prefs.c:285 msgid "Select Handbook Index File" msgstr "Index-Datei des Handbuchs wählen" #: src/prefs.c:287 msgid "Default Palette" msgstr "Standardpalette" #: src/prefs.c:287 msgid "Select Default Palette" msgstr "Wähle Standardpalette" #: src/prefs.c:289 msgid "Default Patterns" msgstr "Standardmuster" #: src/prefs.c:289 msgid "Select Default Patterns File" msgstr "Wähle Datei für Standardmuster" #: src/prefs.c:292 msgid "Default CSS" msgstr "" #: src/prefs.c:292 msgid "Select Default CSS File" msgstr "" #: src/prefs.c:295 msgid "Default Theme" msgstr "Standardthema" #: src/prefs.c:295 msgid "Select Default Theme File" msgstr "Wähle Datei für Standardthema" #: src/prefs.c:300 msgid "Status Bar" msgstr "Statusleiste" #: src/prefs.c:301 msgid "Canvas Geometry" msgstr "Zeichenflächengeometrie" #: src/prefs.c:302 msgid "Cursor X,Y" msgstr "Mauszeigerposition X,Y" #: src/prefs.c:303 msgid "Pixel [I] {RGB}" msgstr "Pixelfarbe [I] {RGB}" # msgstr "Pixelfarbe unter dem Mauszeiger [I] {RGB}" #: src/prefs.c:304 msgid "Selection Geometry" msgstr "Auswahlgeometrie" #: src/prefs.c:305 msgid "Undo / Redo" msgstr "Rückgängig / Wiederherstellen" #: src/prefs.c:308 msgid "Tablet" msgstr "Tablett" #: src/prefs.c:309 msgid "Device Settings" msgstr "Geräteeinstellungen" #: src/prefs.c:313 msgid "Configure Device" msgstr "Gerät einstellen" #: src/prefs.c:319 msgid "Tool Variable" msgstr "Werkzeugvariable" #: src/prefs.c:322 src/toolbar.c:454 msgid "Flow" msgstr "Stärke" #: src/prefs.c:330 msgid "Test Area" msgstr "Testfeld" #: src/prefs.c:373 msgid "Factor" msgstr "Faktor" #: src/prefs.c:459 msgid "This key is builtin" msgstr "" #: src/prefs.c:462 #, c-format msgid "" "This key is mapped to:\n" "\"%s\"" msgstr "" #: src/prefs.c:465 msgid "Remap" msgstr "" #: src/prefs.c:510 msgid "Keyboard Shortcuts" msgstr "" #: src/shifter.c:147 msgid "Frames" msgstr "Einzelbilder (Frames)" #: src/shifter.c:258 msgid "Palette Shifter" msgstr "Animation durch Farbrotation" #: src/shifter.c:263 msgid "Start" msgstr "Beginn" #: src/shifter.c:265 msgid "Finish" msgstr "Ende" #: src/shifter.c:284 msgid "Fix Palette" msgstr "Palette merken" #: src/spawn.c:651 msgid "Configure File Actions" msgstr "Externe Befehle einstellen" #: src/spawn.c:657 src/spawn.c:663 msgid "Command" msgstr "Befehl" #: src/spawn.c:922 #, c-format msgid "Error %i reported when trying to run %s" msgstr "Fehler %i aufgetreten beim Ausführen von %s" #: src/spawn.c:979 msgid "" "I am unable to find the documentation. Either you need to download the " "mtPaint Handbook from the web site and install it, or you need to set the " "correct location in the Preferences window." msgstr "" "Ich kann die Dokumentation nicht auffinden. Entweder laden Sie das mtPaint " "Handbuch von der Webseite http://mtpaint.sourceforge.net/handbook/ herunter " "und installieren es oder legen Sie im Einstellungen-Dialog den richtigen " "Pfad fest." #: src/spawn.c:1018 msgid "" "There was a problem running the HTML browser. You need to set the correct " "program name in the Preferences window." msgstr "" "Beim Start des HTML Browsers ist ein Fehler aufgetreten. Stellen Sie im " "Einstellungen-Dialog den richtigen Namen und Pfad ein." #: src/thread.c:361 msgid "Helper thread is not responding. Save your work and exit the program." msgstr "" "Helfer-Thread antwortet nicht. Bitte Abspeichern und das Programm beenden." #: src/toolbar.c:147 msgid "RGB Cube" msgstr "RGB-Würfel" #: src/toolbar.c:148 msgid "By image channel" msgstr "Nach Bildkanal" #: src/toolbar.c:149 msgid "Gradient-driven" msgstr "Gradienten gesteuert" #: src/toolbar.c:157 msgid "Fill settings" msgstr "Füll-Einstellungen" #: src/toolbar.c:170 msgid "Respect opacity mode" msgstr "Deckkraftmodus berücksichtigen" #: src/toolbar.c:176 msgid "Smudge settings" msgstr "Verschmieren Einstellungen" #: src/toolbar.c:215 msgid "Aligned" msgstr "Ausgerichtet" #: src/toolbar.c:222 msgid "Clone settings" msgstr "Klonen Einstellungen" #: src/toolbar.c:228 msgid "By selection channel" msgstr "" #: src/toolbar.c:234 msgid "Lasso settings" msgstr "Lasso Einstellungen" # fuzzy #: src/toolbar.c:252 msgid "Brush spacing" msgstr "Pinsel Zeichenabstand" #: src/toolbar.c:299 src/toolbar.c:341 msgid "Normal" msgstr "Normal" #: src/toolbar.c:300 msgid "Colour" msgstr "Farbe" #: src/toolbar.c:300 msgid "Saturate More" msgstr "Sättigung erhöhen" #: src/toolbar.c:301 msgid "Multiply" msgstr "Multiplikation" #: src/toolbar.c:301 msgid "Divide" msgstr "Dividieren" #: src/toolbar.c:301 msgid "Dodge" msgstr "Abwedeln" #: src/toolbar.c:302 msgid "Burn" msgstr "Nachbelichten" #: src/toolbar.c:302 msgid "Hard Light" msgstr "Harte Kanten" #: src/toolbar.c:302 msgid "Soft Light" msgstr "Weiche Kanten" #: src/toolbar.c:302 msgid "Difference" msgstr "Unterschied" #: src/toolbar.c:303 msgid "Darken" msgstr "Abdunkeln" #: src/toolbar.c:303 msgid "Lighten" msgstr "Aufhellen" #: src/toolbar.c:303 msgid "Grain Extract" msgstr "Faser extrahieren" #: src/toolbar.c:304 msgid "Grain Merge" msgstr "Faser mischen" #: src/toolbar.c:330 msgid "Blend mode" msgstr "Mischmodus" #: src/toolbar.c:417 msgid "Continuous Mode" msgstr "Kontinuierlicher Modus" #: src/toolbar.c:421 msgid "Opacity Mode" msgstr "Deckkraft-Modus" #: src/toolbar.c:424 msgid "Tint Mode" msgstr "Einfärbemodus" #: src/toolbar.c:427 msgid "Tint +-" msgstr "Einfärben +-" #: src/toolbar.c:434 msgid "Blend Mode" msgstr "Mischmodus" #: src/toolbar.c:438 msgid "Disable All Masks" msgstr "Alle Masken deaktivieren" #: src/toolbar.c:441 msgid "Gradient Mode" msgstr "Gradientmodus" #: src/toolbar.c:486 msgid "Settings Toolbar" msgstr "Einstellungsleiste" #: src/toolbar.c:546 msgid "Cut" msgstr "Ausschneiden" #: src/toolbar.c:548 msgid "Copy" msgstr "Kopieren" #: src/toolbar.c:550 msgid "Paste" msgstr "Einfügen" #: src/toolbar.c:553 msgid "Undo" msgstr "Rückgängig" #: src/toolbar.c:555 msgid "Redo" msgstr "Wiederherstellen" #: src/toolbar.c:559 src/viewer.c:328 msgid "Pan Window" msgstr "Fenster verschieben" #: src/toolbar.c:560 src/toolbar.c:640 msgid "More..." msgstr "Weiter..." #: src/toolbar.c:574 msgid "Paint" msgstr "Malen" #: src/toolbar.c:580 msgid "Shuffle" msgstr "Mischen" #: src/toolbar.c:583 msgid "Flood Fill" msgstr "Füllen" #: src/toolbar.c:587 msgid "Straight Line" msgstr "Gerade Linie" #: src/toolbar.c:590 msgid "Smudge" msgstr "Verschmieren" #: src/toolbar.c:594 msgid "Clone" msgstr "Klonen" #: src/toolbar.c:597 msgid "Make Selection" msgstr "Auswählen" #: src/toolbar.c:600 msgid "Polygon Selection" msgstr "Polygonauswahl" #: src/toolbar.c:603 msgid "Place Gradient" msgstr "Gradient platzieren" #: src/toolbar.c:606 msgid "Lasso Selection" msgstr "Lasso Auswahl" #: src/toolbar.c:614 msgid "Ellipse Outline" msgstr "Ellipsenumriss" #: src/toolbar.c:617 msgid "Filled Ellipse" msgstr "Ellipse ausgefüllt" #: src/toolbar.c:620 msgid "Outline Selection" msgstr "Auswahl umreißen" #: src/toolbar.c:623 msgid "Fill Selection" msgstr "Auswahl füllen" #: src/toolbar.c:627 msgid "Flip Selection Vertically" msgstr "Auswahl vertikal spiegeln" #: src/toolbar.c:630 msgid "Flip Selection Horizontally" msgstr "Auswahl horizontal spiegeln" #: src/toolbar.c:633 msgid "Rotate Selection Clockwise" msgstr "Auswahl rechts drehen" #: src/toolbar.c:636 msgid "Rotate Selection Anti-Clockwise" msgstr "Auswahl links drehen" #: src/vcode.c:5201 msgid "Browse" msgstr "Durchsuchen" #: src/vcode.c:7886 msgid "New key ..." msgstr "" #: src/vcode.c:9909 #, c-format msgid "'%s' does not match any widget" msgstr "" #: src/vcode.c:9910 #, c-format msgid "'%s' value does not fit '%s' widget" msgstr "" #: src/viewer.c:115 msgid "About" msgstr "Über" #: src/viewer.c:1179 msgid "No font selected" msgstr "" #: src/viewer.c:1209 msgid "Left" msgstr "Links" #: src/viewer.c:1209 msgid "Right" msgstr "Rechts" #~ msgid "" #~ "You are trying to save an XPM file with more than 4096 colours. Either " #~ "use another format or posterize the image to 4 bits, or otherwise reduce " #~ "the number of colours." #~ msgstr "" #~ "Eine XPM-Datei kann nicht mehr als 4096 Farben enthalten. Verwenden Sie " #~ "ein anderes Format oder posterisieren Sie das Bild auf 4 Bits, oder " #~ "reduzieren Sie die Anzahl der Farben auf andere Weise." #~ msgid "Create GIF frames" #~ msgstr "GIF-Frames erzeugen" #~ msgid "Store Values" #~ msgstr "Werte speichern" #~ msgid "File: %s invalid - palette not updated" #~ msgstr "Datei %s ungültig - Palette nicht aktualisiert" #~ msgid "Edit Frames" #~ msgstr "Frames Editieren" mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/po/es.po000066400000000000000000003061361471325446300215510ustar00rootroot00000000000000# Spanish translations for mtpaint package # Traducciones al espanol para el paquete mtpaint. # Copyright (C) 2005 THE mtpaint'S COPYRIGHT HOLDER # This file is distributed under the same license as the mtpaint package. # Mark Tyler, 2005. # msgid "" msgstr "" "Project-Id-Version: mtpaint 0.78\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-01-04 21:31+0200\n" "PO-Revision-Date: 2014-07-29 12:55+0000\n" "Last-Translator: Adolfo Jayme \n" "Language-Team: GALPon MiniNo \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Launchpad-Export-Date: 2020-04-05 23:36+0000\n" "X-Generator: Launchpad (build a296f04231dee355be5db73cc878b9e21689a253)\n" #: src/ani.c:647 msgid "Animation Preview" msgstr "Previsualización de la animación" #: src/ani.c:650 src/shifter.c:275 msgid "Play" msgstr "Reproducir" #: src/ani.c:654 msgid "Fix" msgstr "Fijar" #: src/ani.c:655 src/ani.c:1005 src/font.c:1624 src/font.c:1643 #: src/shifter.c:286 src/viewer.c:97 msgid "Close" msgstr "Cerrar" #: src/ani.c:709 src/ani.c:812 src/ani.c:1022 src/ani.c:1028 src/canvas.c:356 #: src/canvas.c:708 src/canvas.c:989 src/canvas.c:1353 src/canvas.c:1383 #: src/canvas.c:1470 src/canvas.c:1545 src/canvas.c:1988 src/canvas.c:1994 #: src/canvas.c:2077 src/canvas.c:2217 src/canvas.c:2240 src/font.c:1352 #: src/fpick.c:636 src/fpick.c:754 src/layer.c:524 src/layer.c:815 #: src/layer.c:970 src/mainwindow.c:341 src/mainwindow.c:370 #: src/mainwindow.c:534 src/mainwindow.c:578 src/mainwindow.c:604 #: src/mainwindow.c:3797 src/mainwindow.c:4045 src/otherwindow.c:931 #: src/otherwindow.c:980 src/otherwindow.c:982 src/prefs.c:459 src/spawn.c:924 #: src/spawn.c:978 src/spawn.c:1017 src/thread.c:360 src/vcode.c:9912 #: src/viewer.c:1161 src/viewer.c:1179 msgid "Error" msgstr "Error" #: src/ani.c:709 msgid "Unable to create output directory" msgstr "No se puede crear directorio de salida" #: src/ani.c:759 msgid "Creating Animation Frames" msgstr "Crear fotogramas de animación" #: src/ani.c:812 msgid "Unable to save image" msgstr "No se puede guardar la imagen" #: src/ani.c:840 src/canvas.c:1171 src/fpick.c:731 src/layer.c:311 #: src/layer.c:379 src/layer.c:826 src/layer.c:840 src/mainwindow.c:375 #: src/mainwindow.c:1026 src/png.c:8794 src/prefs.c:464 msgid "Warning" msgstr "Aviso" #: src/ani.c:840 msgid "" "Do you really want to clear all of the position and cycle data for all of " "the layers?" msgstr "" "¿Realmente desea limpiar todos los datos de posición y ciclo de todas las " "capas?" #: src/ani.c:841 src/fpick.c:731 src/layer.c:311 src/layer.c:842 #: src/mainwindow.c:375 msgid "No" msgstr "No" #: src/ani.c:841 src/fpick.c:731 src/layer.c:311 src/layer.c:842 #: src/mainwindow.c:375 msgid "Yes" msgstr "Sí" #: src/ani.c:954 msgid "Set Key Frame" msgstr "Establecer número de fotogramas" #: src/ani.c:961 msgid "Configure Animation" msgstr "Configurar animación" #: src/ani.c:964 msgid "Output Files" msgstr "Archivos de salida" #: src/ani.c:967 msgid "Start frame" msgstr "Fotograma inicial" #: src/ani.c:969 msgid "End frame" msgstr "Fotograma final" #: src/ani.c:971 src/shifter.c:267 msgid "Delay" msgstr "Retardo" #: src/ani.c:973 msgid "Output path" msgstr "Ruta de salida" #: src/ani.c:973 src/font.c:1637 src/spawn.c:664 msgid "Select Directory" msgstr "Seleccionar directorio" #: src/ani.c:976 msgid "File prefix" msgstr "Prefijo del archivo" #: src/ani.c:978 src/canvas.c:2096 msgid "File Format" msgstr "Formato de archivo" #: src/ani.c:982 msgid "Positions" msgstr "Posiciones" #: src/ani.c:997 msgid "Cycling" msgstr "Ciclo" #: src/ani.c:1006 msgid "Save" msgstr "Guardar" #: src/ani.c:1007 src/font.c:1577 src/otherwindow.c:868 src/otherwindow.c:1615 #: src/otherwindow.c:1728 src/otherwindow.c:2938 src/otherwindow.c:3071 #: src/otherwindow.c:3170 msgid "Preview" msgstr "Previsualizar" #: src/ani.c:1008 src/shifter.c:285 msgid "Create Frames" msgstr "Crear fotogramas" #: src/ani.c:1022 msgid "You must have at least 2 layers to create an animation" msgstr "Debe tener al menos 2 capas para crear una animación" #: src/ani.c:1028 msgid "You must save your layers file before creating an animation" msgstr "Debe guardar las capas antes de crear una animación" #: src/canvas.c:357 msgid "The image is too large to transform." msgstr "La imagen es demasiado grande para la transformación." #: src/canvas.c:393 src/canvas.c:430 src/otherwindow.c:1613 #: src/otherwindow.c:2524 src/otherwindow.c:2583 src/otherwindow.c:3179 msgid "Gradient" msgstr "Degradado" #: src/canvas.c:393 src/otherwindow.c:840 src/otherwindow.c:842 #: src/otherwindow.c:2074 src/otherwindow.c:3180 msgid "Palette" msgstr "Paleta" #: src/canvas.c:393 src/info.c:265 src/otherwindow.c:847 src/otherwindow.c:2757 #: src/otherwindow.c:3180 src/png.c:781 src/png.c:995 msgid "Clipboard" msgstr "Portapapeles" #: src/canvas.c:394 src/cpick.c:831 src/toolbar.c:299 msgid "Value" msgstr "Valor" #: src/canvas.c:394 src/cpick.c:811 src/otherwindow.c:575 src/otherwindow.c:859 #: src/otherwindow.c:3053 src/toolbar.c:318 msgid "Red" msgstr "Rojo" #: src/canvas.c:394 src/cpick.c:815 src/otherwindow.c:575 src/otherwindow.c:860 #: src/otherwindow.c:3053 src/toolbar.c:319 msgid "Green" msgstr "Verde" #: src/canvas.c:394 src/cpick.c:819 src/otherwindow.c:575 src/otherwindow.c:861 #: src/otherwindow.c:3053 src/toolbar.c:320 msgid "Blue" msgstr "Azul" #: src/canvas.c:399 msgid "From " msgstr "" #: src/canvas.c:403 msgid "To " msgstr "" #: src/canvas.c:410 msgid "Map" msgstr "" #: src/canvas.c:429 msgid "MT" msgstr "MT" #: src/canvas.c:429 msgid "Sobel" msgstr "Sobel" #: src/canvas.c:429 msgid "Prewitt" msgstr "Prewitt" #: src/canvas.c:429 msgid "Kirsch" msgstr "Kirsch" #: src/canvas.c:430 msgid "Roberts" msgstr "Roberts" #: src/canvas.c:430 msgid "Laplace" msgstr "Laplace" #: src/canvas.c:430 msgid "Morphological" msgstr "Morfológico" #: src/canvas.c:442 msgid "Edge Detect" msgstr "Detección de bordes" #: src/canvas.c:464 msgid "Edge Sharpen" msgstr "Realzado de bordes" #: src/canvas.c:472 msgid "Edge Soften" msgstr "Suavizado de bordes" #: src/canvas.c:521 msgid "Different X/Y" msgstr "Diferentes X/Y" #: src/canvas.c:522 src/canvas.c:562 src/canvas.c:603 src/canvas.c:637 #: src/canvas.c:722 src/otherwindow.c:1037 src/otherwindow.c:2685 msgid "Gamma corrected" msgstr "Gama corregida" #: src/canvas.c:530 src/memory.c:8219 msgid "Gaussian Blur" msgstr "Desenfoque gaussiano" #: src/canvas.c:558 msgid "Radius" msgstr "Radio" #: src/canvas.c:559 msgid "Amount" msgstr "Cantidad" #: src/canvas.c:560 msgid "Threshold " msgstr "Umbral " #: src/canvas.c:570 src/memory.c:8360 msgid "Unsharp Mask" msgstr "Máscara de desenfoque" #: src/canvas.c:599 msgid "Outer radius" msgstr "Radio exterior" #: src/canvas.c:600 msgid "Inner radius" msgstr "Radio interior" #: src/canvas.c:602 src/info.c:280 msgid "Normalize" msgstr "Normalizar" #: src/canvas.c:611 src/memory.c:8512 msgid "Difference of Gaussians" msgstr "Diferencia de Gauss" #: src/canvas.c:636 msgid "Protect details" msgstr "" #: src/canvas.c:645 msgid "Kuwahara-Nagao Blur" msgstr "Desenfoque Kuwahara-Nagao" #: src/canvas.c:709 msgid "The image is too large for this rotation." msgstr "La imagen es demasiado grande para la rotación." #: src/canvas.c:723 msgid "Smooth" msgstr "Suavizado" #: src/canvas.c:732 msgid "Free Rotate" msgstr "Rotación libre" #: src/canvas.c:989 src/viewer.c:1161 msgid "Not enough memory to create clipboard" msgstr "No hay suficiente memoria para crear el portapapeles" #: src/canvas.c:1172 msgid "" "You have not allocated enough memory in the Preferences window to undo this " "action." msgstr "" #: src/canvas.c:1353 msgid "Invalid palette file" msgstr "Archivo de paleta no válido" #: src/canvas.c:1383 msgid "Invalid channel file." msgstr "Archivo de canal no válido." #: src/canvas.c:1401 msgid "Raw frames" msgstr "" #: src/canvas.c:1401 msgid "Composited frames" msgstr "" #: src/canvas.c:1402 msgid "Composited frames with nonzero delay" msgstr "" #: src/canvas.c:1406 msgid "Load Frames" msgstr "Cargar fotogramas" #: src/canvas.c:1409 msgid "Load into Layers" msgstr "Cargar en capas" #: src/canvas.c:1415 msgid "Load First Frame" msgstr "Cargar primer fotograma" #: src/canvas.c:1416 msgid "Explode Frames" msgstr "" #: src/canvas.c:1418 msgid "View Animation" msgstr "Ver animación" #: src/canvas.c:1434 #, c-format msgid "This is an animated %s file." msgstr "Esto es un %s animado." #: src/canvas.c:1435 #, c-format msgid "This is a multipage %s file." msgstr "Este es un archivo %s con páginas múltiples." #: src/canvas.c:1459 #, c-format msgid "File is too big, must be <= to width=%i height=%i" msgstr "El archivo es demasiado grande, debe ser <= a anchura=%i altura=%i" #: src/canvas.c:1461 msgid "Unable to explode frames" msgstr "" #: src/canvas.c:1463 msgid "Unable to load file" msgstr "No se pudo cargar el archivo" #: src/canvas.c:1465 msgid "" "The file import library had to terminate due to a problem with the file " "(possibly corrupt image data or a truncated file). I have managed to load " "some data as the header seemed fine, but I would suggest you save this image " "to a new file to ensure this does not happen again." msgstr "" "La biblioteca de archivos importados tuvo que cerrarse debido a un problema " "con el archivo (posiblemente datos incorrectos de la imagen o un archivo " "seccionado). Se ha podido cargar alguna información, ya que la cabecera está " "correcta, pero se sugiere que guarde esta imagen a un nuevo archivo, para " "que esto no vuelva a ocurrir." #: src/canvas.c:1467 msgid "The animation is too long to load all of it into layers." msgstr "" #: src/canvas.c:1469 msgid "Could not explode all the frames in the animation." msgstr "" #: src/canvas.c:1481 src/font.c:1556 src/fpick.c:937 src/otherwindow.c:2765 #: src/prefs.c:321 src/toolbar.c:451 msgid "Size" msgstr "Tamaño" #: src/canvas.c:1484 src/otherwindow.c:244 msgid "Width" msgstr "Anchura" #: src/canvas.c:1485 src/otherwindow.c:245 msgid "Height" msgstr "Altura" #: src/canvas.c:1489 src/channels.c:253 src/channels.c:317 src/fpick.c:666 #: src/fpick.c:957 src/mainwindow.c:3990 src/otherwindow.c:255 #: src/otherwindow.c:517 src/otherwindow.c:591 src/otherwindow.c:867 #: src/otherwindow.c:1058 src/otherwindow.c:1727 src/otherwindow.c:2101 #: src/otherwindow.c:2336 src/otherwindow.c:2538 src/otherwindow.c:2691 #: src/otherwindow.c:2776 src/otherwindow.c:2937 src/otherwindow.c:3070 #: src/otherwindow.c:3169 src/prefs.c:338 src/prefs.c:464 src/prefs.c:538 #: src/spawn.c:666 src/viewer.c:1258 msgid "Cancel" msgstr "Cancelar" #: src/canvas.c:1490 src/channels.c:253 src/channels.c:317 src/fpick.c:956 #: src/info.c:297 src/mainwindow.c:3992 src/mygtk.c:233 src/mygtk.c:535 #: src/otherwindow.c:591 src/otherwindow.c:871 src/otherwindow.c:1058 #: src/otherwindow.c:1729 src/otherwindow.c:2101 src/otherwindow.c:2336 #: src/otherwindow.c:2538 src/otherwindow.c:2691 src/otherwindow.c:2776 #: src/otherwindow.c:3072 src/otherwindow.c:3171 src/prefs.c:338 #: src/prefs.c:538 src/spawn.c:666 msgid "OK" msgstr "Aceptar" #: src/canvas.c:1504 #, c-format msgid "This is a scalable %s file." msgstr "" #: src/canvas.c:1545 msgid "Cannot open file" msgstr "No se puede abrir el archivo" #: src/canvas.c:1546 msgid "Unsupported file format" msgstr "Formato de archivo no soportado" #: src/canvas.c:1673 #, c-format msgid "File: %s already exists. Do you want to overwrite it?" msgstr "El archivo: %s ya existe. ¿Desea sobreescribirlo?" #: src/canvas.c:1674 msgid "File Found" msgstr "Archivo encontrado" #: src/canvas.c:1674 src/mainwindow.c:1095 msgid "NO" msgstr "NO" #: src/canvas.c:1674 src/mainwindow.c:1095 msgid "YES" msgstr "SÃ" #: src/canvas.c:1988 msgid "Unable to export undo images" msgstr "No se pudo exportar el historial de cambios" #: src/canvas.c:1994 msgid "Unable to export ASCII file" msgstr "No se pudo exportar el archivo ASCII" #: src/canvas.c:2076 src/layer.c:814 src/mainwindow.c:529 #, c-format msgid "Unable to save file: %s" msgstr "No se pudo guardar el archivo: %s" #: src/canvas.c:2101 src/prefs.c:222 msgid "Transparency index" msgstr "Ãndice de transparencia" #: src/canvas.c:2103 msgid "TIFF Compression" msgstr "" #: src/canvas.c:2105 src/prefs.c:225 msgid "JPEG Save Quality (100=High)" msgstr "Nivel de calidad JPEG (100=Alta)" #: src/canvas.c:2107 msgid "ZIP Compression (0=None)" msgstr "" #: src/canvas.c:2108 src/prefs.c:227 msgid "PNG Compression (0=None)" msgstr "Compresión PNG (0=ninguna)" #: src/canvas.c:2111 src/prefs.c:249 msgid "LZMA2 Compression (0=None)" msgstr "" #: src/canvas.c:2113 src/prefs.c:252 msgid "ZSTD Compression Level" msgstr "" #: src/canvas.c:2115 src/prefs.c:231 msgid "TGA RLE Compression" msgstr "Compresión TGA RLE" #: src/canvas.c:2117 msgid "LBM PackBits Compression" msgstr "" #: src/canvas.c:2118 src/prefs.c:226 msgid "JPEG2000 Compression (0=Lossless)" msgstr "Compresión JPEG2000 (0=sin pérdida)" #: src/canvas.c:2120 msgid "WebP Compression" msgstr "" #: src/canvas.c:2122 msgid "WebP Save Quality (100=High)" msgstr "" #: src/canvas.c:2123 src/prefs.c:263 msgid "V8 Save Quality (100=High)" msgstr "" #: src/canvas.c:2125 src/prefs.c:264 msgid "V8L Compression (0=None)" msgstr "" #: src/canvas.c:2127 msgid "Hotspot at X =" msgstr "Punto en X =" #: src/canvas.c:2129 msgid "Y =" msgstr "Y =" #: src/canvas.c:2133 msgid "Animation delay" msgstr "Retardo para la animación" #: src/canvas.c:2136 src/otherwindow.c:253 msgid "Undoable" msgstr "Reversible" #: src/canvas.c:2138 src/prefs.c:236 msgid "Apply colour profile" msgstr "Aplicar perfil de color" #: src/canvas.c:2176 src/toolbar.c:543 msgid "Load Image File" msgstr "Cargar imagen" #: src/canvas.c:2191 src/toolbar.c:544 msgid "Save Image File" msgstr "Guardar imagen" #: src/canvas.c:2196 msgid "Load Palette File" msgstr "Cargar paleta" #: src/canvas.c:2202 msgid "Save Palette File" msgstr "Guardar paleta" #: src/canvas.c:2207 msgid "Export Undo Images" msgstr "Exportar el historial de cambios" #: src/canvas.c:2212 msgid "Export Undo Images (reversed)" msgstr "Exportar el historial de cambios (a la inversa)" #: src/canvas.c:2217 msgid "You must have 16 or fewer palette colours to export ASCII art." msgstr "" "Tiene que tener 16 colores o menos en la paleta para exportar arte ASCII." #: src/canvas.c:2220 msgid "Export ASCII Art" msgstr "Exportar arte ASCII" #: src/canvas.c:2224 msgid "Save Layer Files" msgstr "Guardar archivos de capas" #: src/canvas.c:2234 msgid "Choose frames directory" msgstr "Elegir el directorio de fotogramas" #: src/canvas.c:2240 msgid "You must save at least one frame to create an animated GIF." msgstr "Debe tener al menos un fotograma para crear un GIF animado." #: src/canvas.c:2243 msgid "Export GIF animation" msgstr "Exportar animación GIF" #: src/canvas.c:2247 msgid "Load Channel" msgstr "Cargar canal" #: src/canvas.c:2255 msgid "Save Channel" msgstr "Guardar canal" #: src/canvas.c:2260 msgid "Save Composite Image" msgstr "Guardar imagen compuesta" #: src/channels.c:243 msgid "Create Channel" msgstr "Crear canal" #: src/channels.c:244 msgid "Channel Type" msgstr "Tipo de canal" #: src/channels.c:247 msgid "Initial Channel State" msgstr "Estado inicial de canal" #: src/channels.c:251 msgid "Inverted" msgstr "Invertido" #: src/channels.c:265 msgid "Cleared" msgstr "Limpiado" #: src/channels.c:266 msgid "Set" msgstr "Establecer" #: src/channels.c:267 msgid "Set colour A radius B" msgstr "Colorear A radio B" #: src/channels.c:268 msgid "Set blend A to B" msgstr "Mezclar A en B" #: src/channels.c:269 msgid "Image Red" msgstr "Imagen roja" #: src/channels.c:270 msgid "Image Green" msgstr "Imagen verde" #: src/channels.c:271 msgid "Image Blue" msgstr "Imagen azul" #: src/channels.c:273 src/channels.c:313 src/mainwindow.c:67 #: src/otherwindow.c:1679 msgid "Alpha" msgstr "Alfa" #: src/channels.c:274 src/channels.c:314 src/mainwindow.c:67 #: src/otherwindow.c:1683 msgid "Selection" msgstr "Selección" #: src/channels.c:275 src/channels.c:315 src/mainwindow.c:67 #: src/otherwindow.c:1687 msgid "Mask" msgstr "Máscara" #: src/channels.c:312 msgid "Delete Channels" msgstr "Eliminar canales" #: src/channels.c:367 msgid "Threshold Channel" msgstr "Umbral de canal" #: src/cpick.c:823 src/otherwindow.c:573 src/otherwindow.c:820 #: src/toolbar.c:299 msgid "Hue" msgstr "Matiz" #: src/cpick.c:827 src/otherwindow.c:573 src/otherwindow.c:818 #: src/toolbar.c:299 msgid "Saturation" msgstr "Saturación" #: src/cpick.c:835 msgid "Hex" msgstr "Hex" #: src/cpick.c:840 src/layer.c:1109 src/otherwindow.c:2530 src/prefs.c:323 #: src/toolbar.c:457 msgid "Opacity" msgstr "Opacidad" #: src/font.c:982 msgid "Creating Font Index" msgstr "Creando índice de tipografías" #: src/font.c:1353 msgid "You must select at least one directory to search for fonts." msgstr "Debe seleccionar al menos un directorio para buscar tipografías." #: src/font.c:1529 src/font.c:1624 src/toolbar.c:609 src/viewer.c:1213 #: src/viewer.c:1258 msgid "Paste Text" msgstr "Pegar texto" #: src/font.c:1533 src/font.c:1572 src/png.c:3578 msgid "Text" msgstr "Texto" #: src/font.c:1540 msgid "Font" msgstr "Tipografía" #: src/font.c:1548 msgid "Style" msgstr "Estilo" #: src/font.c:1566 msgid "Filename" msgstr "Nombre de archivo" #: src/font.c:1567 msgid "Face" msgstr "Diseño" #: src/font.c:1587 src/viewer.c:1222 msgid "Antialias" msgstr "Suavizar" #: src/font.c:1590 src/viewer.c:1224 msgid "Invert" msgstr "Invertir" #: src/font.c:1593 src/viewer.c:1226 msgid "Background colour =" msgstr "Color de fondo =" #: src/font.c:1601 src/viewer.c:1233 msgid "DPI =" msgstr "" #: src/font.c:1610 msgid "Oblique" msgstr "Oblicuo" #: src/font.c:1612 src/viewer.c:1244 msgid "Angle of rotation =" msgstr "Ãngulo de rotación =" #: src/font.c:1617 src/viewer.c:1248 msgid "Align" msgstr "" #: src/font.c:1620 src/viewer.c:1253 msgid "Spacing" msgstr "" #: src/font.c:1629 msgid "Font Directories" msgstr "Directorio de tipografías" #: src/font.c:1634 src/spawn.c:664 msgid "Directory" msgstr "Directorio" #: src/font.c:1637 msgid "New Directory" msgstr "Directorio nuevo" #: src/font.c:1644 src/prefs.c:532 msgid "Add" msgstr "Añadir" #: src/font.c:1645 src/prefs.c:533 msgid "Remove" msgstr "Eliminar" #: src/font.c:1646 msgid "Create Index" msgstr "Crear índice" #: src/font.c:1660 src/viewer.c:1267 msgid "Enter Text Here" msgstr "Introduzca aquí el texto" #: src/fpick.c:635 #, c-format msgid "Could not access directory %s" msgstr "No se puede acceder al directorio %s" #: src/fpick.c:668 src/fpick.c:698 msgid "Delete" msgstr "Eliminar" #: src/fpick.c:669 src/fpick.c:698 msgid "Rename" msgstr "Renombrar" #: src/fpick.c:672 src/otherwindow.c:255 src/otherwindow.c:1666 msgid "Create" msgstr "Crear" #: src/fpick.c:699 msgid "Enter the new filename" msgstr "Introduzca el nuevo nombre de archivo" #: src/fpick.c:704 msgid "Create Directory" msgstr "Crear carpeta" #: src/fpick.c:705 msgid "Enter the name of the new directory" msgstr "Introduzca el nombre de la carpeta nueva" #: src/fpick.c:729 #, c-format msgid "Do you really want to delete \"%s\" ?" msgstr "¿Realmente desea borrar \"%s\"?" #: src/fpick.c:735 msgid "Unable to delete" msgstr "No se puede borrar" #: src/fpick.c:741 msgid "Unable to rename" msgstr "No se puede renombrar" #: src/fpick.c:750 msgid "Unable to create directory" msgstr "No se puede crear el directorio" #: src/fpick.c:924 msgid "Up" msgstr "Arriba" #: src/fpick.c:925 msgid "Home" msgstr "Inicio" #: src/fpick.c:926 msgid "Create New Directory" msgstr "Crear una carpeta nueva" #: src/fpick.c:927 msgid "Show Hidden Files" msgstr "Mostrar archivos ocultos" #: src/fpick.c:929 msgid "Case Insensitive Sort" msgstr "Ordenar por nombre (ignorar min/mayúsculas)" #: src/fpick.c:936 msgid "Name" msgstr "Nombre" #: src/fpick.c:938 msgid "Type" msgstr "Tipo" #: src/fpick.c:939 msgid "Modified" msgstr "Modificado" #: src/help.c:25 src/prefs.c:160 msgid "General" msgstr "General" #: src/help.c:26 msgid "Keyboard shortcuts" msgstr "Atajos de teclado" #: src/help.c:27 msgid "Mouse shortcuts" msgstr "Atajos de ratón" #: src/help.c:28 msgid "Credits" msgstr "Créditos" #: src/help.c:32 msgid "mtPaint 3.51 - Copyright (C) 2004-2021 The Authors\n" msgstr "mtPaint 3.51 - Copyright (C) 2004-2021 Los autores\n" #: src/help.c:33 msgid "See 'Credits' section for a list of the authors.\n" msgstr "Ver la sección de «Créditos» para el listado de autores.\n" #: src/help.c:34 msgid "" "mtPaint 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.\n" msgstr "" "mtPaint es software libre; usted puede redistribuirlo y/o modificarlo bajo " "los términos de la GNU General Public License publicada por la Free Software " "Foundation; ya sea la versión 3 de la licencia, o (a su elección) cualquier " "versión posterior.\n" #: src/help.c:35 msgid "" "mtPaint 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.\n" msgstr "" "mtPaint se distribuye con la esperanza de que sea útil, pero SIN NINGUNA " "GARANTÃA; aún sin la garantía implícita de MERCANTIBILIDAD o IDONEIDAD PARA " "UN PROPÓSITO PARTICULAR. Vea la Licencia Pública General de GNU para más " "detalles.\n" #: src/help.c:36 msgid "" "mtPaint is a simple GTK+1/2/3 painting program designed for creating icons " "and pixel based artwork. It can edit indexed palette or 24 bit RGB images " "and offers basic painting and palette manipulation tools. It also has " "several other more powerful features such as channels, layers and animation. " "Due to its simplicity and lack of dependencies it runs well on GNU/Linux, " "Windows and older PC hardware.\n" msgstr "" "mtPaint es un programa de dibujo GTK+1/2/3 sencillo diseñado para crear " "iconos y demás arte basado en píxeles. Puede editar paletas indizadas e " "imágenes RGB de 24 bits, y ofrece herramientas básicas de edición y " "manipulación de paletas. También ofrece opciones avanzadas como canales, " "capas y animación. Debido a su simplicidad carece de dependencias y se " "ejecuta bien en GNU/Linux, Windows y hardware obsoleto.\n" #: src/help.c:37 msgid "" "There is full documentation of mtPaint's features contained in a handbook. " "If you don't already have this, you can download it from the mtPaint " "website.\n" msgstr "" "Hay una extensa documentación de las características de mtPaint en un " "manual. Si no lo tiene ya, puede descargarlo del sitio web de mtPaint.\n" #: src/help.c:38 msgid "" "If you like mtPaint and you want to keep up to date with new releases, or " "you want to give some feedback, then the mailing lists may be of interest to " "you:\n" msgstr "" "Si le gusta mtPaint y quiere mantenerse informado sobre nuevas " "actualizaciones o quiere enviar algún comentario, puede que le interese la " "lista de correo:\n" #: src/help.c:39 msgid "http://sourceforge.net/mail/?group_id=155874" msgstr "http://sourceforge.net/mail/?group_id=155874" #: src/help.c:42 msgid " Ctrl-N Create new image" msgstr " Ctrl-N Crear imagen nueva" #: src/help.c:43 msgid " Ctrl-O Open Image" msgstr " Ctrl-O Abrir imagen" #: src/help.c:44 msgid " Ctrl-S Save Image" msgstr " Ctrl-S Guardar imagen" #: src/help.c:45 msgid " Ctrl-Shift-S Save layers file" msgstr " Ctrl+Mayús+S Guardar el archivo de capas" #: src/help.c:46 msgid " Ctrl-Q Quit program\n" msgstr " Ctrl+Q Salir del programa\n" #: src/help.c:47 msgid " Ctrl-A Select whole image" msgstr " Ctrl-A Seleccionar toda la imagen" #: src/help.c:48 msgid " Escape Select nothing, cancel paste box" msgstr " Escape No seleccionar nada, cancelar caja de pegado" #: src/help.c:49 msgid " J Lasso selection\n" msgstr " J Selección en lazo\n" #: src/help.c:50 msgid " Ctrl-C Copy selection to clipboard" msgstr " Ctrl+C Copiar la selección al portapapeles" #: src/help.c:51 msgid "" " Ctrl-X Copy selection to clipboard, and then paint current " "pattern to selection area" msgstr "" " Ctrl-X Copiar selección al portapapeles, y pintar el patrón " "actual al área seleccionada" #: src/help.c:52 msgid " Ctrl-V Paste clipboard to centre of current view" msgstr "" " Ctrl-V Pegar del portapapeles al centro de la vista actual" #: src/help.c:53 msgid " Ctrl-K Paste clipboard to location it was copied from" msgstr " Ctrl-K Pegar del portapapeles a sitio del que fue copiado" #: src/help.c:54 msgid " Ctrl-Shift-V Paste clipboard to new layer" msgstr "" #: src/help.c:55 msgid " Enter/Return Commit paste to canvas" msgstr " Intro Pegar en el lienzo" #: src/help.c:56 msgid " Shift+Enter/Return Commit paste and swap canvas into the clipboard\n" msgstr "" #: src/help.c:57 msgid " Arrow keys Paint Mode - Move the mouse pointer" msgstr " Teclas flecha Modo pintura - Mover el puntero del ratón" #: src/help.c:58 msgid "" " Arrow keys Selection Mode - Nudge selection box or paste box by one " "pixel" msgstr "" " Teclas flecha Modo selección - Empujar marco de selección o pegar " "de un píxel en uno" #: src/help.c:59 msgid "" " Shift+Arrow keys Nudge mouse pointer, selection box or paste box by x " "pixels - x is defined by the Preferences window" msgstr "" " Mayús+Teclas flecha Empujar marco de selección o pegar en x pixeles - x " "está definido en la ventana de preferencias" #: src/help.c:60 msgid " Ctrl+Arrows Move layer or resize selection box" msgstr " Ctrl+Teclas flecha Mover capa o redimensionar marco de selección" #: src/help.c:61 msgid " Ctrl+Shift+Arrows Move layer or resize selection box by x pixels\n" msgstr "" #: src/help.c:62 msgid " Enter/Return Paint Mode - Simulate left click" msgstr "" #: src/help.c:63 msgid " Backspace Paint Mode - Simulate right click\n" msgstr "" #: src/help.c:64 msgid "" " [ or ] Change colour A to the next or previous palette item" msgstr "" " [ o ] Cambia el color A al siguiente o al anterior en la paleta" #: src/help.c:65 msgid "" " Shift+[ or ] Change colour B to the next or previous palette item\n" msgstr "" " Mayús+[ o ] Cambia el color B al siguinte o al anterior en la " "paleta\n" #: src/help.c:66 msgid " Delete Crop image to selection" msgstr " Supr Cortar imagen a la selección" #: src/help.c:67 msgid "" " Insert Transform colours - i.e. Brightness, Contrast, " "Saturation, Posterize, Gamma" msgstr "" " Insert Transformar colores - ej. brillo, contraste, saturación, " "posterizar, gama" #: src/help.c:68 msgid " Ctrl-G Greyscale the image" msgstr " Ctrl-G Convertir la imagen a escala de grises" #: src/help.c:69 msgid " Shift-Ctrl-G Greyscale the image (Gamma corrected)" msgstr "" " Mayús-Ctrl-G Convertir la imagen a escala de grises (con gama " "corregida)" #: src/help.c:70 msgid " Ctrl+M Mirror the image" msgstr " Ctrl+M Voltear la imagen" #: src/help.c:71 msgid " Shift-Ctrl-I Invert the image\n" msgstr " Mayús+Ctrl+I Invertir la imagen\n" #: src/help.c:72 msgid "" " Ctrl-T Draw a rectangle around the selection area with the " "current fill" msgstr "" " Ctrl-T Dibujar un rectángulo alrededor del área de selección " "con el relleno actual" #: src/help.c:73 msgid " Ctrl-Shift-T Fill in the selection area with the current fill" msgstr " Ctrl-Mayús-T Llenar el área de selección con el actual relleno" #: src/help.c:74 msgid " Ctrl-L Draw an ellipse spanning the selection area" msgstr "" " Ctrl-L Dibujar una elipse atravesando el área de selección" #: src/help.c:75 msgid " Ctrl-Shift-L Draw a filled ellipse spanning the selection area\n" msgstr "" " Ctrl-Mayús-L Dibujar una elipse rellenada atravesando el área de " "selección\n" #: src/help.c:76 msgid " Ctrl-E Edit the RGB values for colours A & B" msgstr " Ctrl-E Editar los valores RGB para colores A y B" #: src/help.c:77 msgid " Ctrl-W Edit all palette colours\n" msgstr " Ctrl-W Editar toda la paleta de colores\n" #: src/help.c:78 msgid " Ctrl-P Preferences" msgstr " Ctrl-P Preferencias" #: src/help.c:79 msgid " Ctrl-I Information\n" msgstr " Ctrl-I Información\n" #: src/help.c:80 msgid " Ctrl-Z Undo last action" msgstr " Ctrl-Z Deshacer la última acción" #: src/help.c:81 msgid " Ctrl-R Redo an undone action\n" msgstr " Ctrl-R Rehacer una acción deshecha\n" #: src/help.c:82 msgid " Shift-T Text Tool (GTK+)" msgstr " Mayús+T Herramienta de texto (GTK+)" #: src/help.c:83 msgid " T Text Tool (FreeType)\n" msgstr " T Herramienta de texto (FreeType)\n" #: src/help.c:84 msgid " V View Window" msgstr " V Ventana Ver" #: src/help.c:85 msgid " L Layers Window\n" msgstr " L Ventana Capas\n" #: src/help.c:86 msgid " Ctrl-H Toggle Hide Image mode" msgstr "" #: src/help.c:87 msgid " B Toggle Snap to Tile Grid mode\n" msgstr "" #: src/help.c:88 msgid " X Swap Colours A & B" msgstr " X Intercambiar los colores A y B" #: src/help.c:89 msgid " E Choose Colour\n" msgstr " E Elegir un color\n" #: src/help.c:90 msgid "" " A Draw open arrow head when using the line tool (size set " "by flow setting)" msgstr "" " A Dibujar cabeza de flecha abierta con herramienta de línea (según el " "ajuste de tamaño de flujo)" #: src/help.c:91 msgid "" " S Draw closed arrow head when using the line tool (size " "set by flow setting)\n" msgstr "" " S Dibujar cabeza de flecha cerrada con herramienta de línea (según el " "ajuste de tamaño de flujo)\\n\n" #: src/help.c:92 msgid " D Line Tool" msgstr "" #: src/help.c:93 msgid " F Flood Fill Tool\n" msgstr "" #: src/help.c:94 msgid " +,= Main edit window - Zoom in" msgstr " +,= Zoom acercar" #: src/help.c:95 msgid " - Main edit window - Zoom out" msgstr " - Zoom alejar" #: src/help.c:96 msgid " Shift +,= View window - Zoom in" msgstr " Mayús +,= Ventana Ver - Ampliar" #: src/help.c:97 msgid " Shift - View window - Zoom out\n" msgstr " Mayús - Ventana Ver - Reducir\n" #: src/help.c:98 #, c-format msgid " 1 10% zoom" msgstr " 1 10% zoom" #: src/help.c:99 #, c-format msgid " 2 25% zoom" msgstr " 2 25% zoom" #: src/help.c:100 #, c-format msgid " 3 50% zoom" msgstr " 3 50% zoom" #: src/help.c:101 #, c-format msgid " 4 100% zoom" msgstr " 4 100% zoom" #: src/help.c:102 #, c-format msgid " 5 400% zoom" msgstr " 5 400% zoom" #: src/help.c:103 #, c-format msgid " 6 800% zoom" msgstr " 6 800% zoom" #: src/help.c:104 #, c-format msgid " 7 1200% zoom" msgstr " 7 1200% zoom" #: src/help.c:105 #, c-format msgid " 8 1600% zoom" msgstr " 8 1600% zoom" #: src/help.c:106 #, c-format msgid " 9 2000% zoom\n" msgstr " 9 2000% zoom\\n\n" #: src/help.c:107 msgid " Shift + 1 Edit image channel" msgstr " Mayús + 1 Editar canal de imagen" #: src/help.c:108 msgid " Shift + 2 Edit alpha channel" msgstr " Mayús + 2 Editar canal alfa" #: src/help.c:109 msgid " Shift + 3 Edit selection channel" msgstr " Mayús + 3 Editar canal de selección" #: src/help.c:110 msgid " Shift + 4 Edit mask channel\n" msgstr " Mayús + 4 Editar canal de máscara\n" #: src/help.c:111 msgid " F1 Help" msgstr " F1 Ayuda" #: src/help.c:112 msgid " F2 Choose Pattern" msgstr " F2 Elegir patrón" #: src/help.c:113 msgid " F3 Choose Brush" msgstr " F3 Elegir brocha" #: src/help.c:114 msgid " F4 Paint Tool" msgstr " F4 Herramienta de pintura" #: src/help.c:115 msgid " F5 Toggle Main Toolbar" msgstr " F5 Conmutar barra de herramientas principal" #: src/help.c:116 msgid " F6 Toggle Tools Toolbar" msgstr " F6 Conmutar barra de herramientas de Herramientas" #: src/help.c:117 msgid " F7 Toggle Settings Toolbar" msgstr " F7 Conmutar barra de herramientas de Preferencias" #: src/help.c:118 msgid " F8 Toggle Palette" msgstr " F8 Conmutar paleta" #: src/help.c:119 msgid " F9 Selection Tool" msgstr " F9 Herramienta de selección" #: src/help.c:120 msgid " F12 Toggle Dock Area\n" msgstr " F12 Conmutar área acoplada\n" #: src/help.c:121 msgid " Ctrl + F1 - F12 Save current clipboard to file 1-12" msgstr " Ctrl + F1 - F12 Guardar el portapapeles actual al archivo 1-12" #: src/help.c:122 msgid " Shift + F1 - F12 Load clipboard from file 1-12\n" msgstr " Mayús + F1 - F12 Cargar portapapeles desde el archivo 1-12\n" #: src/help.c:123 msgid "" " Ctrl + 1, 2, ... , 0 Set opacity to 10%, 20%, ... , 100% (main or keypad " "numbers)" msgstr "" " Ctrl + 1, 2, ... , 0 Establecer opacidad al 10%, 20%, ... , 100% (números " "de teclado principal o numérico)" #: src/help.c:124 msgid " Ctrl + + or = Increase opacity by 1" msgstr " Ctrl + + o = Incrementar la opacidad en 1" #: src/help.c:125 msgid " Ctrl + - Decrease opacity by 1\n" msgstr " Ctrl + - Disminuir la opacidad en 1\n" #: src/help.c:126 msgid "" " Home Show or hide main window menu/toolbar/status bar/palette" msgstr "" " Inicio Mostrar o esconder el menú de la ventana principal/barra " "de estado/paleta" #: src/help.c:127 msgid " Page Up Scale Image" msgstr " Re Pág Escalar imagen" #: src/help.c:128 msgid " Page Down Resize Image canvas" msgstr " Av Pág Redimensionar lienzo" #: src/help.c:129 msgid " End Pan Window" msgstr " Fin Quitar ventana" #: src/help.c:132 msgid " Left button Paint to canvas using the current tool" msgstr " Botón Izquierdo Pinta en el lienzo usando la herramienta activa" #: src/help.c:133 msgid "" " Middle button Selects the point which will be the centre of the " "image after the next zoom" msgstr " Botón central Fija el centro para el siguiente zoom" #: src/help.c:134 msgid "" " Right button Commit paste to canvas / Stop drawing current line / " "Cancel selection\n" msgstr "" " Botón Derecho Pega en el lienzo / Termina el trazado de una linea / " "Cancela una selección\n" #: src/help.c:135 msgid "" " Scroll Wheel In GTK+2/3 the user can have the scroll wheel zoom in " "or out via the Preferences window\n" msgstr "" " Rueda de Desplazamiento En GTK+2/3 el usuario puede activar el zoom con " "la rueda de desplazamiento en la ventana de preferencias\n" #: src/help.c:136 msgid " Ctrl+Left button Choose colour A from under mouse pointer" msgstr " Ctrl+Botón izquierdo Elegir color A con el ratón" #: src/help.c:137 msgid " Ctrl+Left button Clone tool - Select source" msgstr "" #: src/help.c:138 msgid "" " Ctrl+Middle button Create colour A/B and pattern based on the RGB colour " "in A (RGB images only)" msgstr "" " Ctrl+Botón central Crea color A/B y patrón de puntos basado en " "colores RGB en A (solo imágenes RGB)" #: src/help.c:139 msgid " Ctrl+Right button Choose colour B from under mouse pointer" msgstr " Ctrl+Botón derecho Elegir color B con el ratón" #: src/help.c:140 msgid "" " Ctrl+Right button Polygon tool - Delete last point / Delete nearest " "point" msgstr "" #: src/help.c:141 msgid " Ctrl+Scroll Wheel Scroll the main edit window left or right\n" msgstr "" " Ctrl+Rueda de desplazamiento Moverse en la ventana principal a la " "izquierda ou a la derecha\n" #: src/help.c:142 msgid "" " Ctrl+Double click Set colour A or B to average colour under brush " "square or selection marquee (RGB only)\n" msgstr "" " Ctrl + doble clic establece el color intermedio para A o B que esté bajo " "el pincel o la selección marcada (solo para RGB)\n" #: src/help.c:143 msgid "" " Shift+Right button Selects the point which will be the centre of the " "image after the next zoom\n" "\n" msgstr "" " Mays+Botón Derecho Fija el centro para el zoom siguiente\n" "\n" #: src/help.c:144 msgid "You can fixate the X/Y co-ordinates while moving the mouse:\n" msgstr "Puede fijar las coordenadas X/Y mientras mueve el ratón:\n" #: src/help.c:145 msgid " Shift Constrain mouse movements to vertical line" msgstr "" " Mayús Restringe los movimientos del ratón a una línea " "vertical" #: src/help.c:146 msgid " Shift+Ctrl Constrain mouse movements to horizontal line" msgstr "" " Mayús+Ctrl Restringe los movimientos del ratón a una línea " "horizontal" #: src/help.c:149 msgid "mtPaint is maintained by Dmitry Groshev.\n" msgstr "mtPaint es mantenido por Dmitry Groshev.\n" #: src/help.c:150 msgid "wjaguar@users.sourceforge.net" msgstr "wjaguar@users.sourceforge.net" #: src/help.c:151 msgid "http://mtpaint.sourceforge.net/\n" msgstr "http://mtpaint.sourceforge.net/\n" #: src/help.c:152 msgid "" "The following people (in alphabetical order) have contributed directly to " "the project, and are therefore worthy of gracious thanks for their " "generosity and hard work:\n" "\n" msgstr "" "Las siguientes personas (en orden alfabético) han contribuido directamente " "en el projecto y, por tanto, se les agradece enormemente su generosidad y " "duro trabajo:\n" "\n" #: src/help.c:153 msgid "Authors\n" msgstr "Autores\n" #: src/help.c:154 msgid "" "Dmitry Groshev - Contributing developer for version 2.30. Lead developer and " "maintainer from version 3.00 to the present." msgstr "" "Dmitry Groshev - Contribuyó como desarrollador en la versión 2.30. Principal " "desarrollador y mantenedor a partir de la versión 3.00 hasta la actualidad." #: src/help.c:155 msgid "" "Mark Tyler - Original author and maintainer up to version 3.00, occasional " "contributor thereafter." msgstr "" "Mark Tyler - Autor original y mantenedor hasta la versión 3.00, " "contribuyente ocasional desde entonces." #: src/help.c:156 msgid "" "Xiaolin Wu - Wrote the Wu quantizing method - see wu.c for more " "information.\n" "\n" msgstr "" "Xiaolin Wu - Escribió el metodo de cuantización Wu - ver wu.c para más " "información\n" "\n" #: src/help.c:157 msgid "" "General Contributions (Feedback and Ideas for improvements unless otherwise " "stated)\n" msgstr "" "Contribuciones generales (comentarios e ideas de mejora a menos que se " "indique lo contrario)\n" #: src/help.c:158 msgid "Abdulla Al Muhairi - Website redesign April 2005" msgstr "Abdulla Al Muhairi - Rediseño del sitio web, abril 2005" #: src/help.c:159 msgid "Alan Horkan" msgstr "Alan Horkan" #: src/help.c:160 msgid "Alexandre Prokoudine" msgstr "Alexandre Prokoudine" #: src/help.c:161 msgid "Antonio Andrea Bianco" msgstr "Antonio Andrea Bianco" #: src/help.c:162 msgid "Charlie Ledocq" msgstr "" #: src/help.c:163 msgid "Dennis Lee" msgstr "Dennis Lee" #: src/help.c:164 msgid "Donald White" msgstr "" #: src/help.c:165 msgid "Ed Jason" msgstr "Ed Jason" #: src/help.c:166 msgid "" "Eddie Kohler - Created Gifsicle which is needed for the creation and viewing " "of animated GIF files http://www.lcdf.org/gifsicle/" msgstr "" "Eddie Kohler - Creó Gifsicle que es necesario para la creación y " "visualización de archivos GIF animados http://www.lcdf.org/gifsicle/" #: src/help.c:167 msgid "" "Guadalinex Team (Junta de Andalucia) - man page, Launchpad/Rosetta " "registration" msgstr "" "Guadalinex Team (Junta de Andalucia) - página man, registro en Launchpad/" "Rosetta" #: src/help.c:168 msgid "Lou Afonso" msgstr "Lou Afonso" #: src/help.c:169 msgid "Magnus Hjorth" msgstr "Magnus Hjorth" #: src/help.c:170 msgid "Martin Zelaia" msgstr "Martin Zelaia" #: src/help.c:171 msgid "Pasi Kallinen" msgstr "" #: src/help.c:172 msgid "Pavel Ruzicka" msgstr "Pavel Ruzicka" #: src/help.c:173 msgid "Puppy Linux (Barry Kauler)" msgstr "Puppy Linux (Barry Kauler)" #: src/help.c:174 msgid "Victor Copovi" msgstr "" #: src/help.c:175 msgid "Vlastimil Krejcir" msgstr "Vlastimil Krejcir" #: src/help.c:176 msgid "" "William Kern\n" "\n" msgstr "" "William Kern\n" "\n" #: src/help.c:177 msgid "Translations\n" msgstr "Traducciones\n" #: src/help.c:178 msgid "Brazilian Portuguese - Paulo Trevizan, Valter Nazianzeno" msgstr "Portugues brasilero - Paulo Trevizan, Valter Nazianzeno" #: src/help.c:179 msgid "Czech - Pavel Ruzicka, Martin Petricek, Roman Hornik, Pavel Fric" msgstr "Checo - Pavel Ruzicka, Martin Petricek, Roman Hornik, Pavel Fric" #: src/help.c:180 msgid "Dutch - Hans Strijards, Pjotr" msgstr "Holandés - Hans Strijards, Pjotr" #: src/help.c:181 msgid "" "French - Nicolas Velin, Pascal Billard, Sylvain Cresto, Johan Serre, " "Philippe Etienne, Victor Copovi" msgstr "" "Francés - Nicolas Velin, Pascal Billard, Sylvain Cresto, Johan Serre, " "Philippe Etienne, Victor Copovi" #: src/help.c:182 msgid "Galician - Miguel Anxo Bouzada" msgstr "Gallego (Galicia) - Miguel Anxo Bouzada" #: src/help.c:183 msgid "German - Oliver Frommel, B. Clausius, Ulrich Ringel, Simon Brixel" msgstr "Alemán - Oliver Frommel, B. Clausius, Ulrich Ringel, Simon Brixel" #: src/help.c:184 msgid "Hungarian - Ur Balazs" msgstr "" #: src/help.c:185 msgid "Italian - Angelo Gemmi" msgstr "Italiano - Angelo Gemmi" #: src/help.c:186 msgid "Japanese - Norihiro YONEDA" msgstr "Japones - Norihiro YONEDA" #: src/help.c:187 msgid "Kabyle - Yacine Bouklif" msgstr "" #: src/help.c:188 msgid "Polish - Bartosz Kaszubowski, LucaS" msgstr "Polaco - Bartosz Kaszubowski, LucaS" #: src/help.c:189 msgid "Portuguese - Israel G. Lugo, Tiago Silva" msgstr "Portugues - Israel G. Lugo, Tiago Silva" #: src/help.c:190 msgid "Russian - Sergey Irupin, Dmitry Groshev" msgstr "Ruso - Sergey Irupin, Dmitry Groshev" #: src/help.c:191 msgid "Simplified Chinese - Cecc" msgstr "Chino simplificado - Cecc" #: src/help.c:192 msgid "Slovak - Jozef Riha" msgstr "Eslovaco - Jozef Riha" #: src/help.c:193 msgid "" "Spanish - Guadalinex Team (Junta de Andalucia), Antonio Sanchez Leon, Miguel " "Anxo Bouzada, Francisco Jose Rey, Adolfo Jayme" msgstr "" "Español - Guadalinex Team (Junta de Andalucia), Antonio Sánchez León, Miguel " "Anxo Bouzada, Francisco José Rey" #: src/help.c:194 msgid "Swedish - Daniel Nylander, Daniel Eriksson" msgstr "Sueco - Daniel Nylander, Daniel Eriksson" #: src/help.c:195 msgid "Tagalog - Anjelo delCarmen" msgstr "" #: src/help.c:196 msgid "Taiwanese Chinese - Wei-Lun Chao" msgstr "Chino Taiwanes - Wei-Lun Chao" #: src/help.c:197 msgid "Turkish - Muhammet Kara, Tutku Dalmaz" msgstr "Turco - Muhammet Kara, Tutku Dalmaz" #: src/info.c:258 msgid "Information" msgstr "Información" #: src/info.c:260 msgid "Memory" msgstr "Memoria" #: src/info.c:261 msgid "Total memory for main + undo images" msgstr "Memoria total disponible para principal + deshacer imagenes" #: src/info.c:263 msgid "Undo / Redo / Max levels used" msgstr "Deshacer / Rehacer/ Máximo número de niveles usados" #: src/info.c:265 msgid "Unused" msgstr "Sin usar" #: src/info.c:269 msgid "Unique RGB pixels" msgstr "Píxeles RGB aislados" #: src/info.c:272 src/layer.c:121 msgid "Layers" msgstr "Capas" #: src/info.c:273 msgid "Total layer memory usage" msgstr "Consumo total de memoria de la capa" #: src/info.c:277 msgid "Colour Histogram" msgstr "Histograma de color" #: src/info.c:289 src/otherwindow.c:1614 msgid "Index" msgstr "Ãndice" #: src/info.c:290 msgid "Canvas pixels" msgstr "Píxeles del lienzo" #: src/info.c:328 #, c-format msgid "Clipboard = %i x %i" msgstr "Portapapeles = %i x %i" #: src/info.c:328 #, c-format msgid "Clipboard = %i x %i x RGB" msgstr "Portapapeles = %i x %i x RGB" #: src/info.c:377 msgid "Orphans" msgstr "Huérfanos" #: src/info.c:383 #, c-format msgid "Colour index totals - %i of %i used" msgstr "Total de colores indexados - %i de %i usados" #: src/inifile.c:966 msgid "" "Could not find home directory. Using current directory as home directory." msgstr "" "No se pudo encontrar la carpeta local. Se está usando la carpeta actual como " "local." #: src/layer.c:63 msgid "Background" msgstr "Fondo" #: src/layer.c:122 src/mainwindow.c:5931 msgid "(Modified)" msgstr "(Modificado)" #: src/layer.c:123 src/mainwindow.c:5932 msgid "Untitled" msgstr "Sin título" #: src/layer.c:308 #, c-format msgid "Do you really want to delete layer %i (%s) ?" msgstr "¿Realmente desea borrar la capa %i (%s) ?" #: src/layer.c:380 msgid "" "One or more of the layers contains changes that have not been saved. Do you " "really want to lose these changes?" msgstr "" "Una o más capas contienen cambios que no se han guardado. ¿Seguro que quiere " "perder estos cambios?" #: src/layer.c:381 src/mainwindow.c:1028 msgid "Cancel Operation" msgstr "Cancelar operación" #: src/layer.c:381 src/mainwindow.c:1028 msgid "Lose Changes" msgstr "Perder los cambios" #: src/layer.c:523 #, c-format msgid "%d layers failed to load" msgstr "%d capas fallaron al cargar" #: src/layer.c:826 msgid "" "One or more of the image layers has not been saved. You must save each " "image individually before saving the layers text file in order to load this " "composite image in the future." msgstr "" "No se guardaron una o más capas de la imagen. Debe guardar cada imagen " "individualmente para cargar la imagen compuesta en el futuro." #: src/layer.c:841 msgid "Do you really want to delete all of the layers?" msgstr "¿Está seguro de que quiere borrar todas las capas?" #: src/layer.c:970 msgid "You cannot add any more layers." msgstr "No puede añadir más capas." #: src/layer.c:1083 src/otherwindow.c:241 msgid "New Layer" msgstr "Capa nueva" #: src/layer.c:1085 msgid "Raise" msgstr "Elevar" #: src/layer.c:1087 msgid "Lower" msgstr "Bajar" #: src/layer.c:1089 msgid "Duplicate Layer" msgstr "Duplicar capa" #: src/layer.c:1091 msgid "Centralise Layer" msgstr "Centrar capa" #: src/layer.c:1093 msgid "Delete Layer" msgstr "Eliminar capa" #: src/layer.c:1095 msgid "Close Layers Window" msgstr "Cerrar ventana de capas" #: src/layer.c:1101 msgid "Layer Name" msgstr "Nombre de capa" #: src/layer.c:1104 src/toolbar.c:209 msgid "Position" msgstr "Posición" #: src/layer.c:1112 msgid "Transparent Colour" msgstr "Color transparente" #: src/layer.c:1117 msgid "Show all layers in main window" msgstr "Mostrar todas las capas en la ventana principal" #: src/mainwindow.c:67 src/otherwindow.c:844 src/otherwindow.c:2756 #: src/toolbar.c:342 msgid "Image" msgstr "Imagen" #: src/mainwindow.c:69 src/mainwindow.c:489 src/otherwindow.c:1613 #: src/otherwindow.c:2302 msgid "RGB" msgstr "RGB" #: src/mainwindow.c:69 src/otherwindow.c:1613 src/otherwindow.c:2302 msgid "sRGB" msgstr "" #: src/mainwindow.c:342 msgid "There were no unused colours to remove!" msgstr "No había colores sin usar para eliminar." #: src/mainwindow.c:371 msgid "The palette does not contain 2 colours that have identical RGB values" msgstr "La paleta no contiene 2 colores que posean idénticos valores RGB" #: src/mainwindow.c:374 #, c-format msgid "" "The palette contains %i colours that have identical RGB values. Do you " "really want to merge them into one index and realign the canvas?" msgstr "" "La paleta contiene %i colores que tienen idénticos valores RGB. ¿Quiere " "fusionarlos en uno y realinear el lienzo?" #: src/mainwindow.c:492 msgid "indexed" msgstr "indexado" #: src/mainwindow.c:498 #, c-format msgid "" "You are trying to save an %s image to an %s file which is not possible. I " "would suggest you save with a PNG extension." msgstr "" "Está tratando de guardar una imagen %s en un archivo %s, lo que no es " "posible. Le sugerimos que lo guarde con la extensión PNG." #: src/mainwindow.c:500 #, c-format msgid "" "You are trying to save an %s file with a palette of more than %d colours. " "Either use another format or reduce the palette to %d colours." msgstr "" "Está tratando de guardar un archivo %s con una paleta de más de %d colores. " "Use otro formato o reduzca la paleta a %d colores." #: src/mainwindow.c:578 msgid "Unable to load clipboard" msgstr "No se pudo cargar el portapapeles" #: src/mainwindow.c:604 msgid "Unable to save clipboard" msgstr "No se pudo guardar el portapapeles" #: src/mainwindow.c:775 msgid "Zoom in" msgstr "" #: src/mainwindow.c:777 msgid "Zoom out" msgstr "" #: src/mainwindow.c:779 #, c-format msgid "10% zoom" msgstr "" #: src/mainwindow.c:781 #, c-format msgid "25% zoom" msgstr "" #: src/mainwindow.c:783 #, c-format msgid "50% zoom" msgstr "" #: src/mainwindow.c:785 #, c-format msgid "100% zoom" msgstr "" #: src/mainwindow.c:787 #, c-format msgid "400% zoom" msgstr "" #: src/mainwindow.c:789 #, c-format msgid "600% zoom" msgstr "" #: src/mainwindow.c:791 #, c-format msgid "800% zoom" msgstr "" #: src/mainwindow.c:793 #, c-format msgid "1000% zoom" msgstr "" #: src/mainwindow.c:795 #, c-format msgid "1200% zoom" msgstr "" #: src/mainwindow.c:797 #, c-format msgid "1600% zoom" msgstr "" #: src/mainwindow.c:799 #, c-format msgid "2000% zoom" msgstr "" #: src/mainwindow.c:801 #, c-format msgid "4000% zoom" msgstr "" #: src/mainwindow.c:803 #, c-format msgid "8000% zoom" msgstr "" #: src/mainwindow.c:805 #, c-format msgid "10% opacity" msgstr "" #: src/mainwindow.c:807 #, c-format msgid "20% opacity" msgstr "" #: src/mainwindow.c:809 #, c-format msgid "30% opacity" msgstr "" #: src/mainwindow.c:811 #, c-format msgid "40% opacity" msgstr "" #: src/mainwindow.c:813 #, c-format msgid "50% opacity" msgstr "" #: src/mainwindow.c:815 #, c-format msgid "60% opacity" msgstr "" #: src/mainwindow.c:817 #, c-format msgid "70% opacity" msgstr "" #: src/mainwindow.c:819 #, c-format msgid "80% opacity" msgstr "" #: src/mainwindow.c:821 #, c-format msgid "90% opacity" msgstr "" #: src/mainwindow.c:823 #, c-format msgid "100% opacity" msgstr "" #: src/mainwindow.c:825 msgid "Increase opacity" msgstr "" #: src/mainwindow.c:827 msgid "Decrease opacity" msgstr "" #: src/mainwindow.c:829 msgid "Draw open arrow head" msgstr "" #: src/mainwindow.c:831 msgid "Draw closed arrow head" msgstr "" #: src/mainwindow.c:833 msgid "Previous colour A" msgstr "" #: src/mainwindow.c:835 msgid "Next colour A" msgstr "" #: src/mainwindow.c:837 msgid "Previous colour B" msgstr "" #: src/mainwindow.c:839 msgid "Next colour B" msgstr "" #: src/mainwindow.c:841 msgid "Previous pattern" msgstr "" #: src/mainwindow.c:843 msgid "Next pattern" msgstr "" #: src/mainwindow.c:845 msgid "Larger brush" msgstr "" #: src/mainwindow.c:847 msgid "Smaller brush" msgstr "" #: src/mainwindow.c:849 msgid "View window - Zoom in" msgstr "" #: src/mainwindow.c:851 msgid "View window - Zoom out" msgstr "" #: src/mainwindow.c:1027 msgid "" "This canvas/palette contains changes that have not been saved. Do you " "really want to lose these changes?" msgstr "" "Este lienzo/paleta contiene cambios que no han sido guardados. ¿Seguro que " "quiere perderlos?" #: src/mainwindow.c:1094 msgid "Do you really want to quit?" msgstr "¿Está seguro de querer salir?" #: src/mainwindow.c:3754 msgid "Empty string or broken quoting" msgstr "" #: src/mainwindow.c:3755 msgid "Script must begin with a command" msgstr "" #: src/mainwindow.c:3756 msgid "Script nesting limit exceeded" msgstr "" #: src/mainwindow.c:3765 #, c-format msgid "'%s' does not match any item" msgstr "" #: src/mainwindow.c:3767 #, c-format msgid "'%s' matches a non-scriptable item" msgstr "" #: src/mainwindow.c:3769 #, c-format msgid "'%s' matches a disabled item" msgstr "" #: src/mainwindow.c:3788 #, c-format msgid "'%s' value does not fit item" msgstr "" #: src/mainwindow.c:3969 msgid "Script" msgstr "" #: src/mainwindow.c:3982 src/spawn.c:656 src/spawn.c:662 msgid "Action" msgstr "Acción" #: src/mainwindow.c:3991 src/spawn.c:666 msgid "Execute" msgstr "Ejecutar" #: src/mainwindow.c:4045 msgid "Unable to load script" msgstr "" #: src/mainwindow.c:5182 msgid "/_File" msgstr "/_Archivo" #: src/mainwindow.c:5184 msgid "//New" msgstr "//Nuevo" #: src/mainwindow.c:5186 msgid "//Open ..." msgstr "//Abrir ..." #: src/mainwindow.c:5188 src/mainwindow.c:5669 msgid "//Save" msgstr "//Guardar" #: src/mainwindow.c:5190 src/mainwindow.c:5549 src/mainwindow.c:5627 #: src/mainwindow.c:5671 msgid "//Save As ..." msgstr "//Guardar como ..." #: src/mainwindow.c:5192 msgid "//Export Undo Images ..." msgstr "//Exportar el historial de imágenes ..." #: src/mainwindow.c:5194 msgid "//Export Undo Images (reversed) ..." msgstr "//Exportar el historial de imágenes (a la inversa) ..." #: src/mainwindow.c:5196 msgid "//Export ASCII Art ..." msgstr "//Exportar arte ASCII ..." #: src/mainwindow.c:5198 msgid "//Export Animated GIF ..." msgstr "//Exportar GIF animado ..." #: src/mainwindow.c:5201 msgid "//Actions" msgstr "//Acciones" #: src/mainwindow.c:5235 src/mainwindow.c:5488 msgid "///Configure" msgstr "///Configurar" #: src/mainwindow.c:5290 msgid "//Quit" msgstr "//Salir" #: src/mainwindow.c:5293 msgid "/_Edit" msgstr "/_Editar" #: src/mainwindow.c:5295 msgid "//Undo" msgstr "//Deshacer" #: src/mainwindow.c:5297 msgid "//Redo" msgstr "//Rehacer" #: src/mainwindow.c:5300 msgid "//Cut" msgstr "//Cortar" #: src/mainwindow.c:5302 msgid "//Copy" msgstr "//Copiar" #: src/mainwindow.c:5304 msgid "//Copy To Palette" msgstr "//Copiar a la paleta" #: src/mainwindow.c:5306 msgid "//Paste To Centre" msgstr "//Pegar en el centro" #: src/mainwindow.c:5308 msgid "//Paste To New Layer" msgstr "//Pegar en una nueva capa" #: src/mainwindow.c:5310 msgid "//Paste" msgstr "//Pegar" #: src/mainwindow.c:5312 msgid "//Paste Text" msgstr "//Pegar Texto" #: src/mainwindow.c:5318 msgid "//Paste Text (FreeType)" msgstr "//Pegar texto (FreeType)" #: src/mainwindow.c:5321 msgid "//Paste Palette" msgstr "//Pegar paleta" #: src/mainwindow.c:5323 msgid "//Load Clipboard" msgstr "//Cargar portapapeles" #: src/mainwindow.c:5350 msgid "//Save Clipboard" msgstr "//Guardar portapapeles" #: src/mainwindow.c:5377 msgid "//Import Clipboard from System" msgstr "//Importar de portapapeles del sistema" #: src/mainwindow.c:5378 msgid "//Export Clipboard to System" msgstr "//Exportar al portapapeles del sistema" #: src/mainwindow.c:5381 msgid "//Choose Pattern ..." msgstr "//Escoger patrón ..." #: src/mainwindow.c:5383 msgid "//Choose Brush ..." msgstr "//Escoger brocha ..." #: src/mainwindow.c:5385 msgid "//Choose Colour ..." msgstr "" #: src/mainwindow.c:5392 msgid "/_View" msgstr "/_Ver" #: src/mainwindow.c:5394 msgid "//Show Main Toolbar" msgstr "//Mostrar barra de herramientas principal" #: src/mainwindow.c:5396 msgid "//Show Tools Toolbar" msgstr "//Mostrar barra de herramientas" #: src/mainwindow.c:5399 msgid "//Show Settings Toolbar" msgstr "//Mostrar barra de preferencias" #: src/mainwindow.c:5402 msgid "//Show Dock" msgstr "//Mostrar acoplamiento" #: src/mainwindow.c:5404 msgid "//Show Palette" msgstr "//Mostrar paleta" #: src/mainwindow.c:5406 msgid "//Show Status Bar" msgstr "//Mostrar barra de estado" #: src/mainwindow.c:5409 msgid "//Toggle Image View" msgstr "//Cambiar a vista completa" #: src/mainwindow.c:5413 msgid "//Centralize Image" msgstr "//Centrar imagen" #: src/mainwindow.c:5414 msgid "//Show Zoom Grid" msgstr "//Mostrar rejilla de ampliación" #: src/mainwindow.c:5415 msgid "//Snap To Tile Grid" msgstr "" #: src/mainwindow.c:5417 msgid "//Configure Grid ..." msgstr "//Configurar rejilla ..." #: src/mainwindow.c:5418 msgid "//Tracing Image ..." msgstr "//Trazado de imagen ..." #: src/mainwindow.c:5421 msgid "//View Window" msgstr "//Ver ventana" #: src/mainwindow.c:5423 msgid "//Horizontal Split" msgstr "//Dividir en horizontal" #: src/mainwindow.c:5425 msgid "//Focus View Window" msgstr "//Ver ventana en foco" #: src/mainwindow.c:5427 msgid "//Pan Window" msgstr "//Vista reducida" #: src/mainwindow.c:5430 msgid "//Layers Window" msgstr "//Ventana de capas" #: src/mainwindow.c:5433 msgid "/_Image" msgstr "/_Imagen" #: src/mainwindow.c:5436 msgid "//Convert To RGB" msgstr "//Convertir a RGB" #: src/mainwindow.c:5438 msgid "//Convert To Indexed ..." msgstr "//Convertir a indexado ..." #: src/mainwindow.c:5441 msgid "//Scale Canvas ..." msgstr "//Escalar lienzo ..." #: src/mainwindow.c:5443 msgid "//Resize Canvas ..." msgstr "//Redimensionar lienzo ..." #: src/mainwindow.c:5445 msgid "//Crop" msgstr "//Recortar" #: src/mainwindow.c:5448 src/mainwindow.c:5517 msgid "//Flip Vertically" msgstr "//Voltear verticalmente" #: src/mainwindow.c:5449 src/mainwindow.c:5519 msgid "//Flip Horizontally" msgstr "//Voltear horizontalmente" #: src/mainwindow.c:5452 src/mainwindow.c:5521 msgid "//Rotate Clockwise" msgstr "//Rotar en sentido horario" #: src/mainwindow.c:5453 src/mainwindow.c:5523 msgid "//Rotate Anti-Clockwise" msgstr "//Rotar en sentido anti horario" #: src/mainwindow.c:5454 msgid "//Free Rotate ..." msgstr "//Rotar libremente ..." #: src/mainwindow.c:5455 msgid "//Skew ..." msgstr "//Inclinar ..." #: src/mainwindow.c:5458 msgid "//Segment ..." msgstr "" #: src/mainwindow.c:5462 msgid "//Script ..." msgstr "" #: src/mainwindow.c:5464 msgid "//Scripts" msgstr "" #: src/mainwindow.c:5491 msgid "//Information ..." msgstr "//Información ..." #: src/mainwindow.c:5494 msgid "//Preferences ..." msgstr "//Preferencias ..." #: src/mainwindow.c:5497 msgid "/_Selection" msgstr "/_Selección" #: src/mainwindow.c:5499 msgid "//Select All" msgstr "//Seleccionar todo" #: src/mainwindow.c:5501 msgid "//Select None (Esc)" msgstr "//Eliminar selección (Esc)" #: src/mainwindow.c:5503 msgid "//Lasso Selection" msgstr "//Selección de lazo" #: src/mainwindow.c:5505 msgid "//Lasso Selection Cut" msgstr "//Cortar selección de lazo" #: src/mainwindow.c:5508 msgid "//Outline Selection" msgstr "//Contorno de selección" #: src/mainwindow.c:5510 msgid "//Fill Selection" msgstr "//Llenar selección" #: src/mainwindow.c:5512 msgid "//Outline Ellipse" msgstr "//Contorno de elipse" #: src/mainwindow.c:5514 msgid "//Fill Ellipse" msgstr "//Rellenar elipse" #: src/mainwindow.c:5526 msgid "//Horizontal Ramp" msgstr "//Rampa horizontal" #: src/mainwindow.c:5528 msgid "//Vertical Ramp" msgstr "//Rampa vertical" #: src/mainwindow.c:5531 msgid "//Alpha Blend A,B" msgstr "//Mezclar alfa A,B" #: src/mainwindow.c:5533 msgid "//Move Alpha to Mask" msgstr "//Mover alfa a máscara" #: src/mainwindow.c:5535 msgid "//Mask Colour A,B" msgstr "//Enmascarar colores A,B" #: src/mainwindow.c:5537 msgid "//Unmask Colour A,B" msgstr "//Desenmascarar colores A,B" #: src/mainwindow.c:5539 msgid "//Mask All Colours" msgstr "//Enmascarar todos los colores" #: src/mainwindow.c:5541 msgid "//Clear Mask" msgstr "//Limpiar máscara" #: src/mainwindow.c:5544 msgid "/_Palette" msgstr "/_Paleta" #: src/mainwindow.c:5548 src/mainwindow.c:5626 msgid "//Load ..." msgstr "//Cargar ..." #: src/mainwindow.c:5550 msgid "//Load Default" msgstr "//Cargar valores por defecto" #: src/mainwindow.c:5552 msgid "//Mask All" msgstr "//Enmascarar todo" #: src/mainwindow.c:5553 msgid "//Mask None" msgstr "//No enmascarar nada" #: src/mainwindow.c:5555 msgid "//Swap A & B" msgstr "//Intercambiar A y B" #: src/mainwindow.c:5557 msgid "//Edit Colour A & B ..." msgstr "//Editar colores A y B ..." #: src/mainwindow.c:5559 msgid "//Dither A" msgstr "" #: src/mainwindow.c:5561 msgid "//Palette Editor ..." msgstr "//Editar paleta ..." #: src/mainwindow.c:5563 msgid "//Set Palette Size ..." msgstr "//Establecer el tamaño de la paleta ..." #: src/mainwindow.c:5564 msgid "//Merge Duplicate Colours" msgstr "//Fusionar Duplicar colores" #: src/mainwindow.c:5566 msgid "//Remove Unused Colours" msgstr "//Eliminar colores no usados" #: src/mainwindow.c:5569 msgid "//Create Quantized ..." msgstr "//Crear cuantificado ..." #: src/mainwindow.c:5572 msgid "//Sort Colours ..." msgstr "//Listar colores ..." #: src/mainwindow.c:5573 msgid "//Palette Shifter ..." msgstr "//Paleta «Shifter» ..." #: src/mainwindow.c:5574 msgid "//Pick Gradient ..." msgstr "" #: src/mainwindow.c:5576 msgid "/Effe_cts" msgstr "/Efe_ctos" #: src/mainwindow.c:5578 msgid "//Transform Colour ..." msgstr "//Transformar color ..." #: src/mainwindow.c:5580 msgid "//Invert" msgstr "//Invertir" #: src/mainwindow.c:5582 msgid "//Greyscale" msgstr "//Escala de grises" #: src/mainwindow.c:5584 msgid "//Greyscale (Gamma corrected)" msgstr "//Escala de grises (Gama corregida)" #: src/mainwindow.c:5586 msgid "//Normalize" msgstr "" #: src/mainwindow.c:5587 src/mainwindow.c:5658 msgid "//Threshold ..." msgstr "//Umbral ..." #: src/mainwindow.c:5588 msgid "//Map ..." msgstr "" #: src/mainwindow.c:5590 msgid "//Isometric Transformation" msgstr "//Transformación isométrica" #: src/mainwindow.c:5592 msgid "///Left Side Down" msgstr "///hacia abajo lado izquierdo" #: src/mainwindow.c:5593 msgid "///Right Side Down" msgstr "///hacia abajo lado derecho" #: src/mainwindow.c:5594 msgid "///Top Side Right" msgstr "///hacia la derecha parte superior" #: src/mainwindow.c:5595 msgid "///Bottom Side Right" msgstr "///hacia la derecha parte inferior" #: src/mainwindow.c:5598 msgid "//Edge Detect ..." msgstr "//Detección de bordes ..." #: src/mainwindow.c:5600 msgid "//Difference of Gaussians ..." msgstr "//Diferencia de Gauss ..." #: src/mainwindow.c:5602 msgid "//Sharpen ..." msgstr "//Remarcado ..." #: src/mainwindow.c:5604 msgid "//Unsharp Mask ..." msgstr "//Máscara de desenfoque ..." #: src/mainwindow.c:5606 msgid "//Soften ..." msgstr "//Suavizado ..." #: src/mainwindow.c:5608 msgid "//Gaussian Blur ..." msgstr "//Suavizado Gaussiano ..." #: src/mainwindow.c:5610 msgid "//Kuwahara-Nagao Blur ..." msgstr "//Difuminado Kuwahara-Nagao ..." #: src/mainwindow.c:5612 msgid "//Emboss" msgstr "//Realce" #: src/mainwindow.c:5614 msgid "//Dilate" msgstr "//Dilatar" #: src/mainwindow.c:5616 msgid "//Erode" msgstr "//Erosionar" #: src/mainwindow.c:5619 msgid "//Solid Noise ..." msgstr "" #: src/mainwindow.c:5620 msgid "//Bacteria ..." msgstr "//«Bacteria» ..." #: src/mainwindow.c:5623 msgid "/Cha_nnels" msgstr "/Canales" #: src/mainwindow.c:5625 msgid "//New ..." msgstr "//Nuevo ..." #: src/mainwindow.c:5628 msgid "//Delete ..." msgstr "//Eliminar ..." #: src/mainwindow.c:5632 msgid "//Edit Image" msgstr "//Editar imagen" #: src/mainwindow.c:5635 msgid "//Edit Alpha" msgstr "//Editar alfa" #: src/mainwindow.c:5638 msgid "//Edit Selection" msgstr "//Editar selección" #: src/mainwindow.c:5641 msgid "//Edit Mask" msgstr "//Editar máscara" #: src/mainwindow.c:5645 msgid "//Hide Image" msgstr "//Esconder imagen" #: src/mainwindow.c:5648 msgid "//Disable Alpha" msgstr "//Deshabilitar alfa" #: src/mainwindow.c:5651 msgid "//Disable Selection" msgstr "//Deshabilitar selección" #: src/mainwindow.c:5654 msgid "//Disable Mask" msgstr "//Deshabilitar máscara" #: src/mainwindow.c:5657 msgid "//Couple RGBA Operations" msgstr "//Unir operaciones RGBA" #: src/mainwindow.c:5659 msgid "//Unassociate Alpha" msgstr "//Disociar alfa" #: src/mainwindow.c:5663 msgid "//View Alpha as an Overlay" msgstr "//Ver alfa como un revestimiento" #: src/mainwindow.c:5664 msgid "//Configure Overlays ..." msgstr "//Configurar revestimientos ..." #: src/mainwindow.c:5666 msgid "/_Layers" msgstr "/Capas" #: src/mainwindow.c:5668 msgid "//New Layer" msgstr "//Nueva capa" #: src/mainwindow.c:5672 msgid "//Save Composite Image ..." msgstr "//Guardar imagen compuesta ..." #: src/mainwindow.c:5673 msgid "//Composite to New Layer" msgstr "//Componer en una capa nueva" #: src/mainwindow.c:5674 msgid "//Remove All Layers" msgstr "//Borrar todas las capas" #: src/mainwindow.c:5676 msgid "//Configure Animation ..." msgstr "//Configurar animación ..." #: src/mainwindow.c:5677 msgid "//Preview Animation ..." msgstr "//Vista previa de animación ..." #: src/mainwindow.c:5678 msgid "//Set Key Frame ..." msgstr "//Establecer número de fotogramas ..." #: src/mainwindow.c:5679 msgid "//Remove All Key Frames ..." msgstr "//Borrar todos los fotogramas ..." #: src/mainwindow.c:5681 msgid "/More..." msgstr "/Más" #: src/mainwindow.c:5683 msgid "/_Help" msgstr "/_Ayuda" #: src/mainwindow.c:5684 msgid "//Documentation" msgstr "//Documentación" #: src/mainwindow.c:5686 msgid "//About" msgstr "//Acerca de" #: src/mainwindow.c:5689 msgid "//Keyboard Shortcuts ..." msgstr "" #: src/mainwindow.c:5690 msgid "//Rebind Shortcut Keycodes" msgstr "//Vincular teclas de acceso rápido" #: src/memory.c:2800 msgid "Quantize Pass 1" msgstr "" #: src/memory.c:2854 msgid "Quantize Pass 2" msgstr "" #: src/memory.c:3073 src/memory.c:3458 msgid "Converting to Indexed Palette" msgstr "Convertir a paleta indexada" #: src/memory.c:5135 src/otherwindow.c:540 msgid "Bacteria Effect" msgstr "Efecto «bacteria»" #: src/memory.c:5170 msgid "Rotating" msgstr "Rotando" #: src/memory.c:5511 msgid "Free Rotation" msgstr "Rotación libre" #: src/memory.c:6096 msgid "Scaling Image" msgstr "Escalando la imagen" #: src/memory.c:7560 msgid "Counting Unique RGB Pixels" msgstr "Contando pixeles RGB únicos" #: src/memory.c:7608 msgid "Applying Effect" msgstr "Aplicando efecto" #: src/memory.c:8792 msgid "Kuwahara-Nagao Filter" msgstr "Filtro Kuwahara-Nagao" #: src/memory.c:10456 src/otherwindow.c:2665 msgid "Skew" msgstr "Inclinar" #: src/memory.c:10630 msgid "Segmentation Pass 1" msgstr "" #: src/memory.c:10757 msgid "Segmentation Pass 2" msgstr "" #: src/memory.c:11019 src/otherwindow.c:3156 msgid "Solid Noise" msgstr "" #: src/mygtk.c:134 src/mygtk.c:163 msgid "Please Wait ..." msgstr "Espere por favor ..." #: src/mygtk.c:141 msgid "STOP" msgstr "STOP" #: src/mygtk.c:504 msgid "Disabled" msgstr "" #: src/mygtk.c:504 src/toolbar.c:301 msgid "Screen" msgstr "Pantalla" #: src/mygtk.c:504 msgid "Window" msgstr "" #: src/mygtk.c:508 msgid "Input" msgstr "" #: src/mygtk.c:512 msgid "Device:" msgstr "" #: src/mygtk.c:514 msgid "Mode:" msgstr "" #: src/mygtk.c:519 msgid "Axes" msgstr "" #: src/mygtk.c:524 msgid "X:" msgstr "" #: src/mygtk.c:525 msgid "Y:" msgstr "" #: src/mygtk.c:526 msgid "Pressure:" msgstr "" #: src/mygtk.c:527 msgid "X tilt:" msgstr "" #: src/mygtk.c:528 msgid "Y tilt:" msgstr "" #: src/mygtk.c:529 msgid "Wheel:" msgstr "" #: src/mygtk.c:579 msgid "none" msgstr "" #: src/otherwindow.c:236 msgid "24 bit RGB" msgstr "RGB de 24 bits" #: src/otherwindow.c:236 src/otherwindow.c:3179 msgid "Greyscale" msgstr "Escala de grises" #: src/otherwindow.c:237 msgid "Indexed Palette" msgstr "Paleta indexada" #: src/otherwindow.c:237 msgid "From Clipboard" msgstr "Del portapapeles" #: src/otherwindow.c:237 msgid "Grab Screenshot" msgstr "Capturar pantalla" #: src/otherwindow.c:242 src/toolbar.c:542 msgid "New Image" msgstr "Nueva imagen" #: src/otherwindow.c:246 src/otherwindow.c:3164 msgid "Colours" msgstr "Colores" #: src/otherwindow.c:409 msgid "Pattern Chooser" msgstr "Selector de patrón" #: src/otherwindow.c:497 msgid "Set Palette Size" msgstr "Establecer el tamaño de la paleta" #: src/otherwindow.c:517 src/otherwindow.c:591 src/otherwindow.c:870 #: src/otherwindow.c:2538 src/otherwindow.c:2776 src/otherwindow.c:2939 #: src/prefs.c:338 src/prefs.c:538 msgid "Apply" msgstr "Aplicar" #: src/otherwindow.c:573 msgid "Luminance" msgstr "Luminancia" #: src/otherwindow.c:573 src/otherwindow.c:814 msgid "Brightness" msgstr "Brillo" #: src/otherwindow.c:574 msgid "Distance to A" msgstr "Distancia a A" #: src/otherwindow.c:575 msgid "Projection to A->B" msgstr "Proyección A->B" #: src/otherwindow.c:576 msgid "Frequency" msgstr "Frecuencia" #: src/otherwindow.c:580 msgid "Sort Palette Colours" msgstr "Mostrar paleta de colores" #: src/otherwindow.c:582 msgid "Start Index" msgstr "Inicio del índice" #: src/otherwindow.c:583 msgid "End Index" msgstr "Fin del índice" #: src/otherwindow.c:589 msgid "Reverse Order" msgstr "Invertir el orden" #: src/otherwindow.c:805 msgid "Bitwise" msgstr "" #: src/otherwindow.c:805 msgid "Truncated" msgstr "" #: src/otherwindow.c:805 msgid "Rounded" msgstr "Redondeado" #: src/otherwindow.c:809 src/toolbar.c:311 src/toolbar.c:558 msgid "Transform Colour" msgstr "Tansformar el color" #: src/otherwindow.c:812 msgid "Gamma" msgstr "Gama" #: src/otherwindow.c:816 msgid "Contrast" msgstr "Contraste" #: src/otherwindow.c:822 src/otherwindow.c:1674 msgid "Posterize" msgstr "Posterizar" #: src/otherwindow.c:831 msgid "Show Detail" msgstr "Mostrar detalle" #: src/otherwindow.c:836 msgid "Posterize type" msgstr "" #: src/otherwindow.c:857 msgid "Auto-Preview" msgstr "Auto previsualización" #: src/otherwindow.c:869 msgid "Reset" msgstr "Restablecer" #: src/otherwindow.c:931 msgid "New geometry is the same as now - nothing to do." msgstr "La nueva geometría es la misma que la actual - No se hace nada" #: src/otherwindow.c:980 msgid "The operating system cannot allocate the memory for this operation." msgstr "El sistema operativo no puede asignar memoria para esta operación." #: src/otherwindow.c:982 msgid "" "You have not allocated enough memory in the Preferences window for this " "operation." msgstr "" "No ha asignado la suficiente memoria en la ventana de preferencias para esta " "operación." #: src/otherwindow.c:993 src/otherwindow.c:2495 msgid "Mirror" msgstr "Espejo" #: src/otherwindow.c:993 src/otherwindow.c:994 msgid "Tile" msgstr "Mosaico" #: src/otherwindow.c:993 msgid "Void" msgstr "" #: src/otherwindow.c:994 src/shifter.c:283 msgid "Clear" msgstr "Limpiar" #: src/otherwindow.c:994 msgid "Mirror tile" msgstr "Mosaico de espejo" #: src/otherwindow.c:996 msgid "Nearest Neighbour" msgstr "Vecino más cercano" #: src/otherwindow.c:997 msgid "Bilinear / Area Mapping" msgstr "Bilineal / Mapeo de área" #: src/otherwindow.c:998 msgid "Bicubic" msgstr "Bicúbico" #: src/otherwindow.c:999 msgid "Bicubic edged" msgstr "Bicúbico recortado" #: src/otherwindow.c:1000 msgid "Bicubic better" msgstr "Bicúbico mejorado" #: src/otherwindow.c:1001 msgid "Bicubic sharper" msgstr "Bicúbico realzado" #: src/otherwindow.c:1002 msgid "Blackman-Harris" msgstr "" #: src/otherwindow.c:1008 msgid "Scale Canvas" msgstr "Escalar el lienzo" #: src/otherwindow.c:1009 msgid "Resize Canvas" msgstr "Redimensionar el lienzo" #: src/otherwindow.c:1012 msgid "Original " msgstr "Original " #: src/otherwindow.c:1013 msgid "New" msgstr "Nuevo" #: src/otherwindow.c:1014 msgid "Width " msgstr "Ancho " #: src/otherwindow.c:1018 msgid "Height " msgstr "Alto " #: src/otherwindow.c:1023 src/otherwindow.c:2514 src/otherwindow.c:2672 #: src/toolbar.c:212 msgid "Offset" msgstr "Compensar" #: src/otherwindow.c:1026 src/otherwindow.c:1615 src/viewer.c:1209 msgid "Centre" msgstr "Centrado" #: src/otherwindow.c:1033 src/otherwindow.c:1052 msgid "Fix Aspect Ratio" msgstr "Fijar Relación Alto/Ancho" #: src/otherwindow.c:1039 src/otherwindow.c:2070 src/toolbar.c:312 msgid "Settings" msgstr "Preferencias" #: src/otherwindow.c:1046 msgid "Sharper image reduction" msgstr "Reducción enfocada de imagen" #: src/otherwindow.c:1047 msgid "Boundary extension" msgstr "Extensión del límite" #: src/otherwindow.c:1613 src/otherwindow.c:2302 msgid "HSV" msgstr "HSV" #: src/otherwindow.c:1614 msgid "Highlight" msgstr "" #: src/otherwindow.c:1615 msgid "Limit" msgstr "Límite" #: src/otherwindow.c:1616 msgid "Sphere" msgstr "Esfera" #: src/otherwindow.c:1616 src/otherwindow.c:2670 msgid "Angle" msgstr "Ãngulo" #: src/otherwindow.c:1616 msgid "Cube" msgstr "Cubo" #: src/otherwindow.c:1617 msgid "Opaque" msgstr "Opaco" #: src/otherwindow.c:1617 msgid "Border" msgstr "Borde" #: src/otherwindow.c:1618 msgid "Transparent" msgstr "Transparente" #: src/otherwindow.c:1618 msgid "Tile " msgstr "Mosaico " #: src/otherwindow.c:1618 msgid "Segment" msgstr "" #: src/otherwindow.c:1656 msgid "Scale" msgstr "Escala" #: src/otherwindow.c:1657 src/otherwindow.c:3059 msgid "From" msgstr "Desde" #: src/otherwindow.c:1659 src/otherwindow.c:3061 msgid "To" msgstr "Hacia" #: src/otherwindow.c:1699 msgid "Range" msgstr "Rango" #: src/otherwindow.c:1702 msgid "Inverse" msgstr "Inverso" #: src/otherwindow.c:1710 msgid "Smart grid" msgstr "Rejilla inteligente" #: src/otherwindow.c:1712 msgid "Tile grid" msgstr "Rejilla de mosaico" #: src/otherwindow.c:1714 msgid "Minimum grid zoom" msgstr "Mínima ampliación de la rejilla" #: src/otherwindow.c:1717 msgid "Tile width" msgstr "Anchura del mosaico" #: src/otherwindow.c:1720 msgid "Tile height" msgstr "Altura del mosaico" #: src/otherwindow.c:1744 msgid "Palette Editor" msgstr "Editor de paleta" #: src/otherwindow.c:1763 msgid "Configure Overlays" msgstr "Configurar revestimientos" #: src/otherwindow.c:1782 msgid "Colour Editor" msgstr "Editor de colores" #: src/otherwindow.c:1818 src/toolbar.c:430 msgid "Colour-Selective Mode" msgstr "Color-modo de selección" #: src/otherwindow.c:1843 msgid "Configure Grid" msgstr "Configurar la rejilla" #: src/otherwindow.c:2045 msgid "Exact Conversion" msgstr "Conversión exacta" #: src/otherwindow.c:2045 msgid "Use Current Palette" msgstr "Usar paleta actual" #: src/otherwindow.c:2046 msgid "PNN Quantize (slow, better quality)" msgstr "Cuantificar PNN (lento, mejor calidad)" #: src/otherwindow.c:2047 msgid "Wu Quantize (fast)" msgstr "Cuantificar «Wu» (rápido)" #: src/otherwindow.c:2048 msgid "Max-Min Quantize (best for small palettes and dithering)" msgstr "Cuantificar «Max-Min» (mejor para pequeñas paletas y punteados)" #: src/otherwindow.c:2049 src/otherwindow.c:2495 src/otherwindow.c:2756 #: src/png.c:2794 src/prefs.c:377 msgid "None" msgstr "Ninguno" #: src/otherwindow.c:2049 msgid "Floyd-Steinberg" msgstr "«Floyd-Steinberg»" #: src/otherwindow.c:2049 msgid "Stucki" msgstr "«Stucki»" #: src/otherwindow.c:2052 msgid "Floyd-Steinberg (quick)" msgstr "Floyd-Steinberg (rápido)" #: src/otherwindow.c:2052 msgid "Dithered (effect)" msgstr "Punteado (efecto)" #: src/otherwindow.c:2053 msgid "Scattered (effect)" msgstr "Disperso (efecto)" #: src/otherwindow.c:2054 msgid "Gamut" msgstr "Fuera de gama" #: src/otherwindow.c:2054 msgid "Weakly" msgstr "Débil" #: src/otherwindow.c:2054 msgid "Strongly" msgstr "Fuerte" #: src/otherwindow.c:2055 msgid "Off" msgstr "Apagado" #: src/otherwindow.c:2055 msgid "Separate/Sum" msgstr "Separar/Sumar" #: src/otherwindow.c:2055 msgid "Separate/Split" msgstr "Separar/Cortar" #: src/otherwindow.c:2056 msgid "Length/Sum" msgstr "Longitud/Sumar" #: src/otherwindow.c:2056 msgid "Length/Split" msgstr "Longitud/Cortar" #: src/otherwindow.c:2057 msgid "Largest (Linf)" msgstr "El más grande" #: src/otherwindow.c:2057 msgid "Sum (L1)" msgstr "Suma (L1)" #: src/otherwindow.c:2057 msgid "Euclidean (L2)" msgstr "Euclidiano (L2)" #: src/otherwindow.c:2061 msgid "Create Quantized" msgstr "Crear cuantificado" #: src/otherwindow.c:2062 msgid "Convert To Indexed" msgstr "Convertir a Indexado" #: src/otherwindow.c:2065 msgid "Indexed Colours To Use" msgstr "Colores indexados a usar" #: src/otherwindow.c:2078 msgid "Truncate palette" msgstr "Paleta truncada" #: src/otherwindow.c:2079 msgid "Diameter based weighting" msgstr "Basado en la ponderación del diámetro" #: src/otherwindow.c:2084 msgid "Dither" msgstr "Punteado" #: src/otherwindow.c:2087 src/otherwindow.c:2584 src/otherwindow.c:2928 msgid "Colour space" msgstr "Espacio de color" #: src/otherwindow.c:2088 src/otherwindow.c:2929 msgid "Difference measure" msgstr "Diferencia de medida" #: src/otherwindow.c:2089 msgid "Reduce colour bleed" msgstr "Reducir color sangrado" #: src/otherwindow.c:2090 msgid "Serpentine scan" msgstr "Exploración serpeante" #: src/otherwindow.c:2092 msgid "Error propagation, %" msgstr "Error de propagación, %" #: src/otherwindow.c:2093 msgid "Selective error propagation" msgstr "Error selectivo de propagación" #: src/otherwindow.c:2097 msgid "Full error precision" msgstr "Error total de precisión" #: src/otherwindow.c:2302 msgid "Backward HSV" msgstr "Atrás HSV" #: src/otherwindow.c:2303 src/otherwindow.c:2326 msgid "Constant" msgstr "Constante" #: src/otherwindow.c:2307 msgid "Edit Gradient" msgstr "Editar gradación" #: src/otherwindow.c:2329 msgid "Points:" msgstr "Puntos:" #: src/otherwindow.c:2493 msgid "Linear" msgstr "Lineal" #: src/otherwindow.c:2493 src/otherwindow.c:2703 msgid "Bilinear" msgstr "Bilineal" #: src/otherwindow.c:2493 msgid "Radial" msgstr "Radial" #: src/otherwindow.c:2494 msgid "Square" msgstr "Cuadrado" #: src/otherwindow.c:2494 msgid "Angular" msgstr "Angular" #: src/otherwindow.c:2494 msgid "Conical" msgstr "Cónico" #: src/otherwindow.c:2495 msgid "Level " msgstr "" #: src/otherwindow.c:2495 msgid "Repeat" msgstr "Repetir" #: src/otherwindow.c:2496 msgid "A to B" msgstr "de A a B" #: src/otherwindow.c:2496 msgid "A to B (RGB)" msgstr "de A a B (RGB)" #: src/otherwindow.c:2497 msgid "A to B (sRGB)" msgstr "A a B (sRGB)" #: src/otherwindow.c:2497 msgid "A to B (HSV)" msgstr "de A a B (HSV)" #: src/otherwindow.c:2497 msgid "A to B (backward HSV)" msgstr "de A a B (volver HSV)" #: src/otherwindow.c:2498 msgid "A only" msgstr "Uno solo" #: src/otherwindow.c:2498 src/otherwindow.c:2500 msgid "Custom" msgstr "Personalizado" #: src/otherwindow.c:2499 msgid "Current to 0" msgstr "Actual a 0" #: src/otherwindow.c:2499 msgid "Current only" msgstr "Actual solo" #: src/otherwindow.c:2504 msgid "Configure Gradient" msgstr "Configurar gradación" #: src/otherwindow.c:2507 src/png.c:1001 msgid "Channel" msgstr "Canal" #: src/otherwindow.c:2512 msgid "Length" msgstr "Longitud" #: src/otherwindow.c:2513 msgid "Repeat length" msgstr "Repetir longitud" #: src/otherwindow.c:2515 msgid "Gradient type" msgstr "Tipo de gradación" #: src/otherwindow.c:2516 msgid "Extension type" msgstr "Tipo de extensión" #: src/otherwindow.c:2517 msgid "Distance type" msgstr "" #: src/otherwindow.c:2518 msgid "Preview opacity" msgstr "Previsualizar opacidad" #: src/otherwindow.c:2527 src/otherwindow.c:2533 src/toolbar.c:309 msgid "Reverse" msgstr "Inverso" #: src/otherwindow.c:2528 src/otherwindow.c:2534 msgid "Edit Custom" msgstr "Editar personalización" #: src/otherwindow.c:2592 msgid "Pick Gradient" msgstr "" #: src/otherwindow.c:2668 msgid "Horizontal " msgstr "Horizontal " #: src/otherwindow.c:2674 msgid "At distance" msgstr "A distancia" #: src/otherwindow.c:2675 msgid "Vertical" msgstr "Vertical" #: src/otherwindow.c:2756 msgid "Unchanged" msgstr "Sin cambios" #: src/otherwindow.c:2761 msgid "Tracing Image" msgstr "Trazando imagen" #: src/otherwindow.c:2763 src/toolbar.c:315 msgid "Source" msgstr "Origen" #: src/otherwindow.c:2768 msgid "Origin" msgstr "Origen" #: src/otherwindow.c:2771 msgid "Relative scale" msgstr "Escala Relativa" #: src/otherwindow.c:2774 msgid "Display" msgstr "Mostrar" #: src/otherwindow.c:2926 msgid "Segment Image" msgstr "" #: src/otherwindow.c:2931 src/toolbar.c:304 msgid "Threshold" msgstr "" #: src/otherwindow.c:2933 msgid "Level" msgstr "Nivel" #: src/otherwindow.c:2934 msgid "Minimum size" msgstr "Tamaño mínimo" #: src/otherwindow.c:3053 msgid "Max" msgstr "" #: src/otherwindow.c:3053 msgid "Min" msgstr "" #: src/otherwindow.c:3057 msgid "Threshold Image" msgstr "" #: src/otherwindow.c:3158 msgid "Seed" msgstr "" #: src/otherwindow.c:3160 msgid "X span" msgstr "" #: src/otherwindow.c:3161 msgid "Y span" msgstr "" #: src/otherwindow.c:3162 msgid "Octaves" msgstr "" #: src/png.c:620 #, c-format msgid "Saving %s image" msgstr "Guardar imagen %s" #: src/png.c:620 #, c-format msgid "Loading %s image" msgstr "Cargando imagen %s" #: src/png.c:998 msgid "Layer" msgstr "Capa" #: src/png.c:3577 msgid "Lossless" msgstr "" #: src/png.c:3577 msgid "Default" msgstr "" #: src/png.c:3577 msgid "Picture" msgstr "" #: src/png.c:3577 msgid "Photo" msgstr "" #: src/png.c:3578 msgid "Drawing" msgstr "" #: src/png.c:3578 msgid "Icon" msgstr "" #: src/png.c:8370 msgid "Applying colour profile" msgstr "Aplicando el perfil de color" #: src/png.c:8792 #, c-format msgid "%d out of %d frames could not be saved as %s - saved as PNG instead" msgstr "%d fuera de %d fotogramas no se guardaron como %s - guardados como PNG" #: src/png.c:8809 msgid "Explode frames" msgstr "" #: src/prefs.c:56 msgid "Default System Language" msgstr "Lenguaje predefinido" #: src/prefs.c:57 msgid "Chinese (Simplified)" msgstr "Hino (Simplificado)" #: src/prefs.c:57 msgid "Chinese (Taiwanese)" msgstr "Chino (Taiwanés)" #: src/prefs.c:57 msgid "Czech" msgstr "Checo" #: src/prefs.c:58 msgid "Dutch" msgstr "Holandés" #: src/prefs.c:58 msgid "English (UK)" msgstr "Inglés (Reino Unido)" #: src/prefs.c:58 msgid "French" msgstr "Francés" #: src/prefs.c:58 msgid "Galician" msgstr "Galego" #: src/prefs.c:58 msgid "German" msgstr "Alemán" #: src/prefs.c:59 msgid "Hungarian" msgstr "" #: src/prefs.c:59 msgid "Italian" msgstr "Italiano" #: src/prefs.c:59 msgid "Japanese" msgstr "Japonés" #: src/prefs.c:59 msgid "Kabyle" msgstr "" #: src/prefs.c:59 msgid "Polish" msgstr "Polaco" #: src/prefs.c:60 msgid "Portuguese" msgstr "Portugués" #: src/prefs.c:60 msgid "Portuguese (Brazilian)" msgstr "Portugués (Brasileño)" #: src/prefs.c:60 msgid "Russian" msgstr "Ruso" #: src/prefs.c:60 msgid "Slovak" msgstr "Eslovaco" #: src/prefs.c:61 msgid "Spanish" msgstr "Español" #: src/prefs.c:61 msgid "Swedish" msgstr "Sueco" #: src/prefs.c:61 msgid "Tagalog" msgstr "" #: src/prefs.c:61 msgid "Turkish" msgstr "Turco" #: src/prefs.c:81 msgid "Current Device" msgstr "Dispositivo actual" #: src/prefs.c:135 msgid "Pressure" msgstr "Presión" #: src/prefs.c:149 msgid "Preferences" msgstr "Preferencias" #: src/prefs.c:163 msgid "Max threads (0 to autodetect)" msgstr "" #: src/prefs.c:164 msgid "Min kpixels per render thread" msgstr "" #: src/prefs.c:171 msgid "Max memory used for undo (MB)" msgstr "Máxima memoria usada para deshacer (MB)" #: src/prefs.c:172 msgid "Max undo levels" msgstr "Nivel máximo de deshacer" #: src/prefs.c:173 msgid "Communal layer undo space (%)" msgstr "Porcentaje de espacio que elimina la capa común (%)" #: src/prefs.c:175 msgid "Bayer master pattern" msgstr "" #: src/prefs.c:178 msgid "Use gamma correction by default" msgstr "Unar corrección gama por defecto" #: src/prefs.c:179 msgid "Use gamma correction when painting" msgstr "" #: src/prefs.c:180 msgid "Separate patterns for A & B" msgstr "" #: src/prefs.c:183 msgid "Optimize alpha chequers" msgstr "Optimiza comprobación alpha" #: src/prefs.c:184 msgid "Disable view window transparencies" msgstr "Deshabilitar ventana de transparencias" #: src/prefs.c:185 msgid "Enable overlays by layer" msgstr "" #: src/prefs.c:189 msgid "Language" msgstr "Idioma" #: src/prefs.c:191 msgid "" "Select preferred language translation\n" "\n" "You will need to restart mtPaint\n" "for this to take full effect" msgstr "" "Seleccione la traducción al idioma deseado\n" "\n" "Necesita reiniciar mtPaint\n" "para que esto tenga efecto" #: src/prefs.c:198 msgid "Interface" msgstr "Interfaz" #: src/prefs.c:200 msgid "Greyscale backdrop" msgstr "Fondo de grises" #: src/prefs.c:201 msgid "Selection nudge pixels" msgstr "Selección mover pixeles" #: src/prefs.c:202 msgid "Max Pan Window Size" msgstr "Máximo Tamaño de ventana reducida" #: src/prefs.c:204 msgid "Display clipboard while pasting" msgstr "Mostrar portapapeles mientras se pega" #: src/prefs.c:205 msgid "Mouse cursor = Tool" msgstr "Movimiento del ratón = Herramienta" #: src/prefs.c:206 msgid "Confirm Exit" msgstr "Confirmar salir" #: src/prefs.c:207 msgid "Q key quits mtPaint" msgstr "Pulse Q para salir de mtPaint" #: src/prefs.c:208 msgid "Arrow keys scroll canvas" msgstr "" #: src/prefs.c:209 msgid "Changing tool commits paste" msgstr "El cambio de herramienta implica el pegado" #: src/prefs.c:210 msgid "Centre tool settings dialogs" msgstr "Preferencias de herramienta de centrado" #: src/prefs.c:211 msgid "New image sets zoom to 100%" msgstr "La nueva imagen establece el zoom al 100%" #: src/prefs.c:212 msgid "Zoom on cursor position" msgstr "" #: src/prefs.c:214 msgid "Mouse Scroll Wheel = Zoom" msgstr "Rueda del ratón = Ampliar" #: src/prefs.c:215 msgid "Use menu icons" msgstr "Usar iconos de menú" #: src/prefs.c:220 msgid "Files" msgstr "Archivos" #: src/prefs.c:223 msgid "XBM X hotspot" msgstr "Referencia XBM X" #: src/prefs.c:224 msgid "XBM Y hotspot" msgstr "Referencia XBM Y" #: src/prefs.c:228 msgid "Recently Used Files" msgstr "Archivos recientes" #: src/prefs.c:229 msgid "Progress bar silence limit" msgstr "Límite de silencio de la barra de progreso" #: src/prefs.c:232 msgid "Read 16-bit TGAs as 5:6:5 BGR" msgstr "Leer 16-bit TGAs como 5:6:5 BGR" #: src/prefs.c:233 msgid "Write TGAs in bottom-up row order" msgstr "Escribir TGAs de abajo a arriba según la orden" #: src/prefs.c:234 msgid "Undoable image loading" msgstr "Carga reversible de imagenes" #: src/prefs.c:245 msgid "Compression (RGB)" msgstr "" #: src/prefs.c:246 msgid "Compression (indexed)" msgstr "" #: src/prefs.c:247 msgid "Compression (monochrome)" msgstr "" #: src/prefs.c:255 msgid "Enable predictor" msgstr "" #: src/prefs.c:262 msgid "Compression mode" msgstr "" #: src/prefs.c:271 msgid "Channel for Mask Plane" msgstr "" #: src/prefs.c:273 msgid "Ignore Transparent Colour" msgstr "" #: src/prefs.c:274 msgid "PackBits Compression" msgstr "" #: src/prefs.c:275 msgid "Write Indexed as Planar Bitmap (PBM)" msgstr "" #: src/prefs.c:280 msgid "Paths" msgstr "Rutas" #: src/prefs.c:281 msgid "Clipboard Files" msgstr "Archivos del portapapeles" #: src/prefs.c:281 msgid "Select Clipboard File" msgstr "Seleccione portapapeles" #: src/prefs.c:283 msgid "HTML Browser Program" msgstr "Programa navegador HTML" #: src/prefs.c:283 msgid "Select Browser Program" msgstr "Selecciona programa de navegación" #: src/prefs.c:285 msgid "Location of Handbook index" msgstr "Localización del archivo índice del manual" #: src/prefs.c:285 msgid "Select Handbook Index File" msgstr "Selecciona el archivo índice del manual" #: src/prefs.c:287 msgid "Default Palette" msgstr "Paleta predeterminada" #: src/prefs.c:287 msgid "Select Default Palette" msgstr "Seleccionar paleta predeterminada" #: src/prefs.c:289 msgid "Default Patterns" msgstr "Patrones predeterminados" #: src/prefs.c:289 msgid "Select Default Patterns File" msgstr "Seleccionar archivos de patrones" #: src/prefs.c:292 msgid "Default CSS" msgstr "" #: src/prefs.c:292 msgid "Select Default CSS File" msgstr "" #: src/prefs.c:295 msgid "Default Theme" msgstr "" #: src/prefs.c:295 msgid "Select Default Theme File" msgstr "" #: src/prefs.c:300 msgid "Status Bar" msgstr "Barra de estado" #: src/prefs.c:301 msgid "Canvas Geometry" msgstr "Geometría del lienzo" #: src/prefs.c:302 msgid "Cursor X,Y" msgstr "Cursor X,Y" #: src/prefs.c:303 msgid "Pixel [I] {RGB}" msgstr "Píxel [I] {RGB}" #: src/prefs.c:304 msgid "Selection Geometry" msgstr "Selección de geometria" #: src/prefs.c:305 msgid "Undo / Redo" msgstr "Deshacer /Rehacer" #: src/prefs.c:308 msgid "Tablet" msgstr "Tableta" #: src/prefs.c:309 msgid "Device Settings" msgstr "Parámetros de dispositivo" #: src/prefs.c:313 msgid "Configure Device" msgstr "Configurar dispositivo" #: src/prefs.c:319 msgid "Tool Variable" msgstr "Variables del lápiz" #: src/prefs.c:322 src/toolbar.c:454 msgid "Flow" msgstr "Flujo" #: src/prefs.c:330 msgid "Test Area" msgstr "Area de prueba" #: src/prefs.c:373 msgid "Factor" msgstr "Factor" #: src/prefs.c:459 msgid "This key is builtin" msgstr "" #: src/prefs.c:462 #, c-format msgid "" "This key is mapped to:\n" "\"%s\"" msgstr "" #: src/prefs.c:465 msgid "Remap" msgstr "" #: src/prefs.c:510 msgid "Keyboard Shortcuts" msgstr "" #: src/shifter.c:147 msgid "Frames" msgstr "Fotogramas" #: src/shifter.c:258 msgid "Palette Shifter" msgstr "Paleta «Shifter»" #: src/shifter.c:263 msgid "Start" msgstr "Empezar" #: src/shifter.c:265 msgid "Finish" msgstr "Terminar" #: src/shifter.c:284 msgid "Fix Palette" msgstr "Fijar paleta" #: src/spawn.c:651 msgid "Configure File Actions" msgstr "Configurar acciones de archivos" #: src/spawn.c:657 src/spawn.c:663 msgid "Command" msgstr "Orden" #: src/spawn.c:922 #, c-format msgid "Error %i reported when trying to run %s" msgstr "Se produjo un errr %i cuando se intentaba cargar %s" #: src/spawn.c:979 msgid "" "I am unable to find the documentation. Either you need to download the " "mtPaint Handbook from the web site and install it, or you need to set the " "correct location in the Preferences window." msgstr "" "No se puede encontrar la documentación. Necesitas descargar el manual de " "mtPaint e instalarlo, o establece la correcta localización en la ventana de " "preferencias." #: src/spawn.c:1018 msgid "" "There was a problem running the HTML browser. You need to set the correct " "program name in the Preferences window." msgstr "" "Hay un problema arrancando el navegador HTML. Necesitas establecer un " "programa de navegación en la ventana de preferencias." #: src/thread.c:361 msgid "Helper thread is not responding. Save your work and exit the program." msgstr "" #: src/toolbar.c:147 msgid "RGB Cube" msgstr "Cubo RGB" #: src/toolbar.c:148 msgid "By image channel" msgstr "Por imagen de canal" #: src/toolbar.c:149 msgid "Gradient-driven" msgstr "Ejecutar-gradación" #: src/toolbar.c:157 msgid "Fill settings" msgstr "Preferencias de relleno" #: src/toolbar.c:170 msgid "Respect opacity mode" msgstr "Respetar opacidad" #: src/toolbar.c:176 msgid "Smudge settings" msgstr "Preferencias de emborronado" #: src/toolbar.c:215 msgid "Aligned" msgstr "" #: src/toolbar.c:222 msgid "Clone settings" msgstr "" #: src/toolbar.c:228 msgid "By selection channel" msgstr "" #: src/toolbar.c:234 msgid "Lasso settings" msgstr "" #: src/toolbar.c:252 msgid "Brush spacing" msgstr "Espaciado de brocha" #: src/toolbar.c:299 src/toolbar.c:341 msgid "Normal" msgstr "Normal" #: src/toolbar.c:300 msgid "Colour" msgstr "Color" #: src/toolbar.c:300 msgid "Saturate More" msgstr "Saturar más" #: src/toolbar.c:301 msgid "Multiply" msgstr "Multiplicar" #: src/toolbar.c:301 msgid "Divide" msgstr "Dividir" #: src/toolbar.c:301 msgid "Dodge" msgstr "Blanquear" #: src/toolbar.c:302 msgid "Burn" msgstr "Ennegrecer" #: src/toolbar.c:302 msgid "Hard Light" msgstr "Claridad fuerte" #: src/toolbar.c:302 msgid "Soft Light" msgstr "Claridad suave" #: src/toolbar.c:302 msgid "Difference" msgstr "Diferencia" #: src/toolbar.c:303 msgid "Darken" msgstr "Oscurecer" #: src/toolbar.c:303 msgid "Lighten" msgstr "Clarear" #: src/toolbar.c:303 msgid "Grain Extract" msgstr "Extraer granulado" #: src/toolbar.c:304 msgid "Grain Merge" msgstr "Combinar granulado" #: src/toolbar.c:330 msgid "Blend mode" msgstr "Mod de mezcla" #: src/toolbar.c:417 msgid "Continuous Mode" msgstr "Modo continuo" #: src/toolbar.c:421 msgid "Opacity Mode" msgstr "Modo opaco" #: src/toolbar.c:424 msgid "Tint Mode" msgstr "Modo teñido" #: src/toolbar.c:427 msgid "Tint +-" msgstr "Teñido +-" #: src/toolbar.c:434 msgid "Blend Mode" msgstr "Modo de mezcla" #: src/toolbar.c:438 msgid "Disable All Masks" msgstr "Deshabilitar todas las máscaras" #: src/toolbar.c:441 msgid "Gradient Mode" msgstr "Modo gradación" #: src/toolbar.c:486 msgid "Settings Toolbar" msgstr "Barra de propiedades" #: src/toolbar.c:546 msgid "Cut" msgstr "Cortar" #: src/toolbar.c:548 msgid "Copy" msgstr "Copiar" #: src/toolbar.c:550 msgid "Paste" msgstr "Pegar" #: src/toolbar.c:553 msgid "Undo" msgstr "Deshacer" #: src/toolbar.c:555 msgid "Redo" msgstr "Rehacer" #: src/toolbar.c:559 src/viewer.c:328 msgid "Pan Window" msgstr "Vista preliminar" #: src/toolbar.c:560 src/toolbar.c:640 msgid "More..." msgstr "" #: src/toolbar.c:574 msgid "Paint" msgstr "Dibujar" #: src/toolbar.c:580 msgid "Shuffle" msgstr "Mezclar" #: src/toolbar.c:583 msgid "Flood Fill" msgstr "Rellenar con pintura" #: src/toolbar.c:587 msgid "Straight Line" msgstr "Línea recta" #: src/toolbar.c:590 msgid "Smudge" msgstr "Emborronar" #: src/toolbar.c:594 msgid "Clone" msgstr "Clonar" #: src/toolbar.c:597 msgid "Make Selection" msgstr "Realizar selección" #: src/toolbar.c:600 msgid "Polygon Selection" msgstr "Selección poligonal" #: src/toolbar.c:603 msgid "Place Gradient" msgstr "Situar gradación" #: src/toolbar.c:606 msgid "Lasso Selection" msgstr "Selección libre" #: src/toolbar.c:614 msgid "Ellipse Outline" msgstr "Contorno de elipse" #: src/toolbar.c:617 msgid "Filled Ellipse" msgstr "Elipse rellena" #: src/toolbar.c:620 msgid "Outline Selection" msgstr "Resaltar la selección" #: src/toolbar.c:623 msgid "Fill Selection" msgstr "Rellenar la selección" #: src/toolbar.c:627 msgid "Flip Selection Vertically" msgstr "Voltear la selección verticalmente" #: src/toolbar.c:630 msgid "Flip Selection Horizontally" msgstr "Voltear la selección horizontalmente" #: src/toolbar.c:633 msgid "Rotate Selection Clockwise" msgstr "Rotar la selección en sentido horario" #: src/toolbar.c:636 msgid "Rotate Selection Anti-Clockwise" msgstr "Rotar la selección en sentido anti horario" #: src/vcode.c:5201 msgid "Browse" msgstr "Buscar" #: src/vcode.c:7886 msgid "New key ..." msgstr "" #: src/vcode.c:9909 #, c-format msgid "'%s' does not match any widget" msgstr "" #: src/vcode.c:9910 #, c-format msgid "'%s' value does not fit '%s' widget" msgstr "" #: src/viewer.c:115 msgid "About" msgstr "Acerca de" #: src/viewer.c:1179 msgid "No font selected" msgstr "" #: src/viewer.c:1209 msgid "Left" msgstr "" #: src/viewer.c:1209 msgid "Right" msgstr "" #~ msgid "Create GIF frames" #~ msgstr "Crear fotogramas GIF" #~ msgid "" #~ "You are trying to save an XPM file with more than 4096 colours. Either " #~ "use another format or posterize the image to 4 bits, or otherwise reduce " #~ "the number of colours." #~ msgstr "" #~ "Está tratando de guardar un archivo XPM con más de 4096 colores. Use otro " #~ "formato o posterize la imagen a 4 bits, o también reduzca el número de " #~ "colores." #~ msgid "Store Values" #~ msgstr "Valores guardados" #~ msgid "File: %s invalid - palette not updated" #~ msgstr "El archivo: %s no es válido - La paleta no se actualizó" #~ msgid "Distance to A+B" #~ msgstr "Distancia a A+B" #~ msgid "Edit Frames" #~ msgstr "Editar fotogramas" #~ msgid "Not enough memory to rotate image" #~ msgstr "No hay suficiente memoria para rotar la imagen" #~ msgid "Not enough memory to rotate clipboard" #~ msgstr "No hay suficiente memoria para rotar el portapapeles" #~ msgid "File is too big, must be <= to width=%i height=%i : %s" #~ msgstr "" #~ "Archivo demasiado grande, su tamaño debe ser <= anchura=%i altura=%i : %s" #~ msgid "Could not open %s: %s" #~ msgstr "No se pudo abrir %s: %s" #~ msgid "Error closing %s: %s" #~ msgstr "Error al cerrar %s: %s" #~ msgid "Could not write to %s: %s" #~ msgstr "No se pudo escribir a %s: %s" #~ msgid "The palette does not contain enough colours to do a merge" #~ msgstr "La paleta no contiene suficientes colores para hacer una fusión" #~ msgid "There are too many identical palette items to be reduced." #~ msgstr "Hay demasiados elementos en la paleta a reducir." #~ msgid "patterns_user.c could not be opened in current directory" #~ msgstr "" #~ "El archivo de patrones -patterns_user.c- no pudo abrirse en el directorio " #~ "actual" #~ msgid "Done" #~ msgstr "Hecho" #~ msgid "patterns_user.c created in current directory" #~ msgstr "" #~ "El archivo de patrones -patterns_user.c- no pudo abrirse en el directorio " #~ "actual" #~ msgid "Current image is not 94x94x3 so I cannot create patterns_user.c" #~ msgstr "" #~ "La imagen actual no tiene las dimensiones 94x94x3 así que no puedo crear " #~ "el fichero de patrones patterns_user.c" #~ msgid "" #~ "You are trying to save an RGB image to an XPM file which is not " #~ "possible. I would suggest you save with a PNG extension." #~ msgstr "" #~ "Está intentando guardar una imagen RGB a un fichero XPM, lo cual no es " #~ "posible. Sugiero que lo guarde con extensión PNG." #~ msgid "" #~ "You are trying to save an RGB image to a GIF file which is not possible. " #~ "I would suggest you save with a PNG extension." #~ msgstr "" #~ "Está intentando guardar una imagen RGB a un fichero GIF, lo cual no es " #~ "posible. Sugiero que lo guarde con extensión PNG." #~ msgid "" #~ "You are trying to save an XBM file with a palette of more than 2 " #~ "colours. Either use another format or reduce the palette to 2 colours." #~ msgstr "" #~ "Está intentando guardar un fichero XBM con una paleta de mas de 2 " #~ "colores. Reduzca la paleta a 2 colores o use otro formato." #~ msgid "" #~ "You are trying to save an indexed canvas to a JPEG file which is not " #~ "possible. I would suggest you save with a PNG extension." #~ msgstr "" #~ "Está intentando guardar un lienzo a un fichero JPEG, lo cual no es " #~ "posible.Le sugiero que lo guarde con extensión PNG." #~ msgid "/Edit/Create Patterns" #~ msgstr "/Editar/Crear Patrones" #~ msgid "/View/Command Line Window" #~ msgstr "/Ver/Línea de comandos" #~ msgid "/Palette/Create Quantized (DL1)" #~ msgstr "/Paleta/Crear Cantidades (DL1)" #~ msgid "/Palette/Create Quantized (DL3)" #~ msgstr "/Paleta/Crear Cantidades (DL3)" #~ msgid "/File/%i" #~ msgstr "/Archivo/%i" #~ msgid "JPEG Save Quality (100=High) " #~ msgstr "Calidad JPEG Guardado (100=Alta) " #~ msgid "DL1 Quantize (fastest)" #~ msgstr "Ponderado DL1 (el más rápido)" #~ msgid "DL3 Quantize (very slow, better quality)" #~ msgstr "Ponderado DL3 (muy lento, mejor calidad)" #~ msgid "Loading PNG image" #~ msgstr "Cargar imagen PNG" #~ msgid "Loading clipboard image" #~ msgstr "Cargar imagen del Portapapeles" #~ msgid "Saving PNG image" #~ msgstr "Guardar imagen PNG" #~ msgid "Saving Clipboard image" #~ msgstr "Guardar imagen del Portapapeles" #~ msgid "Saving Layer image" #~ msgstr "Guardar imagen de la capa" #~ msgid "Loading GIF image" #~ msgstr "Cargar imagen GIF" #~ msgid "Saving GIF image" #~ msgstr "Guardar imagen GIF" #~ msgid "Loading JPEG image" #~ msgstr "Cargar imagen JPEG" #~ msgid "Saving JPEG image" #~ msgstr "Guardar imagen JPEG" #~ msgid "Loading TIFF image" #~ msgstr "Cargar imagen TIFF" #~ msgid "Saving TIFF image" #~ msgstr "Guardar imagen TIFF" #~ msgid "Loading BMP image" #~ msgstr "Cargar imagen BMP" #~ msgid "Saving BMP image" #~ msgstr "Guardar imagen BMP" #~ msgid "Loading XPM image" #~ msgstr "Cargar imagen XPM" #~ msgid "Saving XPM image" #~ msgstr "Guardar imagen XPM" #~ msgid "Loading XBM image" #~ msgstr "Cargar imagen XBM" #~ msgid "Saving XBM image" #~ msgstr "Guardar imagen XBM" #~ msgid "Saving UNDO images" #~ msgstr "Guardando histórico de imagenes" #~ msgid "%i Files on Command Line" #~ msgstr "%i Archivos en la línea de ordenes" #~ msgid "/Palette/Create Quantized (Wu)" #~ msgstr "/Paleta/Crear Cuantificado (Wu)" #~ msgid "Wu Quantize (best method for small palettes)" #~ msgstr "Cuantificación Wu (el mejor método para paletas pequeñas)" #~ msgid "Grid colour RGB" #~ msgstr "Color RGB de la rejilla" #~ msgid "Zoom" #~ msgstr "Ampliación" #~ msgid "Lanczos3" #~ msgstr "Lanczos3" #~ msgid "Saving Channel image" #~ msgstr "Guardar imagen de canal" #~ msgid "Loading LSS16 image" #~ msgstr "Cargar imagen LSS16" #~ msgid "Saving LSS16 image" #~ msgstr "Guardar imagen LSS16" #~ msgid " C Command Line Window" #~ msgstr " C Ventana de línea de ordenes" #~ msgid "/File/Actions/sep2" #~ msgstr "/Archivo/Actions/sep2" #~ msgid "/Frames" #~ msgstr "/Fotogramas" #~ msgid "/File/Actions/%i" #~ msgstr "/Archivo/Actions/%i" mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/po/fr.po000066400000000000000000003223661471325446300215540ustar00rootroot00000000000000# French translation for mtpaint # Copyright (c) (c) 2005 Canonical Ltd, and Rosetta Contributors 2005 # This file is distributed under the same license as the mtpaint package. # FIRST AUTHOR , 2005. # Sylvain Cresto , 2007. # msgid "" msgstr "" "Project-Id-Version: mtpaint\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-01-04 21:31+0200\n" "PO-Revision-Date: 2017-09-06 14:24+0200\n" "Last-Translator: wjaguar \n" "Language-Team: French \n" "Language: fr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Launchpad-Export-Date: 2009-11-25 18:32+0000\n" "X-Generator: Poedit 1.8.7.1\n" "X-Rosetta-Version: 0.1\n" #: src/ani.c:647 msgid "Animation Preview" msgstr "Aperçu de l'animation" #: src/ani.c:650 src/shifter.c:275 msgid "Play" msgstr "Jouer" #: src/ani.c:654 msgid "Fix" msgstr "Conserver" #: src/ani.c:655 src/ani.c:1005 src/font.c:1624 src/font.c:1643 #: src/shifter.c:286 src/viewer.c:97 msgid "Close" msgstr "Fermer" #: src/ani.c:709 src/ani.c:812 src/ani.c:1022 src/ani.c:1028 src/canvas.c:356 #: src/canvas.c:708 src/canvas.c:989 src/canvas.c:1353 src/canvas.c:1383 #: src/canvas.c:1470 src/canvas.c:1545 src/canvas.c:1988 src/canvas.c:1994 #: src/canvas.c:2077 src/canvas.c:2217 src/canvas.c:2240 src/font.c:1352 #: src/fpick.c:636 src/fpick.c:754 src/layer.c:524 src/layer.c:815 #: src/layer.c:970 src/mainwindow.c:341 src/mainwindow.c:370 #: src/mainwindow.c:534 src/mainwindow.c:578 src/mainwindow.c:604 #: src/mainwindow.c:3797 src/mainwindow.c:4045 src/otherwindow.c:931 #: src/otherwindow.c:980 src/otherwindow.c:982 src/prefs.c:459 src/spawn.c:924 #: src/spawn.c:978 src/spawn.c:1017 src/thread.c:360 src/vcode.c:9912 #: src/viewer.c:1161 src/viewer.c:1179 msgid "Error" msgstr "Erreur" #: src/ani.c:709 msgid "Unable to create output directory" msgstr "Impossible de créer le répertoire de destination" #: src/ani.c:759 msgid "Creating Animation Frames" msgstr "Création des trames de l'animation" #: src/ani.c:812 msgid "Unable to save image" msgstr "Impossible d'enregistrer l'image" #: src/ani.c:840 src/canvas.c:1171 src/fpick.c:731 src/layer.c:311 #: src/layer.c:379 src/layer.c:826 src/layer.c:840 src/mainwindow.c:375 #: src/mainwindow.c:1026 src/png.c:8794 src/prefs.c:464 msgid "Warning" msgstr "Avertissement" #: src/ani.c:840 msgid "" "Do you really want to clear all of the position and cycle data for all of " "the layers?" msgstr "" "Voulez-vous vraiment effacer toutes les données d'animation de tous les " "calques ?" #: src/ani.c:841 src/fpick.c:731 src/layer.c:311 src/layer.c:842 #: src/mainwindow.c:375 msgid "No" msgstr "Non" #: src/ani.c:841 src/fpick.c:731 src/layer.c:311 src/layer.c:842 #: src/mainwindow.c:375 msgid "Yes" msgstr "Oui" #: src/ani.c:954 msgid "Set Key Frame" msgstr "Définir le numéro de la trame" #: src/ani.c:961 msgid "Configure Animation" msgstr "Configurer l'animation" #: src/ani.c:964 msgid "Output Files" msgstr "Fichiers destination" #: src/ani.c:967 msgid "Start frame" msgstr "Trame de début" #: src/ani.c:969 msgid "End frame" msgstr "Trame de fin" #: src/ani.c:971 src/shifter.c:267 msgid "Delay" msgstr "Délais" #: src/ani.c:973 msgid "Output path" msgstr "Répertoire de destination" #: src/ani.c:973 src/font.c:1637 src/spawn.c:664 msgid "Select Directory" msgstr "Sélectionner le répertoire" #: src/ani.c:976 msgid "File prefix" msgstr "Préfixe des fichiers" #: src/ani.c:978 src/canvas.c:2096 msgid "File Format" msgstr "Format de fichier" #: src/ani.c:982 msgid "Positions" msgstr "Positions" #: src/ani.c:997 msgid "Cycling" msgstr "Cycle" #: src/ani.c:1006 msgid "Save" msgstr "Enregistrer" #: src/ani.c:1007 src/font.c:1577 src/otherwindow.c:868 src/otherwindow.c:1615 #: src/otherwindow.c:1728 src/otherwindow.c:2938 src/otherwindow.c:3071 #: src/otherwindow.c:3170 msgid "Preview" msgstr "Aperçu" #: src/ani.c:1008 src/shifter.c:285 msgid "Create Frames" msgstr "Créer des trames" #: src/ani.c:1022 msgid "You must have at least 2 layers to create an animation" msgstr "Il doit y avoir au moins 2 calques pour créer une animation" #: src/ani.c:1028 msgid "You must save your layers file before creating an animation" msgstr "" "Vous devez enregistrer votre fichier de calques avant de créer une animation" #: src/canvas.c:357 msgid "The image is too large to transform." msgstr "L'image est trop grande pour être transformée." #: src/canvas.c:393 src/canvas.c:430 src/otherwindow.c:1613 #: src/otherwindow.c:2524 src/otherwindow.c:2583 src/otherwindow.c:3179 msgid "Gradient" msgstr "Dégradé" #: src/canvas.c:393 src/otherwindow.c:840 src/otherwindow.c:842 #: src/otherwindow.c:2074 src/otherwindow.c:3180 msgid "Palette" msgstr "Palette" #: src/canvas.c:393 src/info.c:265 src/otherwindow.c:847 src/otherwindow.c:2757 #: src/otherwindow.c:3180 src/png.c:781 src/png.c:995 msgid "Clipboard" msgstr "Presse-papiers" #: src/canvas.c:394 src/cpick.c:831 src/toolbar.c:299 msgid "Value" msgstr "Valeur" #: src/canvas.c:394 src/cpick.c:811 src/otherwindow.c:575 src/otherwindow.c:859 #: src/otherwindow.c:3053 src/toolbar.c:318 msgid "Red" msgstr "Rouge" #: src/canvas.c:394 src/cpick.c:815 src/otherwindow.c:575 src/otherwindow.c:860 #: src/otherwindow.c:3053 src/toolbar.c:319 msgid "Green" msgstr "Vert" #: src/canvas.c:394 src/cpick.c:819 src/otherwindow.c:575 src/otherwindow.c:861 #: src/otherwindow.c:3053 src/toolbar.c:320 msgid "Blue" msgstr "Bleu" #: src/canvas.c:399 msgid "From " msgstr "Depuis " #: src/canvas.c:403 msgid "To " msgstr "Vers " #: src/canvas.c:410 msgid "Map" msgstr "Mapper" #: src/canvas.c:429 msgid "MT" msgstr "" #: src/canvas.c:429 msgid "Sobel" msgstr "Sobel" #: src/canvas.c:429 msgid "Prewitt" msgstr "Prewitt" #: src/canvas.c:429 msgid "Kirsch" msgstr "Kirsch" #: src/canvas.c:430 msgid "Roberts" msgstr "Roberts" #: src/canvas.c:430 msgid "Laplace" msgstr "Laplace" #: src/canvas.c:430 msgid "Morphological" msgstr "Morphologique" #: src/canvas.c:442 msgid "Edge Detect" msgstr "Détecter les contours" #: src/canvas.c:464 msgid "Edge Sharpen" msgstr "Accentuer les contours" #: src/canvas.c:472 msgid "Edge Soften" msgstr "Adoucir les contours" #: src/canvas.c:521 msgid "Different X/Y" msgstr "Différent X/Y" #: src/canvas.c:522 src/canvas.c:562 src/canvas.c:603 src/canvas.c:637 #: src/canvas.c:722 src/otherwindow.c:1037 src/otherwindow.c:2685 msgid "Gamma corrected" msgstr "Correction gamma" #: src/canvas.c:530 src/memory.c:8219 msgid "Gaussian Blur" msgstr "Flou gaussien" #: src/canvas.c:558 msgid "Radius" msgstr "Rayon" #: src/canvas.c:559 msgid "Amount" msgstr "Quantité" #: src/canvas.c:560 msgid "Threshold " msgstr "Seuil " #: src/canvas.c:570 src/memory.c:8360 msgid "Unsharp Mask" msgstr "Masque de netteté" #: src/canvas.c:599 msgid "Outer radius" msgstr "Rayon extérieur" #: src/canvas.c:600 msgid "Inner radius" msgstr "Rayon intérieur" #: src/canvas.c:602 src/info.c:280 msgid "Normalize" msgstr "Normaliser" #: src/canvas.c:611 src/memory.c:8512 msgid "Difference of Gaussians" msgstr "Différence de gaussiens" #: src/canvas.c:636 msgid "Protect details" msgstr "Protéger les détails" #: src/canvas.c:645 msgid "Kuwahara-Nagao Blur" msgstr "Flou Kuwahara-Nagao" #: src/canvas.c:709 msgid "The image is too large for this rotation." msgstr "L'image est trop grande pour cette rotation." #: src/canvas.c:723 msgid "Smooth" msgstr "Lisser" #: src/canvas.c:732 msgid "Free Rotate" msgstr "Rotation libre" #: src/canvas.c:989 src/viewer.c:1161 msgid "Not enough memory to create clipboard" msgstr "Pas assez de mémoire pour créer le presse-papiers" #: src/canvas.c:1172 msgid "" "You have not allocated enough memory in the Preferences window to undo this " "action." msgstr "" "Vous n'avez pas alloué assez de mémoire dans la fenêtre de préférences pour " "annuler cette opération." #: src/canvas.c:1353 msgid "Invalid palette file" msgstr "Fichier de palette invalide" #: src/canvas.c:1383 msgid "Invalid channel file." msgstr "Fichier de canal invalide." #: src/canvas.c:1401 msgid "Raw frames" msgstr "Trames brutes" #: src/canvas.c:1401 msgid "Composited frames" msgstr "Trames composites" #: src/canvas.c:1402 msgid "Composited frames with nonzero delay" msgstr "Trames composites avec délai non nul" #: src/canvas.c:1406 msgid "Load Frames" msgstr "Charger les trames" #: src/canvas.c:1409 msgid "Load into Layers" msgstr "Charger en calques" #: src/canvas.c:1415 msgid "Load First Frame" msgstr "Charger la première trame" #: src/canvas.c:1416 msgid "Explode Frames" msgstr "Décomposer les trames" #: src/canvas.c:1418 msgid "View Animation" msgstr "Aperçu de l'animation" #: src/canvas.c:1434 #, c-format msgid "This is an animated %s file." msgstr "C'est une image %s animée." #: src/canvas.c:1435 #, c-format msgid "This is a multipage %s file." msgstr "C'est un fichier %s multipages." #: src/canvas.c:1459 #, c-format msgid "File is too big, must be <= to width=%i height=%i" msgstr "" "La taille du fichier est trop importante, elle doit être <= largeur=%i " "hauteur=%i" #: src/canvas.c:1461 msgid "Unable to explode frames" msgstr "Impossible de décomposer les trames" #: src/canvas.c:1463 msgid "Unable to load file" msgstr "Impossible de charger le fichier" #: src/canvas.c:1465 msgid "" "The file import library had to terminate due to a problem with the file " "(possibly corrupt image data or a truncated file). I have managed to load " "some data as the header seemed fine, but I would suggest you save this image " "to a new file to ensure this does not happen again." msgstr "" "La bibliothèque d'importation de fichier doit se terminer en raison d'un " "problème avec le fichier (probablement des données corrompues d'image ou un " "fichier tronqué). Je suis parvenu à charger quelques données comme l'en-tête " "qui semblait convenable, mais je suggérerais que vous enregistriez cette " "image dans un nouveau fichier pour vous assurer que ceci ne se produise pas " "de nouveau." #: src/canvas.c:1467 msgid "The animation is too long to load all of it into layers." msgstr "L'animation est trop longue pour la charger en calques." #: src/canvas.c:1469 msgid "Could not explode all the frames in the animation." msgstr "Impossible de décomposer toutes les trames de l'animation." #: src/canvas.c:1481 src/font.c:1556 src/fpick.c:937 src/otherwindow.c:2765 #: src/prefs.c:321 src/toolbar.c:451 msgid "Size" msgstr "Taille" #: src/canvas.c:1484 src/otherwindow.c:244 msgid "Width" msgstr "Largeur" #: src/canvas.c:1485 src/otherwindow.c:245 msgid "Height" msgstr "Hauteur" #: src/canvas.c:1489 src/channels.c:253 src/channels.c:317 src/fpick.c:666 #: src/fpick.c:957 src/mainwindow.c:3990 src/otherwindow.c:255 #: src/otherwindow.c:517 src/otherwindow.c:591 src/otherwindow.c:867 #: src/otherwindow.c:1058 src/otherwindow.c:1727 src/otherwindow.c:2101 #: src/otherwindow.c:2336 src/otherwindow.c:2538 src/otherwindow.c:2691 #: src/otherwindow.c:2776 src/otherwindow.c:2937 src/otherwindow.c:3070 #: src/otherwindow.c:3169 src/prefs.c:338 src/prefs.c:464 src/prefs.c:538 #: src/spawn.c:666 src/viewer.c:1258 msgid "Cancel" msgstr "Annuler" #: src/canvas.c:1490 src/channels.c:253 src/channels.c:317 src/fpick.c:956 #: src/info.c:297 src/mainwindow.c:3992 src/mygtk.c:233 src/mygtk.c:535 #: src/otherwindow.c:591 src/otherwindow.c:871 src/otherwindow.c:1058 #: src/otherwindow.c:1729 src/otherwindow.c:2101 src/otherwindow.c:2336 #: src/otherwindow.c:2538 src/otherwindow.c:2691 src/otherwindow.c:2776 #: src/otherwindow.c:3072 src/otherwindow.c:3171 src/prefs.c:338 #: src/prefs.c:538 src/spawn.c:666 msgid "OK" msgstr "OK" #: src/canvas.c:1504 #, c-format msgid "This is a scalable %s file." msgstr "C'est un fichier %s redimensionnable." #: src/canvas.c:1545 msgid "Cannot open file" msgstr "Ne peux pas ouvrir le fichier" #: src/canvas.c:1546 msgid "Unsupported file format" msgstr "Format non supporté" #: src/canvas.c:1673 #, c-format msgid "File: %s already exists. Do you want to overwrite it?" msgstr "Le fichier %s existe déjà. Voulez-vous le remplacer ?" #: src/canvas.c:1674 msgid "File Found" msgstr "Fichier trouvé" #: src/canvas.c:1674 src/mainwindow.c:1095 msgid "NO" msgstr "NON" #: src/canvas.c:1674 src/mainwindow.c:1095 msgid "YES" msgstr "OUI" #: src/canvas.c:1988 msgid "Unable to export undo images" msgstr "Erreur lors de l'exportation des tampons d'annulation" #: src/canvas.c:1994 msgid "Unable to export ASCII file" msgstr "Erreur lors de l'exportation du fichier ASCII" #: src/canvas.c:2076 src/layer.c:814 src/mainwindow.c:529 #, c-format msgid "Unable to save file: %s" msgstr "Impossible d'enregistrer le fichier : %s" #: src/canvas.c:2101 src/prefs.c:222 msgid "Transparency index" msgstr "Numéro de la couleur transparente" #: src/canvas.c:2103 msgid "TIFF Compression" msgstr "Compression TIFF" #: src/canvas.c:2105 src/prefs.c:225 msgid "JPEG Save Quality (100=High)" msgstr "Qualité de l'image JPEG (100=Haute)" #: src/canvas.c:2107 msgid "ZIP Compression (0=None)" msgstr "Compression ZIP (0=Aucune)" #: src/canvas.c:2108 src/prefs.c:227 msgid "PNG Compression (0=None)" msgstr "Compression PNG (0=Aucune)" #: src/canvas.c:2111 src/prefs.c:249 msgid "LZMA2 Compression (0=None)" msgstr "Compression LZMA2 (0=Aucune)" #: src/canvas.c:2113 src/prefs.c:252 msgid "ZSTD Compression Level" msgstr "Niveau de compression ZSTD" #: src/canvas.c:2115 src/prefs.c:231 msgid "TGA RLE Compression" msgstr "Compression TGA RLE" #: src/canvas.c:2117 msgid "LBM PackBits Compression" msgstr "Compression LBM PackBits" #: src/canvas.c:2118 src/prefs.c:226 msgid "JPEG2000 Compression (0=Lossless)" msgstr "Compression JPEG2000 (0= Sans perte)" #: src/canvas.c:2120 msgid "WebP Compression" msgstr "Compression WebP" #: src/canvas.c:2122 msgid "WebP Save Quality (100=High)" msgstr "Qualité de l'image WebP (100=Haute)" #: src/canvas.c:2123 src/prefs.c:263 msgid "V8 Save Quality (100=High)" msgstr "Qualité de l'image V8 (100=Haute)" #: src/canvas.c:2125 src/prefs.c:264 msgid "V8L Compression (0=None)" msgstr "Compression V8L (0=Aucune)" #: src/canvas.c:2127 msgid "Hotspot at X =" msgstr "Point X =" #: src/canvas.c:2129 msgid "Y =" msgstr "Y =" #: src/canvas.c:2133 msgid "Animation delay" msgstr "Délais de l'animation" #: src/canvas.c:2136 src/otherwindow.c:253 msgid "Undoable" msgstr "Réversible" #: src/canvas.c:2138 src/prefs.c:236 msgid "Apply colour profile" msgstr "Appliquer le profil de couleur" #: src/canvas.c:2176 src/toolbar.c:543 msgid "Load Image File" msgstr "Charger un fichier image" #: src/canvas.c:2191 src/toolbar.c:544 msgid "Save Image File" msgstr "Enregistrer l'image" #: src/canvas.c:2196 msgid "Load Palette File" msgstr "Charger un fichier de palette" #: src/canvas.c:2202 msgid "Save Palette File" msgstr "Enregistrer la palette" #: src/canvas.c:2207 msgid "Export Undo Images" msgstr "Exporter les tampons d'annulation" #: src/canvas.c:2212 msgid "Export Undo Images (reversed)" msgstr "Exporter les tampons d'annulation (inversé)" #: src/canvas.c:2217 msgid "You must have 16 or fewer palette colours to export ASCII art." msgstr "" "Vous devez avoir 16 couleurs de palette ou moins pour exporter de l'art " "d'ASCII." #: src/canvas.c:2220 msgid "Export ASCII Art" msgstr "Exporter au format Art ASCII" #: src/canvas.c:2224 msgid "Save Layer Files" msgstr "Enregistrer les Fichiers de calque" #: src/canvas.c:2234 msgid "Choose frames directory" msgstr "Sélectionner le répertoire contenant les trames" #: src/canvas.c:2240 msgid "You must save at least one frame to create an animated GIF." msgstr "" "Avant de pouvoir créer une animation GIF vous devez d'abord enregistrer au " "moins une trame." #: src/canvas.c:2243 msgid "Export GIF animation" msgstr "Exporter en tant qu'animation GIF" #: src/canvas.c:2247 msgid "Load Channel" msgstr "Charger le canal" #: src/canvas.c:2255 msgid "Save Channel" msgstr "Enregistrer le canal" #: src/canvas.c:2260 msgid "Save Composite Image" msgstr "Enregistrer l'image composite" #: src/channels.c:243 msgid "Create Channel" msgstr "Créer un canal" #: src/channels.c:244 msgid "Channel Type" msgstr "Type de canal" #: src/channels.c:247 msgid "Initial Channel State" msgstr "État initial du canal" #: src/channels.c:251 msgid "Inverted" msgstr "Inversé" #: src/channels.c:265 msgid "Cleared" msgstr "Effacé" #: src/channels.c:266 msgid "Set" msgstr "Définis" #: src/channels.c:267 msgid "Set colour A radius B" msgstr "Définir la couleur A rayon B" #: src/channels.c:268 msgid "Set blend A to B" msgstr "Définir le mélange de A et B" #: src/channels.c:269 msgid "Image Red" msgstr "Rouge" #: src/channels.c:270 msgid "Image Green" msgstr "Vert" #: src/channels.c:271 msgid "Image Blue" msgstr "Bleu" #: src/channels.c:273 src/channels.c:313 src/mainwindow.c:67 #: src/otherwindow.c:1679 msgid "Alpha" msgstr "Alpha" #: src/channels.c:274 src/channels.c:314 src/mainwindow.c:67 #: src/otherwindow.c:1683 msgid "Selection" msgstr "Sélection" #: src/channels.c:275 src/channels.c:315 src/mainwindow.c:67 #: src/otherwindow.c:1687 msgid "Mask" msgstr "Masque" #: src/channels.c:312 msgid "Delete Channels" msgstr "Effacer les canaux" #: src/channels.c:367 msgid "Threshold Channel" msgstr "Seuil du canal" #: src/cpick.c:823 src/otherwindow.c:573 src/otherwindow.c:820 #: src/toolbar.c:299 msgid "Hue" msgstr "Teinte" #: src/cpick.c:827 src/otherwindow.c:573 src/otherwindow.c:818 #: src/toolbar.c:299 msgid "Saturation" msgstr "Saturation" #: src/cpick.c:835 msgid "Hex" msgstr "Hex" #: src/cpick.c:840 src/layer.c:1109 src/otherwindow.c:2530 src/prefs.c:323 #: src/toolbar.c:457 msgid "Opacity" msgstr "Opacité" #: src/font.c:982 msgid "Creating Font Index" msgstr "Création de l'index des polices" #: src/font.c:1353 msgid "You must select at least one directory to search for fonts." msgstr "" "Vous devez sélectionner au moins un répertoire où chercher des polices." #: src/font.c:1529 src/font.c:1624 src/toolbar.c:609 src/viewer.c:1213 #: src/viewer.c:1258 msgid "Paste Text" msgstr "Coller le texte" #: src/font.c:1533 src/font.c:1572 src/png.c:3578 msgid "Text" msgstr "Texte" #: src/font.c:1540 msgid "Font" msgstr "Police de caractères" #: src/font.c:1548 msgid "Style" msgstr "Style" #: src/font.c:1566 msgid "Filename" msgstr "Nom de fichier" #: src/font.c:1567 msgid "Face" msgstr "Dessin" #: src/font.c:1587 src/viewer.c:1222 msgid "Antialias" msgstr "Lissage" #: src/font.c:1590 src/viewer.c:1224 msgid "Invert" msgstr "Inverser" #: src/font.c:1593 src/viewer.c:1226 msgid "Background colour =" msgstr "Couleur d'arrière-plan =" #: src/font.c:1601 src/viewer.c:1233 msgid "DPI =" msgstr "" #: src/font.c:1610 msgid "Oblique" msgstr "Oblique" #: src/font.c:1612 src/viewer.c:1244 msgid "Angle of rotation =" msgstr "Angle de rotation =" #: src/font.c:1617 src/viewer.c:1248 msgid "Align" msgstr "Aligner" #: src/font.c:1620 src/viewer.c:1253 msgid "Spacing" msgstr "Espacement" #: src/font.c:1629 msgid "Font Directories" msgstr "Répertoire des Polices de caractères" #: src/font.c:1634 src/spawn.c:664 msgid "Directory" msgstr "Répertoire" #: src/font.c:1637 msgid "New Directory" msgstr "Nouveau répertoire" #: src/font.c:1644 src/prefs.c:532 msgid "Add" msgstr "Ajouter" #: src/font.c:1645 src/prefs.c:533 msgid "Remove" msgstr "Supprimer" #: src/font.c:1646 msgid "Create Index" msgstr "Créer l'index" #: src/font.c:1660 src/viewer.c:1267 msgid "Enter Text Here" msgstr "Écrivez le texte Ici" #: src/fpick.c:635 #, c-format msgid "Could not access directory %s" msgstr "Ne peut accéder au répertoire %s" #: src/fpick.c:668 src/fpick.c:698 msgid "Delete" msgstr "Supprimer" #: src/fpick.c:669 src/fpick.c:698 msgid "Rename" msgstr "Renommer" #: src/fpick.c:672 src/otherwindow.c:255 src/otherwindow.c:1666 msgid "Create" msgstr "Créer" #: src/fpick.c:699 msgid "Enter the new filename" msgstr "Entrer un nouveau nom de fichier" #: src/fpick.c:704 msgid "Create Directory" msgstr "Créer un répertoire" #: src/fpick.c:705 msgid "Enter the name of the new directory" msgstr "Entrer le nom du nouveau répertoire" #: src/fpick.c:729 #, c-format msgid "Do you really want to delete \"%s\" ?" msgstr "Voulez-vous vraiment supprimer \"%s\" ?" #: src/fpick.c:735 msgid "Unable to delete" msgstr "Impossible de supprimer" #: src/fpick.c:741 msgid "Unable to rename" msgstr "Impossible de renommer" #: src/fpick.c:750 msgid "Unable to create directory" msgstr "Impossible de créer le répertoire" #: src/fpick.c:924 msgid "Up" msgstr "Haut" #: src/fpick.c:925 msgid "Home" msgstr "Répertoire personnel" #: src/fpick.c:926 msgid "Create New Directory" msgstr "Créer un nouveau répertoire" #: src/fpick.c:927 msgid "Show Hidden Files" msgstr "Afficher les fichiers cachés" #: src/fpick.c:929 msgid "Case Insensitive Sort" msgstr "Tri insensible à la casse" #: src/fpick.c:936 msgid "Name" msgstr "Nom" #: src/fpick.c:938 msgid "Type" msgstr "Type" #: src/fpick.c:939 msgid "Modified" msgstr "Modifié" #: src/help.c:25 src/prefs.c:160 msgid "General" msgstr "Général" #: src/help.c:26 msgid "Keyboard shortcuts" msgstr "Raccourcis clavier" #: src/help.c:27 msgid "Mouse shortcuts" msgstr "Raccourcis souris" #: src/help.c:28 msgid "Credits" msgstr "Crédits" #: src/help.c:32 msgid "mtPaint 3.51 - Copyright (C) 2004-2021 The Authors\n" msgstr "mtPaint 3.51 - Copyright (C) 2004-2021 Les auteurs\n" #: src/help.c:33 msgid "See 'Credits' section for a list of the authors.\n" msgstr "La liste de tous les auteurs est présente dans la section 'Crédits'.\n" #: src/help.c:34 msgid "" "mtPaint 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.\n" msgstr "" "mtPaint est un logiciel libre; vous pouvez le redistribuer et/ou le modifier " "sous les conditions définies par la licence GNU General Public License " "publiée par la Free Software Foundation; sous sa version 3 ou (si vous le " "préférez) sous une version plus récente.\n" #: src/help.c:35 msgid "" "mtPaint 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.\n" msgstr "" "mtPaint est distribué dans l'espoir qu'il vous sera utile, mais SANS AUCUNE " "GARANTIE. Regardez la licence GNU General Public License pour plus de " "détails.\n" #: src/help.c:36 msgid "" "mtPaint is a simple GTK+1/2/3 painting program designed for creating icons " "and pixel based artwork. It can edit indexed palette or 24 bit RGB images " "and offers basic painting and palette manipulation tools. It also has " "several other more powerful features such as channels, layers and animation. " "Due to its simplicity and lack of dependencies it runs well on GNU/Linux, " "Windows and older PC hardware.\n" msgstr "" "mtPaint est un simple programme de dessin GTK+1/2/3 conçu pour créer des " "icônes et des dessins bitmaps. Vous pouvez manipuler des images utilisant " "des palettes de couleurs indexées ou couleurs réelles (24 bits) grâce aux " "outils de dessin classiques. Il offre également des fonctionnalités bien " "plus avancées telles que la gestion des canaux, calques et animations. Grâce " "à sa simplicité et son absence de dépendance il fonctionne sous GNU/Linux, " "Windows et ceci même sur les plus vieilles machines PC.\n" #: src/help.c:37 msgid "" "There is full documentation of mtPaint's features contained in a handbook. " "If you don't already have this, you can download it from the mtPaint " "website.\n" msgstr "" "Une documentation présentant toutes les fonctionnalités de mtPaint est " "disponible sous forme d'un manuel. Si vous ne l'avez pas encore, vous pouvez " "le télécharger depuis le site web de mtPaint.\n" #: src/help.c:38 msgid "" "If you like mtPaint and you want to keep up to date with new releases, or " "you want to give some feedback, then the mailing lists may be of interest to " "you:\n" msgstr "" "Si vous aimez mtPaint et que vous souhaitez être informé de la sortie de " "nouvelles versions, où si vous souhaitez faire quelques remarques ou " "suggestions, la liste de diffusion peu vous intéresser:\n" #: src/help.c:39 msgid "http://sourceforge.net/mail/?group_id=155874" msgstr "http://sourceforge.net/mail/?group_id=155874" #: src/help.c:42 msgid " Ctrl-N Create new image" msgstr " Ctrl-N Créer une nouvelle image" #: src/help.c:43 msgid " Ctrl-O Open Image" msgstr " Ctrl-O Ouvrir une image" #: src/help.c:44 msgid " Ctrl-S Save Image" msgstr " Ctrl-S Sauvegarder l'image" #: src/help.c:45 msgid " Ctrl-Shift-S Save layers file" msgstr " Ctrl-Maj-S Sauvegarder le fichier de calques" #: src/help.c:46 msgid " Ctrl-Q Quit program\n" msgstr " Ctrl-Q Quitter le programme\n" #: src/help.c:47 msgid " Ctrl-A Select whole image" msgstr " Ctrl-A Sélectionner toute l'image" #: src/help.c:48 msgid " Escape Select nothing, cancel paste box" msgstr " Escape Ne rien sélectionner, annuler la zone de collage" #: src/help.c:49 msgid " J Lasso selection\n" msgstr " J Lasso la sélection\n" #: src/help.c:50 msgid " Ctrl-C Copy selection to clipboard" msgstr " Ctrl-C Copier la sélection vers le presse-papiers" #: src/help.c:51 msgid "" " Ctrl-X Copy selection to clipboard, and then paint current " "pattern to selection area" msgstr "" " Ctrl-X Copier la sélection vers le presse-papiers, puis peindre la " "sélection avec le motif courant" #: src/help.c:52 msgid " Ctrl-V Paste clipboard to centre of current view" msgstr "" " Ctrl-V Coller le presse-papiers au centre de l'affichage actuel" #: src/help.c:53 msgid " Ctrl-K Paste clipboard to location it was copied from" msgstr "" " Ctrl-K Coller le presse-papiers au même emplacement que celui de " "l'original" #: src/help.c:54 msgid " Ctrl-Shift-V Paste clipboard to new layer" msgstr " Ctrl-Maj-V Coller le presse-papier sur un nouveau calque" #: src/help.c:55 msgid " Enter/Return Commit paste to canvas" msgstr " Entrée Valider les modifications faites au canevas" #: src/help.c:56 msgid " Shift+Enter/Return Commit paste and swap canvas into the clipboard\n" msgstr "" " Maj+Entrée Applique le coller et déplace le canevas vers le presse-" "papier\n" #: src/help.c:57 msgid " Arrow keys Paint Mode - Move the mouse pointer" msgstr " Flèches Mode dessin - Déplacer le curseur de la souris" #: src/help.c:58 msgid "" " Arrow keys Selection Mode - Nudge selection box or paste box by one " "pixel" msgstr "" " Flèches Mode sélection - Déplacer le cadre de sélection ou la zone " "de collage d'un pixel" #: src/help.c:59 msgid "" " Shift+Arrow keys Nudge mouse pointer, selection box or paste box by x " "pixels - x is defined by the Preferences window" msgstr "" " Maj+Flèches Déplacer le curseur de la souris, le cadre de sélection ou " "la zone de collage de x pixels - x est défini dans les préférences" #: src/help.c:60 msgid " Ctrl+Arrows Move layer or resize selection box" msgstr "" " Ctrl+Flèches Déplacer le calque ou redimmensionner le cadre de sélection" #: src/help.c:61 msgid " Ctrl+Shift+Arrows Move layer or resize selection box by x pixels\n" msgstr "" " Ctrl+Maj+Flèches Déplacer le calque ou redimensionner le cadre de " "sélection de x pixels\n" #: src/help.c:62 msgid " Enter/Return Paint Mode - Simulate left click" msgstr " Entrée Mode de peinture - Simulation du clic gauche" #: src/help.c:63 msgid " Backspace Paint Mode - Simulate right click\n" msgstr " Retour arrière Mode de peinture - Simulation du clic droit\n" #: src/help.c:64 msgid "" " [ or ] Change colour A to the next or previous palette item" msgstr "" " [ ou ] Remplacer la couleur A par la prochaine ou précédente " "couleur de la palette" #: src/help.c:65 msgid "" " Shift+[ or ] Change colour B to the next or previous palette item\n" msgstr "" " Maj+[ ou ] Remplacer la couleur B par la prochaine ou précédente " "couleur de la palette\n" #: src/help.c:66 msgid " Delete Crop image to selection" msgstr " Suppr Recadrer l'image" #: src/help.c:67 msgid "" " Insert Transform colours - i.e. Brightness, Contrast, " "Saturation, Posterize, Gamma" msgstr "" " Inser Modifier les couleurs - La luminosité, le contraste, la " "saturation, le gamma ..." #: src/help.c:68 msgid " Ctrl-G Greyscale the image" msgstr "" " Ctrl-G Passer l'image en niveau de gris (sans correction gamma)" #: src/help.c:69 msgid " Shift-Ctrl-G Greyscale the image (Gamma corrected)" msgstr "" " Maj-Ctrl-G Passer l'image en niveau de gris (avec correction gamma)" #: src/help.c:70 msgid " Ctrl+M Mirror the image" msgstr " Ctrl+M Miroir Horizontal" #: src/help.c:71 msgid " Shift-Ctrl-I Invert the image\n" msgstr " Maj-Ctrl-I Inverser l'image\n" #: src/help.c:72 msgid "" " Ctrl-T Draw a rectangle around the selection area with the " "current fill" msgstr "" " Ctrl-T Dessiner un rectangle autour de la zone de sélection avec " "le motif courant" #: src/help.c:73 msgid " Ctrl-Shift-T Fill in the selection area with the current fill" msgstr " Ctrl-Maj-T Remplir la zone de sélection avec le motif courant" #: src/help.c:74 msgid " Ctrl-L Draw an ellipse spanning the selection area" msgstr " Ctrl-L Dessiner une ellipse tenant dans la zone de sélection" #: src/help.c:75 msgid " Ctrl-Shift-L Draw a filled ellipse spanning the selection area\n" msgstr "" " Ctrl-Maj-L Dessiner une ellipse pleine tenant dans la zone de " "sélection\n" #: src/help.c:76 msgid " Ctrl-E Edit the RGB values for colours A & B" msgstr " Ctrl-E Éditer les valeurs RVB des couleurs A & B" #: src/help.c:77 msgid " Ctrl-W Edit all palette colours\n" msgstr " Ctrl-W Éditer la palette de couleur\n" #: src/help.c:78 msgid " Ctrl-P Preferences" msgstr " Ctrl-P Préférences" #: src/help.c:79 msgid " Ctrl-I Information\n" msgstr " Ctrl-I Information\n" #: src/help.c:80 msgid " Ctrl-Z Undo last action" msgstr " Ctrl-Z Annuler la dernière opération" #: src/help.c:81 msgid " Ctrl-R Redo an undone action\n" msgstr " Ctrl-R Refaire une opération annulée\n" #: src/help.c:82 msgid " Shift-T Text Tool (GTK+)" msgstr " Maj-T Outil Texte (GTK+)" #: src/help.c:83 msgid " T Text Tool (FreeType)\n" msgstr " T Outil Texte (FreeType)\n" #: src/help.c:84 msgid " V View Window" msgstr " V Fenêtre d'aperçu" #: src/help.c:85 msgid " L Layers Window\n" msgstr " L Fenêtre des calques\n" #: src/help.c:86 msgid " Ctrl-H Toggle Hide Image mode" msgstr " Ctrl-H Cacher/Afficher l'image" #: src/help.c:87 msgid " B Toggle Snap to Tile Grid mode\n" msgstr " B Dé/Active le magnétisme de grille\n" #: src/help.c:88 msgid " X Swap Colours A & B" msgstr " X Échanger couleurs A & B" #: src/help.c:89 msgid " E Choose Colour\n" msgstr " E Choisir couleur\n" #: src/help.c:90 msgid "" " A Draw open arrow head when using the line tool (size set " "by flow setting)" msgstr "" " A Dessine une tête de flèche ouverte quand l'outil ligne est " "utilisé (taille fixée par l'indicateur flux)" #: src/help.c:91 msgid "" " S Draw closed arrow head when using the line tool (size " "set by flow setting)\n" msgstr "" " S Dessine une tête de flèche fermée quand l'outil ligne est " "utilisé (taille fixée par l'indicateur flux)\n" #: src/help.c:92 msgid " D Line Tool" msgstr " D Outil Ligne" #: src/help.c:93 msgid " F Flood Fill Tool\n" msgstr " F Outil Remplissage\n" #: src/help.c:94 msgid " +,= Main edit window - Zoom in" msgstr " +,= Fenêtre principale - Zoom +" #: src/help.c:95 msgid " - Main edit window - Zoom out" msgstr " - Fenêtre principale - Zoom -" #: src/help.c:96 msgid " Shift +,= View window - Zoom in" msgstr " Maj +,= Fenêtre d'affichage - Zoom +" #: src/help.c:97 msgid " Shift - View window - Zoom out\n" msgstr " Maj - Fenêtre d'affichage - Zoom -\n" #: src/help.c:98 #, c-format msgid " 1 10% zoom" msgstr " 1 10% zoom" #: src/help.c:99 #, c-format msgid " 2 25% zoom" msgstr " 2 25% zoom" #: src/help.c:100 #, c-format msgid " 3 50% zoom" msgstr " 3 50% zoom" #: src/help.c:101 #, c-format msgid " 4 100% zoom" msgstr " 4 100% zoom" #: src/help.c:102 #, c-format msgid " 5 400% zoom" msgstr " 5 400% zoom" #: src/help.c:103 #, c-format msgid " 6 800% zoom" msgstr " 6 800% zoom" #: src/help.c:104 #, c-format msgid " 7 1200% zoom" msgstr " 7 1200% zoom" #: src/help.c:105 #, c-format msgid " 8 1600% zoom" msgstr " 8 1600% zoom" #: src/help.c:106 #, c-format msgid " 9 2000% zoom\n" msgstr " 9 2000% zoom\n" #: src/help.c:107 msgid " Shift + 1 Edit image channel" msgstr " Maj + 1 Éditer le canal Image" #: src/help.c:108 msgid " Shift + 2 Edit alpha channel" msgstr " Maj + 2 Éditer le canal Alpha" #: src/help.c:109 msgid " Shift + 3 Edit selection channel" msgstr " Maj + 3 Éditer le canal Sélection" #: src/help.c:110 msgid " Shift + 4 Edit mask channel\n" msgstr " Maj + 4 Éditer le canal Masque\n" #: src/help.c:111 msgid " F1 Help" msgstr " F1 Aide" #: src/help.c:112 msgid " F2 Choose Pattern" msgstr " F2 Sélectionner un motif" #: src/help.c:113 msgid " F3 Choose Brush" msgstr " F3 Sélectionner le pinceau" #: src/help.c:114 msgid " F4 Paint Tool" msgstr " F4 Outil de peinture" #: src/help.c:115 msgid " F5 Toggle Main Toolbar" msgstr " F5 Basculer la barre principale" #: src/help.c:116 msgid " F6 Toggle Tools Toolbar" msgstr " F6 Basculer la barre des outils" #: src/help.c:117 msgid " F7 Toggle Settings Toolbar" msgstr " F7 Basculer la barre des réglages" #: src/help.c:118 msgid " F8 Toggle Palette" msgstr " F8 Basculer la palette" #: src/help.c:119 msgid " F9 Selection Tool" msgstr " F9 Outil de sélection" #: src/help.c:120 msgid " F12 Toggle Dock Area\n" msgstr " F12 Basculer le Panneau Latéral\n" #: src/help.c:121 msgid " Ctrl + F1 - F12 Save current clipboard to file 1-12" msgstr "" " Ctrl + F1 - F12 Sauver le presse-papiers courant en tant que fichier 1-12" #: src/help.c:122 msgid " Shift + F1 - F12 Load clipboard from file 1-12\n" msgstr " Maj + F1 - F12 Charger le presse-papiers depuis le fichier 1-12\n" #: src/help.c:123 msgid "" " Ctrl + 1, 2, ... , 0 Set opacity to 10%, 20%, ... , 100% (main or keypad " "numbers)" msgstr " Ctrl + 1, 2, ... , 0 Définir l'opacité à 10%, 20%, ... , 100%" #: src/help.c:124 msgid " Ctrl + + or = Increase opacity by 1" msgstr " Ctrl + + or = Augmenter l'opacité de 1" #: src/help.c:125 msgid " Ctrl + - Decrease opacity by 1\n" msgstr " Ctrl + - Réduire l'opacité de 1\n" #: src/help.c:126 msgid "" " Home Show or hide main window menu/toolbar/status bar/palette" msgstr " Origine Basculer le mode plein écran" #: src/help.c:127 msgid " Page Up Scale Image" msgstr " Page Haute Changer l'échelle de l'image" #: src/help.c:128 msgid " Page Down Resize Image canvas" msgstr " Page Basse Redimensionner la taille du canevas" #: src/help.c:129 msgid " End Pan Window" msgstr " Fin Aperçu réduit" #: src/help.c:132 msgid " Left button Paint to canvas using the current tool" msgstr " Bouton gauche Peindre en utilisant l'outil courant" #: src/help.c:133 msgid "" " Middle button Selects the point which will be the centre of the " "image after the next zoom" msgstr "" " Bouton du milieu Sélectionner le point qui deviendra le centre de " "l'image après le prochain zoom" #: src/help.c:134 msgid "" " Right button Commit paste to canvas / Stop drawing current line / " "Cancel selection\n" msgstr "" " Bouton droit Valider l'opération / Arrêter le dessin actuel / " "Annuler la sélection\n" #: src/help.c:135 msgid "" " Scroll Wheel In GTK+2/3 the user can have the scroll wheel zoom in " "or out via the Preferences window\n" msgstr "" " Molette Avec GTK+2/3 l'utilisateur peu zoomer avec la molette " "grâce à la fenêtre des préférences\n" #: src/help.c:136 msgid " Ctrl+Left button Choose colour A from under mouse pointer" msgstr "" " Ctrl+Bouton gauche Définis la couleur se trouvant sous le curseur de la " "souris comme couleur A" #: src/help.c:137 msgid " Ctrl+Left button Clone tool - Select source" msgstr " Ctrl+Bouton gauche Outil de clonage - Sélectionner la source" #: src/help.c:138 msgid "" " Ctrl+Middle button Create colour A/B and pattern based on the RGB colour " "in A (RGB images only)" msgstr "" " Ctrl+bouton du milieu Créer couleur A/B et motif basés sur la couleur RVB " "en A (images RVB seulement)" #: src/help.c:139 msgid " Ctrl+Right button Choose colour B from under mouse pointer" msgstr "" " Ctrl+Bouton droit Définis la couleur se trouvant sous le curseur de la " "souris comme couleur B" #: src/help.c:140 msgid "" " Ctrl+Right button Polygon tool - Delete last point / Delete nearest " "point" msgstr "" " Ctrl+Bouton droit Outil polygone - Supprimer le dernier point / " "Supprimer le point le plus proche" #: src/help.c:141 msgid " Ctrl+Scroll Wheel Scroll the main edit window left or right\n" msgstr "" " Ctrl+Molette Déplacer la fenêtre d'édition vers la gauche ou vers " "la droite\n" #: src/help.c:142 msgid "" " Ctrl+Double click Set colour A or B to average colour under brush " "square or selection marquee (RGB only)\n" msgstr "" " Ctrl+Double clic Régler la couleur A ou B sur la couleur moyenne du " "cadre de sélection ou du carré de pinceau (RVB seulement)\n" #: src/help.c:143 msgid "" " Shift+Right button Selects the point which will be the centre of the " "image after the next zoom\n" "\n" msgstr "" " Maj+Bouton droit Sélectionner le point qui deviendra le centre de " "l'image après le prochain zoom\n" "\n" #: src/help.c:144 msgid "You can fixate the X/Y co-ordinates while moving the mouse:\n" msgstr "" "Vous pouvez bloquer les déplacements X/Y lors du déplacement de la souris:\n" #: src/help.c:145 msgid " Shift Constrain mouse movements to vertical line" msgstr "" " Maj Limiter le mouvement de la souris à une ligne " "verticale" #: src/help.c:146 msgid " Shift+Ctrl Constrain mouse movements to horizontal line" msgstr "" " Maj+Ctrl Limiter le mouvement de la souris à une ligne " "horizontale" #: src/help.c:149 msgid "mtPaint is maintained by Dmitry Groshev.\n" msgstr "mtPaint est maintenu par Dmitry Groshev.\n" #: src/help.c:150 msgid "wjaguar@users.sourceforge.net" msgstr "wjaguar@users.sourceforge.net" #: src/help.c:151 msgid "http://mtpaint.sourceforge.net/\n" msgstr "http://mtpaint.sourceforge.net/\n" #: src/help.c:152 msgid "" "The following people (in alphabetical order) have contributed directly to " "the project, and are therefore worthy of gracious thanks for their " "generosity and hard work:\n" "\n" msgstr "" "Les personnes suivantes (par ordre alphabétique) ont directement participé " "au projet, Nous les remercions pour leur générosité et pour le dur travail " "qu'elles ont fourni:\n" "\n" #: src/help.c:153 msgid "Authors\n" msgstr "Auteurs\n" #: src/help.c:154 msgid "" "Dmitry Groshev - Contributing developer for version 2.30. Lead developer and " "maintainer from version 3.00 to the present." msgstr "" "Dmitry Groshev - A participé au développement de la version 2.30. " "Développeur principal et mainteneur depuis la version 3.00 jusqu'à " "maintenant." #: src/help.c:155 msgid "" "Mark Tyler - Original author and maintainer up to version 3.00, occasional " "contributor thereafter." msgstr "" "Mark Tyler - Auteur original et mainteneur jusqu'à la version 3.00, " "maintenant contributeur occasionnel." #: src/help.c:156 msgid "" "Xiaolin Wu - Wrote the Wu quantizing method - see wu.c for more " "information.\n" "\n" msgstr "" "Xiaolin Wu - A écris la méthode de réduction Wu - voir see wu.c pour plus de " "détails.\n" "\n" #: src/help.c:157 msgid "" "General Contributions (Feedback and Ideas for improvements unless otherwise " "stated)\n" msgstr "" "Contributions diverses (retours sur l'utilisation et idées d'améliorations " "sauf indication contraire)\n" #: src/help.c:158 msgid "Abdulla Al Muhairi - Website redesign April 2005" msgstr "Abdulla Al Muhairi - Nouveau look du site en Avril 2005" #: src/help.c:159 msgid "Alan Horkan" msgstr "Alan Horkan" #: src/help.c:160 msgid "Alexandre Prokoudine" msgstr "Alexandre Prokoudine" #: src/help.c:161 msgid "Antonio Andrea Bianco" msgstr "Antonio Andrea Bianco" #: src/help.c:162 msgid "Charlie Ledocq" msgstr "" #: src/help.c:163 msgid "Dennis Lee" msgstr "Dennis Lee" #: src/help.c:164 msgid "Donald White" msgstr "" #: src/help.c:165 msgid "Ed Jason" msgstr "Ed Jason" #: src/help.c:166 msgid "" "Eddie Kohler - Created Gifsicle which is needed for the creation and viewing " "of animated GIF files http://www.lcdf.org/gifsicle/" msgstr "" "Eddie Kohler - Créateur de Gifsicle qui est utilisé pour la création et " "l'édition des animations GIF http://www.lcdf.org/gifsicle/" #: src/help.c:167 msgid "" "Guadalinex Team (Junta de Andalucia) - man page, Launchpad/Rosetta " "registration" msgstr "" "Guadalinex Team (Junta de Andalucia) - Pages man, import dans Launchpad/" "Rosetta" #: src/help.c:168 msgid "Lou Afonso" msgstr "Lou Afonso" #: src/help.c:169 msgid "Magnus Hjorth" msgstr "Magnus Hjorth" #: src/help.c:170 msgid "Martin Zelaia" msgstr "Martin Zelaia" #: src/help.c:171 msgid "Pasi Kallinen" msgstr "" #: src/help.c:172 msgid "Pavel Ruzicka" msgstr "Pavel Ruzicka" #: src/help.c:173 msgid "Puppy Linux (Barry Kauler)" msgstr "Puppy Linux (Barry Kauler)" #: src/help.c:174 msgid "Victor Copovi" msgstr "" #: src/help.c:175 msgid "Vlastimil Krejcir" msgstr "Vlastimil Krejcir" #: src/help.c:176 msgid "" "William Kern\n" "\n" msgstr "" "William Kern\n" "\n" #: src/help.c:177 msgid "Translations\n" msgstr "Traductions\n" #: src/help.c:178 msgid "Brazilian Portuguese - Paulo Trevizan, Valter Nazianzeno" msgstr "Brésilien Portugais - Paulo Trevizan, Valter Nazianzeno" #: src/help.c:179 msgid "Czech - Pavel Ruzicka, Martin Petricek, Roman Hornik, Pavel Fric" msgstr "Tchèque - Pavel Ruzicka, Martin Petricek, Roman Hornik, Pavel Fric" #: src/help.c:180 msgid "Dutch - Hans Strijards, Pjotr" msgstr "Néerlandais - Hans Strijards, Pjotr" #: src/help.c:181 msgid "" "French - Nicolas Velin, Pascal Billard, Sylvain Cresto, Johan Serre, " "Philippe Etienne, Victor Copovi" msgstr "" "Français - Nicolas Velin, Pascal Billard, Sylvain Cresto, Johan Serre, " "Philippe Etienne, Victor Copovi" #: src/help.c:182 msgid "Galician - Miguel Anxo Bouzada" msgstr "Galicien - Miguel Anxo Bouzada" #: src/help.c:183 msgid "German - Oliver Frommel, B. Clausius, Ulrich Ringel, Simon Brixel" msgstr "Allemand - Oliver Frommel, B. Clausius, Ulrich Ringel, Simon Brixel" #: src/help.c:184 msgid "Hungarian - Ur Balazs" msgstr "Hongrois - Ur Balazs" #: src/help.c:185 msgid "Italian - Angelo Gemmi" msgstr "Italien - Angelo Gemmi" #: src/help.c:186 msgid "Japanese - Norihiro YONEDA" msgstr "Japonais - Norihiro YONEDA" #: src/help.c:187 msgid "Kabyle - Yacine Bouklif" msgstr "" #: src/help.c:188 msgid "Polish - Bartosz Kaszubowski, LucaS" msgstr "Polonais - Bartosz Kaszubowski, LucaS" #: src/help.c:189 msgid "Portuguese - Israel G. Lugo, Tiago Silva" msgstr "Portugais - Israel G. Lugo, Tiago Silva" #: src/help.c:190 msgid "Russian - Sergey Irupin, Dmitry Groshev" msgstr "Russe - Sergey Irupin, Dmitry Groshev" #: src/help.c:191 msgid "Simplified Chinese - Cecc" msgstr "Chinois simplifié - Cecc" #: src/help.c:192 msgid "Slovak - Jozef Riha" msgstr "Slovaque - Jozef Riha" #: src/help.c:193 msgid "" "Spanish - Guadalinex Team (Junta de Andalucia), Antonio Sanchez Leon, Miguel " "Anxo Bouzada, Francisco Jose Rey, Adolfo Jayme" msgstr "" "Espagnol - Guadalinex Team (Junta de Andalucia), Antonio Sanchez Leon, " "Miguel Anxo Bouzada, Francisco Jose Rey, Adolfo Jayme" #: src/help.c:194 msgid "Swedish - Daniel Nylander, Daniel Eriksson" msgstr "Suédois - Daniel Nylander, Daniel Eriksson" #: src/help.c:195 msgid "Tagalog - Anjelo delCarmen" msgstr "" #: src/help.c:196 msgid "Taiwanese Chinese - Wei-Lun Chao" msgstr "Taiwanais - Wei-Lun Chao" #: src/help.c:197 msgid "Turkish - Muhammet Kara, Tutku Dalmaz" msgstr "Turque - Muhammet Kara, Tutku Dalmaz" #: src/info.c:258 msgid "Information" msgstr "Information" #: src/info.c:260 msgid "Memory" msgstr "Mémoire" #: src/info.c:261 msgid "Total memory for main + undo images" msgstr "Mémoire totale pour l'image principale + des annulations" #: src/info.c:263 msgid "Undo / Redo / Max levels used" msgstr "Défaire / Refaire / niveau maximal utilisé" #: src/info.c:265 msgid "Unused" msgstr "Inutilisé" #: src/info.c:269 msgid "Unique RGB pixels" msgstr "Pixels RVB uniques" #: src/info.c:272 src/layer.c:121 msgid "Layers" msgstr "Calques" #: src/info.c:273 msgid "Total layer memory usage" msgstr "Utilisation mémoire des calques" #: src/info.c:277 msgid "Colour Histogram" msgstr "Histogramme des couleurs" #: src/info.c:289 src/otherwindow.c:1614 msgid "Index" msgstr "Index" #: src/info.c:290 msgid "Canvas pixels" msgstr "Pixels du canevas" #: src/info.c:328 #, c-format msgid "Clipboard = %i x %i" msgstr "Presse-papiers = %i x %i" #: src/info.c:328 #, c-format msgid "Clipboard = %i x %i x RGB" msgstr "Presse-papiers = %i x %i x RVB" #: src/info.c:377 msgid "Orphans" msgstr "Orphelins" #: src/info.c:383 #, c-format msgid "Colour index totals - %i of %i used" msgstr "Couleurs indexées - %i couleur(s) sur %i utilisée(s)" #: src/inifile.c:966 msgid "" "Could not find home directory. Using current directory as home directory." msgstr "" "N'a pas pu trouver le répertoire personnel. Emploi du répertoire actuel en " "tant que répertoire personnel." #: src/layer.c:63 msgid "Background" msgstr "Arrière-plan" #: src/layer.c:122 src/mainwindow.c:5931 msgid "(Modified)" msgstr "(Modifié)" #: src/layer.c:123 src/mainwindow.c:5932 msgid "Untitled" msgstr "Sans titre" #: src/layer.c:308 #, c-format msgid "Do you really want to delete layer %i (%s) ?" msgstr "Voulez-vous vraiment supprimer le calque %i (%s) ?" #: src/layer.c:380 msgid "" "One or more of the layers contains changes that have not been saved. Do you " "really want to lose these changes?" msgstr "" "Un ou plusieurs calques contien(nen)t des modifications qui n'ont pas été " "enregistrées. Voulez-vous vraiment perdre ces modifications ?" #: src/layer.c:381 src/mainwindow.c:1028 msgid "Cancel Operation" msgstr "Annuler" #: src/layer.c:381 src/mainwindow.c:1028 msgid "Lose Changes" msgstr "Perdre les modifications" #: src/layer.c:523 #, c-format msgid "%d layers failed to load" msgstr "Erreur lors de l'ouverture de %d calques" #: src/layer.c:826 msgid "" "One or more of the image layers has not been saved. You must save each " "image individually before saving the layers text file in order to load this " "composite image in the future." msgstr "" "Au moins un des calques de l'image n'a pas été sauvegardé. Vous devez " "sauvegarder individuellement toutes les images avant de sauvegarder le " "fichier décrivant cette composition." #: src/layer.c:841 msgid "Do you really want to delete all of the layers?" msgstr "Voulez-vous vraiment supprimer tous les calques ?" #: src/layer.c:970 msgid "You cannot add any more layers." msgstr "Impossible d'ajouter plus de calques." #: src/layer.c:1083 src/otherwindow.c:241 msgid "New Layer" msgstr "Nouveau calque" #: src/layer.c:1085 msgid "Raise" msgstr "Monter" #: src/layer.c:1087 msgid "Lower" msgstr "Descendre" #: src/layer.c:1089 msgid "Duplicate Layer" msgstr "Dupliquer le calque" #: src/layer.c:1091 msgid "Centralise Layer" msgstr "Centrer le calque" #: src/layer.c:1093 msgid "Delete Layer" msgstr "Supprimer le calque" #: src/layer.c:1095 msgid "Close Layers Window" msgstr "Fermer la Fenêtre des Calques" #: src/layer.c:1101 msgid "Layer Name" msgstr "Nom du calque" #: src/layer.c:1104 src/toolbar.c:209 msgid "Position" msgstr "Position" #: src/layer.c:1112 msgid "Transparent Colour" msgstr "Couleur transparente" #: src/layer.c:1117 msgid "Show all layers in main window" msgstr "Afficher tous les calques dans la fenêtre principale" #: src/mainwindow.c:67 src/otherwindow.c:844 src/otherwindow.c:2756 #: src/toolbar.c:342 msgid "Image" msgstr "Image" #: src/mainwindow.c:69 src/mainwindow.c:489 src/otherwindow.c:1613 #: src/otherwindow.c:2302 msgid "RGB" msgstr "RVB" #: src/mainwindow.c:69 src/otherwindow.c:1613 src/otherwindow.c:2302 msgid "sRGB" msgstr "sRVB" #: src/mainwindow.c:342 msgid "There were no unused colours to remove!" msgstr "Il n'y avait aucune couleur inutilisée à enlever !" #: src/mainwindow.c:371 msgid "The palette does not contain 2 colours that have identical RGB values" msgstr "" "La palette ne contient pas 2 couleurs qui ont des valeurs RVB identiques" #: src/mainwindow.c:374 #, c-format msgid "" "The palette contains %i colours that have identical RGB values. Do you " "really want to merge them into one index and realign the canvas?" msgstr "" "La palette contient %i couleurs qui ont des valeurs RVB identiques. Voulez-" "vous vraiment les fusionner en une seule et réaligner le canevas ?" #: src/mainwindow.c:492 msgid "indexed" msgstr "Indexé" #: src/mainwindow.c:498 #, c-format msgid "" "You are trying to save an %s image to an %s file which is not possible. I " "would suggest you save with a PNG extension." msgstr "" "Vous essayez de enregistrer une image %s dans un fichier %s, ce qui n'est " "pas possible. Je vous suggère de enregistrer avec l'extension PNG." #: src/mainwindow.c:500 #, c-format msgid "" "You are trying to save an %s file with a palette of more than %d colours. " "Either use another format or reduce the palette to %d colours." msgstr "" "Vous essayez de enregistrer un fichier %s avec une palette de plus de %d " "couleurs. Utilisez un autre format ou réduisez la palette à %d couleurs." #: src/mainwindow.c:578 msgid "Unable to load clipboard" msgstr "Incapable de charger le presse-papiers" #: src/mainwindow.c:604 msgid "Unable to save clipboard" msgstr "Incapable de sauvegarder le presse-papiers" #: src/mainwindow.c:775 msgid "Zoom in" msgstr "Zoom avant" #: src/mainwindow.c:777 msgid "Zoom out" msgstr "Zoom arrière" #: src/mainwindow.c:779 #, c-format msgid "10% zoom" msgstr "" #: src/mainwindow.c:781 #, c-format msgid "25% zoom" msgstr "" #: src/mainwindow.c:783 #, c-format msgid "50% zoom" msgstr "" #: src/mainwindow.c:785 #, c-format msgid "100% zoom" msgstr "" #: src/mainwindow.c:787 #, c-format msgid "400% zoom" msgstr "" #: src/mainwindow.c:789 #, c-format msgid "600% zoom" msgstr "" #: src/mainwindow.c:791 #, c-format msgid "800% zoom" msgstr "" #: src/mainwindow.c:793 #, c-format msgid "1000% zoom" msgstr "" #: src/mainwindow.c:795 #, c-format msgid "1200% zoom" msgstr "" #: src/mainwindow.c:797 #, c-format msgid "1600% zoom" msgstr "" #: src/mainwindow.c:799 #, c-format msgid "2000% zoom" msgstr "" #: src/mainwindow.c:801 #, c-format msgid "4000% zoom" msgstr "" #: src/mainwindow.c:803 #, c-format msgid "8000% zoom" msgstr "" #: src/mainwindow.c:805 #, c-format msgid "10% opacity" msgstr "10% opacité" #: src/mainwindow.c:807 #, c-format msgid "20% opacity" msgstr "20% opacité" #: src/mainwindow.c:809 #, c-format msgid "30% opacity" msgstr "30% opacité" #: src/mainwindow.c:811 #, c-format msgid "40% opacity" msgstr "40% opacité" #: src/mainwindow.c:813 #, c-format msgid "50% opacity" msgstr "50% opacité" #: src/mainwindow.c:815 #, c-format msgid "60% opacity" msgstr "60% opacité" #: src/mainwindow.c:817 #, c-format msgid "70% opacity" msgstr "70% opacité" #: src/mainwindow.c:819 #, c-format msgid "80% opacity" msgstr "80% opacité" #: src/mainwindow.c:821 #, c-format msgid "90% opacity" msgstr "90% opacité" #: src/mainwindow.c:823 #, c-format msgid "100% opacity" msgstr "100% opacité" #: src/mainwindow.c:825 msgid "Increase opacity" msgstr "Augmenter l'opacité" #: src/mainwindow.c:827 msgid "Decrease opacity" msgstr "Réduire l'opacité" #: src/mainwindow.c:829 msgid "Draw open arrow head" msgstr "Dessine une tête de flèche ouverte" #: src/mainwindow.c:831 msgid "Draw closed arrow head" msgstr "Dessine une tête de flèche fermée" #: src/mainwindow.c:833 msgid "Previous colour A" msgstr "Couleur A précédente" #: src/mainwindow.c:835 msgid "Next colour A" msgstr "Couleur A suivante" #: src/mainwindow.c:837 msgid "Previous colour B" msgstr "Couleur B précédente" #: src/mainwindow.c:839 msgid "Next colour B" msgstr "Couleur B suivante" #: src/mainwindow.c:841 msgid "Previous pattern" msgstr "Motif précédent" #: src/mainwindow.c:843 msgid "Next pattern" msgstr "Motif suivant" #: src/mainwindow.c:845 msgid "Larger brush" msgstr "Brosse plus grande" #: src/mainwindow.c:847 msgid "Smaller brush" msgstr "Brosse plus petite" #: src/mainwindow.c:849 msgid "View window - Zoom in" msgstr "Fenêtre d'affichage - Zoom avant" #: src/mainwindow.c:851 msgid "View window - Zoom out" msgstr "Fenêtre d'affichage - Zoom arrière" #: src/mainwindow.c:1027 msgid "" "This canvas/palette contains changes that have not been saved. Do you " "really want to lose these changes?" msgstr "" "Ce canevas/cette palette contient des modifications qui n'ont pas été " "enregistrées. Voulez-vous vraiment perdre ces modifications ?" #: src/mainwindow.c:1094 msgid "Do you really want to quit?" msgstr "Voulez-vous réellement quitter ?" #: src/mainwindow.c:3754 msgid "Empty string or broken quoting" msgstr "Chaîne vide ou guillemets cassés" #: src/mainwindow.c:3755 msgid "Script must begin with a command" msgstr "Le script doit commencer par une commande" #: src/mainwindow.c:3756 msgid "Script nesting limit exceeded" msgstr "Limite d'imbrication des scripts dépassée" #: src/mainwindow.c:3765 #, c-format msgid "'%s' does not match any item" msgstr "'%s' ne correspond à aucun élément" #: src/mainwindow.c:3767 #, c-format msgid "'%s' matches a non-scriptable item" msgstr "'%s' correspond à un élément non scriptable" #: src/mainwindow.c:3769 #, c-format msgid "'%s' matches a disabled item" msgstr "'%s' correspond à un élément désactivé" #: src/mainwindow.c:3788 #, c-format msgid "'%s' value does not fit item" msgstr "La valeur '%s' ne correspond pas à l'élément" #: src/mainwindow.c:3969 msgid "Script" msgstr "Script" #: src/mainwindow.c:3982 src/spawn.c:656 src/spawn.c:662 msgid "Action" msgstr "Action" #: src/mainwindow.c:3991 src/spawn.c:666 msgid "Execute" msgstr "Appliquer" #: src/mainwindow.c:4045 msgid "Unable to load script" msgstr "Impossible de charger le script" #: src/mainwindow.c:5182 msgid "/_File" msgstr "/_Fichier" #: src/mainwindow.c:5184 msgid "//New" msgstr "//Nouveau" #: src/mainwindow.c:5186 msgid "//Open ..." msgstr "//Ouvrir ..." #: src/mainwindow.c:5188 src/mainwindow.c:5669 msgid "//Save" msgstr "//Enregistrer" #: src/mainwindow.c:5190 src/mainwindow.c:5549 src/mainwindow.c:5627 #: src/mainwindow.c:5671 msgid "//Save As ..." msgstr "//Enregistrer sous ..." #: src/mainwindow.c:5192 msgid "//Export Undo Images ..." msgstr "//Exporter les tampons d'annulation ..." #: src/mainwindow.c:5194 msgid "//Export Undo Images (reversed) ..." msgstr "//Exporter les tampons d'annulation (inversé) ..." #: src/mainwindow.c:5196 msgid "//Export ASCII Art ..." msgstr "//Exporter au format Art ASCII ..." #: src/mainwindow.c:5198 msgid "//Export Animated GIF ..." msgstr "//Exporter une animation GIF ..." #: src/mainwindow.c:5201 msgid "//Actions" msgstr "//Actions" #: src/mainwindow.c:5235 src/mainwindow.c:5488 msgid "///Configure" msgstr "///Paramètrer" #: src/mainwindow.c:5290 msgid "//Quit" msgstr "//Quitter" #: src/mainwindow.c:5293 msgid "/_Edit" msgstr "/_Édition" #: src/mainwindow.c:5295 msgid "//Undo" msgstr "//Annuler" #: src/mainwindow.c:5297 msgid "//Redo" msgstr "//Refaire" #: src/mainwindow.c:5300 msgid "//Cut" msgstr "//Couper" #: src/mainwindow.c:5302 msgid "//Copy" msgstr "//Copier" #: src/mainwindow.c:5304 msgid "//Copy To Palette" msgstr "//Copier dans palette" #: src/mainwindow.c:5306 msgid "//Paste To Centre" msgstr "//Coller au centre" #: src/mainwindow.c:5308 msgid "//Paste To New Layer" msgstr "//Coller dans un nouveau calque" #: src/mainwindow.c:5310 msgid "//Paste" msgstr "//Coller" #: src/mainwindow.c:5312 msgid "//Paste Text" msgstr "//Coller le texte" #: src/mainwindow.c:5318 msgid "//Paste Text (FreeType)" msgstr "//Coller le texte (FreeType)" #: src/mainwindow.c:5321 msgid "//Paste Palette" msgstr "//Coller palette" #: src/mainwindow.c:5323 msgid "//Load Clipboard" msgstr "//Charger le presse-papiers" #: src/mainwindow.c:5350 msgid "//Save Clipboard" msgstr "//Enregister le presse-papiers" #: src/mainwindow.c:5377 msgid "//Import Clipboard from System" msgstr "//Importer presse-papiers du système" #: src/mainwindow.c:5378 msgid "//Export Clipboard to System" msgstr "//Exporter presse-papiers vers le système" #: src/mainwindow.c:5381 msgid "//Choose Pattern ..." msgstr "//Choisir un Motif ..." #: src/mainwindow.c:5383 msgid "//Choose Brush ..." msgstr "//Choisir le Pinceau ..." #: src/mainwindow.c:5385 msgid "//Choose Colour ..." msgstr "//Choisir Couleur ..." #: src/mainwindow.c:5392 msgid "/_View" msgstr "/_Affichage" #: src/mainwindow.c:5394 msgid "//Show Main Toolbar" msgstr "//Barre principale" #: src/mainwindow.c:5396 msgid "//Show Tools Toolbar" msgstr "//Barre des outils" #: src/mainwindow.c:5399 msgid "//Show Settings Toolbar" msgstr "//Barre des réglages" #: src/mainwindow.c:5402 msgid "//Show Dock" msgstr "//Panneau latéral" #: src/mainwindow.c:5404 msgid "//Show Palette" msgstr "//Palette" #: src/mainwindow.c:5406 msgid "//Show Status Bar" msgstr "//Barre d'état" #: src/mainwindow.c:5409 msgid "//Toggle Image View" msgstr "//Mode plein écran" #: src/mainwindow.c:5413 msgid "//Centralize Image" msgstr "//Centrer l'image" #: src/mainwindow.c:5414 msgid "//Show Zoom Grid" msgstr "//Grille de zoom" #: src/mainwindow.c:5415 msgid "//Snap To Tile Grid" msgstr "//Aimanter à la grille de tuile" #: src/mainwindow.c:5417 msgid "//Configure Grid ..." msgstr "//Configurer la grille ..." #: src/mainwindow.c:5418 msgid "//Tracing Image ..." msgstr "//Tracer l'image ..." #: src/mainwindow.c:5421 msgid "//View Window" msgstr "//Fenêtre d'aperçu" #: src/mainwindow.c:5423 msgid "//Horizontal Split" msgstr "//Découper horizontalement" #: src/mainwindow.c:5425 msgid "//Focus View Window" msgstr "//Focaliser la fenêtre d'aperçu" #: src/mainwindow.c:5427 msgid "//Pan Window" msgstr "//Aperçu réduit" #: src/mainwindow.c:5430 msgid "//Layers Window" msgstr "//Fenêtre des calques" #: src/mainwindow.c:5433 msgid "/_Image" msgstr "/_Image" #: src/mainwindow.c:5436 msgid "//Convert To RGB" msgstr "//Convertir en Image RVB" #: src/mainwindow.c:5438 msgid "//Convert To Indexed ..." msgstr "//Convertir en Image indexée ..." #: src/mainwindow.c:5441 msgid "//Scale Canvas ..." msgstr "//Échelle de l'image ..." #: src/mainwindow.c:5443 msgid "//Resize Canvas ..." msgstr "//Taille du canevas ..." #: src/mainwindow.c:5445 msgid "//Crop" msgstr "//Recadrer l'image" #: src/mainwindow.c:5448 src/mainwindow.c:5517 msgid "//Flip Vertically" msgstr "//Miroir vertical" #: src/mainwindow.c:5449 src/mainwindow.c:5519 msgid "//Flip Horizontally" msgstr "//Miroir horizontal" #: src/mainwindow.c:5452 src/mainwindow.c:5521 msgid "//Rotate Clockwise" msgstr "//Rotation horaire" #: src/mainwindow.c:5453 src/mainwindow.c:5523 msgid "//Rotate Anti-Clockwise" msgstr "//Rotation antihoraire" #: src/mainwindow.c:5454 msgid "//Free Rotate ..." msgstr "//Rotation libre ..." #: src/mainwindow.c:5455 msgid "//Skew ..." msgstr "//Biais ..." #: src/mainwindow.c:5458 msgid "//Segment ..." msgstr "//Segmenter ..." #: src/mainwindow.c:5462 msgid "//Script ..." msgstr "//Script ..." #: src/mainwindow.c:5464 msgid "//Scripts" msgstr "//Scripts" #: src/mainwindow.c:5491 msgid "//Information ..." msgstr "//Informations ..." #: src/mainwindow.c:5494 msgid "//Preferences ..." msgstr "//Préférences ..." #: src/mainwindow.c:5497 msgid "/_Selection" msgstr "/_Sélection" #: src/mainwindow.c:5499 msgid "//Select All" msgstr "//Tout sélectionner" #: src/mainwindow.c:5501 msgid "//Select None (Esc)" msgstr "//Aucune (Échap)" #: src/mainwindow.c:5503 msgid "//Lasso Selection" msgstr "//Flottante" #: src/mainwindow.c:5505 msgid "//Lasso Selection Cut" msgstr "//Couper en sélection flottante" #: src/mainwindow.c:5508 msgid "//Outline Selection" msgstr "//Tracer le contour de la sélection" #: src/mainwindow.c:5510 msgid "//Fill Selection" msgstr "//Remplir la sélection" #: src/mainwindow.c:5512 msgid "//Outline Ellipse" msgstr "//Tracer une ellipse" #: src/mainwindow.c:5514 msgid "//Fill Ellipse" msgstr "//Remplir l'ellipse" #: src/mainwindow.c:5526 msgid "//Horizontal Ramp" msgstr "//Rampe horizontale" #: src/mainwindow.c:5528 msgid "//Vertical Ramp" msgstr "//Rampe verticale" #: src/mainwindow.c:5531 msgid "//Alpha Blend A,B" msgstr "//Alpha Mélange A,B" #: src/mainwindow.c:5533 msgid "//Move Alpha to Mask" msgstr "//Déplacer Alpha vers Masque" #: src/mainwindow.c:5535 msgid "//Mask Colour A,B" msgstr "//Masquer les couleurs A,B" #: src/mainwindow.c:5537 msgid "//Unmask Colour A,B" msgstr "//Démasquer les couleurs A,B" #: src/mainwindow.c:5539 msgid "//Mask All Colours" msgstr "//Masquer toutes les couleurs" #: src/mainwindow.c:5541 msgid "//Clear Mask" msgstr "//Effacer Masque" #: src/mainwindow.c:5544 msgid "/_Palette" msgstr "/_Palette" #: src/mainwindow.c:5548 src/mainwindow.c:5626 msgid "//Load ..." msgstr "//Charger ..." #: src/mainwindow.c:5550 msgid "//Load Default" msgstr "//Restaurer la palette par défaut" #: src/mainwindow.c:5552 msgid "//Mask All" msgstr "//Protéger toutes les couleurs" #: src/mainwindow.c:5553 msgid "//Mask None" msgstr "//Aucune protection" #: src/mainwindow.c:5555 msgid "//Swap A & B" msgstr "//Échanger A & B" #: src/mainwindow.c:5557 msgid "//Edit Colour A & B ..." msgstr "//Éditer les couleurs A & B ..." #: src/mainwindow.c:5559 msgid "//Dither A" msgstr "//Tramer la couleur A" #: src/mainwindow.c:5561 msgid "//Palette Editor ..." msgstr "//Éditeur de palette ..." #: src/mainwindow.c:5563 msgid "//Set Palette Size ..." msgstr "//Définir la taille de la palette ..." #: src/mainwindow.c:5564 msgid "//Merge Duplicate Colours" msgstr "//Fusionner les couleurs dupliquées" #: src/mainwindow.c:5566 msgid "//Remove Unused Colours" msgstr "//Supprimer les couleurs non utilisées" #: src/mainwindow.c:5569 msgid "//Create Quantized ..." msgstr "//Créer une palette quantifiée ..." #: src/mainwindow.c:5572 msgid "//Sort Colours ..." msgstr "//Trier les couleurs ..." #: src/mainwindow.c:5573 msgid "//Palette Shifter ..." msgstr "//Cycles ..." #: src/mainwindow.c:5574 msgid "//Pick Gradient ..." msgstr "//Ramasser le dégradé ..." #: src/mainwindow.c:5576 msgid "/Effe_cts" msgstr "/Effe_ts" #: src/mainwindow.c:5578 msgid "//Transform Colour ..." msgstr "//Modifier les couleurs ..." #: src/mainwindow.c:5580 msgid "//Invert" msgstr "//Inverse" #: src/mainwindow.c:5582 msgid "//Greyscale" msgstr "//Niveaux de gris" #: src/mainwindow.c:5584 msgid "//Greyscale (Gamma corrected)" msgstr "//Niveaux de gris (correction gamma)" #: src/mainwindow.c:5586 msgid "//Normalize" msgstr "//Normaliser" #: src/mainwindow.c:5587 src/mainwindow.c:5658 msgid "//Threshold ..." msgstr "//Seuil ..." #: src/mainwindow.c:5588 msgid "//Map ..." msgstr "//Mapper ..." #: src/mainwindow.c:5590 msgid "//Isometric Transformation" msgstr "//Transformation" #: src/mainwindow.c:5592 msgid "///Left Side Down" msgstr "///Côté gauche vers le bas" #: src/mainwindow.c:5593 msgid "///Right Side Down" msgstr "///Côté droit vers le bas" #: src/mainwindow.c:5594 msgid "///Top Side Right" msgstr "///Côté supérieur à droite" #: src/mainwindow.c:5595 msgid "///Bottom Side Right" msgstr "///Côté inférieur à droite" #: src/mainwindow.c:5598 msgid "//Edge Detect ..." msgstr "//Détecter les bords ..." #: src/mainwindow.c:5600 msgid "//Difference of Gaussians ..." msgstr "//Différence de gaussiens ..." #: src/mainwindow.c:5602 msgid "//Sharpen ..." msgstr "//Durcir ..." #: src/mainwindow.c:5604 msgid "//Unsharp Mask ..." msgstr "//Masque de netteté ..." #: src/mainwindow.c:5606 msgid "//Soften ..." msgstr "//Adoucir ..." #: src/mainwindow.c:5608 msgid "//Gaussian Blur ..." msgstr "//Flou gaussien ..." #: src/mainwindow.c:5610 msgid "//Kuwahara-Nagao Blur ..." msgstr "//Flou Kuwahara-Nagao ..." #: src/mainwindow.c:5612 msgid "//Emboss" msgstr "//Relief" #: src/mainwindow.c:5614 msgid "//Dilate" msgstr "//Dilater" #: src/mainwindow.c:5616 msgid "//Erode" msgstr "//Eroder" #: src/mainwindow.c:5619 msgid "//Solid Noise ..." msgstr "//Bruit uniforme ..." #: src/mainwindow.c:5620 msgid "//Bacteria ..." msgstr "//Bactéries ..." #: src/mainwindow.c:5623 msgid "/Cha_nnels" msgstr "/Ca_naux" #: src/mainwindow.c:5625 msgid "//New ..." msgstr "//Nouveau ..." #: src/mainwindow.c:5628 msgid "//Delete ..." msgstr "//Supprimer ..." #: src/mainwindow.c:5632 msgid "//Edit Image" msgstr "//Éditer le canal Image" #: src/mainwindow.c:5635 msgid "//Edit Alpha" msgstr "//Éditer le canal Alpha" #: src/mainwindow.c:5638 msgid "//Edit Selection" msgstr "//Éditer le canal Sélection" #: src/mainwindow.c:5641 msgid "//Edit Mask" msgstr "//Éditer le canal Masque" #: src/mainwindow.c:5645 msgid "//Hide Image" msgstr "//Cacher l'image" #: src/mainwindow.c:5648 msgid "//Disable Alpha" msgstr "//Désactiver le canal Alpha" #: src/mainwindow.c:5651 msgid "//Disable Selection" msgstr "//Désactiver le canal Sélection" #: src/mainwindow.c:5654 msgid "//Disable Mask" msgstr "//Désactiver le canal Masque" #: src/mainwindow.c:5657 msgid "//Couple RGBA Operations" msgstr "//Coupler opérations RVBA" #: src/mainwindow.c:5659 msgid "//Unassociate Alpha" msgstr "//Dissocier Alpha" #: src/mainwindow.c:5663 msgid "//View Alpha as an Overlay" msgstr "//Afficher le canal alpha en superposition" #: src/mainwindow.c:5664 msgid "//Configure Overlays ..." msgstr "//Paramétrer les superpositions ..." #: src/mainwindow.c:5666 msgid "/_Layers" msgstr "/_Calques" #: src/mainwindow.c:5668 msgid "//New Layer" msgstr "//Nouveau calque" #: src/mainwindow.c:5672 msgid "//Save Composite Image ..." msgstr "//Enregistrer l'image composite ..." #: src/mainwindow.c:5673 msgid "//Composite to New Layer" msgstr "//Composite vers nouveau calque" #: src/mainwindow.c:5674 msgid "//Remove All Layers" msgstr "//Supprimer tous les calques" #: src/mainwindow.c:5676 msgid "//Configure Animation ..." msgstr "//Configurer l'animation ..." #: src/mainwindow.c:5677 msgid "//Preview Animation ..." msgstr "//Aperçu de l'animation ..." #: src/mainwindow.c:5678 msgid "//Set Key Frame ..." msgstr "//Définir une trame clé ..." #: src/mainwindow.c:5679 msgid "//Remove All Key Frames ..." msgstr "//Supprimer toutes les trames clé ..." #: src/mainwindow.c:5681 msgid "/More..." msgstr "/Plus..." #: src/mainwindow.c:5683 msgid "/_Help" msgstr "/Aid_e" #: src/mainwindow.c:5684 msgid "//Documentation" msgstr "//Documentation" #: src/mainwindow.c:5686 msgid "//About" msgstr "//À propos" #: src/mainwindow.c:5689 msgid "//Keyboard Shortcuts ..." msgstr "//Raccourcis clavier ..." #: src/mainwindow.c:5690 msgid "//Rebind Shortcut Keycodes" msgstr "//Personnaliser les raccourcis claviers" #: src/memory.c:2800 msgid "Quantize Pass 1" msgstr "Quantification 1ère passe" #: src/memory.c:2854 msgid "Quantize Pass 2" msgstr "Quantification 2ème passe" #: src/memory.c:3073 src/memory.c:3458 msgid "Converting to Indexed Palette" msgstr "Convertir en Palette indexée" #: src/memory.c:5135 src/otherwindow.c:540 msgid "Bacteria Effect" msgstr "Effet bactéries" #: src/memory.c:5170 msgid "Rotating" msgstr "Rotation" #: src/memory.c:5511 msgid "Free Rotation" msgstr "Rotation libre" #: src/memory.c:6096 msgid "Scaling Image" msgstr "Mise à l'Échelle de l'image" #: src/memory.c:7560 msgid "Counting Unique RGB Pixels" msgstr "Comptage des pixels RVB uniques" #: src/memory.c:7608 msgid "Applying Effect" msgstr "Application de l'Effet" #: src/memory.c:8792 msgid "Kuwahara-Nagao Filter" msgstr "Filtre Kuwahara-Nagao" #: src/memory.c:10456 src/otherwindow.c:2665 msgid "Skew" msgstr "Biais" #: src/memory.c:10630 msgid "Segmentation Pass 1" msgstr "Segmentation 1ère passe" #: src/memory.c:10757 msgid "Segmentation Pass 2" msgstr "Segmentation 2ème passe" #: src/memory.c:11019 src/otherwindow.c:3156 msgid "Solid Noise" msgstr "Bruit uniforme" #: src/mygtk.c:134 src/mygtk.c:163 msgid "Please Wait ..." msgstr "Veuillez patienter ..." #: src/mygtk.c:141 msgid "STOP" msgstr "STOP" #: src/mygtk.c:504 msgid "Disabled" msgstr "Désactivé" #: src/mygtk.c:504 src/toolbar.c:301 msgid "Screen" msgstr "Écran" #: src/mygtk.c:504 msgid "Window" msgstr "Fenêtre" #: src/mygtk.c:508 msgid "Input" msgstr "Entrée" #: src/mygtk.c:512 msgid "Device:" msgstr "Périphérique:" #: src/mygtk.c:514 msgid "Mode:" msgstr "Mode:" #: src/mygtk.c:519 msgid "Axes" msgstr "Axes" #: src/mygtk.c:524 msgid "X:" msgstr "" #: src/mygtk.c:525 msgid "Y:" msgstr "" #: src/mygtk.c:526 msgid "Pressure:" msgstr "Pression:" #: src/mygtk.c:527 msgid "X tilt:" msgstr "Inclinaison X:" #: src/mygtk.c:528 msgid "Y tilt:" msgstr "Inclinaison Y:" #: src/mygtk.c:529 msgid "Wheel:" msgstr "Roulette:" #: src/mygtk.c:579 msgid "none" msgstr "aucun" #: src/otherwindow.c:236 msgid "24 bit RGB" msgstr "RVB 24 bits" #: src/otherwindow.c:236 src/otherwindow.c:3179 msgid "Greyscale" msgstr "Niveaux de gris" #: src/otherwindow.c:237 msgid "Indexed Palette" msgstr "Couleurs indexées" #: src/otherwindow.c:237 msgid "From Clipboard" msgstr "Depuis le presse-papiers" #: src/otherwindow.c:237 msgid "Grab Screenshot" msgstr "Prendre une capture d'Écran" #: src/otherwindow.c:242 src/toolbar.c:542 msgid "New Image" msgstr "Nouvelle image" #: src/otherwindow.c:246 src/otherwindow.c:3164 msgid "Colours" msgstr "Couleurs" #: src/otherwindow.c:409 msgid "Pattern Chooser" msgstr "Sélecteur de motifs" #: src/otherwindow.c:497 msgid "Set Palette Size" msgstr "Définir la taille de la palette" #: src/otherwindow.c:517 src/otherwindow.c:591 src/otherwindow.c:870 #: src/otherwindow.c:2538 src/otherwindow.c:2776 src/otherwindow.c:2939 #: src/prefs.c:338 src/prefs.c:538 msgid "Apply" msgstr "Appliquer" #: src/otherwindow.c:573 msgid "Luminance" msgstr "Luminance" #: src/otherwindow.c:573 src/otherwindow.c:814 msgid "Brightness" msgstr "Luminosité" #: src/otherwindow.c:574 msgid "Distance to A" msgstr "Distance jusqu'à A" #: src/otherwindow.c:575 msgid "Projection to A->B" msgstr "Projection sur de A à B" #: src/otherwindow.c:576 msgid "Frequency" msgstr "Fréquence" #: src/otherwindow.c:580 msgid "Sort Palette Colours" msgstr "Trier les couleurs de la palette" #: src/otherwindow.c:582 msgid "Start Index" msgstr "Index de départ" #: src/otherwindow.c:583 msgid "End Index" msgstr "Index de fin" #: src/otherwindow.c:589 msgid "Reverse Order" msgstr "Inverser l'Ordre" #: src/otherwindow.c:805 msgid "Bitwise" msgstr "Au niveau du bit" #: src/otherwindow.c:805 msgid "Truncated" msgstr "Tronqué" #: src/otherwindow.c:805 msgid "Rounded" msgstr "Arrondi" #: src/otherwindow.c:809 src/toolbar.c:311 src/toolbar.c:558 msgid "Transform Colour" msgstr "Modifier les couleurs" #: src/otherwindow.c:812 msgid "Gamma" msgstr "Gamma" #: src/otherwindow.c:816 msgid "Contrast" msgstr "Contraste" #: src/otherwindow.c:822 src/otherwindow.c:1674 msgid "Posterize" msgstr "Postérisation" #: src/otherwindow.c:831 msgid "Show Detail" msgstr "Afficher les détails" #: src/otherwindow.c:836 msgid "Posterize type" msgstr "Type de postérisation" #: src/otherwindow.c:857 msgid "Auto-Preview" msgstr "Aperçu automatique" #: src/otherwindow.c:869 msgid "Reset" msgstr "Réinitialiser" #: src/otherwindow.c:931 msgid "New geometry is the same as now - nothing to do." msgstr "" "Les nouvelles dimensions sont identiques à celles actuelles - rien à faire." #: src/otherwindow.c:980 msgid "The operating system cannot allocate the memory for this operation." msgstr "" "Le système d'exploitation ne peut pas allouer la mémoire pour cette " "opération." #: src/otherwindow.c:982 msgid "" "You have not allocated enough memory in the Preferences window for this " "operation." msgstr "" "Vous n'avez pas alloué assez de mémoire dans la fenêtre de préférences pour " "cette opération." #: src/otherwindow.c:993 src/otherwindow.c:2495 msgid "Mirror" msgstr "Miroir" #: src/otherwindow.c:993 src/otherwindow.c:994 msgid "Tile" msgstr "Carreler" #: src/otherwindow.c:993 msgid "Void" msgstr "Vide" #: src/otherwindow.c:994 src/shifter.c:283 msgid "Clear" msgstr "Effacer" #: src/otherwindow.c:994 msgid "Mirror tile" msgstr "Carreler en miroir" #: src/otherwindow.c:996 msgid "Nearest Neighbour" msgstr "Voisin le plus proche" #: src/otherwindow.c:997 msgid "Bilinear / Area Mapping" msgstr "Bilinéaire / zone de correspondance" #: src/otherwindow.c:998 msgid "Bicubic" msgstr "Bicubique" #: src/otherwindow.c:999 msgid "Bicubic edged" msgstr "Bicubique - Contours" #: src/otherwindow.c:1000 msgid "Bicubic better" msgstr "Bicubique - Meilleur" #: src/otherwindow.c:1001 msgid "Bicubic sharper" msgstr "Bicubique - Accentuer" #: src/otherwindow.c:1002 msgid "Blackman-Harris" msgstr "Blackman-Harris" #: src/otherwindow.c:1008 msgid "Scale Canvas" msgstr "Échelle de l'image" #: src/otherwindow.c:1009 msgid "Resize Canvas" msgstr "Redimensionner la taille du canevas" #: src/otherwindow.c:1012 msgid "Original " msgstr "Original " #: src/otherwindow.c:1013 msgid "New" msgstr "Nouveau" #: src/otherwindow.c:1014 msgid "Width " msgstr "Largeur " #: src/otherwindow.c:1018 msgid "Height " msgstr "Hauteur " #: src/otherwindow.c:1023 src/otherwindow.c:2514 src/otherwindow.c:2672 #: src/toolbar.c:212 msgid "Offset" msgstr "Excentrage" #: src/otherwindow.c:1026 src/otherwindow.c:1615 src/viewer.c:1209 msgid "Centre" msgstr "Centrer" #: src/otherwindow.c:1033 src/otherwindow.c:1052 msgid "Fix Aspect Ratio" msgstr "Conserver les proportions" #: src/otherwindow.c:1039 src/otherwindow.c:2070 src/toolbar.c:312 msgid "Settings" msgstr "Paramètres" #: src/otherwindow.c:1046 msgid "Sharper image reduction" msgstr "Réduction d'image plus nette" #: src/otherwindow.c:1047 msgid "Boundary extension" msgstr "Extension des bords" #: src/otherwindow.c:1613 src/otherwindow.c:2302 msgid "HSV" msgstr "TSV" #: src/otherwindow.c:1614 msgid "Highlight" msgstr "Surlignage" #: src/otherwindow.c:1615 msgid "Limit" msgstr "Limite" #: src/otherwindow.c:1616 msgid "Sphere" msgstr "Sphère" #: src/otherwindow.c:1616 src/otherwindow.c:2670 msgid "Angle" msgstr "Angle" #: src/otherwindow.c:1616 msgid "Cube" msgstr "Cube" #: src/otherwindow.c:1617 msgid "Opaque" msgstr "Opaque" #: src/otherwindow.c:1617 msgid "Border" msgstr "Bordure" #: src/otherwindow.c:1618 msgid "Transparent" msgstr "Transparent" #: src/otherwindow.c:1618 msgid "Tile " msgstr "Tuile " #: src/otherwindow.c:1618 msgid "Segment" msgstr "Segment" #: src/otherwindow.c:1656 msgid "Scale" msgstr "Échelle" #: src/otherwindow.c:1657 src/otherwindow.c:3059 msgid "From" msgstr "De" #: src/otherwindow.c:1659 src/otherwindow.c:3061 msgid "To" msgstr "Vers" #: src/otherwindow.c:1699 msgid "Range" msgstr "Intervalle" #: src/otherwindow.c:1702 msgid "Inverse" msgstr "Inversé" #: src/otherwindow.c:1710 msgid "Smart grid" msgstr "Grille intelligente" #: src/otherwindow.c:1712 msgid "Tile grid" msgstr "Grille de tuile" #: src/otherwindow.c:1714 msgid "Minimum grid zoom" msgstr "Zoom minimum" #: src/otherwindow.c:1717 msgid "Tile width" msgstr "Largeur de tuile" #: src/otherwindow.c:1720 msgid "Tile height" msgstr "Hauteur de tuile" #: src/otherwindow.c:1744 msgid "Palette Editor" msgstr "Éditeur de palette" #: src/otherwindow.c:1763 msgid "Configure Overlays" msgstr "Configurer les superpositions" #: src/otherwindow.c:1782 msgid "Colour Editor" msgstr "Éditeur de couleurs" #: src/otherwindow.c:1818 src/toolbar.c:430 msgid "Colour-Selective Mode" msgstr "Mode Sélectif par couleur" #: src/otherwindow.c:1843 msgid "Configure Grid" msgstr "Configurer la grille" #: src/otherwindow.c:2045 msgid "Exact Conversion" msgstr "Conversion exacte" #: src/otherwindow.c:2045 msgid "Use Current Palette" msgstr "Utiliser la palette courante" #: src/otherwindow.c:2046 msgid "PNN Quantize (slow, better quality)" msgstr "Quantification PNN (lent, meilleure qualité)" #: src/otherwindow.c:2047 msgid "Wu Quantize (fast)" msgstr "Quantification Wu (rapide)" #: src/otherwindow.c:2048 msgid "Max-Min Quantize (best for small palettes and dithering)" msgstr "Quantification Max-min (meilleur pour petites palettes et tramage)" #: src/otherwindow.c:2049 src/otherwindow.c:2495 src/otherwindow.c:2756 #: src/png.c:2794 src/prefs.c:377 msgid "None" msgstr "Aucun" #: src/otherwindow.c:2049 msgid "Floyd-Steinberg" msgstr "Floyd-Steinberg" #: src/otherwindow.c:2049 msgid "Stucki" msgstr "Stucki" #: src/otherwindow.c:2052 msgid "Floyd-Steinberg (quick)" msgstr "Floyd-Steinberg (rapide)" #: src/otherwindow.c:2052 msgid "Dithered (effect)" msgstr "Tramé (effet)" #: src/otherwindow.c:2053 msgid "Scattered (effect)" msgstr "Dispersé (effet)" #: src/otherwindow.c:2054 msgid "Gamut" msgstr "Gamme" #: src/otherwindow.c:2054 msgid "Weakly" msgstr "Faiblement" #: src/otherwindow.c:2054 msgid "Strongly" msgstr "Fortement" #: src/otherwindow.c:2055 msgid "Off" msgstr "Désactivé" #: src/otherwindow.c:2055 msgid "Separate/Sum" msgstr "Séparer/Somme" #: src/otherwindow.c:2055 msgid "Separate/Split" msgstr "Séparer/Découper" #: src/otherwindow.c:2056 msgid "Length/Sum" msgstr "Longueur/Somme" #: src/otherwindow.c:2056 msgid "Length/Split" msgstr "Longueur/Découper" #: src/otherwindow.c:2057 msgid "Largest (Linf)" msgstr "Le plus large (Linf)" #: src/otherwindow.c:2057 msgid "Sum (L1)" msgstr "Somme (L1)" #: src/otherwindow.c:2057 msgid "Euclidean (L2)" msgstr "Euclidien (L2)" #: src/otherwindow.c:2061 msgid "Create Quantized" msgstr "Réduction" #: src/otherwindow.c:2062 msgid "Convert To Indexed" msgstr "Convertir en Image indexée" #: src/otherwindow.c:2065 msgid "Indexed Colours To Use" msgstr "Nombre de couleurs indexées à créer" #: src/otherwindow.c:2078 msgid "Truncate palette" msgstr "Tronquer la palette" #: src/otherwindow.c:2079 msgid "Diameter based weighting" msgstr "Pondération basée sur le diamètre" #: src/otherwindow.c:2084 msgid "Dither" msgstr "Tramage" #: src/otherwindow.c:2087 src/otherwindow.c:2584 src/otherwindow.c:2928 msgid "Colour space" msgstr "Espace de couleurs" #: src/otherwindow.c:2088 src/otherwindow.c:2929 msgid "Difference measure" msgstr "Mesurer les différences" #: src/otherwindow.c:2089 msgid "Reduce colour bleed" msgstr "Réduire l'étalement des couleurs" #: src/otherwindow.c:2090 msgid "Serpentine scan" msgstr "Scan serpentine" #: src/otherwindow.c:2092 msgid "Error propagation, %" msgstr "Propagation d'erreur, %" #: src/otherwindow.c:2093 msgid "Selective error propagation" msgstr "Propagation d'erreur sélective" #: src/otherwindow.c:2097 msgid "Full error precision" msgstr "Précision d'erreur complète" #: src/otherwindow.c:2302 msgid "Backward HSV" msgstr "TSV inversé" #: src/otherwindow.c:2303 src/otherwindow.c:2326 msgid "Constant" msgstr "Constante" #: src/otherwindow.c:2307 msgid "Edit Gradient" msgstr "Édition du dégradé" #: src/otherwindow.c:2329 msgid "Points:" msgstr "Points:" #: src/otherwindow.c:2493 msgid "Linear" msgstr "Linéaire" #: src/otherwindow.c:2493 src/otherwindow.c:2703 msgid "Bilinear" msgstr "Bilinéaire" #: src/otherwindow.c:2493 msgid "Radial" msgstr "Radial" #: src/otherwindow.c:2494 msgid "Square" msgstr "Carré" #: src/otherwindow.c:2494 msgid "Angular" msgstr "Angulaire" #: src/otherwindow.c:2494 msgid "Conical" msgstr "Conique" #: src/otherwindow.c:2495 msgid "Level " msgstr "Uni" #: src/otherwindow.c:2495 msgid "Repeat" msgstr "Répéter" #: src/otherwindow.c:2496 msgid "A to B" msgstr "De A à B" #: src/otherwindow.c:2496 msgid "A to B (RGB)" msgstr "De A à B (RVB)" #: src/otherwindow.c:2497 msgid "A to B (sRGB)" msgstr "De A à B (sRVB)" #: src/otherwindow.c:2497 msgid "A to B (HSV)" msgstr "De A à B (TSV)" #: src/otherwindow.c:2497 msgid "A to B (backward HSV)" msgstr "De A à B (TSV inversé)" #: src/otherwindow.c:2498 msgid "A only" msgstr "A seulement" #: src/otherwindow.c:2498 src/otherwindow.c:2500 msgid "Custom" msgstr "Personnaliser" #: src/otherwindow.c:2499 msgid "Current to 0" msgstr "Du courant à 0" #: src/otherwindow.c:2499 msgid "Current only" msgstr "Courant seulement" #: src/otherwindow.c:2504 msgid "Configure Gradient" msgstr "Paramétrer le dégradé" #: src/otherwindow.c:2507 src/png.c:1001 msgid "Channel" msgstr "Canal" #: src/otherwindow.c:2512 msgid "Length" msgstr "Longueur" #: src/otherwindow.c:2513 msgid "Repeat length" msgstr "Longueur de répétition" #: src/otherwindow.c:2515 msgid "Gradient type" msgstr "Type de dégradé" #: src/otherwindow.c:2516 msgid "Extension type" msgstr "Type d'extension" #: src/otherwindow.c:2517 msgid "Distance type" msgstr "Type de distance" #: src/otherwindow.c:2518 msgid "Preview opacity" msgstr "Opacité de l'aperçu" #: src/otherwindow.c:2527 src/otherwindow.c:2533 src/toolbar.c:309 msgid "Reverse" msgstr "Inverse" #: src/otherwindow.c:2528 src/otherwindow.c:2534 msgid "Edit Custom" msgstr "Édition personnalisée" #: src/otherwindow.c:2592 msgid "Pick Gradient" msgstr "Ramasser le dégradé" #: src/otherwindow.c:2668 msgid "Horizontal " msgstr "Horizontal " #: src/otherwindow.c:2674 msgid "At distance" msgstr "À une distance" #: src/otherwindow.c:2675 msgid "Vertical" msgstr "Vertical" #: src/otherwindow.c:2756 msgid "Unchanged" msgstr "Inchangé" #: src/otherwindow.c:2761 msgid "Tracing Image" msgstr "Tracer l'image" #: src/otherwindow.c:2763 src/toolbar.c:315 msgid "Source" msgstr "Source" #: src/otherwindow.c:2768 msgid "Origin" msgstr "Origine" #: src/otherwindow.c:2771 msgid "Relative scale" msgstr "Échelle relative" #: src/otherwindow.c:2774 msgid "Display" msgstr "Afficher" #: src/otherwindow.c:2926 msgid "Segment Image" msgstr "Segmenter l'image" #: src/otherwindow.c:2931 src/toolbar.c:304 msgid "Threshold" msgstr "Seuil" #: src/otherwindow.c:2933 msgid "Level" msgstr "Niveau" #: src/otherwindow.c:2934 msgid "Minimum size" msgstr "Taille minimum" #: src/otherwindow.c:3053 msgid "Max" msgstr "Max" #: src/otherwindow.c:3053 msgid "Min" msgstr "Min" #: src/otherwindow.c:3057 msgid "Threshold Image" msgstr "Seuil l'image" #: src/otherwindow.c:3158 msgid "Seed" msgstr "Germe" #: src/otherwindow.c:3160 msgid "X span" msgstr "Étendue X" #: src/otherwindow.c:3161 msgid "Y span" msgstr "Étendue Y" #: src/otherwindow.c:3162 msgid "Octaves" msgstr "Octaves" #: src/png.c:620 #, c-format msgid "Saving %s image" msgstr "Enregistre image %s" #: src/png.c:620 #, c-format msgid "Loading %s image" msgstr "Charge image %s" #: src/png.c:998 msgid "Layer" msgstr "Calque" #: src/png.c:3577 msgid "Lossless" msgstr "Sans perte" #: src/png.c:3577 msgid "Default" msgstr "Par défaut" #: src/png.c:3577 msgid "Picture" msgstr "Peinture" #: src/png.c:3577 msgid "Photo" msgstr "Photo" #: src/png.c:3578 msgid "Drawing" msgstr "Dessin" #: src/png.c:3578 msgid "Icon" msgstr "Icône" #: src/png.c:8370 msgid "Applying colour profile" msgstr "Applique le profil de couleur" #: src/png.c:8792 #, c-format msgid "%d out of %d frames could not be saved as %s - saved as PNG instead" msgstr "" "%d des %d trames ne peuvent pas être sauvées en tant que %s - le mode PNG a " "été utilisé" #: src/png.c:8809 msgid "Explode frames" msgstr "Décomposer les trames" #: src/prefs.c:56 msgid "Default System Language" msgstr "Langue par défaut du système" #: src/prefs.c:57 msgid "Chinese (Simplified)" msgstr "Chinois (simplifié)" #: src/prefs.c:57 msgid "Chinese (Taiwanese)" msgstr "Chinois (Taiwanais)" #: src/prefs.c:57 msgid "Czech" msgstr "Tchèque" #: src/prefs.c:58 msgid "Dutch" msgstr "Néerlandais" #: src/prefs.c:58 msgid "English (UK)" msgstr "Anglais (Royaume-Uni)" #: src/prefs.c:58 msgid "French" msgstr "Français" #: src/prefs.c:58 msgid "Galician" msgstr "Galicien" #: src/prefs.c:58 msgid "German" msgstr "Allemand" #: src/prefs.c:59 msgid "Hungarian" msgstr "Hongrois" #: src/prefs.c:59 msgid "Italian" msgstr "Italien" #: src/prefs.c:59 msgid "Japanese" msgstr "Japonais" #: src/prefs.c:59 msgid "Kabyle" msgstr "" #: src/prefs.c:59 msgid "Polish" msgstr "Polonais" #: src/prefs.c:60 msgid "Portuguese" msgstr "Portugais" #: src/prefs.c:60 msgid "Portuguese (Brazilian)" msgstr "Portugais (Brésilien)" #: src/prefs.c:60 msgid "Russian" msgstr "Russe" #: src/prefs.c:60 msgid "Slovak" msgstr "Slovaque" #: src/prefs.c:61 msgid "Spanish" msgstr "Espagnol" #: src/prefs.c:61 msgid "Swedish" msgstr "Suédois" #: src/prefs.c:61 msgid "Tagalog" msgstr "Tagalog" #: src/prefs.c:61 msgid "Turkish" msgstr "Turque" #: src/prefs.c:81 msgid "Current Device" msgstr "Périphérique courant" #: src/prefs.c:135 msgid "Pressure" msgstr "Pression" #: src/prefs.c:149 msgid "Preferences" msgstr "Préférences" #: src/prefs.c:163 msgid "Max threads (0 to autodetect)" msgstr "Max de threads (0 = autodétection)" #: src/prefs.c:164 msgid "Min kpixels per render thread" msgstr "Kpixels minimum par thread de rendu" #: src/prefs.c:171 msgid "Max memory used for undo (MB)" msgstr "Mémoire max utilisée pour les images annulées (MO)" #: src/prefs.c:172 msgid "Max undo levels" msgstr "Nombre max d'annulations" #: src/prefs.c:173 msgid "Communal layer undo space (%)" msgstr "Espace commun d'annulation de calques (%)" #: src/prefs.c:175 msgid "Bayer master pattern" msgstr "Matrice de Bayer" #: src/prefs.c:178 msgid "Use gamma correction by default" msgstr "Utiliser la correction gamma par défaut" #: src/prefs.c:179 msgid "Use gamma correction when painting" msgstr "Utiliser la correction gamma lors de la peinture" #: src/prefs.c:180 msgid "Separate patterns for A & B" msgstr "Motifs séparés pour A & B" #: src/prefs.c:183 msgid "Optimize alpha chequers" msgstr "Optimiser la grille de transparence" #: src/prefs.c:184 msgid "Disable view window transparencies" msgstr "Désactiver la transparence" #: src/prefs.c:185 msgid "Enable overlays by layer" msgstr "Activer les superpositions par calque" #: src/prefs.c:189 msgid "Language" msgstr "Langue" #: src/prefs.c:191 msgid "" "Select preferred language translation\n" "\n" "You will need to restart mtPaint\n" "for this to take full effect" msgstr "" "Sélectionnez la langue dans laquelle afficher l'interface\n" "\n" "Vous devrez redémarrer mtPaint pour que la modification\n" "soit prise en compte" #: src/prefs.c:198 msgid "Interface" msgstr "Interface" #: src/prefs.c:200 msgid "Greyscale backdrop" msgstr "Niveau de gris" #: src/prefs.c:201 msgid "Selection nudge pixels" msgstr "Déplacer la sélection de" #: src/prefs.c:202 msgid "Max Pan Window Size" msgstr "Dimensions maximums de la fenêtre d'aperçu réduit" #: src/prefs.c:204 msgid "Display clipboard while pasting" msgstr "Afficher le presse-papiers pendant le collage" #: src/prefs.c:205 msgid "Mouse cursor = Tool" msgstr "Curseur de la souris = Outil" #: src/prefs.c:206 msgid "Confirm Exit" msgstr "Confirmer La Sortie" #: src/prefs.c:207 msgid "Q key quits mtPaint" msgstr "La touche Q quitte mtPaint" #: src/prefs.c:208 msgid "Arrow keys scroll canvas" msgstr "Les flèches font défiler le canevas" #: src/prefs.c:209 msgid "Changing tool commits paste" msgstr "La sélection d'un nouvel outil valide les modifications" #: src/prefs.c:210 msgid "Centre tool settings dialogs" msgstr "Centrer la boite de dialogue d'outils" #: src/prefs.c:211 msgid "New image sets zoom to 100%" msgstr "Les nouvelles images réinitialisent le zoom à 100%" #: src/prefs.c:212 msgid "Zoom on cursor position" msgstr "Zoom sur la position du curseur" #: src/prefs.c:214 msgid "Mouse Scroll Wheel = Zoom" msgstr "Défilement de molette de souris = Zoom" #: src/prefs.c:215 msgid "Use menu icons" msgstr "Utilise les icônes du menu" #: src/prefs.c:220 msgid "Files" msgstr "Fichiers" #: src/prefs.c:223 msgid "XBM X hotspot" msgstr "Point chaud XBM X" #: src/prefs.c:224 msgid "XBM Y hotspot" msgstr "Point chaud XBM Y" #: src/prefs.c:228 msgid "Recently Used Files" msgstr "Fichiers récemment utilisés" #: src/prefs.c:229 msgid "Progress bar silence limit" msgstr "Sensibilité de la barre de progression" #: src/prefs.c:232 msgid "Read 16-bit TGAs as 5:6:5 BGR" msgstr "Lire TGAs 16-bit comme 5:6:5 BVR" #: src/prefs.c:233 msgid "Write TGAs in bottom-up row order" msgstr "Ecrire les images TGAs du bas vers le haut" #: src/prefs.c:234 msgid "Undoable image loading" msgstr "Chargement d'image réversible" #: src/prefs.c:245 msgid "Compression (RGB)" msgstr "Compression (RVB)" #: src/prefs.c:246 msgid "Compression (indexed)" msgstr "Compression (indexée)" #: src/prefs.c:247 msgid "Compression (monochrome)" msgstr "Compression (monochrome)" #: src/prefs.c:255 msgid "Enable predictor" msgstr "Activer le prédicteur" #: src/prefs.c:262 msgid "Compression mode" msgstr "Mode de compression" #: src/prefs.c:271 msgid "Channel for Mask Plane" msgstr "Canal pour plan de masque" #: src/prefs.c:273 msgid "Ignore Transparent Colour" msgstr "Ignorer la couleur transparente" #: src/prefs.c:274 msgid "PackBits Compression" msgstr "Compression PackBits" #: src/prefs.c:275 msgid "Write Indexed as Planar Bitmap (PBM)" msgstr "Ecrire les images indexées en Bitmap Planaire (PBM)" #: src/prefs.c:280 msgid "Paths" msgstr "Chemins" #: src/prefs.c:281 msgid "Clipboard Files" msgstr "Fichiers Presse-papiers" #: src/prefs.c:281 msgid "Select Clipboard File" msgstr "Sélectionner le fichier presse-papiers" #: src/prefs.c:283 msgid "HTML Browser Program" msgstr "Navigateur HTML" #: src/prefs.c:283 msgid "Select Browser Program" msgstr "Sélectionner le navigateur HTML" #: src/prefs.c:285 msgid "Location of Handbook index" msgstr "Emplacement de l'index du manuel" #: src/prefs.c:285 msgid "Select Handbook Index File" msgstr "Sélectionner le fichier index du manuel" #: src/prefs.c:287 msgid "Default Palette" msgstr "Palette par défaut" #: src/prefs.c:287 msgid "Select Default Palette" msgstr "Sélectionnez la palette par défaut" #: src/prefs.c:289 msgid "Default Patterns" msgstr "Motifs par défaut" #: src/prefs.c:289 msgid "Select Default Patterns File" msgstr "Sélectionnez le fichier de motifs par défaut" #: src/prefs.c:292 msgid "Default CSS" msgstr "CSS par défaut" #: src/prefs.c:292 msgid "Select Default CSS File" msgstr "Sélectionner le fichier CSS par défaut" #: src/prefs.c:295 msgid "Default Theme" msgstr "Thème par défaut" #: src/prefs.c:295 msgid "Select Default Theme File" msgstr "Sélectionner le fichier de thème par défaut" #: src/prefs.c:300 msgid "Status Bar" msgstr "Barre d'état" #: src/prefs.c:301 msgid "Canvas Geometry" msgstr "Dimensions du canevas" #: src/prefs.c:302 msgid "Cursor X,Y" msgstr "Curseur X,Y" #: src/prefs.c:303 msgid "Pixel [I] {RGB}" msgstr "Pixel [I] {RVB}" #: src/prefs.c:304 msgid "Selection Geometry" msgstr "Dimensions de la sélection" #: src/prefs.c:305 msgid "Undo / Redo" msgstr "Annuler / Refaire" #: src/prefs.c:308 msgid "Tablet" msgstr "Tablette" #: src/prefs.c:309 msgid "Device Settings" msgstr "Paramètres du périphérique" #: src/prefs.c:313 msgid "Configure Device" msgstr "Configurer le périphérique" #: src/prefs.c:319 msgid "Tool Variable" msgstr "Outil variable" #: src/prefs.c:322 src/toolbar.c:454 msgid "Flow" msgstr "Flux" #: src/prefs.c:330 msgid "Test Area" msgstr "Zone de test" #: src/prefs.c:373 msgid "Factor" msgstr "Facteur" #: src/prefs.c:459 msgid "This key is builtin" msgstr "Cette touche est intégrée" #: src/prefs.c:462 #, c-format msgid "" "This key is mapped to:\n" "\"%s\"" msgstr "" "Cette touche est assignée à:\n" "\"%s\"" #: src/prefs.c:465 msgid "Remap" msgstr "Réassigner" #: src/prefs.c:510 msgid "Keyboard Shortcuts" msgstr "Raccourcis clavier" #: src/shifter.c:147 msgid "Frames" msgstr "Trames" #: src/shifter.c:258 msgid "Palette Shifter" msgstr "Cycles de la palette" #: src/shifter.c:263 msgid "Start" msgstr "Début" #: src/shifter.c:265 msgid "Finish" msgstr "Fin" #: src/shifter.c:284 msgid "Fix Palette" msgstr "Conserver la palette" #: src/spawn.c:651 msgid "Configure File Actions" msgstr "Paramétrer les actions" #: src/spawn.c:657 src/spawn.c:663 msgid "Command" msgstr "Commande" #: src/spawn.c:922 #, c-format msgid "Error %i reported when trying to run %s" msgstr "Erreur %i lors de l'exécution de la commande %s" #: src/spawn.c:979 msgid "" "I am unable to find the documentation. Either you need to download the " "mtPaint Handbook from the web site and install it, or you need to set the " "correct location in the Preferences window." msgstr "" "Je ne trouve pas la documentation. Si vous ne l'avez pas vous devez " "télécharger le manuel de mtPaint depuis le site web, vous devrez ensuite " "l'installer. Dans le cas contraire vérifiez que son emplacement soit bien " "paramétré dans la fenêtre des préférences." #: src/spawn.c:1018 msgid "" "There was a problem running the HTML browser. You need to set the correct " "program name in the Preferences window." msgstr "" "Une erreur est survenue lors de l'exécution du navigateur HTML. Vous devez " "sélectionner le programme à utiliser dans la fenêtre des préférences." #: src/thread.c:361 msgid "Helper thread is not responding. Save your work and exit the program." msgstr "" "Le thread d'assistance ne répond pas. Sauvegarder votre travail et quitter " "le programme." #: src/toolbar.c:147 msgid "RGB Cube" msgstr "Cube RVB" #: src/toolbar.c:148 msgid "By image channel" msgstr "Par canal Image" #: src/toolbar.c:149 msgid "Gradient-driven" msgstr "Guidé par gradient" #: src/toolbar.c:157 msgid "Fill settings" msgstr "Propriétés du remplissage" #: src/toolbar.c:170 msgid "Respect opacity mode" msgstr "Respecter le mode Opacité" #: src/toolbar.c:176 msgid "Smudge settings" msgstr "Propriétés du barbouillage" #: src/toolbar.c:215 msgid "Aligned" msgstr "Aligné" #: src/toolbar.c:222 msgid "Clone settings" msgstr "Propriétés du clonage" #: src/toolbar.c:228 msgid "By selection channel" msgstr "Par canal Sélection" #: src/toolbar.c:234 msgid "Lasso settings" msgstr "Propriétés du lasso" #: src/toolbar.c:252 msgid "Brush spacing" msgstr "Espacement de la brosse" #: src/toolbar.c:299 src/toolbar.c:341 msgid "Normal" msgstr "Normal" #: src/toolbar.c:300 msgid "Colour" msgstr "Couleur" #: src/toolbar.c:300 msgid "Saturate More" msgstr "Saturer plus" #: src/toolbar.c:301 msgid "Multiply" msgstr "Multiplier" #: src/toolbar.c:301 msgid "Divide" msgstr "Diviser" #: src/toolbar.c:301 msgid "Dodge" msgstr "Éclaircir" #: src/toolbar.c:302 msgid "Burn" msgstr "Assombrir" #: src/toolbar.c:302 msgid "Hard Light" msgstr "Lumière dure" #: src/toolbar.c:302 msgid "Soft Light" msgstr "Lumière douce" #: src/toolbar.c:302 msgid "Difference" msgstr "Différence" #: src/toolbar.c:303 msgid "Darken" msgstr "Assombrir seulement" #: src/toolbar.c:303 msgid "Lighten" msgstr "Éclaircir seulement" #: src/toolbar.c:303 msgid "Grain Extract" msgstr "Extraction de grain" #: src/toolbar.c:304 msgid "Grain Merge" msgstr "Fusion de grain" #: src/toolbar.c:330 msgid "Blend mode" msgstr "Mode Mélange" #: src/toolbar.c:417 msgid "Continuous Mode" msgstr "Mode Continu" #: src/toolbar.c:421 msgid "Opacity Mode" msgstr "Mode Opacité" #: src/toolbar.c:424 msgid "Tint Mode" msgstr "Mode Teinte" #: src/toolbar.c:427 msgid "Tint +-" msgstr "Teinte +-" #: src/toolbar.c:434 msgid "Blend Mode" msgstr "Mode Mélange" #: src/toolbar.c:438 msgid "Disable All Masks" msgstr "Désactiver les protections" #: src/toolbar.c:441 msgid "Gradient Mode" msgstr "Mode Dégradé" #: src/toolbar.c:486 msgid "Settings Toolbar" msgstr "Propriétés" #: src/toolbar.c:546 msgid "Cut" msgstr "Couper" #: src/toolbar.c:548 msgid "Copy" msgstr "Copier" #: src/toolbar.c:550 msgid "Paste" msgstr "Coller" #: src/toolbar.c:553 msgid "Undo" msgstr "Annuler" #: src/toolbar.c:555 msgid "Redo" msgstr "Refaire" #: src/toolbar.c:559 src/viewer.c:328 msgid "Pan Window" msgstr "Aperçu réduit" #: src/toolbar.c:560 src/toolbar.c:640 msgid "More..." msgstr "Plus..." #: src/toolbar.c:574 msgid "Paint" msgstr "Peindre" #: src/toolbar.c:580 msgid "Shuffle" msgstr "Mélanger" #: src/toolbar.c:583 msgid "Flood Fill" msgstr "Remplir" #: src/toolbar.c:587 msgid "Straight Line" msgstr "Ligne droite" #: src/toolbar.c:590 msgid "Smudge" msgstr "Barbouiller" #: src/toolbar.c:594 msgid "Clone" msgstr "Cloner" #: src/toolbar.c:597 msgid "Make Selection" msgstr "Faire une sélection" #: src/toolbar.c:600 msgid "Polygon Selection" msgstr "Sélection polygonale" #: src/toolbar.c:603 msgid "Place Gradient" msgstr "Dégradé" #: src/toolbar.c:606 msgid "Lasso Selection" msgstr "Lasso la sélection" #: src/toolbar.c:614 msgid "Ellipse Outline" msgstr "Contour d'ellipse" #: src/toolbar.c:617 msgid "Filled Ellipse" msgstr "Ellipse remplie" #: src/toolbar.c:620 msgid "Outline Selection" msgstr "Tracer le contour de la sélection" #: src/toolbar.c:623 msgid "Fill Selection" msgstr "Remplir la sélection" #: src/toolbar.c:627 msgid "Flip Selection Vertically" msgstr "Miroir vertical de la sélection" #: src/toolbar.c:630 msgid "Flip Selection Horizontally" msgstr "Miroir horizontal de la sélection" #: src/toolbar.c:633 msgid "Rotate Selection Clockwise" msgstr "Rotation horaire de la sélection" #: src/toolbar.c:636 msgid "Rotate Selection Anti-Clockwise" msgstr "Rotation antihoraire de la sélection" #: src/vcode.c:5201 msgid "Browse" msgstr "Parcourir" #: src/vcode.c:7886 msgid "New key ..." msgstr "Nouvelle touche ..." #: src/vcode.c:9909 #, c-format msgid "'%s' does not match any widget" msgstr "'%s' ne correspond à aucun widget" #: src/vcode.c:9910 #, c-format msgid "'%s' value does not fit '%s' widget" msgstr "La valeur '%s' ne correspond pas au widget '%s'" #: src/viewer.c:115 msgid "About" msgstr "À propos de" #: src/viewer.c:1179 msgid "No font selected" msgstr "Aucune police sélectionnée" #: src/viewer.c:1209 msgid "Left" msgstr "Gauche" #: src/viewer.c:1209 msgid "Right" msgstr "Droite" #~ msgid "" #~ "You are trying to save an XPM file with more than 4096 colours. Either " #~ "use another format or posterize the image to 4 bits, or otherwise reduce " #~ "the number of colours." #~ msgstr "" #~ "Vous essayez de enregistrer un fichier XPM avec plus de 4096 couleurs. " #~ "Utilisez un autre format ou postérisez l'image en 4 bits, sinon réduisez " #~ "le nombre de couleurs." #~ msgid "Create GIF frames" #~ msgstr "Sauver toutes les trames au format GIF" #~ msgid "Store Values" #~ msgstr "Stocker les valeurs" #~ msgid "File: %s invalid - palette not updated" #~ msgstr "Fichier : %s invalide - palette non mise à jour" #~ msgid "Distance to A+B" #~ msgstr "Distance jusqu'à A+B" #~ msgid "Edit Frames" #~ msgstr "Editer les trames" #~ msgid "Not enough memory to rotate image" #~ msgstr "Pas assez de mémoire pour pivoter l'image" #~ msgid "Not enough memory to rotate clipboard" #~ msgstr "Pas assez de mémoire pour pivoter le presse-papiers" #~ msgid "File is too big, must be <= to width=%i height=%i : %s" #~ msgstr "Le fichier est trop grand, il ne doit pas excéder %ix%i : %s" #~ msgid "Could not open %s: %s" #~ msgstr "Impossible d'ouvrir %s : %s" #~ msgid "Error closing %s: %s" #~ msgstr "Erreur lors de la fermeture de %s : %s" #~ msgid "Could not write to %s: %s" #~ msgstr "Impossible d'écrire dans %s : %s" #~ msgid "The palette does not contain enough colours to do a merge" #~ msgstr "La palette ne contient pas assez de couleurs pour faire une fusion" #~ msgid "There are too many identical palette items to be reduced." #~ msgstr "Il y a trop d'éléments identiques à réduire dans la palette." #~ msgid "patterns_user.c could not be opened in current directory" #~ msgstr "patterns_user.c n'a pas pu être ouvert dans le dossier courant" #~ msgid "Done" #~ msgstr "Fait" #~ msgid "patterns_user.c created in current directory" #~ msgstr "patterns_user.c créé dans le dossier courant" #~ msgid "Current image is not 94x94x3 so I cannot create patterns_user.c" #~ msgstr "" #~ "L'image courante n'est pas 94x94x3 donc je ne peux pas créer " #~ "patterns_user.c" #~ msgid "" #~ "You are trying to save an RGB image to an XPM file which is not " #~ "possible. I would suggest you save with a PNG extension." #~ msgstr "" #~ "Vous essayez d'enregistrer une image RVB dans un fichier XPM ce qui n'est " #~ "pas possible. Enregistrez plutôt avec l'extension PNG." #~ msgid "" #~ "You are trying to save an RGB image to a GIF file which is not possible. " #~ "I would suggest you save with a PNG extension." #~ msgstr "" #~ "Vous essayez d'enregistrer une image RVB dans un fichier GIF ce qui n'est " #~ "pas possible. Enregistrez plutôt avec l'extension PNG." #~ msgid "" #~ "You are trying to save an XBM file with a palette of more than 2 " #~ "colours. Either use another format or reduce the palette to 2 colours." #~ msgstr "" #~ "Vous essayez d'enregistrer un fichier XBM avec une palette de plus de 2 " #~ "couleurs. Employez un autre format ou réduisez la palette à 2 couleurs." #~ msgid "" #~ "You are trying to save an indexed canvas to a JPEG file which is not " #~ "possible. I would suggest you save with a PNG extension." #~ msgstr "" #~ "Vous essayez d'enregistrer un canevas indexé dans un fichier JPEG ce qui " #~ "n'est pas possible. Enregistrez plutôt avec l'extension PNG." #~ msgid "/Edit/Create Patterns" #~ msgstr "/Édition/Créer des trames" #~ msgid "/View/Command Line Window" #~ msgstr "/Affichage/Ligne de commande" #~ msgid "/Palette/Create Quantized (DL1)" #~ msgstr "/Palette/Réduction (DL1)" #~ msgid "/Palette/Create Quantized (DL3)" #~ msgstr "/Palette/Réduction (DL3)" #~ msgid "/File/%i" #~ msgstr "/Fichier/%i" #~ msgid "JPEG Save Quality (100=High) " #~ msgstr "Qualité de l'image JPEG (100=Haute) " #~ msgid "DL1 Quantize (fastest)" #~ msgstr "Réduction DL1 (la plus rapide)" #~ msgid "DL3 Quantize (very slow, better quality)" #~ msgstr "Réduction DL3 (très lent, meilleur qualité)" #~ msgid "Loading PNG image" #~ msgstr "Chargement d'une image PNG" #~ msgid "Loading clipboard image" #~ msgstr "Chargement de l'image du presse-papiers" #~ msgid "Saving PNG image" #~ msgstr "Enregistrement d'une image PNG" #~ msgid "Saving Clipboard image" #~ msgstr "Enregistrement du presse-papiers" #~ msgid "Saving Layer image" #~ msgstr "Enregistrement de l'image de calque" #~ msgid "Loading GIF image" #~ msgstr "Chargement d'une image GIF" #~ msgid "Saving GIF image" #~ msgstr "Enregistrement d'une image GIF" #~ msgid "Loading JPEG image" #~ msgstr "Chargement d'une image JPEG" #~ msgid "Saving JPEG image" #~ msgstr "Enregistrement d'une image JPEG" #~ msgid "Loading TIFF image" #~ msgstr "Chargement d'une image TIFF" #~ msgid "Saving TIFF image" #~ msgstr "Enregistrement d'une image TIFF" #~ msgid "Loading BMP image" #~ msgstr "Chargement d'une image BMP" #~ msgid "Saving BMP image" #~ msgstr "Enregistrement d'une image BMP" #~ msgid "Loading XPM image" #~ msgstr "Chargement d'une image XPM" #~ msgid "Saving XPM image" #~ msgstr "Enregistrement d'une image XPM" #~ msgid "Loading XBM image" #~ msgstr "Chargement d'une image XBM" #~ msgid "Saving XBM image" #~ msgstr "Enregistrement d'une image XBM" #~ msgid "Saving UNDO images" #~ msgstr "Enregistrement des tampons d'annulation" #~ msgid "%i Files on Command Line" #~ msgstr "%i Fichiers sur la ligne de commande" #~ msgid "/Palette/Create Quantized (Wu)" #~ msgstr "/Palette/Réduction (Wu)" #~ msgid "Wu Quantize (best method for small palettes)" #~ msgstr "Réduction Wu (la meilleur méthode pour les petites palettes)" #~ msgid "Grid colour RGB" #~ msgstr "Grille de couleur RVB" #~ msgid "Zoom" #~ msgstr "Zoom" #~ msgid "Saving Channel image" #~ msgstr "Enregistrement du canal" #~ msgid "Loading LSS16 image" #~ msgstr "Chargement d'une image LSS16" #~ msgid "Saving LSS16 image" #~ msgstr "Enregistrement d'une image LSS16" #~ msgid " C Command Line Window" #~ msgstr " C Fenêtre ligne de commande" #~ msgid "" #~ "Dennis Lee - Wrote the two quantizing methods DL1 & 3 - see quantizer.c " #~ "for more information." #~ msgstr "" #~ "Dennis Lee - A écris les deux méthode de réduction DL1 & 3 - voir le " #~ "fichier quantizer.c pour plus de détails." #~ msgid "Magnus Hjorth - Wrote inifile.c/h, from mhWaveEdit 1.3.0." #~ msgstr "Magnus Hjorth - A écris inifile.c/h, pour mhWaveEdit 1.3.0." #~ msgid "/File/Actions/sep2" #~ msgstr "/Fichier/Actions/sep2" #~ msgid "/Frames" #~ msgstr "/Trames" #~ msgid "/File/Actions/%i" #~ msgstr "/Fichier/Actions/%i" mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/po/gl.po000066400000000000000000003017071471325446300215430ustar00rootroot00000000000000# Galician translations for mtpaint package # Traduccións ao galego para o paquete mtpaint. # Copyright (C) 2005 THE mtpaint'S COPYRIGHT HOLDER # This file is distributed under the same license as the mtpaint package. # Mark Tyler, 2005. # msgid "" msgstr "" "Project-Id-Version: mtpaint-3.51 galego\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-01-04 21:31+0200\n" "PO-Revision-Date: 2009-10-08 14:26+0000\n" "Last-Translator: Miguel Anxo Bouzada \n" "Language-Team: GALPon MiniNo \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Launchpad-Export-Date: 2009-12-06 22:32+0000\n" "X-Generator: Launchpad (build Unknown)\n" "X-Poedit-Country: SPAIN\n" "X-Poedit-Language: Galician\n" #: src/ani.c:647 msgid "Animation Preview" msgstr "Vista previa da animación" #: src/ani.c:650 src/shifter.c:275 msgid "Play" msgstr "Reproducir" #: src/ani.c:654 msgid "Fix" msgstr "Fixar" #: src/ani.c:655 src/ani.c:1005 src/font.c:1624 src/font.c:1643 #: src/shifter.c:286 src/viewer.c:97 msgid "Close" msgstr "Pechar" #: src/ani.c:709 src/ani.c:812 src/ani.c:1022 src/ani.c:1028 src/canvas.c:356 #: src/canvas.c:708 src/canvas.c:989 src/canvas.c:1353 src/canvas.c:1383 #: src/canvas.c:1470 src/canvas.c:1545 src/canvas.c:1988 src/canvas.c:1994 #: src/canvas.c:2077 src/canvas.c:2217 src/canvas.c:2240 src/font.c:1352 #: src/fpick.c:636 src/fpick.c:754 src/layer.c:524 src/layer.c:815 #: src/layer.c:970 src/mainwindow.c:341 src/mainwindow.c:370 #: src/mainwindow.c:534 src/mainwindow.c:578 src/mainwindow.c:604 #: src/mainwindow.c:3797 src/mainwindow.c:4045 src/otherwindow.c:931 #: src/otherwindow.c:980 src/otherwindow.c:982 src/prefs.c:459 src/spawn.c:924 #: src/spawn.c:978 src/spawn.c:1017 src/thread.c:360 src/vcode.c:9912 #: src/viewer.c:1161 src/viewer.c:1179 msgid "Error" msgstr "Produciuse un erro" #: src/ani.c:709 msgid "Unable to create output directory" msgstr "Non se pode crear o directório" #: src/ani.c:759 msgid "Creating Animation Frames" msgstr "Crear fotogramas" #: src/ani.c:812 msgid "Unable to save image" msgstr "Imposible gardar a imaxe" #: src/ani.c:840 src/canvas.c:1171 src/fpick.c:731 src/layer.c:311 #: src/layer.c:379 src/layer.c:826 src/layer.c:840 src/mainwindow.c:375 #: src/mainwindow.c:1026 src/png.c:8794 src/prefs.c:464 msgid "Warning" msgstr "Aviso" #: src/ani.c:840 msgid "" "Do you really want to clear all of the position and cycle data for all of " "the layers?" msgstr "Realmente queres limpar todas as capas?" #: src/ani.c:841 src/fpick.c:731 src/layer.c:311 src/layer.c:842 #: src/mainwindow.c:375 msgid "No" msgstr "Non" #: src/ani.c:841 src/fpick.c:731 src/layer.c:311 src/layer.c:842 #: src/mainwindow.c:375 msgid "Yes" msgstr "Si" #: src/ani.c:954 msgid "Set Key Frame" msgstr "Establecer número de fotogramas" #: src/ani.c:961 msgid "Configure Animation" msgstr "Configurar animación" #: src/ani.c:964 msgid "Output Files" msgstr "Ficheiros de saida" #: src/ani.c:967 msgid "Start frame" msgstr "Comezar no fotograma" #: src/ani.c:969 msgid "End frame" msgstr "Rematar no fotograma" #: src/ani.c:971 src/shifter.c:267 msgid "Delay" msgstr "Retardo" #: src/ani.c:973 msgid "Output path" msgstr "Ruta de saida" #: src/ani.c:973 src/font.c:1637 src/spawn.c:664 msgid "Select Directory" msgstr "Seleccionar directório" #: src/ani.c:976 msgid "File prefix" msgstr "Prefixo do ficheiro" #: src/ani.c:978 src/canvas.c:2096 msgid "File Format" msgstr "Formato de ficheiro" #: src/ani.c:982 msgid "Positions" msgstr "Posicions" #: src/ani.c:997 msgid "Cycling" msgstr "Ciclo" #: src/ani.c:1006 msgid "Save" msgstr "Gardar" #: src/ani.c:1007 src/font.c:1577 src/otherwindow.c:868 src/otherwindow.c:1615 #: src/otherwindow.c:1728 src/otherwindow.c:2938 src/otherwindow.c:3071 #: src/otherwindow.c:3170 msgid "Preview" msgstr "Vista previa" #: src/ani.c:1008 src/shifter.c:285 msgid "Create Frames" msgstr "Crear fotogramas" #: src/ani.c:1022 msgid "You must have at least 2 layers to create an animation" msgstr "Debes ter ao menos 2 capas para crear unha animación" #: src/ani.c:1028 msgid "You must save your layers file before creating an animation" msgstr "Debes gardar as capas antes de crear unha animación" #: src/canvas.c:357 msgid "The image is too large to transform." msgstr "A imaxe é demasiado grande para a transformación." #: src/canvas.c:393 src/canvas.c:430 src/otherwindow.c:1613 #: src/otherwindow.c:2524 src/otherwindow.c:2583 src/otherwindow.c:3179 msgid "Gradient" msgstr "Gradación" #: src/canvas.c:393 src/otherwindow.c:840 src/otherwindow.c:842 #: src/otherwindow.c:2074 src/otherwindow.c:3180 msgid "Palette" msgstr "Paleta" #: src/canvas.c:393 src/info.c:265 src/otherwindow.c:847 src/otherwindow.c:2757 #: src/otherwindow.c:3180 src/png.c:781 src/png.c:995 msgid "Clipboard" msgstr "Portapapeis" #: src/canvas.c:394 src/cpick.c:831 src/toolbar.c:299 msgid "Value" msgstr "Valor" #: src/canvas.c:394 src/cpick.c:811 src/otherwindow.c:575 src/otherwindow.c:859 #: src/otherwindow.c:3053 src/toolbar.c:318 msgid "Red" msgstr "Vermello" #: src/canvas.c:394 src/cpick.c:815 src/otherwindow.c:575 src/otherwindow.c:860 #: src/otherwindow.c:3053 src/toolbar.c:319 msgid "Green" msgstr "Verde" #: src/canvas.c:394 src/cpick.c:819 src/otherwindow.c:575 src/otherwindow.c:861 #: src/otherwindow.c:3053 src/toolbar.c:320 msgid "Blue" msgstr "Azul" #: src/canvas.c:399 msgid "From " msgstr "" #: src/canvas.c:403 msgid "To " msgstr "" #: src/canvas.c:410 msgid "Map" msgstr "" #: src/canvas.c:429 msgid "MT" msgstr "MT" #: src/canvas.c:429 msgid "Sobel" msgstr "Sobel" #: src/canvas.c:429 msgid "Prewitt" msgstr "Prewitt" #: src/canvas.c:429 msgid "Kirsch" msgstr "Kirsch" #: src/canvas.c:430 msgid "Roberts" msgstr "Roberts" #: src/canvas.c:430 msgid "Laplace" msgstr "Laplace" #: src/canvas.c:430 msgid "Morphological" msgstr "Morfolóxica" #: src/canvas.c:442 msgid "Edge Detect" msgstr "Detección de bordos" #: src/canvas.c:464 msgid "Edge Sharpen" msgstr "Realzado de bordos" #: src/canvas.c:472 msgid "Edge Soften" msgstr "Suavizado de bordos" #: src/canvas.c:521 msgid "Different X/Y" msgstr "Diferenza X/Y" #: src/canvas.c:522 src/canvas.c:562 src/canvas.c:603 src/canvas.c:637 #: src/canvas.c:722 src/otherwindow.c:1037 src/otherwindow.c:2685 msgid "Gamma corrected" msgstr "Gama corrixida" #: src/canvas.c:530 src/memory.c:8219 msgid "Gaussian Blur" msgstr "Desenfoque Gausiano" #: src/canvas.c:558 msgid "Radius" msgstr "Radio" #: src/canvas.c:559 msgid "Amount" msgstr "Cantidade" #: src/canvas.c:560 msgid "Threshold " msgstr "Limiar " #: src/canvas.c:570 src/memory.c:8360 msgid "Unsharp Mask" msgstr "Máscara de desenfoque" #: src/canvas.c:599 msgid "Outer radius" msgstr "Radio exterior" #: src/canvas.c:600 msgid "Inner radius" msgstr "Radio interior" #: src/canvas.c:602 src/info.c:280 msgid "Normalize" msgstr "Normalizar" #: src/canvas.c:611 src/memory.c:8512 msgid "Difference of Gaussians" msgstr "Diferenza de Gauss" #: src/canvas.c:636 msgid "Protect details" msgstr "" #: src/canvas.c:645 msgid "Kuwahara-Nagao Blur" msgstr "Difuminado Kuwahara-Nagao" #: src/canvas.c:709 msgid "The image is too large for this rotation." msgstr "A imaxe é demasiado grande para a rotación." #: src/canvas.c:723 msgid "Smooth" msgstr "Suavizado" #: src/canvas.c:732 msgid "Free Rotate" msgstr "Rotación libre" #: src/canvas.c:989 src/viewer.c:1161 msgid "Not enough memory to create clipboard" msgstr "Non hai memoria dabondo para crear o portapapeis" #: src/canvas.c:1172 msgid "" "You have not allocated enough memory in the Preferences window to undo this " "action." msgstr "" #: src/canvas.c:1353 msgid "Invalid palette file" msgstr "" #: src/canvas.c:1383 msgid "Invalid channel file." msgstr "Canle non válido" #: src/canvas.c:1401 msgid "Raw frames" msgstr "" #: src/canvas.c:1401 msgid "Composited frames" msgstr "" #: src/canvas.c:1402 msgid "Composited frames with nonzero delay" msgstr "" #: src/canvas.c:1406 msgid "Load Frames" msgstr "" #: src/canvas.c:1409 msgid "Load into Layers" msgstr "" #: src/canvas.c:1415 msgid "Load First Frame" msgstr "" #: src/canvas.c:1416 msgid "Explode Frames" msgstr "" #: src/canvas.c:1418 msgid "View Animation" msgstr "Ver animación" #: src/canvas.c:1434 #, c-format msgid "This is an animated %s file." msgstr "Esto é un %s animado." #: src/canvas.c:1435 #, c-format msgid "This is a multipage %s file." msgstr "" #: src/canvas.c:1459 #, c-format msgid "File is too big, must be <= to width=%i height=%i" msgstr "O ficheiro é demasiado grande, debe ser <= a anchura=%i altura=%i" #: src/canvas.c:1461 msgid "Unable to explode frames" msgstr "" #: src/canvas.c:1463 msgid "Unable to load file" msgstr "Non é posible cargar o ficheiro" #: src/canvas.c:1465 msgid "" "The file import library had to terminate due to a problem with the file " "(possibly corrupt image data or a truncated file). I have managed to load " "some data as the header seemed fine, but I would suggest you save this image " "to a new file to ensure this does not happen again." msgstr "" "A biblioteca de ficheiros importados pechouse debido a un problema co " "ficheiro (posiblemente por datos incorrectos da imaxe ou un ficheiro " "danado). Puidose cargar algunha información, xa que a cabeceira está " "correcta, pero suxiro que garde esta imaxe nun novo ficheiro, para que esto " "no volva a ocurrir." #: src/canvas.c:1467 msgid "The animation is too long to load all of it into layers." msgstr "" #: src/canvas.c:1469 msgid "Could not explode all the frames in the animation." msgstr "" #: src/canvas.c:1481 src/font.c:1556 src/fpick.c:937 src/otherwindow.c:2765 #: src/prefs.c:321 src/toolbar.c:451 msgid "Size" msgstr "Tamaño" #: src/canvas.c:1484 src/otherwindow.c:244 msgid "Width" msgstr "Anchura" #: src/canvas.c:1485 src/otherwindow.c:245 msgid "Height" msgstr "Altura" #: src/canvas.c:1489 src/channels.c:253 src/channels.c:317 src/fpick.c:666 #: src/fpick.c:957 src/mainwindow.c:3990 src/otherwindow.c:255 #: src/otherwindow.c:517 src/otherwindow.c:591 src/otherwindow.c:867 #: src/otherwindow.c:1058 src/otherwindow.c:1727 src/otherwindow.c:2101 #: src/otherwindow.c:2336 src/otherwindow.c:2538 src/otherwindow.c:2691 #: src/otherwindow.c:2776 src/otherwindow.c:2937 src/otherwindow.c:3070 #: src/otherwindow.c:3169 src/prefs.c:338 src/prefs.c:464 src/prefs.c:538 #: src/spawn.c:666 src/viewer.c:1258 msgid "Cancel" msgstr "Cancelar" #: src/canvas.c:1490 src/channels.c:253 src/channels.c:317 src/fpick.c:956 #: src/info.c:297 src/mainwindow.c:3992 src/mygtk.c:233 src/mygtk.c:535 #: src/otherwindow.c:591 src/otherwindow.c:871 src/otherwindow.c:1058 #: src/otherwindow.c:1729 src/otherwindow.c:2101 src/otherwindow.c:2336 #: src/otherwindow.c:2538 src/otherwindow.c:2691 src/otherwindow.c:2776 #: src/otherwindow.c:3072 src/otherwindow.c:3171 src/prefs.c:338 #: src/prefs.c:538 src/spawn.c:666 msgid "OK" msgstr "Conforme" #: src/canvas.c:1504 #, c-format msgid "This is a scalable %s file." msgstr "" #: src/canvas.c:1545 msgid "Cannot open file" msgstr "No se pode abrir o ficheiro" #: src/canvas.c:1546 msgid "Unsupported file format" msgstr "Formato non soportado" #: src/canvas.c:1673 #, c-format msgid "File: %s already exists. Do you want to overwrite it?" msgstr "O ficheiro: %s xa existe. Desexa sobreescribirlo?" #: src/canvas.c:1674 msgid "File Found" msgstr "Ficheiro atopado" #: src/canvas.c:1674 src/mainwindow.c:1095 msgid "NO" msgstr "NON" #: src/canvas.c:1674 src/mainwindow.c:1095 msgid "YES" msgstr "SI" #: src/canvas.c:1988 msgid "Unable to export undo images" msgstr "Non se puido exportar o historial de cambios" #: src/canvas.c:1994 msgid "Unable to export ASCII file" msgstr "Non se puido exportar ficheiro ASCII" #: src/canvas.c:2076 src/layer.c:814 src/mainwindow.c:529 #, c-format msgid "Unable to save file: %s" msgstr "Non se puido gardar: %s" #: src/canvas.c:2101 src/prefs.c:222 msgid "Transparency index" msgstr "Ãndice de transparencia" #: src/canvas.c:2103 msgid "TIFF Compression" msgstr "" #: src/canvas.c:2105 src/prefs.c:225 msgid "JPEG Save Quality (100=High)" msgstr "Nivel de calidade JPEG (100=Alta)" #: src/canvas.c:2107 msgid "ZIP Compression (0=None)" msgstr "" #: src/canvas.c:2108 src/prefs.c:227 msgid "PNG Compression (0=None)" msgstr "Compresión PNG (0=ningunha)" #: src/canvas.c:2111 src/prefs.c:249 msgid "LZMA2 Compression (0=None)" msgstr "" #: src/canvas.c:2113 src/prefs.c:252 msgid "ZSTD Compression Level" msgstr "" #: src/canvas.c:2115 src/prefs.c:231 msgid "TGA RLE Compression" msgstr "Compresión TGA RLE" #: src/canvas.c:2117 msgid "LBM PackBits Compression" msgstr "" #: src/canvas.c:2118 src/prefs.c:226 msgid "JPEG2000 Compression (0=Lossless)" msgstr "Compresión JPEG2000 (0=sen perda)" #: src/canvas.c:2120 msgid "WebP Compression" msgstr "" #: src/canvas.c:2122 msgid "WebP Save Quality (100=High)" msgstr "" #: src/canvas.c:2123 src/prefs.c:263 msgid "V8 Save Quality (100=High)" msgstr "" #: src/canvas.c:2125 src/prefs.c:264 msgid "V8L Compression (0=None)" msgstr "" #: src/canvas.c:2127 msgid "Hotspot at X =" msgstr "Punto en X =" #: src/canvas.c:2129 msgid "Y =" msgstr "Y =" #: src/canvas.c:2133 msgid "Animation delay" msgstr "Retardo para a animación" #: src/canvas.c:2136 src/otherwindow.c:253 msgid "Undoable" msgstr "Reversíbel" #: src/canvas.c:2138 src/prefs.c:236 msgid "Apply colour profile" msgstr "" #: src/canvas.c:2176 src/toolbar.c:543 msgid "Load Image File" msgstr "Cargar imaxe" #: src/canvas.c:2191 src/toolbar.c:544 msgid "Save Image File" msgstr "Gardar imaxe" #: src/canvas.c:2196 msgid "Load Palette File" msgstr "Cargar paleta" #: src/canvas.c:2202 msgid "Save Palette File" msgstr "Gardar paleta" #: src/canvas.c:2207 msgid "Export Undo Images" msgstr "Exportar o historial de cambios" #: src/canvas.c:2212 msgid "Export Undo Images (reversed)" msgstr "Exportar o historial de cambios (á inversa)" #: src/canvas.c:2217 msgid "You must have 16 or fewer palette colours to export ASCII art." msgstr "Ten que ter 16 ou menos cores na paleta para exportar arte ASCII." #: src/canvas.c:2220 msgid "Export ASCII Art" msgstr "Exportar arte ASCII" #: src/canvas.c:2224 msgid "Save Layer Files" msgstr "Gravar ficheiros de capas" #: src/canvas.c:2234 msgid "Choose frames directory" msgstr "Elixe directório de fotogramas" #: src/canvas.c:2240 msgid "You must save at least one frame to create an animated GIF." msgstr "Debes ter ao menos un debuxo para crear un GIF animado" #: src/canvas.c:2243 msgid "Export GIF animation" msgstr "Exportar animación GIF" #: src/canvas.c:2247 msgid "Load Channel" msgstr "Cargar canle" #: src/canvas.c:2255 msgid "Save Channel" msgstr "Gardar canle" #: src/canvas.c:2260 msgid "Save Composite Image" msgstr "Gardar imaxe composta" #: src/channels.c:243 msgid "Create Channel" msgstr "Crear canle" #: src/channels.c:244 msgid "Channel Type" msgstr "Tipo de canle" #: src/channels.c:247 msgid "Initial Channel State" msgstr "Estado inicial da canle" #: src/channels.c:251 msgid "Inverted" msgstr "Invertida" #: src/channels.c:265 msgid "Cleared" msgstr "Limpando" #: src/channels.c:266 msgid "Set" msgstr "Establecer" #: src/channels.c:267 msgid "Set colour A radius B" msgstr "Corar A radio B" #: src/channels.c:268 msgid "Set blend A to B" msgstr "Misturar A en B" #: src/channels.c:269 msgid "Image Red" msgstr "Imaxe vermella" #: src/channels.c:270 msgid "Image Green" msgstr "Imaxe verde" #: src/channels.c:271 msgid "Image Blue" msgstr "Imaxe azul" #: src/channels.c:273 src/channels.c:313 src/mainwindow.c:67 #: src/otherwindow.c:1679 msgid "Alpha" msgstr "Alfa" #: src/channels.c:274 src/channels.c:314 src/mainwindow.c:67 #: src/otherwindow.c:1683 msgid "Selection" msgstr "Selección" #: src/channels.c:275 src/channels.c:315 src/mainwindow.c:67 #: src/otherwindow.c:1687 msgid "Mask" msgstr "Máscara" #: src/channels.c:312 msgid "Delete Channels" msgstr "Borrar canles" #: src/channels.c:367 msgid "Threshold Channel" msgstr "Limiar da canle" #: src/cpick.c:823 src/otherwindow.c:573 src/otherwindow.c:820 #: src/toolbar.c:299 msgid "Hue" msgstr "Matiz" #: src/cpick.c:827 src/otherwindow.c:573 src/otherwindow.c:818 #: src/toolbar.c:299 msgid "Saturation" msgstr "Saturación" #: src/cpick.c:835 msgid "Hex" msgstr "Hex" #: src/cpick.c:840 src/layer.c:1109 src/otherwindow.c:2530 src/prefs.c:323 #: src/toolbar.c:457 msgid "Opacity" msgstr "Opacidade" #: src/font.c:982 msgid "Creating Font Index" msgstr "Crear índice de fontes" #: src/font.c:1353 msgid "You must select at least one directory to search for fonts." msgstr "Debe seleccionar ao menos un directório para buscar fontes." #: src/font.c:1529 src/font.c:1624 src/toolbar.c:609 src/viewer.c:1213 #: src/viewer.c:1258 msgid "Paste Text" msgstr "Pegar texto" #: src/font.c:1533 src/font.c:1572 src/png.c:3578 msgid "Text" msgstr "Texto" #: src/font.c:1540 msgid "Font" msgstr "Fonte" #: src/font.c:1548 msgid "Style" msgstr "Estilo" #: src/font.c:1566 msgid "Filename" msgstr "Nome do ficheiro" #: src/font.c:1567 msgid "Face" msgstr "Cara" #: src/font.c:1587 src/viewer.c:1222 msgid "Antialias" msgstr "Suavizar" #: src/font.c:1590 src/viewer.c:1224 msgid "Invert" msgstr "Invertir" #: src/font.c:1593 src/viewer.c:1226 msgid "Background colour =" msgstr "Cor de fondo =" #: src/font.c:1601 src/viewer.c:1233 msgid "DPI =" msgstr "" #: src/font.c:1610 msgid "Oblique" msgstr "Oblicuo" #: src/font.c:1612 src/viewer.c:1244 msgid "Angle of rotation =" msgstr "Ãngulo de rotación =" #: src/font.c:1617 src/viewer.c:1248 msgid "Align" msgstr "" #: src/font.c:1620 src/viewer.c:1253 msgid "Spacing" msgstr "" #: src/font.c:1629 msgid "Font Directories" msgstr "Directório de fontes" #: src/font.c:1634 src/spawn.c:664 msgid "Directory" msgstr "Directório" #: src/font.c:1637 msgid "New Directory" msgstr "Novo directório" #: src/font.c:1644 src/prefs.c:532 msgid "Add" msgstr "Engadir" #: src/font.c:1645 src/prefs.c:533 msgid "Remove" msgstr "Eliminar" #: src/font.c:1646 msgid "Create Index" msgstr "Crear índice" #: src/font.c:1660 src/viewer.c:1267 msgid "Enter Text Here" msgstr "Introduza aquí o texto" #: src/fpick.c:635 #, c-format msgid "Could not access directory %s" msgstr "Non se pode acceder ao directorio %s" #: src/fpick.c:668 src/fpick.c:698 msgid "Delete" msgstr "Borrar" #: src/fpick.c:669 src/fpick.c:698 msgid "Rename" msgstr "Renomear" #: src/fpick.c:672 src/otherwindow.c:255 src/otherwindow.c:1666 msgid "Create" msgstr "Crear" #: src/fpick.c:699 msgid "Enter the new filename" msgstr "Introduza o novo nome do ficheiro" #: src/fpick.c:704 msgid "Create Directory" msgstr "Crear cartafol" #: src/fpick.c:705 msgid "Enter the name of the new directory" msgstr "Introduza o nome do novo directorio" #: src/fpick.c:729 #, c-format msgid "Do you really want to delete \"%s\" ?" msgstr "Desexa borrar \"%s\" ?" #: src/fpick.c:735 msgid "Unable to delete" msgstr "Non se pode borrar" #: src/fpick.c:741 msgid "Unable to rename" msgstr "Non se pode renomear" #: src/fpick.c:750 msgid "Unable to create directory" msgstr "Non se pode crear o cartafol" #: src/fpick.c:924 msgid "Up" msgstr "Arriba" #: src/fpick.c:925 msgid "Home" msgstr "Inicio" #: src/fpick.c:926 msgid "Create New Directory" msgstr "Crear novo cartafol" #: src/fpick.c:927 msgid "Show Hidden Files" msgstr "Mostrar os ficheiros agochados" #: src/fpick.c:929 msgid "Case Insensitive Sort" msgstr "Ordenar sen sensibilidade a maiúsculas" #: src/fpick.c:936 msgid "Name" msgstr "Nome" #: src/fpick.c:938 msgid "Type" msgstr "Tipo" #: src/fpick.c:939 msgid "Modified" msgstr "Modificado" #: src/help.c:25 src/prefs.c:160 msgid "General" msgstr "Xeral" #: src/help.c:26 msgid "Keyboard shortcuts" msgstr "Atallos de teclado" #: src/help.c:27 msgid "Mouse shortcuts" msgstr "Atallos de rato" #: src/help.c:28 msgid "Credits" msgstr "Créditos" #: src/help.c:32 msgid "mtPaint 3.51 - Copyright (C) 2004-2021 The Authors\n" msgstr "mtPaint 3.51 - Copyright (C) 2004-2021 Os Autores\n" #: src/help.c:33 msgid "See 'Credits' section for a list of the authors.\n" msgstr "Ver a sección de «Créditos» para o listado de autores.\n" #: src/help.c:34 msgid "" "mtPaint 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.\n" msgstr "" "mtPaint é Software Libre; podes residtribuilo e/ou modificalo baixo os " "termos da GNU General Public License publicada pola Free Software " "Foundation; coa versión 3 da licencia, ou calquer versión posterior.\n" #: src/help.c:35 msgid "" "mtPaint 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.\n" msgstr "" "mtPaint distribuese coa esperanza de que sexa útil, pero SIN NINGUNHA " "GARANTÃA. Ver a GNU General Public License para máis detalles.\n" #: src/help.c:36 msgid "" "mtPaint is a simple GTK+1/2/3 painting program designed for creating icons " "and pixel based artwork. It can edit indexed palette or 24 bit RGB images " "and offers basic painting and palette manipulation tools. It also has " "several other more powerful features such as channels, layers and animation. " "Due to its simplicity and lack of dependencies it runs well on GNU/Linux, " "Windows and older PC hardware.\n" msgstr "" "mtPaint é un programa de pintura sinxelo baseado en GTK+1/2/3 deseñado para " "crear iconas e traballos artísticos de píxeles. Pode editar paletas " "indexadas ou imaxes de 24 bit RGB e fornece ferramentas básicas para pintar " "e manipular paletas. Ten moitas outras características interesantes como " "canles, capas e animacións. Debido a sua simplicidade carece de dependencias " "e funciona moi ben en GNU/Linux e en Windows con hardware anticuado.\n" #: src/help.c:37 msgid "" "There is full documentation of mtPaint's features contained in a handbook. " "If you don't already have this, you can download it from the mtPaint " "website.\n" msgstr "" "Ha unha extensa documentación de mtPaint no manual. Se non o tes xa, podes " "descargarlo do sitio web de mtPaint.\n" #: src/help.c:38 msgid "" "If you like mtPaint and you want to keep up to date with new releases, or " "you want to give some feedback, then the mailing lists may be of interest to " "you:\n" msgstr "" "Si mtPaint é do teu gusto e queres manterte informado sobre novas " "actualizacions ou queres enviar algún comentario, entonces pode que che " "interese a lista de correo:\n" #: src/help.c:39 msgid "http://sourceforge.net/mail/?group_id=155874" msgstr "ttp://sourceforge.net/mail/?group_id=155874" #: src/help.c:42 msgid " Ctrl-N Create new image" msgstr " Ctrl-N Crear nova imaxe" #: src/help.c:43 msgid " Ctrl-O Open Image" msgstr " Ctrl-O Abrir imaxe" #: src/help.c:44 msgid " Ctrl-S Save Image" msgstr " Ctrl-S Gardar imaxe" #: src/help.c:45 msgid " Ctrl-Shift-S Save layers file" msgstr "" #: src/help.c:46 msgid " Ctrl-Q Quit program\n" msgstr " Ctrl-Q Sair\n" #: src/help.c:47 msgid " Ctrl-A Select whole image" msgstr " Ctrl-A Seleccionar imaxe enteira" #: src/help.c:48 msgid " Escape Select nothing, cancel paste box" msgstr " Escape Non seleccionar nada, cancelar caixa de pegado" #: src/help.c:49 msgid " J Lasso selection\n" msgstr "" #: src/help.c:50 msgid " Ctrl-C Copy selection to clipboard" msgstr " Ctrl-C Copiar selección ao portapapeis" #: src/help.c:51 msgid "" " Ctrl-X Copy selection to clipboard, and then paint current " "pattern to selection area" msgstr "" " Ctrl-X Copiar a selección ao portapapeis, e entonces pintar o " "actual patrón a área seleccionada" #: src/help.c:52 msgid " Ctrl-V Paste clipboard to centre of current view" msgstr " Ctrl-V Pegar do portapepeis" #: src/help.c:53 msgid " Ctrl-K Paste clipboard to location it was copied from" msgstr " Ctrl-K Pegar do portapapeis ao sitio do que foi copiado" #: src/help.c:54 msgid " Ctrl-Shift-V Paste clipboard to new layer" msgstr "" #: src/help.c:55 msgid " Enter/Return Commit paste to canvas" msgstr " Intro/Retorno Pegar no lenzo" #: src/help.c:56 msgid " Shift+Enter/Return Commit paste and swap canvas into the clipboard\n" msgstr "" #: src/help.c:57 msgid " Arrow keys Paint Mode - Move the mouse pointer" msgstr " Teclas de frecha Modo pintar - Cambiar cor A o B" #: src/help.c:58 msgid "" " Arrow keys Selection Mode - Nudge selection box or paste box by one " "pixel" msgstr "" " Teclas de frecha Modo selección - Empurrar marco de selección ou " "pegar de un en un (píxeles)" #: src/help.c:59 msgid "" " Shift+Arrow keys Nudge mouse pointer, selection box or paste box by x " "pixels - x is defined by the Preferences window" msgstr "" " Mayús+Teclas de frecha Empurrar marco de selección ou pegar en x píxeles " "- x está definido na ventá de preferencias" #: src/help.c:60 msgid " Ctrl+Arrows Move layer or resize selection box" msgstr " Ctrl+Frechas Mover capa ou redimensionar marco de selección" #: src/help.c:61 msgid " Ctrl+Shift+Arrows Move layer or resize selection box by x pixels\n" msgstr "" #: src/help.c:62 msgid " Enter/Return Paint Mode - Simulate left click" msgstr "" #: src/help.c:63 msgid " Backspace Paint Mode - Simulate right click\n" msgstr "" #: src/help.c:64 msgid "" " [ or ] Change colour A to the next or previous palette item" msgstr " [ ou ] Cambia a cor A á seguinte ou á anterior na paleta" #: src/help.c:65 msgid "" " Shift+[ or ] Change colour B to the next or previous palette item\n" msgstr "" " Mayús+[ ou ] Cambia a cor B á seguinte ou á anterior na paleta\n" #: src/help.c:66 msgid " Delete Crop image to selection" msgstr " Supr Cortar imaxe á selección" #: src/help.c:67 msgid "" " Insert Transform colours - i.e. Brightness, Contrast, " "Saturation, Posterize, Gamma" msgstr "" " Insert Transformar cores - ex. brillo, contraste, saturación, " "posterizar, gama" #: src/help.c:68 msgid " Ctrl-G Greyscale the image" msgstr " Ctrl-G Escala de grises da imaxe" #: src/help.c:69 msgid " Shift-Ctrl-G Greyscale the image (Gamma corrected)" msgstr " Mayús-Ctrl-G Escala a imaxe á grises (gama corrixida)" #: src/help.c:70 msgid " Ctrl+M Mirror the image" msgstr "" #: src/help.c:71 msgid " Shift-Ctrl-I Invert the image\n" msgstr "" #: src/help.c:72 msgid "" " Ctrl-T Draw a rectangle around the selection area with the " "current fill" msgstr "" " Ctrl-T Debuxar un rectángulo arredor da área de selección co " "recheo actual" #: src/help.c:73 msgid " Ctrl-Shift-T Fill in the selection area with the current fill" msgstr " Ctrl-Mayús-T Encher a área de selección co actual recheo" #: src/help.c:74 msgid " Ctrl-L Draw an ellipse spanning the selection area" msgstr "" " Ctrl-L Debuxar unha elipse atravesando a área de selección" #: src/help.c:75 msgid " Ctrl-Shift-L Draw a filled ellipse spanning the selection area\n" msgstr "" " Ctrl-Mayús-L Debuxar unha elipse enchida atravesando a área de " "selección\n" #: src/help.c:76 msgid " Ctrl-E Edit the RGB values for colours A & B" msgstr " Ctrl-E Editar os valores RGB para as cores A e B" #: src/help.c:77 msgid " Ctrl-W Edit all palette colours\n" msgstr " Ctrl-W Editar toda a paleta de cores\n" #: src/help.c:78 msgid " Ctrl-P Preferences" msgstr " Ctrl-P Preferencias" #: src/help.c:79 msgid " Ctrl-I Information\n" msgstr " Ctrl-I Información\n" #: src/help.c:80 msgid " Ctrl-Z Undo last action" msgstr " Ctrl-Z Desfacer a última acción" #: src/help.c:81 msgid " Ctrl-R Redo an undone action\n" msgstr " Ctrl-R Refacer a acción\n" #: src/help.c:82 msgid " Shift-T Text Tool (GTK+)" msgstr "" #: src/help.c:83 msgid " T Text Tool (FreeType)\n" msgstr "" #: src/help.c:84 msgid " V View Window" msgstr " V Ver ventá" #: src/help.c:85 msgid " L Layers Window\n" msgstr " L Ventá de capas\n" #: src/help.c:86 msgid " Ctrl-H Toggle Hide Image mode" msgstr "" #: src/help.c:87 msgid " B Toggle Snap to Tile Grid mode\n" msgstr "" #: src/help.c:88 msgid " X Swap Colours A & B" msgstr "" #: src/help.c:89 msgid " E Choose Colour\n" msgstr "" #: src/help.c:90 msgid "" " A Draw open arrow head when using the line tool (size set " "by flow setting)" msgstr "" " A Debuxar cabeza de frecha aberta coa ferramenta de liña " "(según o axuste de tamaño de fluxo)" #: src/help.c:91 msgid "" " S Draw closed arrow head when using the line tool (size " "set by flow setting)\n" msgstr "" " S Debuxar cabeza de frecha pechada coa ferramenta de liña " "(según o axuste de tamaño de fluxo)\n" #: src/help.c:92 msgid " D Line Tool" msgstr "" #: src/help.c:93 msgid " F Flood Fill Tool\n" msgstr "" #: src/help.c:94 msgid " +,= Main edit window - Zoom in" msgstr " +,= Zoom acercar" #: src/help.c:95 msgid " - Main edit window - Zoom out" msgstr " - Zoom alonxar" #: src/help.c:96 msgid " Shift +,= View window - Zoom in" msgstr " Mayús +,= Ampliar" #: src/help.c:97 msgid " Shift - View window - Zoom out\n" msgstr " Mayús - Reducir\n" #: src/help.c:98 #, c-format msgid " 1 10% zoom" msgstr " 1 10% zoom" #: src/help.c:99 #, c-format msgid " 2 25% zoom" msgstr " 2 25% zoom" #: src/help.c:100 #, c-format msgid " 3 50% zoom" msgstr " 3 50% zoom" #: src/help.c:101 #, c-format msgid " 4 100% zoom" msgstr " 4 100% zoom" #: src/help.c:102 #, c-format msgid " 5 400% zoom" msgstr " 5 400% zoom" #: src/help.c:103 #, c-format msgid " 6 800% zoom" msgstr " 6 800% zoom" #: src/help.c:104 #, c-format msgid " 7 1200% zoom" msgstr " 7 1200% zoom" #: src/help.c:105 #, c-format msgid " 8 1600% zoom" msgstr " 8 1600% zoo" #: src/help.c:106 #, c-format msgid " 9 2000% zoom\n" msgstr " 9 2000% zoom\n" #: src/help.c:107 msgid " Shift + 1 Edit image channel" msgstr " Mayús + 1 Editar canle de imaxe" #: src/help.c:108 msgid " Shift + 2 Edit alpha channel" msgstr " Mayús + 2 Editar canle alfa" #: src/help.c:109 msgid " Shift + 3 Edit selection channel" msgstr " Mayús + 3 Editar canle de selección" #: src/help.c:110 msgid " Shift + 4 Edit mask channel\n" msgstr " Mayús + 4 Editar canle de máscara\n" #: src/help.c:111 msgid " F1 Help" msgstr " F1 Axuda" #: src/help.c:112 msgid " F2 Choose Pattern" msgstr " F2 Elixir patrón" #: src/help.c:113 msgid " F3 Choose Brush" msgstr " F3 Elixir brocha" #: src/help.c:114 msgid " F4 Paint Tool" msgstr " F4 Ferramenta de pintura" #: src/help.c:115 msgid " F5 Toggle Main Toolbar" msgstr " F5 Elixir barra principal" #: src/help.c:116 msgid " F6 Toggle Tools Toolbar" msgstr " F6 Elixir barra de ferramentas" #: src/help.c:117 msgid " F7 Toggle Settings Toolbar" msgstr " F7 Elixir barra de preferencias" #: src/help.c:118 msgid " F8 Toggle Palette" msgstr " F8 Elixir paleta" #: src/help.c:119 msgid " F9 Selection Tool" msgstr " F9 Ferramenta de selección" #: src/help.c:120 msgid " F12 Toggle Dock Area\n" msgstr " F12 Alternar área ancorada\n" #: src/help.c:121 msgid " Ctrl + F1 - F12 Save current clipboard to file 1-12" msgstr " Ctrl + F1 - F12 Gardar o portapapeis actual ao ficheiro 1-12" #: src/help.c:122 msgid " Shift + F1 - F12 Load clipboard from file 1-12\n" msgstr " Mayús + F1 - F12 Cargar portapapeis desde o ficheiro 1-12\n" #: src/help.c:123 msgid "" " Ctrl + 1, 2, ... , 0 Set opacity to 10%, 20%, ... , 100% (main or keypad " "numbers)" msgstr "" " Ctrl + 1, 2, ... , 0 Establecer opacidade ao 10%, 20%, ... , 100% (no " "teclado numérico ou no principal)" #: src/help.c:124 msgid " Ctrl + + or = Increase opacity by 1" msgstr " Ctrl + + ou = Incrementar opacidade nun 1" #: src/help.c:125 msgid " Ctrl + - Decrease opacity by 1\n" msgstr " Ctrl + - Diminuir opacidade nun 1\n" #: src/help.c:126 msgid "" " Home Show or hide main window menu/toolbar/status bar/palette" msgstr "" " Inicio Amosar ou esconder a ventá principal menu/barra de " "ferramentas/barra de estado/paleta" #: src/help.c:127 msgid " Page Up Scale Image" msgstr " Re Pag Escalar a imaxe" #: src/help.c:128 msgid " Page Down Resize Image canvas" msgstr " Av Pag Redimensionar o lenzo" #: src/help.c:129 msgid " End Pan Window" msgstr " Fin Quitar a ventá" #: src/help.c:132 msgid " Left button Paint to canvas using the current tool" msgstr " Botón esquerdo Pinta no lenzo usando a ferramenta activa" #: src/help.c:133 msgid "" " Middle button Selects the point which will be the centre of the " "image after the next zoom" msgstr " Botón central Fixa o centro para o seguinte zoom" #: src/help.c:134 msgid "" " Right button Commit paste to canvas / Stop drawing current line / " "Cancel selection\n" msgstr "" " Botón dereito Pega no lenzo / Termina o trazado dunha liña / " "Cancela unha selección\n" #: src/help.c:135 msgid "" " Scroll Wheel In GTK+2/3 the user can have the scroll wheel zoom in " "or out via the Preferences window\n" msgstr "" " Roda de desprazamento En GTK+2/3 o usuario pode activar o zoom coa " "roda de desprazamento na ventá de preferencias\n" #: src/help.c:136 msgid " Ctrl+Left button Choose colour A from under mouse pointer" msgstr " Ctrl+Botón esquerdo Elixir cor A co rato" #: src/help.c:137 msgid " Ctrl+Left button Clone tool - Select source" msgstr "" #: src/help.c:138 msgid "" " Ctrl+Middle button Create colour A/B and pattern based on the RGB colour " "in A (RGB images only)" msgstr "" " Ctrl+Botón central Crea cor A/B e patrón de puntos baseado en cores RGB " "en A (só imaxes RGB)" #: src/help.c:139 msgid " Ctrl+Right button Choose colour B from under mouse pointer" msgstr " Ctrl+Botón dereito Elixir cor B co rato" #: src/help.c:140 msgid "" " Ctrl+Right button Polygon tool - Delete last point / Delete nearest " "point" msgstr "" #: src/help.c:141 msgid " Ctrl+Scroll Wheel Scroll the main edit window left or right\n" msgstr "" " Ctrl+Roda de desprazamento Moverse na ventá principal á esquerda ou á " "dereita\n" #: src/help.c:142 msgid "" " Ctrl+Double click Set colour A or B to average colour under brush " "square or selection marquee (RGB only)\n" msgstr "" " Ctrl + doble clic establece a cor intermedia para A ou B que esté baixo o " "pincel ou a selección marcada (só para RGB)\n" #: src/help.c:143 msgid "" " Shift+Right button Selects the point which will be the centre of the " "image after the next zoom\n" "\n" msgstr "" " Mayús+Botón dereito Fixa o centro para o zoom seguinte\n" "\n" #: src/help.c:144 msgid "You can fixate the X/Y co-ordinates while moving the mouse:\n" msgstr "Pode fixar as coordenadas X/Y mentras move o rato:\n" #: src/help.c:145 msgid " Shift Constrain mouse movements to vertical line" msgstr "" " Mayús Restrinxe os movimentos do rato a unha liña vertical" #: src/help.c:146 msgid " Shift+Ctrl Constrain mouse movements to horizontal line" msgstr "" " Mayús+Ctrl Restrinxe os movimentos do rato a unha liña horizontal" #: src/help.c:149 msgid "mtPaint is maintained by Dmitry Groshev.\n" msgstr "mtPaint é mantido por Dmitry Groshev.\n" #: src/help.c:150 msgid "wjaguar@users.sourceforge.net" msgstr "wjaguar@users.sourceforge.net" #: src/help.c:151 msgid "http://mtpaint.sourceforge.net/\n" msgstr "http://mtpaint.sourceforge.net/\n" #: src/help.c:152 msgid "" "The following people (in alphabetical order) have contributed directly to " "the project, and are therefore worthy of gracious thanks for their " "generosity and hard work:\n" "\n" msgstr "" "As seguintes persoas (en orde alfabético) contribuiron directamente no " "proxecto e, por tanto, agradeceselles moitisimo a sua xenerosidade e " "traballo arreo:\n" "\n" #: src/help.c:153 msgid "Authors\n" msgstr "Autores\n" #: src/help.c:154 msgid "" "Dmitry Groshev - Contributing developer for version 2.30. Lead developer and " "maintainer from version 3.00 to the present." msgstr "" "Dmitry Groshev - Contribuiu como desenvolvedor na versión 2.30. Principal " "desenvolvedor e mantedor dende a versión 3.00 até a actualidade." #: src/help.c:155 msgid "" "Mark Tyler - Original author and maintainer up to version 3.00, occasional " "contributor thereafter." msgstr "" "Mark Tyler - Autor orixinal e mantedor até a versión 3.00, colaborador " "ocasional desde entón." #: src/help.c:156 msgid "" "Xiaolin Wu - Wrote the Wu quantizing method - see wu.c for more " "information.\n" "\n" msgstr "" "Xiaolin Wu - Escribiu o metodo de cuantización Wu - ver wu.c para máis " "información.\n" "\n" #: src/help.c:157 msgid "" "General Contributions (Feedback and Ideas for improvements unless otherwise " "stated)\n" msgstr "Contribucions xerais (retornos e ideas de mellora)\n" #: src/help.c:158 msgid "Abdulla Al Muhairi - Website redesign April 2005" msgstr "Abdulla Al Muhairi - Redeseñou o sito wen en Abril do 2005" #: src/help.c:159 msgid "Alan Horkan" msgstr "Alan Horkan" #: src/help.c:160 msgid "Alexandre Prokoudine" msgstr "Alexandre Prokoudine" #: src/help.c:161 msgid "Antonio Andrea Bianco" msgstr "Antonio Andrea Bianco" #: src/help.c:162 msgid "Charlie Ledocq" msgstr "" #: src/help.c:163 msgid "Dennis Lee" msgstr "Dennis Lee" #: src/help.c:164 msgid "Donald White" msgstr "" #: src/help.c:165 msgid "Ed Jason" msgstr "Ed Jason" #: src/help.c:166 msgid "" "Eddie Kohler - Created Gifsicle which is needed for the creation and viewing " "of animated GIF files http://www.lcdf.org/gifsicle/" msgstr "" "Eddie Kohler - Creo Gifsicle que é necesario para a creación e visualización " "de ficheiros GIF animados http://www.lcdf.org/gifsicle/" #: src/help.c:167 msgid "" "Guadalinex Team (Junta de Andalucia) - man page, Launchpad/Rosetta " "registration" msgstr "" "Guadalinex Team (Junta de Andalucia) - man page, Launchpad/Rosetta " "registration" #: src/help.c:168 msgid "Lou Afonso" msgstr "Lou Afonso" #: src/help.c:169 msgid "Magnus Hjorth" msgstr "Magnus Hjorth" #: src/help.c:170 msgid "Martin Zelaia" msgstr "Martin Zelaia" #: src/help.c:171 msgid "Pasi Kallinen" msgstr "" #: src/help.c:172 msgid "Pavel Ruzicka" msgstr "Pavel Ruzicka" #: src/help.c:173 msgid "Puppy Linux (Barry Kauler)" msgstr "Puppy Linux (Barry Kauler)" #: src/help.c:174 msgid "Victor Copovi" msgstr "" #: src/help.c:175 msgid "Vlastimil Krejcir" msgstr "Vlastimil Krejcir" #: src/help.c:176 msgid "" "William Kern\n" "\n" msgstr "" "William Kern\n" "\n" #: src/help.c:177 msgid "Translations\n" msgstr "Traduccions\n" #: src/help.c:178 msgid "Brazilian Portuguese - Paulo Trevizan, Valter Nazianzeno" msgstr "Portugés do Brasil - Paulo Trevizan, Valter Nazianzeno" #: src/help.c:179 msgid "Czech - Pavel Ruzicka, Martin Petricek, Roman Hornik, Pavel Fric" msgstr "Checo - Pavel Ruzicka, Martin Petricek, Roman Hornik, Pavel Fric" #: src/help.c:180 msgid "Dutch - Hans Strijards, Pjotr" msgstr "Holandés - Hans Strijards, Pjotr" #: src/help.c:181 msgid "" "French - Nicolas Velin, Pascal Billard, Sylvain Cresto, Johan Serre, " "Philippe Etienne, Victor Copovi" msgstr "" "Francés - Nicolas Velin, Pascal Billard, Sylvain Cresto, Johan Serre, " "Philippe Etienne, Victor Copovi" #: src/help.c:182 msgid "Galician - Miguel Anxo Bouzada" msgstr "Galego - Miguel Anxo Bouzada" #: src/help.c:183 msgid "German - Oliver Frommel, B. Clausius, Ulrich Ringel, Simon Brixel" msgstr "Alemán - Oliver Frommel, B. Clausius, Ulrich Ringel, Simon Brixel" #: src/help.c:184 msgid "Hungarian - Ur Balazs" msgstr "" #: src/help.c:185 msgid "Italian - Angelo Gemmi" msgstr "Italiano - Angelo Gemmi" #: src/help.c:186 msgid "Japanese - Norihiro YONEDA" msgstr "Xaponés - Norihiro YONEDA" #: src/help.c:187 msgid "Kabyle - Yacine Bouklif" msgstr "" #: src/help.c:188 msgid "Polish - Bartosz Kaszubowski, LucaS" msgstr "Polaco - Bartosz Kaszubowski, LucaS" #: src/help.c:189 msgid "Portuguese - Israel G. Lugo, Tiago Silva" msgstr "Portugués - Israel G. Lugo, Tiago Silva" #: src/help.c:190 msgid "Russian - Sergey Irupin, Dmitry Groshev" msgstr "Ruso - Sergey Irupin, Dmitry Groshev" #: src/help.c:191 msgid "Simplified Chinese - Cecc" msgstr "Chinés simplificado - Cecc" #: src/help.c:192 msgid "Slovak - Jozef Riha" msgstr "Eslovaco - Jozef Riha" #: src/help.c:193 msgid "" "Spanish - Guadalinex Team (Junta de Andalucia), Antonio Sanchez Leon, Miguel " "Anxo Bouzada, Francisco Jose Rey, Adolfo Jayme" msgstr "" "Castelán - Guadalinex Team (Junta de Andalucia), Antonio Sanchez Leon, " "Miguel Anxo Bouzada, Francisco Jose Rey, Adolfo Jayme" #: src/help.c:194 msgid "Swedish - Daniel Nylander, Daniel Eriksson" msgstr "Sueco - Daniel Nylander, Daniel Eriksson" #: src/help.c:195 msgid "Tagalog - Anjelo delCarmen" msgstr "" #: src/help.c:196 msgid "Taiwanese Chinese - Wei-Lun Chao" msgstr "Chines de Taiwan - Wei-Lun Chao" #: src/help.c:197 msgid "Turkish - Muhammet Kara, Tutku Dalmaz" msgstr "Turco - Muhammet Kara, Tutku Dalmaz" #: src/info.c:258 msgid "Information" msgstr "Información" #: src/info.c:260 msgid "Memory" msgstr "Memoria" #: src/info.c:261 msgid "Total memory for main + undo images" msgstr "Memoria total dispoñible para principal + desfacer imaxes" #: src/info.c:263 msgid "Undo / Redo / Max levels used" msgstr "Desfacer / Refacer/ Máximo número de niveis usados" #: src/info.c:265 msgid "Unused" msgstr "Sin usar" #: src/info.c:269 msgid "Unique RGB pixels" msgstr "Píxeles RGB illados" #: src/info.c:272 src/layer.c:121 msgid "Layers" msgstr "Capas" #: src/info.c:273 msgid "Total layer memory usage" msgstr "Consumo total de memoria da capa" #: src/info.c:277 msgid "Colour Histogram" msgstr "Histograma da cor" #: src/info.c:289 src/otherwindow.c:1614 msgid "Index" msgstr "Ãndice" #: src/info.c:290 msgid "Canvas pixels" msgstr "Píxeles do lenzo" #: src/info.c:328 #, c-format msgid "Clipboard = %i x %i" msgstr "Portapapeis = %i x %i" #: src/info.c:328 #, c-format msgid "Clipboard = %i x %i x RGB" msgstr "Portapapeis = %i x %i x RGB" #: src/info.c:377 msgid "Orphans" msgstr "Orfos" #: src/info.c:383 #, c-format msgid "Colour index totals - %i of %i used" msgstr "Total de cores indexadas - %i de %i usados" #: src/inifile.c:966 msgid "" "Could not find home directory. Using current directory as home directory." msgstr "No se puido atopar o cartafol. Usarase o cartafol actual como local." #: src/layer.c:63 msgid "Background" msgstr "Fondo" #: src/layer.c:122 src/mainwindow.c:5931 msgid "(Modified)" msgstr "(Modificado)" #: src/layer.c:123 src/mainwindow.c:5932 msgid "Untitled" msgstr "Sin nome" #: src/layer.c:308 #, c-format msgid "Do you really want to delete layer %i (%s) ?" msgstr "Seguro que desexa borrar a capa %i (%s) ?" #: src/layer.c:380 msgid "" "One or more of the layers contains changes that have not been saved. Do you " "really want to lose these changes?" msgstr "" "Unha ou máis capas conteñen cambios que non se gardaron gardaron. Seguro que " "quere perder estos cambios?" #: src/layer.c:381 src/mainwindow.c:1028 msgid "Cancel Operation" msgstr "Cancelar operación" #: src/layer.c:381 src/mainwindow.c:1028 msgid "Lose Changes" msgstr "Perder os cambios" #: src/layer.c:523 #, c-format msgid "%d layers failed to load" msgstr "%d capas fallaron ao cargar" #: src/layer.c:826 msgid "" "One or more of the image layers has not been saved. You must save each " "image individually before saving the layers text file in order to load this " "composite image in the future." msgstr "" "Unha ou máis capas da imaxe non foron gardadas. Debes gardar cada imaxe " "individualmente para cargar a imaxe composta no futuro." #: src/layer.c:841 msgid "Do you really want to delete all of the layers?" msgstr "Está seguro de que desexa borrar todas as capas?" #: src/layer.c:970 msgid "You cannot add any more layers." msgstr "Non podes engadir máis capas." #: src/layer.c:1083 src/otherwindow.c:241 msgid "New Layer" msgstr "Nova capa" #: src/layer.c:1085 msgid "Raise" msgstr "Elevar" #: src/layer.c:1087 msgid "Lower" msgstr "Baixar" #: src/layer.c:1089 msgid "Duplicate Layer" msgstr "Duplicar capa" #: src/layer.c:1091 msgid "Centralise Layer" msgstr "Centrar capa" #: src/layer.c:1093 msgid "Delete Layer" msgstr "Borrar capa" #: src/layer.c:1095 msgid "Close Layers Window" msgstr "Cerrar ventá de capas" #: src/layer.c:1101 msgid "Layer Name" msgstr "Nome da capa" #: src/layer.c:1104 src/toolbar.c:209 msgid "Position" msgstr "Posición" #: src/layer.c:1112 msgid "Transparent Colour" msgstr "Cor transparente" #: src/layer.c:1117 msgid "Show all layers in main window" msgstr "Amosar todalas capas na ventá principal" #: src/mainwindow.c:67 src/otherwindow.c:844 src/otherwindow.c:2756 #: src/toolbar.c:342 msgid "Image" msgstr "imaxe" #: src/mainwindow.c:69 src/mainwindow.c:489 src/otherwindow.c:1613 #: src/otherwindow.c:2302 msgid "RGB" msgstr "RGB" #: src/mainwindow.c:69 src/otherwindow.c:1613 src/otherwindow.c:2302 msgid "sRGB" msgstr "" #: src/mainwindow.c:342 msgid "There were no unused colours to remove!" msgstr "Non había cores sin usar para eliminar!" #: src/mainwindow.c:371 msgid "The palette does not contain 2 colours that have identical RGB values" msgstr "A paleta non conten 2 cores que posuan idénticos valores RGB" #: src/mainwindow.c:374 #, c-format msgid "" "The palette contains %i colours that have identical RGB values. Do you " "really want to merge them into one index and realign the canvas?" msgstr "" "A paleta conten %i cores que teñen idénticos valores RGB. Quere misturalos " "nun e realiñar o lenzo?" #: src/mainwindow.c:492 msgid "indexed" msgstr "indexado" #: src/mainwindow.c:498 #, c-format msgid "" "You are trying to save an %s image to an %s file which is not possible. I " "would suggest you save with a PNG extension." msgstr "" "Pretende gardar unha imaxe %s nun ficheiro %s o que non és posible. " "Suxirolle que o garde coa extensión PNG." #: src/mainwindow.c:500 #, c-format msgid "" "You are trying to save an %s file with a palette of more than %d colours. " "Either use another format or reduce the palette to %d colours." msgstr "" "Pretende gardar un ficheiro %s con unha paleta de máis de %d cores. Use " "outro formato o reduza la paleta a %d cores." #: src/mainwindow.c:578 msgid "Unable to load clipboard" msgstr "Non se puido cargar o portapapeis" #: src/mainwindow.c:604 msgid "Unable to save clipboard" msgstr "Non se puido gardar o portapapeis" #: src/mainwindow.c:775 msgid "Zoom in" msgstr "" #: src/mainwindow.c:777 msgid "Zoom out" msgstr "" #: src/mainwindow.c:779 #, c-format msgid "10% zoom" msgstr "" #: src/mainwindow.c:781 #, c-format msgid "25% zoom" msgstr "" #: src/mainwindow.c:783 #, c-format msgid "50% zoom" msgstr "" #: src/mainwindow.c:785 #, c-format msgid "100% zoom" msgstr "" #: src/mainwindow.c:787 #, c-format msgid "400% zoom" msgstr "" #: src/mainwindow.c:789 #, c-format msgid "600% zoom" msgstr "" #: src/mainwindow.c:791 #, c-format msgid "800% zoom" msgstr "" #: src/mainwindow.c:793 #, c-format msgid "1000% zoom" msgstr "" #: src/mainwindow.c:795 #, c-format msgid "1200% zoom" msgstr "" #: src/mainwindow.c:797 #, c-format msgid "1600% zoom" msgstr "" #: src/mainwindow.c:799 #, c-format msgid "2000% zoom" msgstr "" #: src/mainwindow.c:801 #, c-format msgid "4000% zoom" msgstr "" #: src/mainwindow.c:803 #, c-format msgid "8000% zoom" msgstr "" #: src/mainwindow.c:805 #, c-format msgid "10% opacity" msgstr "" #: src/mainwindow.c:807 #, c-format msgid "20% opacity" msgstr "" #: src/mainwindow.c:809 #, c-format msgid "30% opacity" msgstr "" #: src/mainwindow.c:811 #, c-format msgid "40% opacity" msgstr "" #: src/mainwindow.c:813 #, c-format msgid "50% opacity" msgstr "" #: src/mainwindow.c:815 #, c-format msgid "60% opacity" msgstr "" #: src/mainwindow.c:817 #, c-format msgid "70% opacity" msgstr "" #: src/mainwindow.c:819 #, c-format msgid "80% opacity" msgstr "" #: src/mainwindow.c:821 #, c-format msgid "90% opacity" msgstr "" #: src/mainwindow.c:823 #, c-format msgid "100% opacity" msgstr "" #: src/mainwindow.c:825 msgid "Increase opacity" msgstr "" #: src/mainwindow.c:827 msgid "Decrease opacity" msgstr "" #: src/mainwindow.c:829 msgid "Draw open arrow head" msgstr "" #: src/mainwindow.c:831 msgid "Draw closed arrow head" msgstr "" #: src/mainwindow.c:833 msgid "Previous colour A" msgstr "" #: src/mainwindow.c:835 msgid "Next colour A" msgstr "" #: src/mainwindow.c:837 msgid "Previous colour B" msgstr "" #: src/mainwindow.c:839 msgid "Next colour B" msgstr "" #: src/mainwindow.c:841 msgid "Previous pattern" msgstr "" #: src/mainwindow.c:843 msgid "Next pattern" msgstr "" #: src/mainwindow.c:845 msgid "Larger brush" msgstr "" #: src/mainwindow.c:847 msgid "Smaller brush" msgstr "" #: src/mainwindow.c:849 msgid "View window - Zoom in" msgstr "" #: src/mainwindow.c:851 msgid "View window - Zoom out" msgstr "" #: src/mainwindow.c:1027 msgid "" "This canvas/palette contains changes that have not been saved. Do you " "really want to lose these changes?" msgstr "" "Este lenzo/paleta conten cambios que non foron gardados. Seguro que quere " "perdelos?" #: src/mainwindow.c:1094 msgid "Do you really want to quit?" msgstr "Seguro que desexa sair?" #: src/mainwindow.c:3754 msgid "Empty string or broken quoting" msgstr "" #: src/mainwindow.c:3755 msgid "Script must begin with a command" msgstr "" #: src/mainwindow.c:3756 msgid "Script nesting limit exceeded" msgstr "" #: src/mainwindow.c:3765 #, c-format msgid "'%s' does not match any item" msgstr "" #: src/mainwindow.c:3767 #, c-format msgid "'%s' matches a non-scriptable item" msgstr "" #: src/mainwindow.c:3769 #, c-format msgid "'%s' matches a disabled item" msgstr "" #: src/mainwindow.c:3788 #, c-format msgid "'%s' value does not fit item" msgstr "" #: src/mainwindow.c:3969 msgid "Script" msgstr "" #: src/mainwindow.c:3982 src/spawn.c:656 src/spawn.c:662 msgid "Action" msgstr "Acción" #: src/mainwindow.c:3991 src/spawn.c:666 msgid "Execute" msgstr "Executar" #: src/mainwindow.c:4045 msgid "Unable to load script" msgstr "" #: src/mainwindow.c:5182 msgid "/_File" msgstr "/_Ficheiro" #: src/mainwindow.c:5184 msgid "//New" msgstr "//Novo" #: src/mainwindow.c:5186 msgid "//Open ..." msgstr "//Abrir ..." #: src/mainwindow.c:5188 src/mainwindow.c:5669 msgid "//Save" msgstr "//Gardar" #: src/mainwindow.c:5190 src/mainwindow.c:5549 src/mainwindow.c:5627 #: src/mainwindow.c:5671 msgid "//Save As ..." msgstr "//Gardar como ..." #: src/mainwindow.c:5192 msgid "//Export Undo Images ..." msgstr "//Exportar o historial de imaxes ..." #: src/mainwindow.c:5194 msgid "//Export Undo Images (reversed) ..." msgstr "//Exportar o historial de imaxes (á inversa) ..." #: src/mainwindow.c:5196 msgid "//Export ASCII Art ..." msgstr "//Exportar en ASCII ..." #: src/mainwindow.c:5198 msgid "//Export Animated GIF ..." msgstr "//Exportar GIF Animado ..." #: src/mainwindow.c:5201 msgid "//Actions" msgstr "//Accións" #: src/mainwindow.c:5235 src/mainwindow.c:5488 msgid "///Configure" msgstr "///Configurar" #: src/mainwindow.c:5290 msgid "//Quit" msgstr "//Sair" #: src/mainwindow.c:5293 msgid "/_Edit" msgstr "/_Editar" #: src/mainwindow.c:5295 msgid "//Undo" msgstr "//Desfacer" #: src/mainwindow.c:5297 msgid "//Redo" msgstr "//Refacer" #: src/mainwindow.c:5300 msgid "//Cut" msgstr "//Cortar" #: src/mainwindow.c:5302 msgid "//Copy" msgstr "//Copiar" #: src/mainwindow.c:5304 msgid "//Copy To Palette" msgstr "//Copiar na paleta" #: src/mainwindow.c:5306 msgid "//Paste To Centre" msgstr "//Pegar no centro" #: src/mainwindow.c:5308 msgid "//Paste To New Layer" msgstr "//Pegar nunha nova capa" #: src/mainwindow.c:5310 msgid "//Paste" msgstr "//Pegar" #: src/mainwindow.c:5312 msgid "//Paste Text" msgstr "//Pegar texto" #: src/mainwindow.c:5318 msgid "//Paste Text (FreeType)" msgstr "//Pegar texto (FreeType)" #: src/mainwindow.c:5321 msgid "//Paste Palette" msgstr "" #: src/mainwindow.c:5323 msgid "//Load Clipboard" msgstr "//Cargar portapapeis" #: src/mainwindow.c:5350 msgid "//Save Clipboard" msgstr "//Gardar portapapeis" #: src/mainwindow.c:5377 msgid "//Import Clipboard from System" msgstr "//Importar de portapapeis do sistema" #: src/mainwindow.c:5378 msgid "//Export Clipboard to System" msgstr "" #: src/mainwindow.c:5381 msgid "//Choose Pattern ..." msgstr "//Escoller patrón ..." #: src/mainwindow.c:5383 msgid "//Choose Brush ..." msgstr "//Escoller brocha ..." #: src/mainwindow.c:5385 msgid "//Choose Colour ..." msgstr "" #: src/mainwindow.c:5392 msgid "/_View" msgstr "/_Ver" #: src/mainwindow.c:5394 msgid "//Show Main Toolbar" msgstr "//Amosar barra de ferramentas principal" #: src/mainwindow.c:5396 msgid "//Show Tools Toolbar" msgstr "//Amosar barra de ferramentas" #: src/mainwindow.c:5399 msgid "//Show Settings Toolbar" msgstr "//Amosar barra de preferencias" #: src/mainwindow.c:5402 msgid "//Show Dock" msgstr "//Amosar ancoraxe" #: src/mainwindow.c:5404 msgid "//Show Palette" msgstr "//Amosar paleta" #: src/mainwindow.c:5406 msgid "//Show Status Bar" msgstr "//Amosar barra de estado" #: src/mainwindow.c:5409 msgid "//Toggle Image View" msgstr "//Cambiar a vista completa" #: src/mainwindow.c:5413 msgid "//Centralize Image" msgstr "//Centrar imaxe" #: src/mainwindow.c:5414 msgid "//Show Zoom Grid" msgstr "//Amosar rella de ampliación" #: src/mainwindow.c:5415 msgid "//Snap To Tile Grid" msgstr "" #: src/mainwindow.c:5417 msgid "//Configure Grid ..." msgstr "//Configurar rella ..." #: src/mainwindow.c:5418 msgid "//Tracing Image ..." msgstr "//Trazado de imaxe ..." #: src/mainwindow.c:5421 msgid "//View Window" msgstr "//Ver ventá" #: src/mainwindow.c:5423 msgid "//Horizontal Split" msgstr "//Dividir en horizontal" #: src/mainwindow.c:5425 msgid "//Focus View Window" msgstr "//Ver ventá en foco" #: src/mainwindow.c:5427 msgid "//Pan Window" msgstr "//Vista reducida" #: src/mainwindow.c:5430 msgid "//Layers Window" msgstr "//Ventá de capas" #: src/mainwindow.c:5433 msgid "/_Image" msgstr "/_Imaxe" #: src/mainwindow.c:5436 msgid "//Convert To RGB" msgstr "//Converter a RGB" #: src/mainwindow.c:5438 msgid "//Convert To Indexed ..." msgstr "//Converter a Indexado ..." #: src/mainwindow.c:5441 msgid "//Scale Canvas ..." msgstr "//Escalar lenzo ..." #: src/mainwindow.c:5443 msgid "//Resize Canvas ..." msgstr "//Redimensionar lenzo ..." #: src/mainwindow.c:5445 msgid "//Crop" msgstr "//Recortar" #: src/mainwindow.c:5448 src/mainwindow.c:5517 msgid "//Flip Vertically" msgstr "//Reflexo vertical" #: src/mainwindow.c:5449 src/mainwindow.c:5519 msgid "//Flip Horizontally" msgstr "//Reflexo horizontal" #: src/mainwindow.c:5452 src/mainwindow.c:5521 msgid "//Rotate Clockwise" msgstr "//Rotar no sentido do reloxo" #: src/mainwindow.c:5453 src/mainwindow.c:5523 msgid "//Rotate Anti-Clockwise" msgstr "//Rotar no sentido contrario do reloxo" #: src/mainwindow.c:5454 msgid "//Free Rotate ..." msgstr "//Rotar libremente ..." #: src/mainwindow.c:5455 msgid "//Skew ..." msgstr "//Inclinar ..." #: src/mainwindow.c:5458 msgid "//Segment ..." msgstr "" #: src/mainwindow.c:5462 msgid "//Script ..." msgstr "" #: src/mainwindow.c:5464 msgid "//Scripts" msgstr "" #: src/mainwindow.c:5491 msgid "//Information ..." msgstr "//Información ..." #: src/mainwindow.c:5494 msgid "//Preferences ..." msgstr "//Preferencias ..." #: src/mainwindow.c:5497 msgid "/_Selection" msgstr "/_Selección" #: src/mainwindow.c:5499 msgid "//Select All" msgstr "//Seleccionar todo" #: src/mainwindow.c:5501 msgid "//Select None (Esc)" msgstr "//Eliminar selección (Esc)" #: src/mainwindow.c:5503 msgid "//Lasso Selection" msgstr "//Selección de lazo" #: src/mainwindow.c:5505 msgid "//Lasso Selection Cut" msgstr "//Cortar selección de lazo" #: src/mainwindow.c:5508 msgid "//Outline Selection" msgstr "//Contorna de selección" #: src/mainwindow.c:5510 msgid "//Fill Selection" msgstr "//Encher selección" #: src/mainwindow.c:5512 msgid "//Outline Ellipse" msgstr "//Contorna de elipse" #: src/mainwindow.c:5514 msgid "//Fill Ellipse" msgstr "//Encher elipse" #: src/mainwindow.c:5526 msgid "//Horizontal Ramp" msgstr "//Rampa horizontal" #: src/mainwindow.c:5528 msgid "//Vertical Ramp" msgstr "//Rampa vertical" #: src/mainwindow.c:5531 msgid "//Alpha Blend A,B" msgstr "//Misturar alfa A,B" #: src/mainwindow.c:5533 msgid "//Move Alpha to Mask" msgstr "//Mover alfa a máscara" #: src/mainwindow.c:5535 msgid "//Mask Colour A,B" msgstr "//Enmascarar cores A,B" #: src/mainwindow.c:5537 msgid "//Unmask Colour A,B" msgstr "//Eliminar máscara cores A,B" #: src/mainwindow.c:5539 msgid "//Mask All Colours" msgstr "//Enmascarar todas as Cores" #: src/mainwindow.c:5541 msgid "//Clear Mask" msgstr "//Limpar máscara" #: src/mainwindow.c:5544 msgid "/_Palette" msgstr "/_Paleta" #: src/mainwindow.c:5548 src/mainwindow.c:5626 msgid "//Load ..." msgstr "//Cargar ..." #: src/mainwindow.c:5550 msgid "//Load Default" msgstr "//Cargar valores predeterminados" #: src/mainwindow.c:5552 msgid "//Mask All" msgstr "//Enmascarar todo" #: src/mainwindow.c:5553 msgid "//Mask None" msgstr "//Non enmascarar nada" #: src/mainwindow.c:5555 msgid "//Swap A & B" msgstr "//Intercambiar A e B" #: src/mainwindow.c:5557 msgid "//Edit Colour A & B ..." msgstr "//Editar cores A e B ..." #: src/mainwindow.c:5559 msgid "//Dither A" msgstr "//Trama A" #: src/mainwindow.c:5561 msgid "//Palette Editor ..." msgstr "//Editar paleta ..." #: src/mainwindow.c:5563 msgid "//Set Palette Size ..." msgstr "//Establecer o tamaño da paleta ..." #: src/mainwindow.c:5564 msgid "//Merge Duplicate Colours" msgstr "//Misturar cores duplicados" #: src/mainwindow.c:5566 msgid "//Remove Unused Colours" msgstr "//Eliminar cores non usados" #: src/mainwindow.c:5569 msgid "//Create Quantized ..." msgstr "//Crear cuantificado ..." #: src/mainwindow.c:5572 msgid "//Sort Colours ..." msgstr "//Listar cores ..." #: src/mainwindow.c:5573 msgid "//Palette Shifter ..." msgstr "//Paleta «Shifter» ..." #: src/mainwindow.c:5574 msgid "//Pick Gradient ..." msgstr "" #: src/mainwindow.c:5576 msgid "/Effe_cts" msgstr "/Efe_ctos" #: src/mainwindow.c:5578 msgid "//Transform Colour ..." msgstr "//Transformar cor ..." #: src/mainwindow.c:5580 msgid "//Invert" msgstr "//Invertir" #: src/mainwindow.c:5582 msgid "//Greyscale" msgstr "//Escala de grises" #: src/mainwindow.c:5584 msgid "//Greyscale (Gamma corrected)" msgstr "//Escala de grises (gama corrixida)" #: src/mainwindow.c:5586 msgid "//Normalize" msgstr "" #: src/mainwindow.c:5587 src/mainwindow.c:5658 msgid "//Threshold ..." msgstr "//Limiar ..." #: src/mainwindow.c:5588 msgid "//Map ..." msgstr "" #: src/mainwindow.c:5590 msgid "//Isometric Transformation" msgstr "//Transformación isométrica" #: src/mainwindow.c:5592 msgid "///Left Side Down" msgstr "///Hacia abaixo lado esquerdo" #: src/mainwindow.c:5593 msgid "///Right Side Down" msgstr "///Hacia abaixo lado dereito" #: src/mainwindow.c:5594 msgid "///Top Side Right" msgstr "///Deica a dereita parte superior" #: src/mainwindow.c:5595 msgid "///Bottom Side Right" msgstr "///Deica a dereita parte inferior" #: src/mainwindow.c:5598 msgid "//Edge Detect ..." msgstr "//Detección de bordos ..." #: src/mainwindow.c:5600 msgid "//Difference of Gaussians ..." msgstr "//Diferenza de Gauss ..." #: src/mainwindow.c:5602 msgid "//Sharpen ..." msgstr "//Remarcado ..." #: src/mainwindow.c:5604 msgid "//Unsharp Mask ..." msgstr "//Máscara de desenfoque ..." #: src/mainwindow.c:5606 msgid "//Soften ..." msgstr "//Suavizado ..." #: src/mainwindow.c:5608 msgid "//Gaussian Blur ..." msgstr "//Desenfoque gaussiano ..." #: src/mainwindow.c:5610 msgid "//Kuwahara-Nagao Blur ..." msgstr "//Difuminado Kuwahara-Nagao ..." #: src/mainwindow.c:5612 msgid "//Emboss" msgstr "//Realce" #: src/mainwindow.c:5614 msgid "//Dilate" msgstr "//Dilatar" #: src/mainwindow.c:5616 msgid "//Erode" msgstr "//Erosionar" #: src/mainwindow.c:5619 msgid "//Solid Noise ..." msgstr "" #: src/mainwindow.c:5620 msgid "//Bacteria ..." msgstr "//«Bacteria» ..." #: src/mainwindow.c:5623 msgid "/Cha_nnels" msgstr "/Ca_nles" #: src/mainwindow.c:5625 msgid "//New ..." msgstr "//Novo ..." #: src/mainwindow.c:5628 msgid "//Delete ..." msgstr "//Borrar ..." #: src/mainwindow.c:5632 msgid "//Edit Image" msgstr "//Editar imaxe" #: src/mainwindow.c:5635 msgid "//Edit Alpha" msgstr "//Editar alfa" #: src/mainwindow.c:5638 msgid "//Edit Selection" msgstr "//Editar selección" #: src/mainwindow.c:5641 msgid "//Edit Mask" msgstr "//Editar máscara" #: src/mainwindow.c:5645 msgid "//Hide Image" msgstr "//Esconder imaxe" #: src/mainwindow.c:5648 msgid "//Disable Alpha" msgstr "//Deshabilitar alfa" #: src/mainwindow.c:5651 msgid "//Disable Selection" msgstr "//Deshabilitar selección" #: src/mainwindow.c:5654 msgid "//Disable Mask" msgstr "//Deshabilitar máscara" #: src/mainwindow.c:5657 msgid "//Couple RGBA Operations" msgstr "//Xuntar operacions RGBA" #: src/mainwindow.c:5659 msgid "//Unassociate Alpha" msgstr "//Disociar alfa" #: src/mainwindow.c:5663 msgid "//View Alpha as an Overlay" msgstr "//Ver alfa como un revestimento" #: src/mainwindow.c:5664 msgid "//Configure Overlays ..." msgstr "//Configurar revestimentos ..." #: src/mainwindow.c:5666 msgid "/_Layers" msgstr "/_Capas" #: src/mainwindow.c:5668 msgid "//New Layer" msgstr "//Nova capa" #: src/mainwindow.c:5672 msgid "//Save Composite Image ..." msgstr "//Gardar imaxe composta ..." #: src/mainwindow.c:5673 msgid "//Composite to New Layer" msgstr "//Compoñer nunha capa nova" #: src/mainwindow.c:5674 msgid "//Remove All Layers" msgstr "//Borrar todalas capas" #: src/mainwindow.c:5676 msgid "//Configure Animation ..." msgstr "//Configurar animación ..." #: src/mainwindow.c:5677 msgid "//Preview Animation ..." msgstr "//Animación vista previa ..." #: src/mainwindow.c:5678 msgid "//Set Key Frame ..." msgstr "//Establecer número de fotogramas ..." #: src/mainwindow.c:5679 msgid "//Remove All Key Frames ..." msgstr "//Borrar todolos fotogramas ..." #: src/mainwindow.c:5681 msgid "/More..." msgstr "/Máis..." #: src/mainwindow.c:5683 msgid "/_Help" msgstr "/_Axuda" #: src/mainwindow.c:5684 msgid "//Documentation" msgstr "//Documentación" #: src/mainwindow.c:5686 msgid "//About" msgstr "//Acerca de" #: src/mainwindow.c:5689 msgid "//Keyboard Shortcuts ..." msgstr "" #: src/mainwindow.c:5690 msgid "//Rebind Shortcut Keycodes" msgstr "//Vincular teclas acceso rápido" #: src/memory.c:2800 msgid "Quantize Pass 1" msgstr "" #: src/memory.c:2854 msgid "Quantize Pass 2" msgstr "" #: src/memory.c:3073 src/memory.c:3458 msgid "Converting to Indexed Palette" msgstr "Convertir á paleta indexada" #: src/memory.c:5135 src/otherwindow.c:540 msgid "Bacteria Effect" msgstr "Efecto «bacteria»" #: src/memory.c:5170 msgid "Rotating" msgstr "Rotando" #: src/memory.c:5511 msgid "Free Rotation" msgstr "Rotación libre" #: src/memory.c:6096 msgid "Scaling Image" msgstr "Escalando a imaxe" #: src/memory.c:7560 msgid "Counting Unique RGB Pixels" msgstr "Contando píxeles RGB únicos" #: src/memory.c:7608 msgid "Applying Effect" msgstr "Aplicando efecto" #: src/memory.c:8792 msgid "Kuwahara-Nagao Filter" msgstr "Filtro Kuwahara-Nagao" #: src/memory.c:10456 src/otherwindow.c:2665 msgid "Skew" msgstr "Inclinar" #: src/memory.c:10630 msgid "Segmentation Pass 1" msgstr "" #: src/memory.c:10757 msgid "Segmentation Pass 2" msgstr "" #: src/memory.c:11019 src/otherwindow.c:3156 msgid "Solid Noise" msgstr "" #: src/mygtk.c:134 src/mygtk.c:163 msgid "Please Wait ..." msgstr "Agarde por favor ..." #: src/mygtk.c:141 msgid "STOP" msgstr "PARAR" #: src/mygtk.c:504 msgid "Disabled" msgstr "" #: src/mygtk.c:504 src/toolbar.c:301 msgid "Screen" msgstr "Pantalla" #: src/mygtk.c:504 msgid "Window" msgstr "" #: src/mygtk.c:508 msgid "Input" msgstr "" #: src/mygtk.c:512 msgid "Device:" msgstr "" #: src/mygtk.c:514 msgid "Mode:" msgstr "" #: src/mygtk.c:519 msgid "Axes" msgstr "" #: src/mygtk.c:524 msgid "X:" msgstr "" #: src/mygtk.c:525 msgid "Y:" msgstr "" #: src/mygtk.c:526 msgid "Pressure:" msgstr "" #: src/mygtk.c:527 msgid "X tilt:" msgstr "" #: src/mygtk.c:528 msgid "Y tilt:" msgstr "" #: src/mygtk.c:529 msgid "Wheel:" msgstr "" #: src/mygtk.c:579 msgid "none" msgstr "" #: src/otherwindow.c:236 msgid "24 bit RGB" msgstr "RGB de 24 bits" #: src/otherwindow.c:236 src/otherwindow.c:3179 msgid "Greyscale" msgstr "Escala de grises" #: src/otherwindow.c:237 msgid "Indexed Palette" msgstr "Paleta indexada" #: src/otherwindow.c:237 msgid "From Clipboard" msgstr "De portapapeis" #: src/otherwindow.c:237 msgid "Grab Screenshot" msgstr "Capturar pantalla" #: src/otherwindow.c:242 src/toolbar.c:542 msgid "New Image" msgstr "Nova imaxe" #: src/otherwindow.c:246 src/otherwindow.c:3164 msgid "Colours" msgstr "Cores" #: src/otherwindow.c:409 msgid "Pattern Chooser" msgstr "Selector de patrón" #: src/otherwindow.c:497 msgid "Set Palette Size" msgstr "Establecer o tamaño da paleta" #: src/otherwindow.c:517 src/otherwindow.c:591 src/otherwindow.c:870 #: src/otherwindow.c:2538 src/otherwindow.c:2776 src/otherwindow.c:2939 #: src/prefs.c:338 src/prefs.c:538 msgid "Apply" msgstr "Aplicar" #: src/otherwindow.c:573 msgid "Luminance" msgstr "Luminancia" #: src/otherwindow.c:573 src/otherwindow.c:814 msgid "Brightness" msgstr "Brillo" #: src/otherwindow.c:574 msgid "Distance to A" msgstr "Distancia á A" #: src/otherwindow.c:575 msgid "Projection to A->B" msgstr "Proxección A->B" #: src/otherwindow.c:576 msgid "Frequency" msgstr "Frecuencia" #: src/otherwindow.c:580 msgid "Sort Palette Colours" msgstr "Amosar paleta de cores" #: src/otherwindow.c:582 msgid "Start Index" msgstr "Inicio do índice" #: src/otherwindow.c:583 msgid "End Index" msgstr "Fin do índice" #: src/otherwindow.c:589 msgid "Reverse Order" msgstr "Invertir a orde" #: src/otherwindow.c:805 msgid "Bitwise" msgstr "" #: src/otherwindow.c:805 msgid "Truncated" msgstr "" #: src/otherwindow.c:805 msgid "Rounded" msgstr "" #: src/otherwindow.c:809 src/toolbar.c:311 src/toolbar.c:558 msgid "Transform Colour" msgstr "Tansformar a cor" #: src/otherwindow.c:812 msgid "Gamma" msgstr "Gama" #: src/otherwindow.c:816 msgid "Contrast" msgstr "Contraste" #: src/otherwindow.c:822 src/otherwindow.c:1674 msgid "Posterize" msgstr "Posterizar" #: src/otherwindow.c:831 msgid "Show Detail" msgstr "Amosar detalle" #: src/otherwindow.c:836 msgid "Posterize type" msgstr "" #: src/otherwindow.c:857 msgid "Auto-Preview" msgstr "Auto previsualización" #: src/otherwindow.c:869 msgid "Reset" msgstr "Restablecer" #: src/otherwindow.c:931 msgid "New geometry is the same as now - nothing to do." msgstr "A nova xeometría é a mesma que a actual - Non se fai nada" #: src/otherwindow.c:980 msgid "The operating system cannot allocate the memory for this operation." msgstr "O sistema operativo non pode asignar memoria para esta operación." #: src/otherwindow.c:982 msgid "" "You have not allocated enough memory in the Preferences window for this " "operation." msgstr "" "Non asignou a suficiente memoria na ventá de preferencias para esta " "operación." #: src/otherwindow.c:993 src/otherwindow.c:2495 msgid "Mirror" msgstr "Espello" #: src/otherwindow.c:993 src/otherwindow.c:994 msgid "Tile" msgstr "Mosaico" #: src/otherwindow.c:993 msgid "Void" msgstr "" #: src/otherwindow.c:994 src/shifter.c:283 msgid "Clear" msgstr "Limpar" #: src/otherwindow.c:994 msgid "Mirror tile" msgstr "Mosaico de espello" #: src/otherwindow.c:996 msgid "Nearest Neighbour" msgstr "Inmediato máis próximo" #: src/otherwindow.c:997 msgid "Bilinear / Area Mapping" msgstr "Bilineal / Mapear área" #: src/otherwindow.c:998 msgid "Bicubic" msgstr "Bicúbico" #: src/otherwindow.c:999 msgid "Bicubic edged" msgstr "Bicúbico recortado" #: src/otherwindow.c:1000 msgid "Bicubic better" msgstr "Bicubic mellorado" #: src/otherwindow.c:1001 msgid "Bicubic sharper" msgstr "Bicúbico realzado" #: src/otherwindow.c:1002 msgid "Blackman-Harris" msgstr "«Blackman-Harris»" #: src/otherwindow.c:1008 msgid "Scale Canvas" msgstr "Escalar o lenzo" #: src/otherwindow.c:1009 msgid "Resize Canvas" msgstr "Redimensionar o lenzo" #: src/otherwindow.c:1012 msgid "Original " msgstr "Orixinal " #: src/otherwindow.c:1013 msgid "New" msgstr "Novo" #: src/otherwindow.c:1014 msgid "Width " msgstr "Ancho " #: src/otherwindow.c:1018 msgid "Height " msgstr "Alto " #: src/otherwindow.c:1023 src/otherwindow.c:2514 src/otherwindow.c:2672 #: src/toolbar.c:212 msgid "Offset" msgstr "Compensar" #: src/otherwindow.c:1026 src/otherwindow.c:1615 src/viewer.c:1209 msgid "Centre" msgstr "Centrado" #: src/otherwindow.c:1033 src/otherwindow.c:1052 msgid "Fix Aspect Ratio" msgstr "Fixar relación alto/ancho" #: src/otherwindow.c:1039 src/otherwindow.c:2070 src/toolbar.c:312 msgid "Settings" msgstr "Preferencias" #: src/otherwindow.c:1046 msgid "Sharper image reduction" msgstr "Reducción enfocada de imaxe" #: src/otherwindow.c:1047 msgid "Boundary extension" msgstr "" #: src/otherwindow.c:1613 src/otherwindow.c:2302 msgid "HSV" msgstr "HSV" #: src/otherwindow.c:1614 msgid "Highlight" msgstr "" #: src/otherwindow.c:1615 msgid "Limit" msgstr "Límite" #: src/otherwindow.c:1616 msgid "Sphere" msgstr "Esfera" #: src/otherwindow.c:1616 src/otherwindow.c:2670 msgid "Angle" msgstr "Ãngulo" #: src/otherwindow.c:1616 msgid "Cube" msgstr "Cubo" #: src/otherwindow.c:1617 msgid "Opaque" msgstr "Opaco" #: src/otherwindow.c:1617 msgid "Border" msgstr "Bordo" #: src/otherwindow.c:1618 msgid "Transparent" msgstr "Transparente" #: src/otherwindow.c:1618 msgid "Tile " msgstr "Mosaico " #: src/otherwindow.c:1618 msgid "Segment" msgstr "" #: src/otherwindow.c:1656 msgid "Scale" msgstr "Escala" #: src/otherwindow.c:1657 src/otherwindow.c:3059 msgid "From" msgstr "Desde" #: src/otherwindow.c:1659 src/otherwindow.c:3061 msgid "To" msgstr "Deica" #: src/otherwindow.c:1699 msgid "Range" msgstr "Rango" #: src/otherwindow.c:1702 msgid "Inverse" msgstr "Inverso" #: src/otherwindow.c:1710 msgid "Smart grid" msgstr "Rella intelixente" #: src/otherwindow.c:1712 msgid "Tile grid" msgstr "Rella de mosaico" #: src/otherwindow.c:1714 msgid "Minimum grid zoom" msgstr "Mínima ampliación da rella" #: src/otherwindow.c:1717 msgid "Tile width" msgstr "Ancho do mosaico" #: src/otherwindow.c:1720 msgid "Tile height" msgstr "Altura do mosaico" #: src/otherwindow.c:1744 msgid "Palette Editor" msgstr "Editor da paleta" #: src/otherwindow.c:1763 msgid "Configure Overlays" msgstr "Configurar resvestimentos" #: src/otherwindow.c:1782 msgid "Colour Editor" msgstr "Editor de cores" #: src/otherwindow.c:1818 src/toolbar.c:430 msgid "Colour-Selective Mode" msgstr "Cor-modo de selección" #: src/otherwindow.c:1843 msgid "Configure Grid" msgstr "Configurar rella" #: src/otherwindow.c:2045 msgid "Exact Conversion" msgstr "Conversión exacta" #: src/otherwindow.c:2045 msgid "Use Current Palette" msgstr "Usar paleta actual" #: src/otherwindow.c:2046 msgid "PNN Quantize (slow, better quality)" msgstr "Cuantificar PNN (lento, mellor calidade)" #: src/otherwindow.c:2047 msgid "Wu Quantize (fast)" msgstr "Cuantificar «Wu» (rápido)" #: src/otherwindow.c:2048 msgid "Max-Min Quantize (best for small palettes and dithering)" msgstr "Cuantificar «Max-Min» (mellor para pequenas paletas e punteados)" #: src/otherwindow.c:2049 src/otherwindow.c:2495 src/otherwindow.c:2756 #: src/png.c:2794 src/prefs.c:377 msgid "None" msgstr "Ningún" #: src/otherwindow.c:2049 msgid "Floyd-Steinberg" msgstr "«Floyd-Steinberg»" #: src/otherwindow.c:2049 msgid "Stucki" msgstr "«Stucki»" #: src/otherwindow.c:2052 msgid "Floyd-Steinberg (quick)" msgstr "Floyd-Steinberg (rápido)" #: src/otherwindow.c:2052 msgid "Dithered (effect)" msgstr "Punteado (efecto)" #: src/otherwindow.c:2053 msgid "Scattered (effect)" msgstr "Disperso (efecto)" #: src/otherwindow.c:2054 msgid "Gamut" msgstr "Fora de gama" #: src/otherwindow.c:2054 msgid "Weakly" msgstr "Débil" #: src/otherwindow.c:2054 msgid "Strongly" msgstr "Forte" #: src/otherwindow.c:2055 msgid "Off" msgstr "Apagado" #: src/otherwindow.c:2055 msgid "Separate/Sum" msgstr "Separar/Sumar" #: src/otherwindow.c:2055 msgid "Separate/Split" msgstr "Separar/Cortar" #: src/otherwindow.c:2056 msgid "Length/Sum" msgstr "Lonxitude/Sumar" #: src/otherwindow.c:2056 msgid "Length/Split" msgstr "Lonxitude/Cortar" #: src/otherwindow.c:2057 msgid "Largest (Linf)" msgstr "El más grande" #: src/otherwindow.c:2057 msgid "Sum (L1)" msgstr "Suma (L1)" #: src/otherwindow.c:2057 msgid "Euclidean (L2)" msgstr "Euclidiano (L2)" #: src/otherwindow.c:2061 msgid "Create Quantized" msgstr "Crear cuantificado" #: src/otherwindow.c:2062 msgid "Convert To Indexed" msgstr "Converter a indexado" #: src/otherwindow.c:2065 msgid "Indexed Colours To Use" msgstr "Cores indexados a usar" #: src/otherwindow.c:2078 msgid "Truncate palette" msgstr "Paleta truncada" #: src/otherwindow.c:2079 msgid "Diameter based weighting" msgstr "Baseado na ponderación do diámetro" #: src/otherwindow.c:2084 msgid "Dither" msgstr "Punteado" #: src/otherwindow.c:2087 src/otherwindow.c:2584 src/otherwindow.c:2928 msgid "Colour space" msgstr "Espacio de cor" #: src/otherwindow.c:2088 src/otherwindow.c:2929 msgid "Difference measure" msgstr "Diferenza de medida" #: src/otherwindow.c:2089 msgid "Reduce colour bleed" msgstr "Reducir cor sangrado" #: src/otherwindow.c:2090 msgid "Serpentine scan" msgstr "Exploración serpeante" #: src/otherwindow.c:2092 msgid "Error propagation, %" msgstr "Erro de propagación, %" #: src/otherwindow.c:2093 msgid "Selective error propagation" msgstr "Produciuse un erro selectivo de propagación" #: src/otherwindow.c:2097 msgid "Full error precision" msgstr "Produciuse un erro total de precisión" #: src/otherwindow.c:2302 msgid "Backward HSV" msgstr "Atrás HSV" #: src/otherwindow.c:2303 src/otherwindow.c:2326 msgid "Constant" msgstr "Constante" #: src/otherwindow.c:2307 msgid "Edit Gradient" msgstr "Editar a gradación" #: src/otherwindow.c:2329 msgid "Points:" msgstr "Puntos:" #: src/otherwindow.c:2493 msgid "Linear" msgstr "Lineal" #: src/otherwindow.c:2493 src/otherwindow.c:2703 msgid "Bilinear" msgstr "Bilineal" #: src/otherwindow.c:2493 msgid "Radial" msgstr "Radial" #: src/otherwindow.c:2494 msgid "Square" msgstr "Cadrado" #: src/otherwindow.c:2494 msgid "Angular" msgstr "Angular" #: src/otherwindow.c:2494 msgid "Conical" msgstr "Cónico" #: src/otherwindow.c:2495 msgid "Level " msgstr "" #: src/otherwindow.c:2495 msgid "Repeat" msgstr "Repetir" #: src/otherwindow.c:2496 msgid "A to B" msgstr "de A á B" #: src/otherwindow.c:2496 msgid "A to B (RGB)" msgstr "de A á B (RGB)" #: src/otherwindow.c:2497 msgid "A to B (sRGB)" msgstr "" #: src/otherwindow.c:2497 msgid "A to B (HSV)" msgstr "de A á B (HSV)" #: src/otherwindow.c:2497 msgid "A to B (backward HSV)" msgstr "de A á B (voltar HSV)" #: src/otherwindow.c:2498 msgid "A only" msgstr "Só A" #: src/otherwindow.c:2498 src/otherwindow.c:2500 msgid "Custom" msgstr "Personalizado" #: src/otherwindow.c:2499 msgid "Current to 0" msgstr "Actual á 0" #: src/otherwindow.c:2499 msgid "Current only" msgstr "Só o actual" #: src/otherwindow.c:2504 msgid "Configure Gradient" msgstr "Configurar a gradación" #: src/otherwindow.c:2507 src/png.c:1001 msgid "Channel" msgstr "Canle" #: src/otherwindow.c:2512 msgid "Length" msgstr "Lonxitude" #: src/otherwindow.c:2513 msgid "Repeat length" msgstr "Repetir lonxitude" #: src/otherwindow.c:2515 msgid "Gradient type" msgstr "Tipo de gradación" #: src/otherwindow.c:2516 msgid "Extension type" msgstr "Tipo de extensión" #: src/otherwindow.c:2517 msgid "Distance type" msgstr "" #: src/otherwindow.c:2518 msgid "Preview opacity" msgstr "Previsualizar opacidade" #: src/otherwindow.c:2527 src/otherwindow.c:2533 src/toolbar.c:309 msgid "Reverse" msgstr "Inverso" #: src/otherwindow.c:2528 src/otherwindow.c:2534 msgid "Edit Custom" msgstr "Editar a personalización" #: src/otherwindow.c:2592 msgid "Pick Gradient" msgstr "" #: src/otherwindow.c:2668 msgid "Horizontal " msgstr "Horizontal " #: src/otherwindow.c:2674 msgid "At distance" msgstr "A distancia" #: src/otherwindow.c:2675 msgid "Vertical" msgstr "Vertical" #: src/otherwindow.c:2756 msgid "Unchanged" msgstr "Sen cambios" #: src/otherwindow.c:2761 msgid "Tracing Image" msgstr "Trazando imaxe" #: src/otherwindow.c:2763 src/toolbar.c:315 msgid "Source" msgstr "Orixe" #: src/otherwindow.c:2768 msgid "Origin" msgstr "Orixe" #: src/otherwindow.c:2771 msgid "Relative scale" msgstr "Escala relativa" #: src/otherwindow.c:2774 msgid "Display" msgstr "Visualización" #: src/otherwindow.c:2926 msgid "Segment Image" msgstr "" #: src/otherwindow.c:2931 src/toolbar.c:304 msgid "Threshold" msgstr "" #: src/otherwindow.c:2933 msgid "Level" msgstr "Nivel" #: src/otherwindow.c:2934 msgid "Minimum size" msgstr "" #: src/otherwindow.c:3053 msgid "Max" msgstr "" #: src/otherwindow.c:3053 msgid "Min" msgstr "" #: src/otherwindow.c:3057 msgid "Threshold Image" msgstr "" #: src/otherwindow.c:3158 msgid "Seed" msgstr "" #: src/otherwindow.c:3160 msgid "X span" msgstr "" #: src/otherwindow.c:3161 msgid "Y span" msgstr "" #: src/otherwindow.c:3162 msgid "Octaves" msgstr "" #: src/png.c:620 #, c-format msgid "Saving %s image" msgstr "Gardar imaxe %s" #: src/png.c:620 #, c-format msgid "Loading %s image" msgstr "Cargando imaxe %s" #: src/png.c:998 msgid "Layer" msgstr "Capa" #: src/png.c:3577 msgid "Lossless" msgstr "" #: src/png.c:3577 msgid "Default" msgstr "" #: src/png.c:3577 msgid "Picture" msgstr "" #: src/png.c:3577 msgid "Photo" msgstr "" #: src/png.c:3578 msgid "Drawing" msgstr "" #: src/png.c:3578 msgid "Icon" msgstr "" #: src/png.c:8370 msgid "Applying colour profile" msgstr "" #: src/png.c:8792 #, c-format msgid "%d out of %d frames could not be saved as %s - saved as PNG instead" msgstr "%d fora de %d fotogramas non se gardaron como %s - guardados como PNG" #: src/png.c:8809 msgid "Explode frames" msgstr "" #: src/prefs.c:56 msgid "Default System Language" msgstr "Idioma predefinido" #: src/prefs.c:57 msgid "Chinese (Simplified)" msgstr "Chinés (Simplificado)" #: src/prefs.c:57 msgid "Chinese (Taiwanese)" msgstr "Chinés (Taiwanés)" #: src/prefs.c:57 msgid "Czech" msgstr "Checo" #: src/prefs.c:58 msgid "Dutch" msgstr "Holandés" #: src/prefs.c:58 msgid "English (UK)" msgstr "Inglés (Reino Unido)" #: src/prefs.c:58 msgid "French" msgstr "Francés" #: src/prefs.c:58 msgid "Galician" msgstr "Galego" #: src/prefs.c:58 msgid "German" msgstr "Alemán" #: src/prefs.c:59 msgid "Hungarian" msgstr "" #: src/prefs.c:59 msgid "Italian" msgstr "Italiano" #: src/prefs.c:59 msgid "Japanese" msgstr "Xaponés" #: src/prefs.c:59 msgid "Kabyle" msgstr "" #: src/prefs.c:59 msgid "Polish" msgstr "Polaco" #: src/prefs.c:60 msgid "Portuguese" msgstr "Portugués" #: src/prefs.c:60 msgid "Portuguese (Brazilian)" msgstr "Portugués (Brasileño)" #: src/prefs.c:60 msgid "Russian" msgstr "Ruso" #: src/prefs.c:60 msgid "Slovak" msgstr "Eslovaco" #: src/prefs.c:61 msgid "Spanish" msgstr "Español" #: src/prefs.c:61 msgid "Swedish" msgstr "Sueco" #: src/prefs.c:61 msgid "Tagalog" msgstr "" #: src/prefs.c:61 msgid "Turkish" msgstr "Turco" #: src/prefs.c:81 msgid "Current Device" msgstr "Dispositivo actual" #: src/prefs.c:135 msgid "Pressure" msgstr "Presión" #: src/prefs.c:149 msgid "Preferences" msgstr "Preferencias" #: src/prefs.c:163 msgid "Max threads (0 to autodetect)" msgstr "" #: src/prefs.c:164 msgid "Min kpixels per render thread" msgstr "" #: src/prefs.c:171 msgid "Max memory used for undo (MB)" msgstr "Máxima memoria usada para desfacer (MB)" #: src/prefs.c:172 msgid "Max undo levels" msgstr "Nivel máximo de desfacer" #: src/prefs.c:173 msgid "Communal layer undo space (%)" msgstr "Porcentaxe de espazo que elimina a capa común (%)" #: src/prefs.c:175 msgid "Bayer master pattern" msgstr "" #: src/prefs.c:178 msgid "Use gamma correction by default" msgstr "Usar corrección gama por defecto" #: src/prefs.c:179 msgid "Use gamma correction when painting" msgstr "" #: src/prefs.c:180 msgid "Separate patterns for A & B" msgstr "" #: src/prefs.c:183 msgid "Optimize alpha chequers" msgstr "Optimiza comprobación alpha" #: src/prefs.c:184 msgid "Disable view window transparencies" msgstr "Deshabilitar ventá de transparencias" #: src/prefs.c:185 msgid "Enable overlays by layer" msgstr "" #: src/prefs.c:189 msgid "Language" msgstr "Idioma" #: src/prefs.c:191 msgid "" "Select preferred language translation\n" "\n" "You will need to restart mtPaint\n" "for this to take full effect" msgstr "" "Seleccione a traducción ao idioma desexado\n" "\n" "Necesita reiniciar mtPaint\n" "para que esta selección teña efecto" #: src/prefs.c:198 msgid "Interface" msgstr "Interface" #: src/prefs.c:200 msgid "Greyscale backdrop" msgstr "Fondo de grises" #: src/prefs.c:201 msgid "Selection nudge pixels" msgstr "Selección mover pixeles" #: src/prefs.c:202 msgid "Max Pan Window Size" msgstr "Máximo tamaño de ventá reducida" #: src/prefs.c:204 msgid "Display clipboard while pasting" msgstr "Amosar portapapeis mentras se pega" #: src/prefs.c:205 msgid "Mouse cursor = Tool" msgstr "Movimento do rato = Ferramenta" #: src/prefs.c:206 msgid "Confirm Exit" msgstr "Confirmar saida" #: src/prefs.c:207 msgid "Q key quits mtPaint" msgstr "Prema Q para sair de mtPaint" #: src/prefs.c:208 msgid "Arrow keys scroll canvas" msgstr "" #: src/prefs.c:209 msgid "Changing tool commits paste" msgstr "O cambio de ferramenta implica o pegado" #: src/prefs.c:210 msgid "Centre tool settings dialogs" msgstr "Preferencias de ferramenta de centrado" #: src/prefs.c:211 msgid "New image sets zoom to 100%" msgstr "A nova imaxe establece o zoom ao 100%" #: src/prefs.c:212 msgid "Zoom on cursor position" msgstr "" #: src/prefs.c:214 msgid "Mouse Scroll Wheel = Zoom" msgstr "Roda do rato = Ampliar" #: src/prefs.c:215 msgid "Use menu icons" msgstr "Usar iconas de menu" #: src/prefs.c:220 msgid "Files" msgstr "Ficheiros" #: src/prefs.c:223 msgid "XBM X hotspot" msgstr "Referencia XBM X" #: src/prefs.c:224 msgid "XBM Y hotspot" msgstr "Referencia XBM Y" #: src/prefs.c:228 msgid "Recently Used Files" msgstr "Ficheiros recentes" #: src/prefs.c:229 msgid "Progress bar silence limit" msgstr "Límite de silencio da barra de progreso" #: src/prefs.c:232 msgid "Read 16-bit TGAs as 5:6:5 BGR" msgstr "Ler 16-bit TGAs como 5:6:5 BGR" #: src/prefs.c:233 msgid "Write TGAs in bottom-up row order" msgstr "Escribir TGAs de abaixo á arriba según orden" #: src/prefs.c:234 msgid "Undoable image loading" msgstr "Carga reversibel de imaxes" #: src/prefs.c:245 msgid "Compression (RGB)" msgstr "" #: src/prefs.c:246 msgid "Compression (indexed)" msgstr "" #: src/prefs.c:247 msgid "Compression (monochrome)" msgstr "" #: src/prefs.c:255 msgid "Enable predictor" msgstr "" #: src/prefs.c:262 msgid "Compression mode" msgstr "" #: src/prefs.c:271 msgid "Channel for Mask Plane" msgstr "" #: src/prefs.c:273 msgid "Ignore Transparent Colour" msgstr "" #: src/prefs.c:274 msgid "PackBits Compression" msgstr "" #: src/prefs.c:275 msgid "Write Indexed as Planar Bitmap (PBM)" msgstr "" #: src/prefs.c:280 msgid "Paths" msgstr "Rutas" #: src/prefs.c:281 msgid "Clipboard Files" msgstr "Ficheiros do portapapeis" #: src/prefs.c:281 msgid "Select Clipboard File" msgstr "Seleccione portapapeis" #: src/prefs.c:283 msgid "HTML Browser Program" msgstr "Programa navegador HTML" #: src/prefs.c:283 msgid "Select Browser Program" msgstr "Seleccionar programa de navegación" #: src/prefs.c:285 msgid "Location of Handbook index" msgstr "Localización do ficheiro indice do manual" #: src/prefs.c:285 msgid "Select Handbook Index File" msgstr "Seleccionar o Ficheiro índice do manual" #: src/prefs.c:287 msgid "Default Palette" msgstr "Paleta predeterminada" #: src/prefs.c:287 msgid "Select Default Palette" msgstr "Seleccionar paleta predefinida" #: src/prefs.c:289 msgid "Default Patterns" msgstr "Patróns predefinidos" #: src/prefs.c:289 msgid "Select Default Patterns File" msgstr "Seleccionar ficheiros de patróns predefinidos" #: src/prefs.c:292 msgid "Default CSS" msgstr "" #: src/prefs.c:292 msgid "Select Default CSS File" msgstr "" #: src/prefs.c:295 msgid "Default Theme" msgstr "" #: src/prefs.c:295 msgid "Select Default Theme File" msgstr "" #: src/prefs.c:300 msgid "Status Bar" msgstr "Barra de estado" #: src/prefs.c:301 msgid "Canvas Geometry" msgstr "Xeometría do lenzo" #: src/prefs.c:302 msgid "Cursor X,Y" msgstr "Cursor X,Y" #: src/prefs.c:303 msgid "Pixel [I] {RGB}" msgstr "Píxel [I] {RGB}" #: src/prefs.c:304 msgid "Selection Geometry" msgstr "Selección da xeometria" #: src/prefs.c:305 msgid "Undo / Redo" msgstr "Desfacer / Refacer" #: src/prefs.c:308 msgid "Tablet" msgstr "Tableta" #: src/prefs.c:309 msgid "Device Settings" msgstr "Parámetros de dispositivo" #: src/prefs.c:313 msgid "Configure Device" msgstr "Configurar dispositivo" #: src/prefs.c:319 msgid "Tool Variable" msgstr "Variables do lápis" #: src/prefs.c:322 src/toolbar.c:454 msgid "Flow" msgstr "Fluxo" #: src/prefs.c:330 msgid "Test Area" msgstr "Area de proba" #: src/prefs.c:373 msgid "Factor" msgstr "Factor" #: src/prefs.c:459 msgid "This key is builtin" msgstr "" #: src/prefs.c:462 #, c-format msgid "" "This key is mapped to:\n" "\"%s\"" msgstr "" #: src/prefs.c:465 msgid "Remap" msgstr "" #: src/prefs.c:510 msgid "Keyboard Shortcuts" msgstr "" #: src/shifter.c:147 msgid "Frames" msgstr "Fotogramas" #: src/shifter.c:258 msgid "Palette Shifter" msgstr "Paleta «Shifter»" #: src/shifter.c:263 msgid "Start" msgstr "Comezar" #: src/shifter.c:265 msgid "Finish" msgstr "Terminar" #: src/shifter.c:284 msgid "Fix Palette" msgstr "Pegar paleta" #: src/spawn.c:651 msgid "Configure File Actions" msgstr "Configurar accións de ficheiros" #: src/spawn.c:657 src/spawn.c:663 msgid "Command" msgstr "Orde" #: src/spawn.c:922 #, c-format msgid "Error %i reported when trying to run %s" msgstr "Produciuse un erro %i cando se intentaba cargar %s" #: src/spawn.c:979 msgid "" "I am unable to find the documentation. Either you need to download the " "mtPaint Handbook from the web site and install it, or you need to set the " "correct location in the Preferences window." msgstr "" "Non se pode atopar a documentación. Necesitas descargar o manual de mtPaint " "e instalálo, ou determinar a localización correcta na ventá de preferencias." #: src/spawn.c:1018 msgid "" "There was a problem running the HTML browser. You need to set the correct " "program name in the Preferences window." msgstr "" "Ha un problema arrancando o navegador HTML. Necesitas determinar un programa " "de navegación na ventá de preferencias." #: src/thread.c:361 msgid "Helper thread is not responding. Save your work and exit the program." msgstr "" #: src/toolbar.c:147 msgid "RGB Cube" msgstr "Cubo RGB" #: src/toolbar.c:148 msgid "By image channel" msgstr "No lugar de canle de imaxe" #: src/toolbar.c:149 msgid "Gradient-driven" msgstr "Executar-gradación" #: src/toolbar.c:157 msgid "Fill settings" msgstr "Preferencias de recheo" #: src/toolbar.c:170 msgid "Respect opacity mode" msgstr "Respetar opacidade" #: src/toolbar.c:176 msgid "Smudge settings" msgstr "Preferencias de esborranchado" #: src/toolbar.c:215 msgid "Aligned" msgstr "" #: src/toolbar.c:222 msgid "Clone settings" msgstr "" #: src/toolbar.c:228 msgid "By selection channel" msgstr "" #: src/toolbar.c:234 msgid "Lasso settings" msgstr "" #: src/toolbar.c:252 msgid "Brush spacing" msgstr "Espaciado da brocha" #: src/toolbar.c:299 src/toolbar.c:341 msgid "Normal" msgstr "Normal" #: src/toolbar.c:300 msgid "Colour" msgstr "Cor" #: src/toolbar.c:300 msgid "Saturate More" msgstr "Saturar máis" #: src/toolbar.c:301 msgid "Multiply" msgstr "Multiplicar" #: src/toolbar.c:301 msgid "Divide" msgstr "Dividir" #: src/toolbar.c:301 msgid "Dodge" msgstr "Subexposición" #: src/toolbar.c:302 msgid "Burn" msgstr "Superexposición" #: src/toolbar.c:302 msgid "Hard Light" msgstr "Luz forte" #: src/toolbar.c:302 msgid "Soft Light" msgstr "Luz suave" #: src/toolbar.c:302 msgid "Difference" msgstr "Diferenza" #: src/toolbar.c:303 msgid "Darken" msgstr "Escurecer" #: src/toolbar.c:303 msgid "Lighten" msgstr "Aclarar" #: src/toolbar.c:303 msgid "Grain Extract" msgstr "Extraer granulado" #: src/toolbar.c:304 msgid "Grain Merge" msgstr "Combinar granulado" #: src/toolbar.c:330 msgid "Blend mode" msgstr "Modo de mistura" #: src/toolbar.c:417 msgid "Continuous Mode" msgstr "Modo continuo" #: src/toolbar.c:421 msgid "Opacity Mode" msgstr "Modo opaco" #: src/toolbar.c:424 msgid "Tint Mode" msgstr "Modo tinguido" #: src/toolbar.c:427 msgid "Tint +-" msgstr "Tinguido +-" #: src/toolbar.c:434 msgid "Blend Mode" msgstr "Modo de mistura" #: src/toolbar.c:438 msgid "Disable All Masks" msgstr "Deshabilitar todas as máscaras" #: src/toolbar.c:441 msgid "Gradient Mode" msgstr "Modo de gradación" #: src/toolbar.c:486 msgid "Settings Toolbar" msgstr "Barra de propiedades" #: src/toolbar.c:546 msgid "Cut" msgstr "Cortar" #: src/toolbar.c:548 msgid "Copy" msgstr "Copiar" #: src/toolbar.c:550 msgid "Paste" msgstr "Pegar" #: src/toolbar.c:553 msgid "Undo" msgstr "Desfacer" #: src/toolbar.c:555 msgid "Redo" msgstr "Refacer" #: src/toolbar.c:559 src/viewer.c:328 msgid "Pan Window" msgstr "Vista preliminar" #: src/toolbar.c:560 src/toolbar.c:640 msgid "More..." msgstr "" #: src/toolbar.c:574 msgid "Paint" msgstr "Debuxar" #: src/toolbar.c:580 msgid "Shuffle" msgstr "Esborranchar" #: src/toolbar.c:583 msgid "Flood Fill" msgstr "Encher con pintura" #: src/toolbar.c:587 msgid "Straight Line" msgstr "Liña recta" #: src/toolbar.c:590 msgid "Smudge" msgstr "Esborranchar" #: src/toolbar.c:594 msgid "Clone" msgstr "Clonar" #: src/toolbar.c:597 msgid "Make Selection" msgstr "Facer selección" #: src/toolbar.c:600 msgid "Polygon Selection" msgstr "Selección poligonal" #: src/toolbar.c:603 msgid "Place Gradient" msgstr "Situar gradación" #: src/toolbar.c:606 msgid "Lasso Selection" msgstr "Selección libre" #: src/toolbar.c:614 msgid "Ellipse Outline" msgstr "Contorna de elipse" #: src/toolbar.c:617 msgid "Filled Ellipse" msgstr "Elipse chea" #: src/toolbar.c:620 msgid "Outline Selection" msgstr "Resaltar a selección" #: src/toolbar.c:623 msgid "Fill Selection" msgstr "Encher a selección" #: src/toolbar.c:627 msgid "Flip Selection Vertically" msgstr "Voltear selección verticalmente" #: src/toolbar.c:630 msgid "Flip Selection Horizontally" msgstr "Voltear selección horizontalmente" #: src/toolbar.c:633 msgid "Rotate Selection Clockwise" msgstr "Rotar a Selección no sentido do reloxo" #: src/toolbar.c:636 msgid "Rotate Selection Anti-Clockwise" msgstr "Rotar a elección no sentido contrario do reloxo" #: src/vcode.c:5201 msgid "Browse" msgstr "Buscar" #: src/vcode.c:7886 msgid "New key ..." msgstr "" #: src/vcode.c:9909 #, c-format msgid "'%s' does not match any widget" msgstr "" #: src/vcode.c:9910 #, c-format msgid "'%s' value does not fit '%s' widget" msgstr "" #: src/viewer.c:115 msgid "About" msgstr "Acerca de" #: src/viewer.c:1179 msgid "No font selected" msgstr "" #: src/viewer.c:1209 msgid "Left" msgstr "" #: src/viewer.c:1209 msgid "Right" msgstr "" #~ msgid "Create GIF frames" #~ msgstr "Crear fotogramas GIF" #~ msgid "" #~ "You are trying to save an XPM file with more than 4096 colours. Either " #~ "use another format or posterize the image to 4 bits, or otherwise reduce " #~ "the number of colours." #~ msgstr "" #~ "Pretende gardar un ficheiro XPM con máis de 4096 cores. Use outro formato " #~ "ou posterize a imaxe a 4 bits, ou de outro xeito reduza o número de cores." #~ msgid "Store Values" #~ msgstr "Valores gardados" #~ msgid "File: %s invalid - palette not updated" #~ msgstr "O ficheiro: %s non é valido - A paleta non se actualizou" #~ msgid "Distance to A+B" #~ msgstr "Distancia á A+B" #~ msgid "Edit Frames" #~ msgstr "Editar fotogramas" #~ msgid "File is too big, must be <= to width=%i height=%i : %s" #~ msgstr "" #~ "Ficheiro demasiado grande, o tamaño debe ser <= ancho=%i alto=%i : %s" #~ msgid "Could not open %s: %s" #~ msgstr "Non se pudo abrir %s: %s" #~ msgid "Error closing %s: %s" #~ msgstr "Produciuse un erro ao pechar %s: %s" #~ msgid "Could not write to %s: %s" #~ msgstr "Non se puido escribir a %s: %s" #~ msgid "The palette does not contain enough colours to do a merge" #~ msgstr "A paleta non conten suficientes cores para facer unha fusión" #~ msgid "There are too many identical palette items to be reduced." #~ msgstr "Ha demasiados elementos na paleta a reducir." #~ msgid "Done" #~ msgstr "Feito" #~ msgid "Current image is not 94x94x3 so I cannot create patterns_user.c" #~ msgstr "" #~ "A imaxe actual non ten as dimensions 94x94x3 polo que non pode crearse o " #~ "ficheiro de patróns «patterns_user.c»" #~ msgid "" #~ "You are trying to save an RGB image to an XPM file which is not " #~ "possible. I would suggest you save with a PNG extension." #~ msgstr "" #~ "Está intentando gardar unha imaxe RGB nun fichero XPM, o que non é " #~ "posible. Suxiro que o garde con extensión PNG." #~ msgid "" #~ "You are trying to save an RGB image to a GIF file which is not possible. " #~ "I would suggest you save with a PNG extension." #~ msgstr "" #~ "Está intentando gardar unha imaxe RGB a un fichero GIF, o que non é " #~ "posible. Suxiro que o garde con extensión PNG." #~ msgid "" #~ "You are trying to save an XBM file with a palette of more than 2 " #~ "colours. Either use another format or reduce the palette to 2 colours." #~ msgstr "" #~ "Está intentando gardar un ficheiro XBM con unha paleta de máis de 2 " #~ "cores. Reduza a paleta a 2 cores ou use outro formato." #~ msgid "" #~ "You are trying to save an indexed canvas to a JPEG file which is not " #~ "possible. I would suggest you save with a PNG extension." #~ msgstr "" #~ "Está intentando gardar un lenzo nun fichero JPEG, o que non é posible. " #~ "Suxiro que o garde con extensión PNG." #~ msgid "/Edit/Create Patterns" #~ msgstr "/Editar/Crear Patróns" #~ msgid "/View/Command Line Window" #~ msgstr "/Ver/Liña de ordenes" #~ msgid "/Palette/Create Quantized (DL1)" #~ msgstr "/Paleta/Crear cuantificado (DL1)" #~ msgid "/Palette/Create Quantized (DL3)" #~ msgstr "/Paleta/Crear cuantificado (DL3)" #~ msgid "/File/%i" #~ msgstr "/Ficheiro/%i" #~ msgid "JPEG Save Quality (100=High) " #~ msgstr "Calidade JPEG para gardar (100=Alta) " #~ msgid "DL1 Quantize (fastest)" #~ msgstr "Ponderado DL1 (o máis rápido)" #~ msgid "DL3 Quantize (very slow, better quality)" #~ msgstr "Ponderado DL3 (moi lento, mellor calidade)" #~ msgid "Loading PNG image" #~ msgstr "Cargar imaxe PNG" #~ msgid "Loading clipboard image" #~ msgstr "Cargar imaxe do portapapeis" #~ msgid "Saving PNG image" #~ msgstr "Gardar imaxe PNG" #~ msgid "Saving Clipboard image" #~ msgstr "Gardar imaxe do portapapeis" #~ msgid "Saving Layer image" #~ msgstr "Gardar imaxe da capa" #~ msgid "Loading GIF image" #~ msgstr "Cargar imaxe GIF" #~ msgid "Saving GIF image" #~ msgstr "Gardar imaxe GIF" #~ msgid "Loading JPEG image" #~ msgstr "Cargar imaxe JPEG" #~ msgid "Saving JPEG image" #~ msgstr "Gardar imaxe JPEG" #~ msgid "Loading TIFF image" #~ msgstr "Cargar imaxe TIFF" #~ msgid "Saving TIFF image" #~ msgstr "Gardar imaxe TIFF" #~ msgid "Loading BMP image" #~ msgstr "Cargar imaxe BMP" #~ msgid "Saving BMP image" #~ msgstr "Gardar imaxe BMP" #~ msgid "Loading XPM image" #~ msgstr "Cargar imaxe XPM" #~ msgid "Saving XPM image" #~ msgstr "Gardar imaxe XPM" #~ msgid "Loading XBM image" #~ msgstr "Cargar imaxe XBM" #~ msgid "Saving XBM image" #~ msgstr "Gardar imaxe XBM" #~ msgid "Saving UNDO images" #~ msgstr "Gardando histórico de imaxes" #~ msgid "%i Files on Command Line" #~ msgstr "%i Ficheiros na liña de ordenes" #~ msgid "/Palette/Create Quantized (Wu)" #~ msgstr "/Paleta/Crear cuantificado (Wu)" #~ msgid "Wu Quantize (best method for small palettes)" #~ msgstr "Cuantificación «Wu» (o mellor método para paletas pequenas)" #~ msgid "Grid colour RGB" #~ msgstr "Cor RGB da rella" #~ msgid "Zoom" #~ msgstr "Ampliación" #~ msgid "Lanczos3" #~ msgstr "Lanczos3" #~ msgid "Saving Channel image" #~ msgstr "Gardar imaxe da canle" #~ msgid "Loading LSS16 image" #~ msgstr "Cargar imaxe LSS16" #~ msgid "Saving LSS16 image" #~ msgstr "Gardar imaxe LSS16" #~ msgid " C Command Line Window" #~ msgstr " C Ventá de liña de ordenes" #~ msgid "/File/Actions/sep2" #~ msgstr "/Ficheiro/Accións/sep2" #~ msgid "/Frames" #~ msgstr "/Fotogramas" #~ msgid "/File/Actions/%i" #~ msgstr "/Ficheiro/Accións/%i" mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/po/hu.po000066400000000000000000002563731471325446300215650ustar00rootroot00000000000000# Hungarian translation for mtpaint # This file is distributed under the same license as the mtpaint package. # Balázs Úr , 2011. # msgid "" msgstr "" "Project-Id-Version: mtpaint\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-01-04 21:31+0200\n" "PO-Revision-Date: 2009-09-26 16:34+0000\n" "Last-Translator: Balázs Úr \n" "Language-Team: Hungarian\n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Launchpad-Export-Date: 2009-12-04 18:32+0000\n" "X-Generator: Launchpad (build Unknown)\n" "X-Rosetta-Version: 0.1\n" #: src/ani.c:647 msgid "Animation Preview" msgstr "Animáció elÅ‘nézet" #: src/ani.c:650 src/shifter.c:275 msgid "Play" msgstr "Lejátszás" #: src/ani.c:654 msgid "Fix" msgstr "" #: src/ani.c:655 src/ani.c:1005 src/font.c:1624 src/font.c:1643 #: src/shifter.c:286 src/viewer.c:97 msgid "Close" msgstr "Bezárás" #: src/ani.c:709 src/ani.c:812 src/ani.c:1022 src/ani.c:1028 src/canvas.c:356 #: src/canvas.c:708 src/canvas.c:989 src/canvas.c:1353 src/canvas.c:1383 #: src/canvas.c:1470 src/canvas.c:1545 src/canvas.c:1988 src/canvas.c:1994 #: src/canvas.c:2077 src/canvas.c:2217 src/canvas.c:2240 src/font.c:1352 #: src/fpick.c:636 src/fpick.c:754 src/layer.c:524 src/layer.c:815 #: src/layer.c:970 src/mainwindow.c:341 src/mainwindow.c:370 #: src/mainwindow.c:534 src/mainwindow.c:578 src/mainwindow.c:604 #: src/mainwindow.c:3797 src/mainwindow.c:4045 src/otherwindow.c:931 #: src/otherwindow.c:980 src/otherwindow.c:982 src/prefs.c:459 src/spawn.c:924 #: src/spawn.c:978 src/spawn.c:1017 src/thread.c:360 src/vcode.c:9912 #: src/viewer.c:1161 src/viewer.c:1179 msgid "Error" msgstr "Hiba" #: src/ani.c:709 msgid "Unable to create output directory" msgstr "Nem sikerült a kimeneti mappa létrehozása" #: src/ani.c:759 msgid "Creating Animation Frames" msgstr "" #: src/ani.c:812 msgid "Unable to save image" msgstr "Nem sikerült a kép mentése" #: src/ani.c:840 src/canvas.c:1171 src/fpick.c:731 src/layer.c:311 #: src/layer.c:379 src/layer.c:826 src/layer.c:840 src/mainwindow.c:375 #: src/mainwindow.c:1026 src/png.c:8794 src/prefs.c:464 msgid "Warning" msgstr "Figyelem" #: src/ani.c:840 msgid "" "Do you really want to clear all of the position and cycle data for all of " "the layers?" msgstr "" #: src/ani.c:841 src/fpick.c:731 src/layer.c:311 src/layer.c:842 #: src/mainwindow.c:375 msgid "No" msgstr "Nem" #: src/ani.c:841 src/fpick.c:731 src/layer.c:311 src/layer.c:842 #: src/mainwindow.c:375 msgid "Yes" msgstr "Igen" #: src/ani.c:954 msgid "Set Key Frame" msgstr "" #: src/ani.c:961 msgid "Configure Animation" msgstr "Animáció beállítása" #: src/ani.c:964 msgid "Output Files" msgstr "Kimeneti fájlok" #: src/ani.c:967 msgid "Start frame" msgstr "" #: src/ani.c:969 msgid "End frame" msgstr "" #: src/ani.c:971 src/shifter.c:267 msgid "Delay" msgstr "Késleltetés" #: src/ani.c:973 msgid "Output path" msgstr "Kimeneti elérési út" #: src/ani.c:973 src/font.c:1637 src/spawn.c:664 msgid "Select Directory" msgstr "Válasszon mappát" #: src/ani.c:976 msgid "File prefix" msgstr "Fájl elÅ‘tag" #: src/ani.c:978 src/canvas.c:2096 msgid "File Format" msgstr "Fájlformátum" #: src/ani.c:982 msgid "Positions" msgstr "" #: src/ani.c:997 msgid "Cycling" msgstr "" #: src/ani.c:1006 msgid "Save" msgstr "Mentés" #: src/ani.c:1007 src/font.c:1577 src/otherwindow.c:868 src/otherwindow.c:1615 #: src/otherwindow.c:1728 src/otherwindow.c:2938 src/otherwindow.c:3071 #: src/otherwindow.c:3170 msgid "Preview" msgstr "ElÅ‘nézet" #: src/ani.c:1008 src/shifter.c:285 msgid "Create Frames" msgstr "" #: src/ani.c:1022 msgid "You must have at least 2 layers to create an animation" msgstr "Legalább 2 réteg szükséges az animáció létrehozásához" #: src/ani.c:1028 msgid "You must save your layers file before creating an animation" msgstr "A rétegeket el kell menteni az animáció létrehozása elÅ‘tt" #: src/canvas.c:357 msgid "The image is too large to transform." msgstr "A kép túl nagy a transzformációhoz." #: src/canvas.c:393 src/canvas.c:430 src/otherwindow.c:1613 #: src/otherwindow.c:2524 src/otherwindow.c:2583 src/otherwindow.c:3179 msgid "Gradient" msgstr "" #: src/canvas.c:393 src/otherwindow.c:840 src/otherwindow.c:842 #: src/otherwindow.c:2074 src/otherwindow.c:3180 msgid "Palette" msgstr "Paletta" #: src/canvas.c:393 src/info.c:265 src/otherwindow.c:847 src/otherwindow.c:2757 #: src/otherwindow.c:3180 src/png.c:781 src/png.c:995 msgid "Clipboard" msgstr "Vágólap" #: src/canvas.c:394 src/cpick.c:831 src/toolbar.c:299 msgid "Value" msgstr "Érték" #: src/canvas.c:394 src/cpick.c:811 src/otherwindow.c:575 src/otherwindow.c:859 #: src/otherwindow.c:3053 src/toolbar.c:318 msgid "Red" msgstr "Vörös" #: src/canvas.c:394 src/cpick.c:815 src/otherwindow.c:575 src/otherwindow.c:860 #: src/otherwindow.c:3053 src/toolbar.c:319 msgid "Green" msgstr "Zöld" #: src/canvas.c:394 src/cpick.c:819 src/otherwindow.c:575 src/otherwindow.c:861 #: src/otherwindow.c:3053 src/toolbar.c:320 msgid "Blue" msgstr "Kék" #: src/canvas.c:399 msgid "From " msgstr "" #: src/canvas.c:403 msgid "To " msgstr "" #: src/canvas.c:410 msgid "Map" msgstr "" #: src/canvas.c:429 msgid "MT" msgstr "MT" #: src/canvas.c:429 msgid "Sobel" msgstr "Sobel" #: src/canvas.c:429 msgid "Prewitt" msgstr "Prewitt" #: src/canvas.c:429 msgid "Kirsch" msgstr "Kirsch" #: src/canvas.c:430 msgid "Roberts" msgstr "Roberts" #: src/canvas.c:430 msgid "Laplace" msgstr "Laplace" #: src/canvas.c:430 msgid "Morphological" msgstr "" #: src/canvas.c:442 msgid "Edge Detect" msgstr "" #: src/canvas.c:464 msgid "Edge Sharpen" msgstr "Kontúrélesítés" #: src/canvas.c:472 msgid "Edge Soften" msgstr "" #: src/canvas.c:521 msgid "Different X/Y" msgstr "" #: src/canvas.c:522 src/canvas.c:562 src/canvas.c:603 src/canvas.c:637 #: src/canvas.c:722 src/otherwindow.c:1037 src/otherwindow.c:2685 msgid "Gamma corrected" msgstr "Gamma korrigált" #: src/canvas.c:530 src/memory.c:8219 msgid "Gaussian Blur" msgstr "Gauss-elmosás" #: src/canvas.c:558 msgid "Radius" msgstr "Sugár" #: src/canvas.c:559 msgid "Amount" msgstr "Mennyiség" #: src/canvas.c:560 msgid "Threshold " msgstr "Küszöb" #: src/canvas.c:570 src/memory.c:8360 msgid "Unsharp Mask" msgstr "" #: src/canvas.c:599 msgid "Outer radius" msgstr "KülsÅ‘ sugár" #: src/canvas.c:600 msgid "Inner radius" msgstr "BelsÅ‘ sugár" #: src/canvas.c:602 src/info.c:280 msgid "Normalize" msgstr "Normalizálás" #: src/canvas.c:611 src/memory.c:8512 msgid "Difference of Gaussians" msgstr "" #: src/canvas.c:636 msgid "Protect details" msgstr "" #: src/canvas.c:645 msgid "Kuwahara-Nagao Blur" msgstr "Kuwahara-Nagao elmosás" #: src/canvas.c:709 msgid "The image is too large for this rotation." msgstr "A kép túl nagy ehhez a forgatáshoz." #: src/canvas.c:723 msgid "Smooth" msgstr "Simítás" #: src/canvas.c:732 msgid "Free Rotate" msgstr "Szabad forgatás" #: src/canvas.c:989 src/viewer.c:1161 msgid "Not enough memory to create clipboard" msgstr "Nincs elég memória a vágólap létrehozásához" #: src/canvas.c:1172 msgid "" "You have not allocated enough memory in the Preferences window to undo this " "action." msgstr "" #: src/canvas.c:1353 msgid "Invalid palette file" msgstr "" #: src/canvas.c:1383 msgid "Invalid channel file." msgstr "Érvénytelen csatornafájl." #: src/canvas.c:1401 msgid "Raw frames" msgstr "" #: src/canvas.c:1401 msgid "Composited frames" msgstr "" #: src/canvas.c:1402 msgid "Composited frames with nonzero delay" msgstr "" #: src/canvas.c:1406 msgid "Load Frames" msgstr "" #: src/canvas.c:1409 msgid "Load into Layers" msgstr "" #: src/canvas.c:1415 msgid "Load First Frame" msgstr "" #: src/canvas.c:1416 msgid "Explode Frames" msgstr "" #: src/canvas.c:1418 msgid "View Animation" msgstr "Animáció megtekintése" #: src/canvas.c:1434 #, c-format msgid "This is an animated %s file." msgstr "Ez egy animált %s fájl." #: src/canvas.c:1435 #, c-format msgid "This is a multipage %s file." msgstr "" #: src/canvas.c:1459 #, c-format msgid "File is too big, must be <= to width=%i height=%i" msgstr "A fájl túl nagy, legyen <= szélesség=%i magasság=%i" #: src/canvas.c:1461 msgid "Unable to explode frames" msgstr "" #: src/canvas.c:1463 msgid "Unable to load file" msgstr "Nem tölthetÅ‘ be a fájl" #: src/canvas.c:1465 msgid "" "The file import library had to terminate due to a problem with the file " "(possibly corrupt image data or a truncated file). I have managed to load " "some data as the header seemed fine, but I would suggest you save this image " "to a new file to ensure this does not happen again." msgstr "" #: src/canvas.c:1467 msgid "The animation is too long to load all of it into layers." msgstr "" #: src/canvas.c:1469 msgid "Could not explode all the frames in the animation." msgstr "" #: src/canvas.c:1481 src/font.c:1556 src/fpick.c:937 src/otherwindow.c:2765 #: src/prefs.c:321 src/toolbar.c:451 msgid "Size" msgstr "Méret" #: src/canvas.c:1484 src/otherwindow.c:244 msgid "Width" msgstr "Szélesség" #: src/canvas.c:1485 src/otherwindow.c:245 msgid "Height" msgstr "Magasság" #: src/canvas.c:1489 src/channels.c:253 src/channels.c:317 src/fpick.c:666 #: src/fpick.c:957 src/mainwindow.c:3990 src/otherwindow.c:255 #: src/otherwindow.c:517 src/otherwindow.c:591 src/otherwindow.c:867 #: src/otherwindow.c:1058 src/otherwindow.c:1727 src/otherwindow.c:2101 #: src/otherwindow.c:2336 src/otherwindow.c:2538 src/otherwindow.c:2691 #: src/otherwindow.c:2776 src/otherwindow.c:2937 src/otherwindow.c:3070 #: src/otherwindow.c:3169 src/prefs.c:338 src/prefs.c:464 src/prefs.c:538 #: src/spawn.c:666 src/viewer.c:1258 msgid "Cancel" msgstr "Mégse" #: src/canvas.c:1490 src/channels.c:253 src/channels.c:317 src/fpick.c:956 #: src/info.c:297 src/mainwindow.c:3992 src/mygtk.c:233 src/mygtk.c:535 #: src/otherwindow.c:591 src/otherwindow.c:871 src/otherwindow.c:1058 #: src/otherwindow.c:1729 src/otherwindow.c:2101 src/otherwindow.c:2336 #: src/otherwindow.c:2538 src/otherwindow.c:2691 src/otherwindow.c:2776 #: src/otherwindow.c:3072 src/otherwindow.c:3171 src/prefs.c:338 #: src/prefs.c:538 src/spawn.c:666 msgid "OK" msgstr "OK" #: src/canvas.c:1504 #, c-format msgid "This is a scalable %s file." msgstr "" #: src/canvas.c:1545 msgid "Cannot open file" msgstr "Nem lehet megnyitni a fájlt" #: src/canvas.c:1546 msgid "Unsupported file format" msgstr "Nem támogatott fájlformátum" #: src/canvas.c:1673 #, c-format msgid "File: %s already exists. Do you want to overwrite it?" msgstr "Fájl: %s már létezik. Szeretné felülírni?" #: src/canvas.c:1674 msgid "File Found" msgstr "" #: src/canvas.c:1674 src/mainwindow.c:1095 msgid "NO" msgstr "NEM" #: src/canvas.c:1674 src/mainwindow.c:1095 msgid "YES" msgstr "IGEN" #: src/canvas.c:1988 msgid "Unable to export undo images" msgstr "" #: src/canvas.c:1994 msgid "Unable to export ASCII file" msgstr "Nem lehet exportálni az ASCII fájlt" #: src/canvas.c:2076 src/layer.c:814 src/mainwindow.c:529 #, c-format msgid "Unable to save file: %s" msgstr "Nem menthetÅ‘ a fájl: %s" #: src/canvas.c:2101 src/prefs.c:222 msgid "Transparency index" msgstr "Ãtlátszóság index" #: src/canvas.c:2103 msgid "TIFF Compression" msgstr "" #: src/canvas.c:2105 src/prefs.c:225 msgid "JPEG Save Quality (100=High)" msgstr "JPEG mentés minÅ‘ség (100 = magas)" #: src/canvas.c:2107 msgid "ZIP Compression (0=None)" msgstr "" #: src/canvas.c:2108 src/prefs.c:227 msgid "PNG Compression (0=None)" msgstr "PNG tömörítés (0 = nincs)" #: src/canvas.c:2111 src/prefs.c:249 msgid "LZMA2 Compression (0=None)" msgstr "" #: src/canvas.c:2113 src/prefs.c:252 msgid "ZSTD Compression Level" msgstr "" #: src/canvas.c:2115 src/prefs.c:231 msgid "TGA RLE Compression" msgstr "TGA RLE tömörítés" #: src/canvas.c:2117 msgid "LBM PackBits Compression" msgstr "" #: src/canvas.c:2118 src/prefs.c:226 msgid "JPEG2000 Compression (0=Lossless)" msgstr "JPEG2000 tömörítés (0 = veszteségmentes)" #: src/canvas.c:2120 msgid "WebP Compression" msgstr "" #: src/canvas.c:2122 msgid "WebP Save Quality (100=High)" msgstr "" #: src/canvas.c:2123 src/prefs.c:263 msgid "V8 Save Quality (100=High)" msgstr "" #: src/canvas.c:2125 src/prefs.c:264 msgid "V8L Compression (0=None)" msgstr "" #: src/canvas.c:2127 msgid "Hotspot at X =" msgstr "Hotspot X =" #: src/canvas.c:2129 msgid "Y =" msgstr "Y =" #: src/canvas.c:2133 msgid "Animation delay" msgstr "Animáció késleltetés" #: src/canvas.c:2136 src/otherwindow.c:253 msgid "Undoable" msgstr "" #: src/canvas.c:2138 src/prefs.c:236 msgid "Apply colour profile" msgstr "" #: src/canvas.c:2176 src/toolbar.c:543 msgid "Load Image File" msgstr "Képfájl betöltése" #: src/canvas.c:2191 src/toolbar.c:544 msgid "Save Image File" msgstr "Képfájl mentése" #: src/canvas.c:2196 msgid "Load Palette File" msgstr "Palettafájl betöltése" #: src/canvas.c:2202 msgid "Save Palette File" msgstr "Palettafájl mentése" #: src/canvas.c:2207 msgid "Export Undo Images" msgstr "" #: src/canvas.c:2212 msgid "Export Undo Images (reversed)" msgstr "" #: src/canvas.c:2217 msgid "You must have 16 or fewer palette colours to export ASCII art." msgstr "16 vagy kevesebb palettaszín szükséges az ASCII Art exporthoz." #: src/canvas.c:2220 msgid "Export ASCII Art" msgstr "ASCII Art exportálása" #: src/canvas.c:2224 msgid "Save Layer Files" msgstr "Rétegfájlok mentése" #: src/canvas.c:2234 msgid "Choose frames directory" msgstr "" #: src/canvas.c:2240 msgid "You must save at least one frame to create an animated GIF." msgstr "Legalább egy keretet el kell mentenie az animált GIF létrehozásához." #: src/canvas.c:2243 msgid "Export GIF animation" msgstr "GIF animáció exportálása" #: src/canvas.c:2247 msgid "Load Channel" msgstr "Csatorna betöltése" #: src/canvas.c:2255 msgid "Save Channel" msgstr "Csatorna mentése" #: src/canvas.c:2260 msgid "Save Composite Image" msgstr "KOmpozitkép mentése" #: src/channels.c:243 msgid "Create Channel" msgstr "Csatorna létrehozása" #: src/channels.c:244 msgid "Channel Type" msgstr "Csatornatípus" #: src/channels.c:247 msgid "Initial Channel State" msgstr "Kezdeti csatornaállapot" #: src/channels.c:251 msgid "Inverted" msgstr "Invertált" #: src/channels.c:265 msgid "Cleared" msgstr "" #: src/channels.c:266 msgid "Set" msgstr "" #: src/channels.c:267 msgid "Set colour A radius B" msgstr "" #: src/channels.c:268 msgid "Set blend A to B" msgstr "" #: src/channels.c:269 msgid "Image Red" msgstr "Kép vörös" #: src/channels.c:270 msgid "Image Green" msgstr "Kép zöld" #: src/channels.c:271 msgid "Image Blue" msgstr "Kép kék" #: src/channels.c:273 src/channels.c:313 src/mainwindow.c:67 #: src/otherwindow.c:1679 msgid "Alpha" msgstr "Alfa" #: src/channels.c:274 src/channels.c:314 src/mainwindow.c:67 #: src/otherwindow.c:1683 msgid "Selection" msgstr "Kijelölés" #: src/channels.c:275 src/channels.c:315 src/mainwindow.c:67 #: src/otherwindow.c:1687 msgid "Mask" msgstr "Maszk" #: src/channels.c:312 msgid "Delete Channels" msgstr "Csatornák törlése" #: src/channels.c:367 msgid "Threshold Channel" msgstr "Küszöb csatorna" #: src/cpick.c:823 src/otherwindow.c:573 src/otherwindow.c:820 #: src/toolbar.c:299 msgid "Hue" msgstr "Ãrnyalat" #: src/cpick.c:827 src/otherwindow.c:573 src/otherwindow.c:818 #: src/toolbar.c:299 msgid "Saturation" msgstr "Telítettség" #: src/cpick.c:835 msgid "Hex" msgstr "Hex" #: src/cpick.c:840 src/layer.c:1109 src/otherwindow.c:2530 src/prefs.c:323 #: src/toolbar.c:457 msgid "Opacity" msgstr "Ãtlátszatlanság" #: src/font.c:982 msgid "Creating Font Index" msgstr "Betűindex létrehozása" #: src/font.c:1353 msgid "You must select at least one directory to search for fonts." msgstr "Legalább egy mappát ki kell választani a betűkereséshez." #: src/font.c:1529 src/font.c:1624 src/toolbar.c:609 src/viewer.c:1213 #: src/viewer.c:1258 msgid "Paste Text" msgstr "Szöveg beillesztése" #: src/font.c:1533 src/font.c:1572 src/png.c:3578 msgid "Text" msgstr "Szöveg" #: src/font.c:1540 msgid "Font" msgstr "Betűkészlet" #: src/font.c:1548 msgid "Style" msgstr "Stílus" #: src/font.c:1566 msgid "Filename" msgstr "Fájlnév" #: src/font.c:1567 msgid "Face" msgstr "" #: src/font.c:1587 src/viewer.c:1222 msgid "Antialias" msgstr "Élsimítás" #: src/font.c:1590 src/viewer.c:1224 msgid "Invert" msgstr "" #: src/font.c:1593 src/viewer.c:1226 msgid "Background colour =" msgstr "Háttérszín =" #: src/font.c:1601 src/viewer.c:1233 msgid "DPI =" msgstr "" #: src/font.c:1610 msgid "Oblique" msgstr "Kurzív" #: src/font.c:1612 src/viewer.c:1244 msgid "Angle of rotation =" msgstr "Forgatás szöge =" #: src/font.c:1617 src/viewer.c:1248 msgid "Align" msgstr "" #: src/font.c:1620 src/viewer.c:1253 msgid "Spacing" msgstr "" #: src/font.c:1629 msgid "Font Directories" msgstr "Betűkészlet mappa" #: src/font.c:1634 src/spawn.c:664 msgid "Directory" msgstr "Mappa" #: src/font.c:1637 msgid "New Directory" msgstr "Új mappa" #: src/font.c:1644 src/prefs.c:532 msgid "Add" msgstr "Hozzáadás" #: src/font.c:1645 src/prefs.c:533 msgid "Remove" msgstr "Eltávolítás" #: src/font.c:1646 msgid "Create Index" msgstr "Index létrehozása" #: src/font.c:1660 src/viewer.c:1267 msgid "Enter Text Here" msgstr "Ide írja a szöveget" #: src/fpick.c:635 #, c-format msgid "Could not access directory %s" msgstr "Nem lehet hozzáférni ehhez a mappához: %s" #: src/fpick.c:668 src/fpick.c:698 msgid "Delete" msgstr "Törlés" #: src/fpick.c:669 src/fpick.c:698 msgid "Rename" msgstr "Ãtnevezés" #: src/fpick.c:672 src/otherwindow.c:255 src/otherwindow.c:1666 msgid "Create" msgstr "Létrehozás" #: src/fpick.c:699 msgid "Enter the new filename" msgstr "Adja meg az új fájlnevet" #: src/fpick.c:704 msgid "Create Directory" msgstr "Mappa létrehozása" #: src/fpick.c:705 msgid "Enter the name of the new directory" msgstr "Adja meg az új mappa nevét" #: src/fpick.c:729 #, c-format msgid "Do you really want to delete \"%s\" ?" msgstr "Biztosan törölni szeretné ezt: \"%s\" ?" #: src/fpick.c:735 msgid "Unable to delete" msgstr "Nem lehet törölni" #: src/fpick.c:741 msgid "Unable to rename" msgstr "Nem lehet átnevezni" #: src/fpick.c:750 msgid "Unable to create directory" msgstr "Nem lehet mappát létrehozni" #: src/fpick.c:924 msgid "Up" msgstr "Fel" #: src/fpick.c:925 msgid "Home" msgstr "Saját mappa" #: src/fpick.c:926 msgid "Create New Directory" msgstr "Új mappa létrehozása" #: src/fpick.c:927 msgid "Show Hidden Files" msgstr "Rejtett fájlok megjelenítése" #: src/fpick.c:929 msgid "Case Insensitive Sort" msgstr "Kis- és nagybetű érzéketlen rendezés" #: src/fpick.c:936 msgid "Name" msgstr "Név" #: src/fpick.c:938 msgid "Type" msgstr "Típus" #: src/fpick.c:939 msgid "Modified" msgstr "Módosítva" #: src/help.c:25 src/prefs.c:160 msgid "General" msgstr "Ãltalános" #: src/help.c:26 msgid "Keyboard shortcuts" msgstr "Gyorsbillentyűk" #: src/help.c:27 msgid "Mouse shortcuts" msgstr "Egér gyorsbillentyűk" #: src/help.c:28 msgid "Credits" msgstr "Köszönet" #: src/help.c:32 msgid "mtPaint 3.51 - Copyright (C) 2004-2021 The Authors\n" msgstr "mtPaint 3.51 - Copyright (C) 2004-2021 A szerzÅ‘k\n" #: src/help.c:33 msgid "See 'Credits' section for a list of the authors.\n" msgstr "Tekintse meg a 'Köszönet' részt a szerzÅ‘k listájához.\n" #: src/help.c:34 msgid "" "mtPaint 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.\n" msgstr "" "Az mtPaint szabad szoftver; terjeszthetÅ‘ illetve módosítható a Free Software " "Foundation által kiadott GNU General Public License dokumentumban leírtak, " "akár a licenc 3-as, akár (tetszÅ‘leges) késÅ‘bbi változata szerint.\n" #: src/help.c:35 msgid "" "mtPaint 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.\n" msgstr "" "Az mtPaint abban a reményben kerül közreadásra, hogy hasznos lesz, de minden " "egyéb GARANCIA NÉLKÜL, az ELADHATÓSÃGRA vagy VALAMELY CÉLRA VALÓ " "ALKALMAZHATÓSÃGRA való származtatott garanciát is beleértve. További " "részleteket a GNU Public License tartalmaz.\n" #: src/help.c:36 msgid "" "mtPaint is a simple GTK+1/2/3 painting program designed for creating icons " "and pixel based artwork. It can edit indexed palette or 24 bit RGB images " "and offers basic painting and palette manipulation tools. It also has " "several other more powerful features such as channels, layers and animation. " "Due to its simplicity and lack of dependencies it runs well on GNU/Linux, " "Windows and older PC hardware.\n" msgstr "" #: src/help.c:37 msgid "" "There is full documentation of mtPaint's features contained in a handbook. " "If you don't already have this, you can download it from the mtPaint " "website.\n" msgstr "" "A kézikönyvben az mtPaint minden funkciójáról teljes dokumentációt talál. " "Ha ez még nincs meg önnek, letöltheti azt az mtPaint weboldaláról.\n" #: src/help.c:38 msgid "" "If you like mtPaint and you want to keep up to date with new releases, or " "you want to give some feedback, then the mailing lists may be of interest to " "you:\n" msgstr "" #: src/help.c:39 msgid "http://sourceforge.net/mail/?group_id=155874" msgstr "http://sourceforge.net/mail/?group_id=155874" #: src/help.c:42 msgid " Ctrl-N Create new image" msgstr " Ctrl-N Új kép létrehozása" #: src/help.c:43 msgid " Ctrl-O Open Image" msgstr " Ctrl-O Kép megnyitása" #: src/help.c:44 msgid " Ctrl-S Save Image" msgstr " Ctrl-S Kép mentése" #: src/help.c:45 msgid " Ctrl-Shift-S Save layers file" msgstr "" #: src/help.c:46 msgid " Ctrl-Q Quit program\n" msgstr " Ctrl-Q Kilépés a programból\n" #: src/help.c:47 msgid " Ctrl-A Select whole image" msgstr " Ctrl-A Az egész kép kijelölése" #: src/help.c:48 msgid " Escape Select nothing, cancel paste box" msgstr " Escape Kijelölés megszüntetése, beillesztésdobox bezárása" #: src/help.c:49 msgid " J Lasso selection\n" msgstr "" #: src/help.c:50 msgid " Ctrl-C Copy selection to clipboard" msgstr " Ctrl-C Kijelölés másolása a vágólapra" #: src/help.c:51 msgid "" " Ctrl-X Copy selection to clipboard, and then paint current " "pattern to selection area" msgstr "" #: src/help.c:52 msgid " Ctrl-V Paste clipboard to centre of current view" msgstr " Ctrl-V Beilleszti a vágólapot az aktuális nézet közepére" #: src/help.c:53 msgid " Ctrl-K Paste clipboard to location it was copied from" msgstr "" #: src/help.c:54 msgid " Ctrl-Shift-V Paste clipboard to new layer" msgstr "" #: src/help.c:55 msgid " Enter/Return Commit paste to canvas" msgstr "" #: src/help.c:56 msgid " Shift+Enter/Return Commit paste and swap canvas into the clipboard\n" msgstr "" #: src/help.c:57 msgid " Arrow keys Paint Mode - Move the mouse pointer" msgstr " Nyílbillentyűk Rajz mód - Mozgatja az egérmutatót" #: src/help.c:58 msgid "" " Arrow keys Selection Mode - Nudge selection box or paste box by one " "pixel" msgstr "" #: src/help.c:59 msgid "" " Shift+Arrow keys Nudge mouse pointer, selection box or paste box by x " "pixels - x is defined by the Preferences window" msgstr "" #: src/help.c:60 msgid " Ctrl+Arrows Move layer or resize selection box" msgstr " Ctrl+Nyilak Réteg mozgatása vagy kijelölÅ‘doboz átméretezése" #: src/help.c:61 msgid " Ctrl+Shift+Arrows Move layer or resize selection box by x pixels\n" msgstr "" #: src/help.c:62 msgid " Enter/Return Paint Mode - Simulate left click" msgstr "" #: src/help.c:63 msgid " Backspace Paint Mode - Simulate right click\n" msgstr "" #: src/help.c:64 msgid "" " [ or ] Change colour A to the next or previous palette item" msgstr "" " [ vagy ] Szín A megváltoztatása a következÅ‘ vagy elÅ‘zÅ‘ " "palettaelemre" #: src/help.c:65 msgid "" " Shift+[ or ] Change colour B to the next or previous palette item\n" msgstr "" " Shift+[ vagy ] Szín B megváltoztatása a következÅ‘ vagy elÅ‘zÅ‘ " "palettaelemre\n" #: src/help.c:66 msgid " Delete Crop image to selection" msgstr " Delete Kép vágása a kijelölésre" #: src/help.c:67 msgid "" " Insert Transform colours - i.e. Brightness, Contrast, " "Saturation, Posterize, Gamma" msgstr "" " Insert Színtranszformációk - azaz fényerÅ‘, kontraszt, " "telítettség, poszterizálás, gamma" #: src/help.c:68 msgid " Ctrl-G Greyscale the image" msgstr " Ctrl-G Szürkeárnyalatossá teszi a képet" #: src/help.c:69 msgid " Shift-Ctrl-G Greyscale the image (Gamma corrected)" msgstr "" " Shift-Ctrl-G Szürkeárnyalatossá teszi a képet (Gamma korrigáltan)" #: src/help.c:70 msgid " Ctrl+M Mirror the image" msgstr "" #: src/help.c:71 msgid " Shift-Ctrl-I Invert the image\n" msgstr "" #: src/help.c:72 msgid "" " Ctrl-T Draw a rectangle around the selection area with the " "current fill" msgstr "" " Ctrl-T Téglalapot rajzol a kijelölt terület köré az aktuális " "kitöltÅ‘színnel" #: src/help.c:73 msgid " Ctrl-Shift-T Fill in the selection area with the current fill" msgstr "" " Ctrl-Shift-T Kitölti a kijelölt területet az aktuális kitöltÅ‘színnel" #: src/help.c:74 msgid " Ctrl-L Draw an ellipse spanning the selection area" msgstr " Ctrl-L Ellipszist rajzol a kijelölt trületre" #: src/help.c:75 msgid " Ctrl-Shift-L Draw a filled ellipse spanning the selection area\n" msgstr " Ctrl-Shift-L Kitöltött ellipszist rajzol a kijelölt trületre\n" #: src/help.c:76 msgid " Ctrl-E Edit the RGB values for colours A & B" msgstr " Ctrl-E Szín A & B RGB értékeit szerkeszti" #: src/help.c:77 msgid " Ctrl-W Edit all palette colours\n" msgstr " Ctrl-W Minden palettaszín szerkesztése\n" #: src/help.c:78 msgid " Ctrl-P Preferences" msgstr " Ctrl-P Beállítások" #: src/help.c:79 msgid " Ctrl-I Information\n" msgstr " Ctrl-I Információ\n" #: src/help.c:80 msgid " Ctrl-Z Undo last action" msgstr " Ctrl-Z Visszavonja a legutóbbi műveletet" #: src/help.c:81 msgid " Ctrl-R Redo an undone action\n" msgstr " Ctrl-R Ismétli a visszavont műveletet\n" #: src/help.c:82 msgid " Shift-T Text Tool (GTK+)" msgstr "" #: src/help.c:83 msgid " T Text Tool (FreeType)\n" msgstr "" #: src/help.c:84 msgid " V View Window" msgstr " V Nézet ablak" #: src/help.c:85 msgid " L Layers Window\n" msgstr " L Rétegek ablak\n" #: src/help.c:86 msgid " Ctrl-H Toggle Hide Image mode" msgstr "" #: src/help.c:87 msgid " B Toggle Snap to Tile Grid mode\n" msgstr "" #: src/help.c:88 msgid " X Swap Colours A & B" msgstr "" #: src/help.c:89 msgid " E Choose Colour\n" msgstr "" #: src/help.c:90 msgid "" " A Draw open arrow head when using the line tool (size set " "by flow setting)" msgstr "" #: src/help.c:91 msgid "" " S Draw closed arrow head when using the line tool (size " "set by flow setting)\n" msgstr "" #: src/help.c:92 msgid " D Line Tool" msgstr "" #: src/help.c:93 msgid " F Flood Fill Tool\n" msgstr "" #: src/help.c:94 msgid " +,= Main edit window - Zoom in" msgstr " +,= FÅ‘ szerkesztÅ‘ablak - Nagyítás" #: src/help.c:95 msgid " - Main edit window - Zoom out" msgstr " - FÅ‘ szerkesztÅ‘ablak - Kicsinyítés" #: src/help.c:96 msgid " Shift +,= View window - Zoom in" msgstr " Shift +,= Nézet ablak - Nagyítás" #: src/help.c:97 msgid " Shift - View window - Zoom out\n" msgstr " Shift - Nézet ablak - Kicsinyítés\n" #: src/help.c:98 #, c-format msgid " 1 10% zoom" msgstr " 1 10% nagyítás" #: src/help.c:99 #, c-format msgid " 2 25% zoom" msgstr " 2 25% nagyítás" #: src/help.c:100 #, c-format msgid " 3 50% zoom" msgstr " 3 50% nagyítás" #: src/help.c:101 #, c-format msgid " 4 100% zoom" msgstr " 4 100% nagyítás" #: src/help.c:102 #, c-format msgid " 5 400% zoom" msgstr " 5 400% nagyítás" #: src/help.c:103 #, c-format msgid " 6 800% zoom" msgstr " 6 800% nagyítás" #: src/help.c:104 #, c-format msgid " 7 1200% zoom" msgstr " 7 1200% nagyítás" #: src/help.c:105 #, c-format msgid " 8 1600% zoom" msgstr " 8 1600% nagyítás" #: src/help.c:106 #, c-format msgid " 9 2000% zoom\n" msgstr " 9 2000% nagyítás\n" #: src/help.c:107 msgid " Shift + 1 Edit image channel" msgstr " Shift + 1 Kép csatorna szerkesztése" #: src/help.c:108 msgid " Shift + 2 Edit alpha channel" msgstr " Shift + 2 Alfa csatorna szerkesztésa" #: src/help.c:109 msgid " Shift + 3 Edit selection channel" msgstr " Shift + 3 Kijelölés csatorna szerkesztése" #: src/help.c:110 msgid " Shift + 4 Edit mask channel\n" msgstr " Shift + 4 Maszk csatorna szerkesztése\n" #: src/help.c:111 msgid " F1 Help" msgstr " F1 Súgó" #: src/help.c:112 msgid " F2 Choose Pattern" msgstr " F2 Minta választása" #: src/help.c:113 msgid " F3 Choose Brush" msgstr " F3 Ecset választása" #: src/help.c:114 msgid " F4 Paint Tool" msgstr " F4 FestÅ‘ eszköz" #: src/help.c:115 msgid " F5 Toggle Main Toolbar" msgstr " F5 FÅ‘ eszköztár ki/be kapcsolása" #: src/help.c:116 msgid " F6 Toggle Tools Toolbar" msgstr " F6 Eszközök eszköztár ki/be kapcsolása" #: src/help.c:117 msgid " F7 Toggle Settings Toolbar" msgstr " F7 Beállítások eszköztár ki/be kapcsolása" #: src/help.c:118 msgid " F8 Toggle Palette" msgstr " F8 Paletta ki/be kapcsolása" #: src/help.c:119 msgid " F9 Selection Tool" msgstr " F9 KijelölÅ‘ eszköz" #: src/help.c:120 msgid " F12 Toggle Dock Area\n" msgstr " F12 Dokk terület ki/be kapcsolása\n" #: src/help.c:121 msgid " Ctrl + F1 - F12 Save current clipboard to file 1-12" msgstr " Ctrl + F1 - F12 Az aktuális vágólap mentése az 1-12 fájlba" #: src/help.c:122 msgid " Shift + F1 - F12 Load clipboard from file 1-12\n" msgstr " Shift + F1 - F12 Vágólap betöltése az 1-12 fájlból\n" #: src/help.c:123 msgid "" " Ctrl + 1, 2, ... , 0 Set opacity to 10%, 20%, ... , 100% (main or keypad " "numbers)" msgstr "" " Ctrl + 1, 2, ... , 0 Ãtlátszatlanság beállítása 10%, 20%, ... , 100% " "értékre (felsÅ‘, vagy numerikus rész számai)" #: src/help.c:124 msgid " Ctrl + + or = Increase opacity by 1" msgstr " Ctrl + + or = Ãtlátszatlanság növelése 1-gyel" #: src/help.c:125 msgid " Ctrl + - Decrease opacity by 1\n" msgstr " Ctrl + - Ãtlátszatlanság csökkentése 1-gyel\n" #: src/help.c:126 msgid "" " Home Show or hide main window menu/toolbar/status bar/palette" msgstr "" " Home FÅ‘ablak menü/eszköztár/állapotsor/paletta megjelenítése " "vagy elrejtése" #: src/help.c:127 msgid " Page Up Scale Image" msgstr " Page Up Kép nyújtása" #: src/help.c:128 msgid " Page Down Resize Image canvas" msgstr " Page Down Képvászon átméretezése" #: src/help.c:129 msgid " End Pan Window" msgstr "" #: src/help.c:132 msgid " Left button Paint to canvas using the current tool" msgstr " Bal egérgomb Rajzolás a vászora az aktuális eszközzel" #: src/help.c:133 msgid "" " Middle button Selects the point which will be the centre of the " "image after the next zoom" msgstr "" " KözépsÅ‘ egérgomb Annak a pontnak a kiválasztása, amelyik a " "következÅ‘ nagyításkor a kép közepe legyen" #: src/help.c:134 msgid "" " Right button Commit paste to canvas / Stop drawing current line / " "Cancel selection\n" msgstr "" #: src/help.c:135 msgid "" " Scroll Wheel In GTK+2/3 the user can have the scroll wheel zoom in " "or out via the Preferences window\n" msgstr "" #: src/help.c:136 msgid " Ctrl+Left button Choose colour A from under mouse pointer" msgstr "" #: src/help.c:137 msgid " Ctrl+Left button Clone tool - Select source" msgstr "" #: src/help.c:138 msgid "" " Ctrl+Middle button Create colour A/B and pattern based on the RGB colour " "in A (RGB images only)" msgstr "" #: src/help.c:139 msgid " Ctrl+Right button Choose colour B from under mouse pointer" msgstr "" #: src/help.c:140 msgid "" " Ctrl+Right button Polygon tool - Delete last point / Delete nearest " "point" msgstr "" #: src/help.c:141 msgid " Ctrl+Scroll Wheel Scroll the main edit window left or right\n" msgstr "" #: src/help.c:142 msgid "" " Ctrl+Double click Set colour A or B to average colour under brush " "square or selection marquee (RGB only)\n" msgstr "" #: src/help.c:143 msgid "" " Shift+Right button Selects the point which will be the centre of the " "image after the next zoom\n" "\n" msgstr "" #: src/help.c:144 msgid "You can fixate the X/Y co-ordinates while moving the mouse:\n" msgstr "" #: src/help.c:145 msgid " Shift Constrain mouse movements to vertical line" msgstr "" #: src/help.c:146 msgid " Shift+Ctrl Constrain mouse movements to horizontal line" msgstr "" #: src/help.c:149 msgid "mtPaint is maintained by Dmitry Groshev.\n" msgstr "Az mtPaint karbantartója Dmitry Groshev.\n" #: src/help.c:150 msgid "wjaguar@users.sourceforge.net" msgstr "wjaguar@users.sourceforge.net" #: src/help.c:151 msgid "http://mtpaint.sourceforge.net/\n" msgstr "http://mtpaint.sourceforge.net/\n" #: src/help.c:152 msgid "" "The following people (in alphabetical order) have contributed directly to " "the project, and are therefore worthy of gracious thanks for their " "generosity and hard work:\n" "\n" msgstr "" "A következÅ‘ személyek (ábécé sorrendben) járultak hozzá a projekthez " "közvetlenül, és ezért méltó köszönet jár a nagylelkűségükért és a kemény " "munkájukért:\n" #: src/help.c:153 msgid "Authors\n" msgstr "SzerzÅ‘k\n" #: src/help.c:154 msgid "" "Dmitry Groshev - Contributing developer for version 2.30. Lead developer and " "maintainer from version 3.00 to the present." msgstr "" "Dmitry Groshev - A 2.30 verzió közreműködÅ‘ fejlesztÅ‘je. VezetÅ‘ fejlesztÅ‘ és " "karbantartó a 3.00 verziótól egészen máig." #: src/help.c:155 msgid "" "Mark Tyler - Original author and maintainer up to version 3.00, occasional " "contributor thereafter." msgstr "" "Mark Tyler - Eredeti szerzÅ‘ és karbantartó a 3.00 verzióig, ezt követÅ‘en " "alkalmi közreműködÅ‘." #: src/help.c:156 msgid "" "Xiaolin Wu - Wrote the Wu quantizing method - see wu.c for more " "information.\n" "\n" msgstr "" "Xiaolin Wu - A Wu kvantálás eljárás írója - tekintse meg a wu.c fájlt " "további információért.\n" "\n" #: src/help.c:157 msgid "" "General Contributions (Feedback and Ideas for improvements unless otherwise " "stated)\n" msgstr "" "Ãltalános hozzájárulás (visszajelzések és ötletek a javításokhoz, hacsak " "másképp nem jelzik)\n" #: src/help.c:158 msgid "Abdulla Al Muhairi - Website redesign April 2005" msgstr "Abdulla Al Muhairi - Website új dizájn 2005 április" #: src/help.c:159 msgid "Alan Horkan" msgstr "Alan Horkan" #: src/help.c:160 msgid "Alexandre Prokoudine" msgstr "Alexandre Prokoudine" #: src/help.c:161 msgid "Antonio Andrea Bianco" msgstr "Antonio Andrea Bianco" #: src/help.c:162 msgid "Charlie Ledocq" msgstr "" #: src/help.c:163 msgid "Dennis Lee" msgstr "Dennis Lee" #: src/help.c:164 msgid "Donald White" msgstr "" #: src/help.c:165 msgid "Ed Jason" msgstr "Ed Jason" #: src/help.c:166 msgid "" "Eddie Kohler - Created Gifsicle which is needed for the creation and viewing " "of animated GIF files http://www.lcdf.org/gifsicle/" msgstr "" "Eddie Kohler - A Gifsicle alkotója, amely szükséges az animált GIF fájlok " "létrehozásához és megtekintéséhez http://www.lcdf.org/gifsicle/" #: src/help.c:167 msgid "" "Guadalinex Team (Junta de Andalucia) - man page, Launchpad/Rosetta " "registration" msgstr "" "Guadalinex Csapat (Junta de Andalucia) - man page, Launchpad/Rosetta " "regisztráció" #: src/help.c:168 msgid "Lou Afonso" msgstr "Lou Afonso" #: src/help.c:169 msgid "Magnus Hjorth" msgstr "Magnus Hjorth" #: src/help.c:170 msgid "Martin Zelaia" msgstr "Martin Zelaia" #: src/help.c:171 msgid "Pasi Kallinen" msgstr "" #: src/help.c:172 msgid "Pavel Ruzicka" msgstr "Pavel Ruzicka" #: src/help.c:173 msgid "Puppy Linux (Barry Kauler)" msgstr "Puppy Linux (Barry Kauler)" #: src/help.c:174 msgid "Victor Copovi" msgstr "" #: src/help.c:175 msgid "Vlastimil Krejcir" msgstr "Vlastimil Krejcir" #: src/help.c:176 msgid "" "William Kern\n" "\n" msgstr "" "William Kern\n" "\n" #: src/help.c:177 msgid "Translations\n" msgstr "Fordítások\n" #: src/help.c:178 msgid "Brazilian Portuguese - Paulo Trevizan, Valter Nazianzeno" msgstr "Brazíliai portugál - Paulo Trevizan, Valter Nazianzeno" #: src/help.c:179 msgid "Czech - Pavel Ruzicka, Martin Petricek, Roman Hornik, Pavel Fric" msgstr "Cseh - Pavel Ruzicka, Martin Petricek, Roman Hornik, Pavel Fric" #: src/help.c:180 msgid "Dutch - Hans Strijards, Pjotr" msgstr "Holland - Hans Strijards, Pjotr" #: src/help.c:181 msgid "" "French - Nicolas Velin, Pascal Billard, Sylvain Cresto, Johan Serre, " "Philippe Etienne, Victor Copovi" msgstr "" "Francia - Nicolas Velin, Pascal Billard, Sylvain Cresto, Johan Serre, " "Philippe Etienne, Victor Copovi" #: src/help.c:182 msgid "Galician - Miguel Anxo Bouzada" msgstr "Galíciai - Miguel Anxo Bouzada" #: src/help.c:183 msgid "German - Oliver Frommel, B. Clausius, Ulrich Ringel, Simon Brixel" msgstr "Német - Oliver Frommel, B. Clausius, Ulrich Ringel, Simon Brixel" #: src/help.c:184 msgid "Hungarian - Ur Balazs" msgstr "" #: src/help.c:185 msgid "Italian - Angelo Gemmi" msgstr "Olasz - Angelo Gemmi" #: src/help.c:186 msgid "Japanese - Norihiro YONEDA" msgstr "Japán - Norihiro YONEDA" #: src/help.c:187 msgid "Kabyle - Yacine Bouklif" msgstr "" #: src/help.c:188 msgid "Polish - Bartosz Kaszubowski, LucaS" msgstr "Lengyel - Bartosz Kaszubowski, LucaS" #: src/help.c:189 msgid "Portuguese - Israel G. Lugo, Tiago Silva" msgstr "Portugál - Israel G. Lugo, Tiago Silva" #: src/help.c:190 msgid "Russian - Sergey Irupin, Dmitry Groshev" msgstr "Orosz - Sergey Irupin, Dmitry Groshev" #: src/help.c:191 msgid "Simplified Chinese - Cecc" msgstr "Egyszerűsített kínai - Cecc" #: src/help.c:192 msgid "Slovak - Jozef Riha" msgstr "Szlovák - Jozef Riha" #: src/help.c:193 msgid "" "Spanish - Guadalinex Team (Junta de Andalucia), Antonio Sanchez Leon, Miguel " "Anxo Bouzada, Francisco Jose Rey, Adolfo Jayme" msgstr "" "Spanyol - Guadalinex Team (Junta de Andalucia), Antonio Sanchez Leon, Miguel " "Anxo Bouzada, Francisco Jose Rey, Adolfo Jayme" #: src/help.c:194 msgid "Swedish - Daniel Nylander, Daniel Eriksson" msgstr "Svéd - Daniel Nylander, Daniel Eriksson" #: src/help.c:195 msgid "Tagalog - Anjelo delCarmen" msgstr "" #: src/help.c:196 msgid "Taiwanese Chinese - Wei-Lun Chao" msgstr "Taiwani kínai - Wei-Lun Chao" #: src/help.c:197 msgid "Turkish - Muhammet Kara, Tutku Dalmaz" msgstr "Török - Muhammet Kara, Tutku Dalmaz" #: src/info.c:258 msgid "Information" msgstr "Információ" #: src/info.c:260 msgid "Memory" msgstr "Memória" #: src/info.c:261 msgid "Total memory for main + undo images" msgstr "Teljes memória a fÅ‘ + visszavont képekhez" #: src/info.c:263 msgid "Undo / Redo / Max levels used" msgstr "Visszavont / Ismételt / Max szint használat" #: src/info.c:265 msgid "Unused" msgstr "Nem használt" #: src/info.c:269 msgid "Unique RGB pixels" msgstr "Egyedi RGB pixelek" #: src/info.c:272 src/layer.c:121 msgid "Layers" msgstr "Rétegek" #: src/info.c:273 msgid "Total layer memory usage" msgstr "Teljes réteg memória használat" #: src/info.c:277 msgid "Colour Histogram" msgstr "Színhisztogram" #: src/info.c:289 src/otherwindow.c:1614 msgid "Index" msgstr "Index" #: src/info.c:290 msgid "Canvas pixels" msgstr "Vászon pixelek" #: src/info.c:328 #, c-format msgid "Clipboard = %i x %i" msgstr "Vágólap = %i x %i" #: src/info.c:328 #, c-format msgid "Clipboard = %i x %i x RGB" msgstr "Vágólap = %i x %i x RGB" #: src/info.c:377 msgid "Orphans" msgstr "Ãrvák" #: src/info.c:383 #, c-format msgid "Colour index totals - %i of %i used" msgstr "" #: src/inifile.c:966 msgid "" "Could not find home directory. Using current directory as home directory." msgstr "" "A saját mappa nem található. Az aktuális mappa lesz saját mappaként " "használva." #: src/layer.c:63 msgid "Background" msgstr "Háttér" #: src/layer.c:122 src/mainwindow.c:5931 msgid "(Modified)" msgstr "(Módosítva)" #: src/layer.c:123 src/mainwindow.c:5932 msgid "Untitled" msgstr "Névtelen" #: src/layer.c:308 #, c-format msgid "Do you really want to delete layer %i (%s) ?" msgstr "" #: src/layer.c:380 msgid "" "One or more of the layers contains changes that have not been saved. Do you " "really want to lose these changes?" msgstr "" "Egy vagy több réteg olyan módosításokat tartalmaz, amelyek még nincsenek " "elmentve. Biztosan elveti ezeket a módosításokat?" #: src/layer.c:381 src/mainwindow.c:1028 msgid "Cancel Operation" msgstr "Művelet megszakítása" #: src/layer.c:381 src/mainwindow.c:1028 msgid "Lose Changes" msgstr "Változások elvetése" #: src/layer.c:523 #, c-format msgid "%d layers failed to load" msgstr "%d réteg betöltése meghiúsult" #: src/layer.c:826 msgid "" "One or more of the image layers has not been saved. You must save each " "image individually before saving the layers text file in order to load this " "composite image in the future." msgstr "" #: src/layer.c:841 msgid "Do you really want to delete all of the layers?" msgstr "Biztosan törölni szeretné az összes réteget?" #: src/layer.c:970 msgid "You cannot add any more layers." msgstr "Nem adhat hozzá több réteget." #: src/layer.c:1083 src/otherwindow.c:241 msgid "New Layer" msgstr "Új réteg" #: src/layer.c:1085 msgid "Raise" msgstr "Növel" #: src/layer.c:1087 msgid "Lower" msgstr "Csökkent" #: src/layer.c:1089 msgid "Duplicate Layer" msgstr "Réteg kettÅ‘zése" #: src/layer.c:1091 msgid "Centralise Layer" msgstr "Réteg középre helyezése" #: src/layer.c:1093 msgid "Delete Layer" msgstr "Réteg törlése" #: src/layer.c:1095 msgid "Close Layers Window" msgstr "Rétegek ablak bezárása" #: src/layer.c:1101 msgid "Layer Name" msgstr "Réteg neve" #: src/layer.c:1104 src/toolbar.c:209 msgid "Position" msgstr "Pozíció" #: src/layer.c:1112 msgid "Transparent Colour" msgstr "Ãtlátszó szín" #: src/layer.c:1117 msgid "Show all layers in main window" msgstr "Minden réteg mejelenítése a fÅ‘ ablakban" #: src/mainwindow.c:67 src/otherwindow.c:844 src/otherwindow.c:2756 #: src/toolbar.c:342 msgid "Image" msgstr "Kép" #: src/mainwindow.c:69 src/mainwindow.c:489 src/otherwindow.c:1613 #: src/otherwindow.c:2302 msgid "RGB" msgstr "RGB" #: src/mainwindow.c:69 src/otherwindow.c:1613 src/otherwindow.c:2302 msgid "sRGB" msgstr "" #: src/mainwindow.c:342 msgid "There were no unused colours to remove!" msgstr "Nincsen eltávolítható használaton kívüli szín!" #: src/mainwindow.c:371 msgid "The palette does not contain 2 colours that have identical RGB values" msgstr "" "A paletta nem tartalmaz 2 olyan színt, amelyeknek azonosak az RGB értékeik" #: src/mainwindow.c:374 #, c-format msgid "" "The palette contains %i colours that have identical RGB values. Do you " "really want to merge them into one index and realign the canvas?" msgstr "" "A paletta %i olyan színt tartalmaz, amelyeknek azonosak az RGB értékeik. " "Biztosan egyesíteni szeretné Å‘ket egy indexbe és újraigazítani a vásznat?" #: src/mainwindow.c:492 msgid "indexed" msgstr "indexelt" #: src/mainwindow.c:498 #, c-format msgid "" "You are trying to save an %s image to an %s file which is not possible. I " "would suggest you save with a PNG extension." msgstr "" #: src/mainwindow.c:500 #, c-format msgid "" "You are trying to save an %s file with a palette of more than %d colours. " "Either use another format or reduce the palette to %d colours." msgstr "" #: src/mainwindow.c:578 msgid "Unable to load clipboard" msgstr "A vególap nem tölthetÅ‘ be." #: src/mainwindow.c:604 msgid "Unable to save clipboard" msgstr "A vágólap nem menthetÅ‘ el." #: src/mainwindow.c:775 msgid "Zoom in" msgstr "" #: src/mainwindow.c:777 msgid "Zoom out" msgstr "" #: src/mainwindow.c:779 #, c-format msgid "10% zoom" msgstr "" #: src/mainwindow.c:781 #, c-format msgid "25% zoom" msgstr "" #: src/mainwindow.c:783 #, c-format msgid "50% zoom" msgstr "" #: src/mainwindow.c:785 #, c-format msgid "100% zoom" msgstr "" #: src/mainwindow.c:787 #, c-format msgid "400% zoom" msgstr "" #: src/mainwindow.c:789 #, c-format msgid "600% zoom" msgstr "" #: src/mainwindow.c:791 #, c-format msgid "800% zoom" msgstr "" #: src/mainwindow.c:793 #, c-format msgid "1000% zoom" msgstr "" #: src/mainwindow.c:795 #, c-format msgid "1200% zoom" msgstr "" #: src/mainwindow.c:797 #, c-format msgid "1600% zoom" msgstr "" #: src/mainwindow.c:799 #, c-format msgid "2000% zoom" msgstr "" #: src/mainwindow.c:801 #, c-format msgid "4000% zoom" msgstr "" #: src/mainwindow.c:803 #, c-format msgid "8000% zoom" msgstr "" #: src/mainwindow.c:805 #, c-format msgid "10% opacity" msgstr "" #: src/mainwindow.c:807 #, c-format msgid "20% opacity" msgstr "" #: src/mainwindow.c:809 #, c-format msgid "30% opacity" msgstr "" #: src/mainwindow.c:811 #, c-format msgid "40% opacity" msgstr "" #: src/mainwindow.c:813 #, c-format msgid "50% opacity" msgstr "" #: src/mainwindow.c:815 #, c-format msgid "60% opacity" msgstr "" #: src/mainwindow.c:817 #, c-format msgid "70% opacity" msgstr "" #: src/mainwindow.c:819 #, c-format msgid "80% opacity" msgstr "" #: src/mainwindow.c:821 #, c-format msgid "90% opacity" msgstr "" #: src/mainwindow.c:823 #, c-format msgid "100% opacity" msgstr "" #: src/mainwindow.c:825 msgid "Increase opacity" msgstr "" #: src/mainwindow.c:827 msgid "Decrease opacity" msgstr "" #: src/mainwindow.c:829 msgid "Draw open arrow head" msgstr "" #: src/mainwindow.c:831 msgid "Draw closed arrow head" msgstr "" #: src/mainwindow.c:833 msgid "Previous colour A" msgstr "" #: src/mainwindow.c:835 msgid "Next colour A" msgstr "" #: src/mainwindow.c:837 msgid "Previous colour B" msgstr "" #: src/mainwindow.c:839 msgid "Next colour B" msgstr "" #: src/mainwindow.c:841 msgid "Previous pattern" msgstr "" #: src/mainwindow.c:843 msgid "Next pattern" msgstr "" #: src/mainwindow.c:845 msgid "Larger brush" msgstr "" #: src/mainwindow.c:847 msgid "Smaller brush" msgstr "" #: src/mainwindow.c:849 msgid "View window - Zoom in" msgstr "" #: src/mainwindow.c:851 msgid "View window - Zoom out" msgstr "" #: src/mainwindow.c:1027 msgid "" "This canvas/palette contains changes that have not been saved. Do you " "really want to lose these changes?" msgstr "" "Ez a vászon/paletta el nem mentett módosításokat tartalmaz. Biztos benne, " "hogy elveti ezeket a módosításokat?" #: src/mainwindow.c:1094 msgid "Do you really want to quit?" msgstr "Biztosan ki szeretne lépni?" #: src/mainwindow.c:3754 msgid "Empty string or broken quoting" msgstr "" #: src/mainwindow.c:3755 msgid "Script must begin with a command" msgstr "" #: src/mainwindow.c:3756 msgid "Script nesting limit exceeded" msgstr "" #: src/mainwindow.c:3765 #, c-format msgid "'%s' does not match any item" msgstr "" #: src/mainwindow.c:3767 #, c-format msgid "'%s' matches a non-scriptable item" msgstr "" #: src/mainwindow.c:3769 #, c-format msgid "'%s' matches a disabled item" msgstr "" #: src/mainwindow.c:3788 #, c-format msgid "'%s' value does not fit item" msgstr "" #: src/mainwindow.c:3969 msgid "Script" msgstr "" #: src/mainwindow.c:3982 src/spawn.c:656 src/spawn.c:662 msgid "Action" msgstr "Művelet" #: src/mainwindow.c:3991 src/spawn.c:666 msgid "Execute" msgstr "Végrehajtás" #: src/mainwindow.c:4045 msgid "Unable to load script" msgstr "" #: src/mainwindow.c:5182 msgid "/_File" msgstr "/_Fájl" #: src/mainwindow.c:5184 msgid "//New" msgstr "//Új" #: src/mainwindow.c:5186 msgid "//Open ..." msgstr "//Megnyitás ..." #: src/mainwindow.c:5188 src/mainwindow.c:5669 msgid "//Save" msgstr "//Mentés" #: src/mainwindow.c:5190 src/mainwindow.c:5549 src/mainwindow.c:5627 #: src/mainwindow.c:5671 msgid "//Save As ..." msgstr "//Mentés másként ..." #: src/mainwindow.c:5192 msgid "//Export Undo Images ..." msgstr "" #: src/mainwindow.c:5194 msgid "//Export Undo Images (reversed) ..." msgstr "" #: src/mainwindow.c:5196 msgid "//Export ASCII Art ..." msgstr "//Exportálás ASCII Art formátumba ..." #: src/mainwindow.c:5198 msgid "//Export Animated GIF ..." msgstr "//Exportálás animált GIF formátumba ..." #: src/mainwindow.c:5201 msgid "//Actions" msgstr "//Műveletek" #: src/mainwindow.c:5235 src/mainwindow.c:5488 msgid "///Configure" msgstr "///Beállítás" #: src/mainwindow.c:5290 msgid "//Quit" msgstr "//Kilépés" #: src/mainwindow.c:5293 msgid "/_Edit" msgstr "/S_zerkesztés" #: src/mainwindow.c:5295 msgid "//Undo" msgstr "//Visszavonás" #: src/mainwindow.c:5297 msgid "//Redo" msgstr "//Újra" #: src/mainwindow.c:5300 msgid "//Cut" msgstr "//Kivágás" #: src/mainwindow.c:5302 msgid "//Copy" msgstr "//Másolás" #: src/mainwindow.c:5304 msgid "//Copy To Palette" msgstr "//Másolás a palettára" #: src/mainwindow.c:5306 msgid "//Paste To Centre" msgstr "//Beillesztés középre" #: src/mainwindow.c:5308 msgid "//Paste To New Layer" msgstr "//Beillesztés új rétegként" #: src/mainwindow.c:5310 msgid "//Paste" msgstr "//Beillesztés" #: src/mainwindow.c:5312 msgid "//Paste Text" msgstr "//Szöveg beillesztése" #: src/mainwindow.c:5318 msgid "//Paste Text (FreeType)" msgstr "//Szöveg beillesztése (FreeType)" #: src/mainwindow.c:5321 msgid "//Paste Palette" msgstr "//Paletta beillesztésa" #: src/mainwindow.c:5323 msgid "//Load Clipboard" msgstr "//Vágólap betöltése" #: src/mainwindow.c:5350 msgid "//Save Clipboard" msgstr "//Vágólap mentése" #: src/mainwindow.c:5377 msgid "//Import Clipboard from System" msgstr "//Vágólap importálása a rendszerbÅ‘l" #: src/mainwindow.c:5378 msgid "//Export Clipboard to System" msgstr "//Vágólap exportálása a rendszerbe" #: src/mainwindow.c:5381 msgid "//Choose Pattern ..." msgstr "//Minta kiválasztása ..." #: src/mainwindow.c:5383 msgid "//Choose Brush ..." msgstr "//Ecset kiválasztása ..." #: src/mainwindow.c:5385 msgid "//Choose Colour ..." msgstr "" #: src/mainwindow.c:5392 msgid "/_View" msgstr "/_Nézet" #: src/mainwindow.c:5394 msgid "//Show Main Toolbar" msgstr "//FÅ‘ eszköztár megjelenítése" #: src/mainwindow.c:5396 msgid "//Show Tools Toolbar" msgstr "//Eszközök eszköztár megjelenítése" #: src/mainwindow.c:5399 msgid "//Show Settings Toolbar" msgstr "//Beállítások eszköztár megjelenítése" #: src/mainwindow.c:5402 msgid "//Show Dock" msgstr "//Dokk megjelenítése" #: src/mainwindow.c:5404 msgid "//Show Palette" msgstr "//Paletta megjelenítése" #: src/mainwindow.c:5406 msgid "//Show Status Bar" msgstr "//Ãllapotsor megjelenítése" #: src/mainwindow.c:5409 msgid "//Toggle Image View" msgstr "//Kép nézetre váltás" #: src/mainwindow.c:5413 msgid "//Centralize Image" msgstr "//Kép központosítása" #: src/mainwindow.c:5414 msgid "//Show Zoom Grid" msgstr "//Nagyításrács megjelenítése" #: src/mainwindow.c:5415 msgid "//Snap To Tile Grid" msgstr "" #: src/mainwindow.c:5417 msgid "//Configure Grid ..." msgstr "//Rács beállítása ..." #: src/mainwindow.c:5418 msgid "//Tracing Image ..." msgstr "" #: src/mainwindow.c:5421 msgid "//View Window" msgstr "//Nézet ablak" #: src/mainwindow.c:5423 msgid "//Horizontal Split" msgstr "//Vízszintes felosztás" #: src/mainwindow.c:5425 msgid "//Focus View Window" msgstr "" #: src/mainwindow.c:5427 msgid "//Pan Window" msgstr "" #: src/mainwindow.c:5430 msgid "//Layers Window" msgstr "//Rétegek ablak" #: src/mainwindow.c:5433 msgid "/_Image" msgstr "/_Kép" #: src/mainwindow.c:5436 msgid "//Convert To RGB" msgstr "//Konvertálás RGB-be" #: src/mainwindow.c:5438 msgid "//Convert To Indexed ..." msgstr "//Konvertálás indexeltbe ..." #: src/mainwindow.c:5441 msgid "//Scale Canvas ..." msgstr "//Vászon nyújtása ..." #: src/mainwindow.c:5443 msgid "//Resize Canvas ..." msgstr "//Vászon átméretezése ..." #: src/mainwindow.c:5445 msgid "//Crop" msgstr "//Levágás" #: src/mainwindow.c:5448 src/mainwindow.c:5517 msgid "//Flip Vertically" msgstr "//FüggÅ‘leges tökrözés" #: src/mainwindow.c:5449 src/mainwindow.c:5519 msgid "//Flip Horizontally" msgstr "//Vízszintes tükrözés" #: src/mainwindow.c:5452 src/mainwindow.c:5521 msgid "//Rotate Clockwise" msgstr "//Forgatás jobbra" #: src/mainwindow.c:5453 src/mainwindow.c:5523 msgid "//Rotate Anti-Clockwise" msgstr "//Forgatás balra" #: src/mainwindow.c:5454 msgid "//Free Rotate ..." msgstr "//Forgatás szabadon ..." #: src/mainwindow.c:5455 msgid "//Skew ..." msgstr "//Döntés ..." #: src/mainwindow.c:5458 msgid "//Segment ..." msgstr "" #: src/mainwindow.c:5462 msgid "//Script ..." msgstr "" #: src/mainwindow.c:5464 msgid "//Scripts" msgstr "" #: src/mainwindow.c:5491 msgid "//Information ..." msgstr "//Információ ..." #: src/mainwindow.c:5494 msgid "//Preferences ..." msgstr "//Beállítások ..." #: src/mainwindow.c:5497 msgid "/_Selection" msgstr "/Ki_jelölés" #: src/mainwindow.c:5499 msgid "//Select All" msgstr "//Mindent kijelöl" #: src/mainwindow.c:5501 msgid "//Select None (Esc)" msgstr "//Kijelölés megszüntetése (Esc)" #: src/mainwindow.c:5503 msgid "//Lasso Selection" msgstr "//Lasszókijelölés" #: src/mainwindow.c:5505 msgid "//Lasso Selection Cut" msgstr "" #: src/mainwindow.c:5508 msgid "//Outline Selection" msgstr "" #: src/mainwindow.c:5510 msgid "//Fill Selection" msgstr "" #: src/mainwindow.c:5512 msgid "//Outline Ellipse" msgstr "" #: src/mainwindow.c:5514 msgid "//Fill Ellipse" msgstr "" #: src/mainwindow.c:5526 msgid "//Horizontal Ramp" msgstr "" #: src/mainwindow.c:5528 msgid "//Vertical Ramp" msgstr "" #: src/mainwindow.c:5531 msgid "//Alpha Blend A,B" msgstr "" #: src/mainwindow.c:5533 msgid "//Move Alpha to Mask" msgstr "" #: src/mainwindow.c:5535 msgid "//Mask Colour A,B" msgstr "" #: src/mainwindow.c:5537 msgid "//Unmask Colour A,B" msgstr "" #: src/mainwindow.c:5539 msgid "//Mask All Colours" msgstr "" #: src/mainwindow.c:5541 msgid "//Clear Mask" msgstr "//Maszk törlése" #: src/mainwindow.c:5544 msgid "/_Palette" msgstr "/_Paletta" #: src/mainwindow.c:5548 src/mainwindow.c:5626 msgid "//Load ..." msgstr "//Betöltés ..." #: src/mainwindow.c:5550 msgid "//Load Default" msgstr "//Alapértelmezett betöltése" #: src/mainwindow.c:5552 msgid "//Mask All" msgstr "" #: src/mainwindow.c:5553 msgid "//Mask None" msgstr "//Nincs maszkolás" #: src/mainwindow.c:5555 msgid "//Swap A & B" msgstr "//A és B felcserélése" #: src/mainwindow.c:5557 msgid "//Edit Colour A & B ..." msgstr "//Szín A & B szerkesztése" #: src/mainwindow.c:5559 msgid "//Dither A" msgstr "" #: src/mainwindow.c:5561 msgid "//Palette Editor ..." msgstr "//PalettaszerkesztÅ‘ ..." #: src/mainwindow.c:5563 msgid "//Set Palette Size ..." msgstr "//Palettaméret megadása ..." #: src/mainwindow.c:5564 msgid "//Merge Duplicate Colours" msgstr "//Duplikált színek egyesítése" #: src/mainwindow.c:5566 msgid "//Remove Unused Colours" msgstr "//Nem használt színek eltávolítása" #: src/mainwindow.c:5569 msgid "//Create Quantized ..." msgstr "" #: src/mainwindow.c:5572 msgid "//Sort Colours ..." msgstr "//Színek rendezése ..." #: src/mainwindow.c:5573 msgid "//Palette Shifter ..." msgstr "//Palettaváltó" #: src/mainwindow.c:5574 msgid "//Pick Gradient ..." msgstr "" #: src/mainwindow.c:5576 msgid "/Effe_cts" msgstr "/_Hatások" #: src/mainwindow.c:5578 msgid "//Transform Colour ..." msgstr "//Színtranszformáció ..." #: src/mainwindow.c:5580 msgid "//Invert" msgstr "//Negatív" #: src/mainwindow.c:5582 msgid "//Greyscale" msgstr "//Szürkeárnyalatos" #: src/mainwindow.c:5584 msgid "//Greyscale (Gamma corrected)" msgstr "//Szürkeárnyalatos (Gamma korrigált)" #: src/mainwindow.c:5586 msgid "//Normalize" msgstr "" #: src/mainwindow.c:5587 src/mainwindow.c:5658 msgid "//Threshold ..." msgstr "//Küszöb ..." #: src/mainwindow.c:5588 msgid "//Map ..." msgstr "" #: src/mainwindow.c:5590 msgid "//Isometric Transformation" msgstr "//Izometrikus transformáció" #: src/mainwindow.c:5592 msgid "///Left Side Down" msgstr "///Bal oldal lefelé" #: src/mainwindow.c:5593 msgid "///Right Side Down" msgstr "///Jobb oldal lefelé" #: src/mainwindow.c:5594 msgid "///Top Side Right" msgstr "///FelsÅ‘ rész jobbra" #: src/mainwindow.c:5595 msgid "///Bottom Side Right" msgstr "///Alsó rész jobbra" #: src/mainwindow.c:5598 msgid "//Edge Detect ..." msgstr "//Szélek keresése ..." #: src/mainwindow.c:5600 msgid "//Difference of Gaussians ..." msgstr "" #: src/mainwindow.c:5602 msgid "//Sharpen ..." msgstr "//Élesítés ..." #: src/mainwindow.c:5604 msgid "//Unsharp Mask ..." msgstr "" #: src/mainwindow.c:5606 msgid "//Soften ..." msgstr "" #: src/mainwindow.c:5608 msgid "//Gaussian Blur ..." msgstr "//Gauss-elmosás ..." #: src/mainwindow.c:5610 msgid "//Kuwahara-Nagao Blur ..." msgstr "//Kuwahara-Nagao elmosás ..." #: src/mainwindow.c:5612 msgid "//Emboss" msgstr "//Domborítás" #: src/mainwindow.c:5614 msgid "//Dilate" msgstr "" #: src/mainwindow.c:5616 msgid "//Erode" msgstr "//Erodál" #: src/mainwindow.c:5619 msgid "//Solid Noise ..." msgstr "" #: src/mainwindow.c:5620 msgid "//Bacteria ..." msgstr "//Baktérium ..." #: src/mainwindow.c:5623 msgid "/Cha_nnels" msgstr "/_Csatornák" #: src/mainwindow.c:5625 msgid "//New ..." msgstr "//Új ..." #: src/mainwindow.c:5628 msgid "//Delete ..." msgstr "//Törlés ..." #: src/mainwindow.c:5632 msgid "//Edit Image" msgstr "//Kép szerkesztése" #: src/mainwindow.c:5635 msgid "//Edit Alpha" msgstr "//Alfa szerkesztése" #: src/mainwindow.c:5638 msgid "//Edit Selection" msgstr "//Kijelölés szerkesztése" #: src/mainwindow.c:5641 msgid "//Edit Mask" msgstr "//Maszk szerkesztése" #: src/mainwindow.c:5645 msgid "//Hide Image" msgstr "//Kép elrejtése" #: src/mainwindow.c:5648 msgid "//Disable Alpha" msgstr "//Alfa tiltása" #: src/mainwindow.c:5651 msgid "//Disable Selection" msgstr "//Kijelölés tiltása" #: src/mainwindow.c:5654 msgid "//Disable Mask" msgstr "//Maszk tiltása" #: src/mainwindow.c:5657 msgid "//Couple RGBA Operations" msgstr "" #: src/mainwindow.c:5659 msgid "//Unassociate Alpha" msgstr "" #: src/mainwindow.c:5663 msgid "//View Alpha as an Overlay" msgstr "" #: src/mainwindow.c:5664 msgid "//Configure Overlays ..." msgstr "" #: src/mainwindow.c:5666 msgid "/_Layers" msgstr "/_Rétegek" #: src/mainwindow.c:5668 msgid "//New Layer" msgstr "//Új réteg" #: src/mainwindow.c:5672 msgid "//Save Composite Image ..." msgstr "//Kompozitkép mentése ..." #: src/mainwindow.c:5673 msgid "//Composite to New Layer" msgstr "//Kompozitot új réteggé" #: src/mainwindow.c:5674 msgid "//Remove All Layers" msgstr "//Minden réteg eltávolítása" #: src/mainwindow.c:5676 msgid "//Configure Animation ..." msgstr "//Animáció beállítása ..." #: src/mainwindow.c:5677 msgid "//Preview Animation ..." msgstr "//Animáció elÅ‘nézete ..." #: src/mainwindow.c:5678 msgid "//Set Key Frame ..." msgstr "//Kulcskocka megadása ..." #: src/mainwindow.c:5679 msgid "//Remove All Key Frames ..." msgstr "//Minden kulcskocka eltávolítása ..." #: src/mainwindow.c:5681 msgid "/More..." msgstr "/Továbbiak..." #: src/mainwindow.c:5683 msgid "/_Help" msgstr "/_Súgó" #: src/mainwindow.c:5684 msgid "//Documentation" msgstr "//Dokumentáció" #: src/mainwindow.c:5686 msgid "//About" msgstr "//Névjegy" #: src/mainwindow.c:5689 msgid "//Keyboard Shortcuts ..." msgstr "" #: src/mainwindow.c:5690 msgid "//Rebind Shortcut Keycodes" msgstr "//Gyorsbillentyűk újrakötése" #: src/memory.c:2800 msgid "Quantize Pass 1" msgstr "" #: src/memory.c:2854 msgid "Quantize Pass 2" msgstr "" #: src/memory.c:3073 src/memory.c:3458 msgid "Converting to Indexed Palette" msgstr "Konvertálás indexelt palettára" #: src/memory.c:5135 src/otherwindow.c:540 msgid "Bacteria Effect" msgstr "Baktérium hatás" #: src/memory.c:5170 msgid "Rotating" msgstr "Forgatás" #: src/memory.c:5511 msgid "Free Rotation" msgstr "Szabad forgatás" #: src/memory.c:6096 msgid "Scaling Image" msgstr "Kép nyújtása" #: src/memory.c:7560 msgid "Counting Unique RGB Pixels" msgstr "Egyedi RGB képpontok megszámolása" #: src/memory.c:7608 msgid "Applying Effect" msgstr "Hatás alkalmazása" #: src/memory.c:8792 msgid "Kuwahara-Nagao Filter" msgstr "Kuwahara-Nagao szűrÅ‘" #: src/memory.c:10456 src/otherwindow.c:2665 msgid "Skew" msgstr "Döntés" #: src/memory.c:10630 msgid "Segmentation Pass 1" msgstr "" #: src/memory.c:10757 msgid "Segmentation Pass 2" msgstr "" #: src/memory.c:11019 src/otherwindow.c:3156 msgid "Solid Noise" msgstr "" #: src/mygtk.c:134 src/mygtk.c:163 msgid "Please Wait ..." msgstr "Kérem várjon ..." #: src/mygtk.c:141 msgid "STOP" msgstr "STOP" #: src/mygtk.c:504 msgid "Disabled" msgstr "" #: src/mygtk.c:504 src/toolbar.c:301 msgid "Screen" msgstr "" #: src/mygtk.c:504 msgid "Window" msgstr "" #: src/mygtk.c:508 msgid "Input" msgstr "" #: src/mygtk.c:512 msgid "Device:" msgstr "" #: src/mygtk.c:514 msgid "Mode:" msgstr "" #: src/mygtk.c:519 msgid "Axes" msgstr "" #: src/mygtk.c:524 msgid "X:" msgstr "" #: src/mygtk.c:525 msgid "Y:" msgstr "" #: src/mygtk.c:526 msgid "Pressure:" msgstr "" #: src/mygtk.c:527 msgid "X tilt:" msgstr "" #: src/mygtk.c:528 msgid "Y tilt:" msgstr "" #: src/mygtk.c:529 msgid "Wheel:" msgstr "" #: src/mygtk.c:579 msgid "none" msgstr "" #: src/otherwindow.c:236 msgid "24 bit RGB" msgstr "24 bites RGB" #: src/otherwindow.c:236 src/otherwindow.c:3179 msgid "Greyscale" msgstr "Szürkeárnyalatos" #: src/otherwindow.c:237 msgid "Indexed Palette" msgstr "Indexelt paletta" #: src/otherwindow.c:237 msgid "From Clipboard" msgstr "Vágólapról" #: src/otherwindow.c:237 msgid "Grab Screenshot" msgstr "KépernyÅ‘kép rögzítése" #: src/otherwindow.c:242 src/toolbar.c:542 msgid "New Image" msgstr "Új kép" #: src/otherwindow.c:246 src/otherwindow.c:3164 msgid "Colours" msgstr "Színek" #: src/otherwindow.c:409 msgid "Pattern Chooser" msgstr "Mintaválasztó" #: src/otherwindow.c:497 msgid "Set Palette Size" msgstr "Palettaméret megadása" #: src/otherwindow.c:517 src/otherwindow.c:591 src/otherwindow.c:870 #: src/otherwindow.c:2538 src/otherwindow.c:2776 src/otherwindow.c:2939 #: src/prefs.c:338 src/prefs.c:538 msgid "Apply" msgstr "Alkalmaz" #: src/otherwindow.c:573 msgid "Luminance" msgstr "Luminancia" #: src/otherwindow.c:573 src/otherwindow.c:814 msgid "Brightness" msgstr "FényerÅ‘" #: src/otherwindow.c:574 msgid "Distance to A" msgstr "" #: src/otherwindow.c:575 msgid "Projection to A->B" msgstr "" #: src/otherwindow.c:576 msgid "Frequency" msgstr "Frekvencia" #: src/otherwindow.c:580 msgid "Sort Palette Colours" msgstr "Palettaszínek rendezése" #: src/otherwindow.c:582 msgid "Start Index" msgstr "KezdÅ‘ index" #: src/otherwindow.c:583 msgid "End Index" msgstr "Vég index" #: src/otherwindow.c:589 msgid "Reverse Order" msgstr "Fordított sorrend" #: src/otherwindow.c:805 msgid "Bitwise" msgstr "" #: src/otherwindow.c:805 msgid "Truncated" msgstr "" #: src/otherwindow.c:805 msgid "Rounded" msgstr "" #: src/otherwindow.c:809 src/toolbar.c:311 src/toolbar.c:558 msgid "Transform Colour" msgstr "Színtraszformáció" #: src/otherwindow.c:812 msgid "Gamma" msgstr "Gamma" #: src/otherwindow.c:816 msgid "Contrast" msgstr "Kontraszt" #: src/otherwindow.c:822 src/otherwindow.c:1674 msgid "Posterize" msgstr "Poszterizálás" #: src/otherwindow.c:831 msgid "Show Detail" msgstr "Részletek megjelenítése" #: src/otherwindow.c:836 msgid "Posterize type" msgstr "" #: src/otherwindow.c:857 msgid "Auto-Preview" msgstr "Automatikus elÅ‘nézet" #: src/otherwindow.c:869 msgid "Reset" msgstr "Visszaállítás" #: src/otherwindow.c:931 msgid "New geometry is the same as now - nothing to do." msgstr "Az új geometria megegyzik a mostanival - nincs mit tenni." #: src/otherwindow.c:980 msgid "The operating system cannot allocate the memory for this operation." msgstr "" "Az operációs rendszer nem tudott memóriát lefoglalni ehhez a művelethez." #: src/otherwindow.c:982 msgid "" "You have not allocated enough memory in the Preferences window for this " "operation." msgstr "" "Nem foglalt le elég memóriát ehhez a művelethez a Beállítások ablakban." #: src/otherwindow.c:993 src/otherwindow.c:2495 msgid "Mirror" msgstr "Tükrözés" #: src/otherwindow.c:993 src/otherwindow.c:994 msgid "Tile" msgstr "Csempe" #: src/otherwindow.c:993 msgid "Void" msgstr "" #: src/otherwindow.c:994 src/shifter.c:283 msgid "Clear" msgstr "" #: src/otherwindow.c:994 msgid "Mirror tile" msgstr "" #: src/otherwindow.c:996 msgid "Nearest Neighbour" msgstr "Legközelebbi szomszéd" #: src/otherwindow.c:997 msgid "Bilinear / Area Mapping" msgstr "Bilineáris / Area Mapping" #: src/otherwindow.c:998 msgid "Bicubic" msgstr "" #: src/otherwindow.c:999 msgid "Bicubic edged" msgstr "" #: src/otherwindow.c:1000 msgid "Bicubic better" msgstr "" #: src/otherwindow.c:1001 msgid "Bicubic sharper" msgstr "" #: src/otherwindow.c:1002 msgid "Blackman-Harris" msgstr "Blackman-Harris" #: src/otherwindow.c:1008 msgid "Scale Canvas" msgstr "Vászon nyújtása" #: src/otherwindow.c:1009 msgid "Resize Canvas" msgstr "Vászon átméretezése" #: src/otherwindow.c:1012 msgid "Original " msgstr "Eredeti " #: src/otherwindow.c:1013 msgid "New" msgstr "Új" #: src/otherwindow.c:1014 msgid "Width " msgstr "Szélesség " #: src/otherwindow.c:1018 msgid "Height " msgstr "Magasság " #: src/otherwindow.c:1023 src/otherwindow.c:2514 src/otherwindow.c:2672 #: src/toolbar.c:212 msgid "Offset" msgstr "Eltolás" #: src/otherwindow.c:1026 src/otherwindow.c:1615 src/viewer.c:1209 msgid "Centre" msgstr "Közép" #: src/otherwindow.c:1033 src/otherwindow.c:1052 msgid "Fix Aspect Ratio" msgstr "Méretarány megtartása" #: src/otherwindow.c:1039 src/otherwindow.c:2070 src/toolbar.c:312 msgid "Settings" msgstr "Beállítások" #: src/otherwindow.c:1046 msgid "Sharper image reduction" msgstr "" #: src/otherwindow.c:1047 msgid "Boundary extension" msgstr "" #: src/otherwindow.c:1613 src/otherwindow.c:2302 msgid "HSV" msgstr "HSV" #: src/otherwindow.c:1614 msgid "Highlight" msgstr "" #: src/otherwindow.c:1615 msgid "Limit" msgstr "Határ" #: src/otherwindow.c:1616 msgid "Sphere" msgstr "Gömb" #: src/otherwindow.c:1616 src/otherwindow.c:2670 msgid "Angle" msgstr "Fok" #: src/otherwindow.c:1616 msgid "Cube" msgstr "Kocka" #: src/otherwindow.c:1617 msgid "Opaque" msgstr "Ãtlátszatlan" #: src/otherwindow.c:1617 msgid "Border" msgstr "Szegély" #: src/otherwindow.c:1618 msgid "Transparent" msgstr "Ãtlátszó" #: src/otherwindow.c:1618 msgid "Tile " msgstr "Csempe " #: src/otherwindow.c:1618 msgid "Segment" msgstr "" #: src/otherwindow.c:1656 msgid "Scale" msgstr "Nyújtás" #: src/otherwindow.c:1657 src/otherwindow.c:3059 msgid "From" msgstr "" #: src/otherwindow.c:1659 src/otherwindow.c:3061 msgid "To" msgstr "" #: src/otherwindow.c:1699 msgid "Range" msgstr "" #: src/otherwindow.c:1702 msgid "Inverse" msgstr "" #: src/otherwindow.c:1710 msgid "Smart grid" msgstr "Inteligens rács" #: src/otherwindow.c:1712 msgid "Tile grid" msgstr "Csempe rács" #: src/otherwindow.c:1714 msgid "Minimum grid zoom" msgstr "Minimális rács nagyítás" #: src/otherwindow.c:1717 msgid "Tile width" msgstr "Csempeszélesség" #: src/otherwindow.c:1720 msgid "Tile height" msgstr "Csempemagasság" #: src/otherwindow.c:1744 msgid "Palette Editor" msgstr "Paletta szerkesztÅ‘" #: src/otherwindow.c:1763 msgid "Configure Overlays" msgstr "" #: src/otherwindow.c:1782 msgid "Colour Editor" msgstr "SzínszerkesztÅ‘" #: src/otherwindow.c:1818 src/toolbar.c:430 msgid "Colour-Selective Mode" msgstr "" #: src/otherwindow.c:1843 msgid "Configure Grid" msgstr "Rács beállítása" #: src/otherwindow.c:2045 msgid "Exact Conversion" msgstr "" #: src/otherwindow.c:2045 msgid "Use Current Palette" msgstr "Aktuális paletta használata" #: src/otherwindow.c:2046 msgid "PNN Quantize (slow, better quality)" msgstr "PNN kvantálás (lassú, de jobb minÅ‘ség)" #: src/otherwindow.c:2047 msgid "Wu Quantize (fast)" msgstr "Wu kvantálás (gyors)" # fuzzy #: src/otherwindow.c:2048 msgid "Max-Min Quantize (best for small palettes and dithering)" msgstr "Max-Min kvantálás (best for small palettes and dithering)" #: src/otherwindow.c:2049 src/otherwindow.c:2495 src/otherwindow.c:2756 #: src/png.c:2794 src/prefs.c:377 msgid "None" msgstr "Nincs" #: src/otherwindow.c:2049 msgid "Floyd-Steinberg" msgstr "Floyd-Steinberg" #: src/otherwindow.c:2049 msgid "Stucki" msgstr "Stucki" #: src/otherwindow.c:2052 msgid "Floyd-Steinberg (quick)" msgstr "Floyd-Steinberg (gyors)" #: src/otherwindow.c:2052 msgid "Dithered (effect)" msgstr "" #: src/otherwindow.c:2053 msgid "Scattered (effect)" msgstr "" #: src/otherwindow.c:2054 msgid "Gamut" msgstr "" #: src/otherwindow.c:2054 msgid "Weakly" msgstr "" #: src/otherwindow.c:2054 msgid "Strongly" msgstr "" #: src/otherwindow.c:2055 msgid "Off" msgstr "" #: src/otherwindow.c:2055 msgid "Separate/Sum" msgstr "" #: src/otherwindow.c:2055 msgid "Separate/Split" msgstr "" #: src/otherwindow.c:2056 msgid "Length/Sum" msgstr "" #: src/otherwindow.c:2056 msgid "Length/Split" msgstr "" #: src/otherwindow.c:2057 msgid "Largest (Linf)" msgstr "" #: src/otherwindow.c:2057 msgid "Sum (L1)" msgstr "" #: src/otherwindow.c:2057 msgid "Euclidean (L2)" msgstr "" #: src/otherwindow.c:2061 msgid "Create Quantized" msgstr "" #: src/otherwindow.c:2062 msgid "Convert To Indexed" msgstr "" #: src/otherwindow.c:2065 msgid "Indexed Colours To Use" msgstr "" #: src/otherwindow.c:2078 msgid "Truncate palette" msgstr "" #: src/otherwindow.c:2079 msgid "Diameter based weighting" msgstr "" #: src/otherwindow.c:2084 msgid "Dither" msgstr "" #: src/otherwindow.c:2087 src/otherwindow.c:2584 src/otherwindow.c:2928 msgid "Colour space" msgstr "" #: src/otherwindow.c:2088 src/otherwindow.c:2929 msgid "Difference measure" msgstr "" #: src/otherwindow.c:2089 msgid "Reduce colour bleed" msgstr "" #: src/otherwindow.c:2090 msgid "Serpentine scan" msgstr "" #: src/otherwindow.c:2092 msgid "Error propagation, %" msgstr "" #: src/otherwindow.c:2093 msgid "Selective error propagation" msgstr "" #: src/otherwindow.c:2097 msgid "Full error precision" msgstr "" #: src/otherwindow.c:2302 msgid "Backward HSV" msgstr "" #: src/otherwindow.c:2303 src/otherwindow.c:2326 msgid "Constant" msgstr "Konstans" #: src/otherwindow.c:2307 msgid "Edit Gradient" msgstr "Színátmenet szerkesztése" #: src/otherwindow.c:2329 msgid "Points:" msgstr "Pont:" #: src/otherwindow.c:2493 msgid "Linear" msgstr "Lineáris" #: src/otherwindow.c:2493 src/otherwindow.c:2703 msgid "Bilinear" msgstr "Bilineáris" #: src/otherwindow.c:2493 msgid "Radial" msgstr "Sugaras" #: src/otherwindow.c:2494 msgid "Square" msgstr "Négyzetes" #: src/otherwindow.c:2494 msgid "Angular" msgstr "Szögletes" #: src/otherwindow.c:2494 msgid "Conical" msgstr "Kúpos" #: src/otherwindow.c:2495 msgid "Level " msgstr "" #: src/otherwindow.c:2495 msgid "Repeat" msgstr "Ismétlés" #: src/otherwindow.c:2496 msgid "A to B" msgstr "A-ból B-be" #: src/otherwindow.c:2496 msgid "A to B (RGB)" msgstr "A-ból B-be (RGB)" #: src/otherwindow.c:2497 msgid "A to B (sRGB)" msgstr "" #: src/otherwindow.c:2497 msgid "A to B (HSV)" msgstr "A-ból B-be (HSV)" #: src/otherwindow.c:2497 msgid "A to B (backward HSV)" msgstr "A-ból B-be (fordított HSV)" #: src/otherwindow.c:2498 msgid "A only" msgstr "Csak A" #: src/otherwindow.c:2498 src/otherwindow.c:2500 msgid "Custom" msgstr "Egyéni" #: src/otherwindow.c:2499 msgid "Current to 0" msgstr "" #: src/otherwindow.c:2499 msgid "Current only" msgstr "Csak a jelenlegi" #: src/otherwindow.c:2504 msgid "Configure Gradient" msgstr "Színátmenet beállítása" #: src/otherwindow.c:2507 src/png.c:1001 msgid "Channel" msgstr "Csatorna" #: src/otherwindow.c:2512 msgid "Length" msgstr "Hossz" #: src/otherwindow.c:2513 msgid "Repeat length" msgstr "" #: src/otherwindow.c:2515 msgid "Gradient type" msgstr "Ãtmenet típus" #: src/otherwindow.c:2516 msgid "Extension type" msgstr "Kiterjesztés típus" #: src/otherwindow.c:2517 msgid "Distance type" msgstr "" #: src/otherwindow.c:2518 msgid "Preview opacity" msgstr "" #: src/otherwindow.c:2527 src/otherwindow.c:2533 src/toolbar.c:309 msgid "Reverse" msgstr "Fordított" #: src/otherwindow.c:2528 src/otherwindow.c:2534 msgid "Edit Custom" msgstr "" #: src/otherwindow.c:2592 msgid "Pick Gradient" msgstr "" #: src/otherwindow.c:2668 msgid "Horizontal " msgstr "Vízszintesi" #: src/otherwindow.c:2674 msgid "At distance" msgstr "" #: src/otherwindow.c:2675 msgid "Vertical" msgstr "FüggÅ‘leges" #: src/otherwindow.c:2756 msgid "Unchanged" msgstr "" #: src/otherwindow.c:2761 msgid "Tracing Image" msgstr "" #: src/otherwindow.c:2763 src/toolbar.c:315 msgid "Source" msgstr "Forrás" #: src/otherwindow.c:2768 msgid "Origin" msgstr "Kezdet" #: src/otherwindow.c:2771 msgid "Relative scale" msgstr "" #: src/otherwindow.c:2774 msgid "Display" msgstr "" #: src/otherwindow.c:2926 msgid "Segment Image" msgstr "" #: src/otherwindow.c:2931 src/toolbar.c:304 msgid "Threshold" msgstr "" #: src/otherwindow.c:2933 msgid "Level" msgstr "Szint" #: src/otherwindow.c:2934 msgid "Minimum size" msgstr "" #: src/otherwindow.c:3053 msgid "Max" msgstr "" #: src/otherwindow.c:3053 msgid "Min" msgstr "" #: src/otherwindow.c:3057 msgid "Threshold Image" msgstr "" #: src/otherwindow.c:3158 msgid "Seed" msgstr "" #: src/otherwindow.c:3160 msgid "X span" msgstr "" #: src/otherwindow.c:3161 msgid "Y span" msgstr "" #: src/otherwindow.c:3162 msgid "Octaves" msgstr "" #: src/png.c:620 #, c-format msgid "Saving %s image" msgstr "%s kép mentése" #: src/png.c:620 #, c-format msgid "Loading %s image" msgstr "%s kép betöltése" #: src/png.c:998 msgid "Layer" msgstr "Réteg" #: src/png.c:3577 msgid "Lossless" msgstr "" #: src/png.c:3577 msgid "Default" msgstr "" #: src/png.c:3577 msgid "Picture" msgstr "" #: src/png.c:3577 msgid "Photo" msgstr "" #: src/png.c:3578 msgid "Drawing" msgstr "" #: src/png.c:3578 msgid "Icon" msgstr "" #: src/png.c:8370 msgid "Applying colour profile" msgstr "" #: src/png.c:8792 #, c-format msgid "%d out of %d frames could not be saved as %s - saved as PNG instead" msgstr "" #: src/png.c:8809 msgid "Explode frames" msgstr "" #: src/prefs.c:56 msgid "Default System Language" msgstr "Alapértelmezett rendszer nyelv" #: src/prefs.c:57 msgid "Chinese (Simplified)" msgstr "Kínai (egyszerűsített)" #: src/prefs.c:57 msgid "Chinese (Taiwanese)" msgstr "Kínai (Taiwan)" #: src/prefs.c:57 msgid "Czech" msgstr "Cseh" #: src/prefs.c:58 msgid "Dutch" msgstr "Holland" #: src/prefs.c:58 msgid "English (UK)" msgstr "Angol (UK)" #: src/prefs.c:58 msgid "French" msgstr "Francia" #: src/prefs.c:58 msgid "Galician" msgstr "Galíciai" #: src/prefs.c:58 msgid "German" msgstr "Német" #: src/prefs.c:59 msgid "Hungarian" msgstr "" #: src/prefs.c:59 msgid "Italian" msgstr "Olasz" #: src/prefs.c:59 msgid "Japanese" msgstr "Japán" #: src/prefs.c:59 msgid "Kabyle" msgstr "" #: src/prefs.c:59 msgid "Polish" msgstr "Lengyel" #: src/prefs.c:60 msgid "Portuguese" msgstr "Portugál" #: src/prefs.c:60 msgid "Portuguese (Brazilian)" msgstr "Portugál (Brazil)" #: src/prefs.c:60 msgid "Russian" msgstr "Orosz" #: src/prefs.c:60 msgid "Slovak" msgstr "Szlovák" #: src/prefs.c:61 msgid "Spanish" msgstr "Spanyol" #: src/prefs.c:61 msgid "Swedish" msgstr "Svéd" #: src/prefs.c:61 msgid "Tagalog" msgstr "" #: src/prefs.c:61 msgid "Turkish" msgstr "Török" #: src/prefs.c:81 msgid "Current Device" msgstr "Aktuális eszköz" #: src/prefs.c:135 msgid "Pressure" msgstr "Nyomás" #: src/prefs.c:149 msgid "Preferences" msgstr "Beállítások" #: src/prefs.c:163 msgid "Max threads (0 to autodetect)" msgstr "" #: src/prefs.c:164 msgid "Min kpixels per render thread" msgstr "" #: src/prefs.c:171 msgid "Max memory used for undo (MB)" msgstr "Max memóriahasználat visszavonáshoz (MB)" #: src/prefs.c:172 msgid "Max undo levels" msgstr "Max visszavonás szint" #: src/prefs.c:173 msgid "Communal layer undo space (%)" msgstr "" #: src/prefs.c:175 msgid "Bayer master pattern" msgstr "" #: src/prefs.c:178 msgid "Use gamma correction by default" msgstr "Gammakorrekció használat alapértelmezetten" #: src/prefs.c:179 msgid "Use gamma correction when painting" msgstr "" #: src/prefs.c:180 msgid "Separate patterns for A & B" msgstr "" #: src/prefs.c:183 msgid "Optimize alpha chequers" msgstr "" #: src/prefs.c:184 msgid "Disable view window transparencies" msgstr "" #: src/prefs.c:185 msgid "Enable overlays by layer" msgstr "" #: src/prefs.c:189 msgid "Language" msgstr "Nyelv" #: src/prefs.c:191 msgid "" "Select preferred language translation\n" "\n" "You will need to restart mtPaint\n" "for this to take full effect" msgstr "" "Válassza ki a kívánt nyelvi fordítást\n" "\n" "Az mtPaint újraindítása szükséges\n" "a teljes hatás elérése érdekében." #: src/prefs.c:198 msgid "Interface" msgstr "Felület" #: src/prefs.c:200 msgid "Greyscale backdrop" msgstr "Szürkeárnyalatos háttér" #: src/prefs.c:201 msgid "Selection nudge pixels" msgstr "" #: src/prefs.c:202 msgid "Max Pan Window Size" msgstr "" #: src/prefs.c:204 msgid "Display clipboard while pasting" msgstr "" #: src/prefs.c:205 msgid "Mouse cursor = Tool" msgstr "Egérkurzor = Eszköz" #: src/prefs.c:206 msgid "Confirm Exit" msgstr "" #: src/prefs.c:207 msgid "Q key quits mtPaint" msgstr "Q billentyűvel kilép az mtPaint" #: src/prefs.c:208 msgid "Arrow keys scroll canvas" msgstr "" #: src/prefs.c:209 msgid "Changing tool commits paste" msgstr "" #: src/prefs.c:210 msgid "Centre tool settings dialogs" msgstr "" #: src/prefs.c:211 msgid "New image sets zoom to 100%" msgstr "" #: src/prefs.c:212 msgid "Zoom on cursor position" msgstr "" #: src/prefs.c:214 msgid "Mouse Scroll Wheel = Zoom" msgstr "EgérgörgÅ‘ = Nagyítás" #: src/prefs.c:215 msgid "Use menu icons" msgstr "" #: src/prefs.c:220 msgid "Files" msgstr "Fájlok" #: src/prefs.c:223 msgid "XBM X hotspot" msgstr "XBM X hotspot" #: src/prefs.c:224 msgid "XBM Y hotspot" msgstr "XBM Y hotspot" #: src/prefs.c:228 msgid "Recently Used Files" msgstr "Legutóbb használt fájlok" #: src/prefs.c:229 msgid "Progress bar silence limit" msgstr "" #: src/prefs.c:232 msgid "Read 16-bit TGAs as 5:6:5 BGR" msgstr "16-bites TGA-k beolvasása 5:6:5 BGR-ként" #: src/prefs.c:233 msgid "Write TGAs in bottom-up row order" msgstr "TGA-k írása lentrÅ‘l-fel sorrendben" #: src/prefs.c:234 msgid "Undoable image loading" msgstr "" #: src/prefs.c:245 msgid "Compression (RGB)" msgstr "" #: src/prefs.c:246 msgid "Compression (indexed)" msgstr "" #: src/prefs.c:247 msgid "Compression (monochrome)" msgstr "" #: src/prefs.c:255 msgid "Enable predictor" msgstr "" #: src/prefs.c:262 msgid "Compression mode" msgstr "" #: src/prefs.c:271 msgid "Channel for Mask Plane" msgstr "" #: src/prefs.c:273 msgid "Ignore Transparent Colour" msgstr "" #: src/prefs.c:274 msgid "PackBits Compression" msgstr "" #: src/prefs.c:275 msgid "Write Indexed as Planar Bitmap (PBM)" msgstr "" #: src/prefs.c:280 msgid "Paths" msgstr "Utak" #: src/prefs.c:281 msgid "Clipboard Files" msgstr "Vágólap fájlok" #: src/prefs.c:281 msgid "Select Clipboard File" msgstr "Vágólapfájl kiválasztása" #: src/prefs.c:283 msgid "HTML Browser Program" msgstr "HTML böngészÅ‘ program" #: src/prefs.c:283 msgid "Select Browser Program" msgstr "BöngészÅ‘ program kiválasztása" #: src/prefs.c:285 msgid "Location of Handbook index" msgstr "Kézikönyv index helye" #: src/prefs.c:285 msgid "Select Handbook Index File" msgstr "Kézikönyv index fájl kiválasztása" #: src/prefs.c:287 msgid "Default Palette" msgstr "Alapértelmezett paletta" #: src/prefs.c:287 msgid "Select Default Palette" msgstr "Alapértelmezett paletta kiválasztása" #: src/prefs.c:289 msgid "Default Patterns" msgstr "Alapértelmezett minták" #: src/prefs.c:289 msgid "Select Default Patterns File" msgstr "Alapértelmezett mintafájlok kiválasztása" #: src/prefs.c:292 msgid "Default CSS" msgstr "" #: src/prefs.c:292 msgid "Select Default CSS File" msgstr "" #: src/prefs.c:295 msgid "Default Theme" msgstr "" #: src/prefs.c:295 msgid "Select Default Theme File" msgstr "" #: src/prefs.c:300 msgid "Status Bar" msgstr "Ãllapotsor" #: src/prefs.c:301 msgid "Canvas Geometry" msgstr "Vászon geometria" #: src/prefs.c:302 msgid "Cursor X,Y" msgstr "Kurzor X,Y" #: src/prefs.c:303 msgid "Pixel [I] {RGB}" msgstr "Pixel [I] {RGB}" #: src/prefs.c:304 msgid "Selection Geometry" msgstr "Kijelölés geometria" #: src/prefs.c:305 msgid "Undo / Redo" msgstr "Visszavonás / Újra" #: src/prefs.c:308 msgid "Tablet" msgstr "Tábla" #: src/prefs.c:309 msgid "Device Settings" msgstr "Eszközbeállítások" #: src/prefs.c:313 msgid "Configure Device" msgstr "Eszköz beállítása" #: src/prefs.c:319 msgid "Tool Variable" msgstr "Eszközváltozó" #: src/prefs.c:322 src/toolbar.c:454 msgid "Flow" msgstr "" #: src/prefs.c:330 msgid "Test Area" msgstr "Teszt terület" #: src/prefs.c:373 msgid "Factor" msgstr "Faktor" #: src/prefs.c:459 msgid "This key is builtin" msgstr "" #: src/prefs.c:462 #, c-format msgid "" "This key is mapped to:\n" "\"%s\"" msgstr "" #: src/prefs.c:465 msgid "Remap" msgstr "" #: src/prefs.c:510 msgid "Keyboard Shortcuts" msgstr "" #: src/shifter.c:147 msgid "Frames" msgstr "Keretek" #: src/shifter.c:258 msgid "Palette Shifter" msgstr "Palettaváltó" #: src/shifter.c:263 msgid "Start" msgstr "Start" #: src/shifter.c:265 msgid "Finish" msgstr "Kész" #: src/shifter.c:284 msgid "Fix Palette" msgstr "" #: src/spawn.c:651 msgid "Configure File Actions" msgstr "" #: src/spawn.c:657 src/spawn.c:663 msgid "Command" msgstr "Parancs" #: src/spawn.c:922 #, c-format msgid "Error %i reported when trying to run %s" msgstr "" #: src/spawn.c:979 msgid "" "I am unable to find the documentation. Either you need to download the " "mtPaint Handbook from the web site and install it, or you need to set the " "correct location in the Preferences window." msgstr "" #: src/spawn.c:1018 msgid "" "There was a problem running the HTML browser. You need to set the correct " "program name in the Preferences window." msgstr "" "Probléma történt a HTML böngészÅ‘ futtatásakor. Ãllítsa be a megfelelÅ‘ " "program nevét a Beállítások ablakban." #: src/thread.c:361 msgid "Helper thread is not responding. Save your work and exit the program." msgstr "" #: src/toolbar.c:147 msgid "RGB Cube" msgstr "RGB kocka" #: src/toolbar.c:148 msgid "By image channel" msgstr "" #: src/toolbar.c:149 msgid "Gradient-driven" msgstr "" #: src/toolbar.c:157 msgid "Fill settings" msgstr "" #: src/toolbar.c:170 msgid "Respect opacity mode" msgstr "" #: src/toolbar.c:176 msgid "Smudge settings" msgstr "" #: src/toolbar.c:215 msgid "Aligned" msgstr "" #: src/toolbar.c:222 msgid "Clone settings" msgstr "" #: src/toolbar.c:228 msgid "By selection channel" msgstr "" #: src/toolbar.c:234 msgid "Lasso settings" msgstr "" #: src/toolbar.c:252 msgid "Brush spacing" msgstr "" #: src/toolbar.c:299 src/toolbar.c:341 msgid "Normal" msgstr "Normál" #: src/toolbar.c:300 msgid "Colour" msgstr "Szín" #: src/toolbar.c:300 msgid "Saturate More" msgstr "" #: src/toolbar.c:301 msgid "Multiply" msgstr "" #: src/toolbar.c:301 msgid "Divide" msgstr "" #: src/toolbar.c:301 msgid "Dodge" msgstr "" #: src/toolbar.c:302 msgid "Burn" msgstr "" #: src/toolbar.c:302 msgid "Hard Light" msgstr "" #: src/toolbar.c:302 msgid "Soft Light" msgstr "" #: src/toolbar.c:302 msgid "Difference" msgstr "" #: src/toolbar.c:303 msgid "Darken" msgstr "" #: src/toolbar.c:303 msgid "Lighten" msgstr "" #: src/toolbar.c:303 msgid "Grain Extract" msgstr "" #: src/toolbar.c:304 msgid "Grain Merge" msgstr "" #: src/toolbar.c:330 msgid "Blend mode" msgstr "" #: src/toolbar.c:417 msgid "Continuous Mode" msgstr "" #: src/toolbar.c:421 msgid "Opacity Mode" msgstr "" #: src/toolbar.c:424 msgid "Tint Mode" msgstr "" #: src/toolbar.c:427 msgid "Tint +-" msgstr "" #: src/toolbar.c:434 msgid "Blend Mode" msgstr "" #: src/toolbar.c:438 msgid "Disable All Masks" msgstr "Minden maszk tiltása" #: src/toolbar.c:441 msgid "Gradient Mode" msgstr "" #: src/toolbar.c:486 msgid "Settings Toolbar" msgstr "" #: src/toolbar.c:546 msgid "Cut" msgstr "Kivágás" #: src/toolbar.c:548 msgid "Copy" msgstr "Másolás" #: src/toolbar.c:550 msgid "Paste" msgstr "Beillesztés" #: src/toolbar.c:553 msgid "Undo" msgstr "Visszavonás" #: src/toolbar.c:555 msgid "Redo" msgstr "Újra" #: src/toolbar.c:559 src/viewer.c:328 msgid "Pan Window" msgstr "" #: src/toolbar.c:560 src/toolbar.c:640 msgid "More..." msgstr "" #: src/toolbar.c:574 msgid "Paint" msgstr "Festés" #: src/toolbar.c:580 msgid "Shuffle" msgstr "Keverés" #: src/toolbar.c:583 msgid "Flood Fill" msgstr "Kitöltés" #: src/toolbar.c:587 msgid "Straight Line" msgstr "Egyenes vonal" #: src/toolbar.c:590 msgid "Smudge" msgstr "" #: src/toolbar.c:594 msgid "Clone" msgstr "Klón" #: src/toolbar.c:597 msgid "Make Selection" msgstr "Kijelölés készítése" #: src/toolbar.c:600 msgid "Polygon Selection" msgstr "Poligonkijelölés" #: src/toolbar.c:603 msgid "Place Gradient" msgstr "Színátmenet elhelyezése" #: src/toolbar.c:606 msgid "Lasso Selection" msgstr "Lassszókijelölés" #: src/toolbar.c:614 msgid "Ellipse Outline" msgstr "Ellipszis körvonal" #: src/toolbar.c:617 msgid "Filled Ellipse" msgstr "Ellipszis kitöltés" #: src/toolbar.c:620 msgid "Outline Selection" msgstr "Kijelölés körberajzolása" #: src/toolbar.c:623 msgid "Fill Selection" msgstr "Kijelölés kitöltése" #: src/toolbar.c:627 msgid "Flip Selection Vertically" msgstr "Kijelölés tükrözése függÅ‘legesen" #: src/toolbar.c:630 msgid "Flip Selection Horizontally" msgstr "Kijelölés tükrözése vízszintesen" #: src/toolbar.c:633 msgid "Rotate Selection Clockwise" msgstr "Kijelölés forgatása jobbra" #: src/toolbar.c:636 msgid "Rotate Selection Anti-Clockwise" msgstr "KijelÅ‘lés forgatása balra" #: src/vcode.c:5201 msgid "Browse" msgstr "Tallózás" #: src/vcode.c:7886 msgid "New key ..." msgstr "" #: src/vcode.c:9909 #, c-format msgid "'%s' does not match any widget" msgstr "" #: src/vcode.c:9910 #, c-format msgid "'%s' value does not fit '%s' widget" msgstr "" #: src/viewer.c:115 msgid "About" msgstr "Névjegy" #: src/viewer.c:1179 msgid "No font selected" msgstr "" #: src/viewer.c:1209 msgid "Left" msgstr "" #: src/viewer.c:1209 msgid "Right" msgstr "" #~ msgid "File: %s invalid - palette not updated" #~ msgstr "Fájl: %s érvénytelen - a paletta nem lett frissítve" mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/po/it.po000066400000000000000000002745751471325446300215710ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # msgid "" msgstr "" "Project-Id-Version: mtpaint-3.51\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-01-04 21:31+0200\n" "PO-Revision-Date: 2009-11-29 21:20+0800\n" "Last-Translator: angelo gemmi \n" "Language-Team: LANGUAGE \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Language: Italian\n" "X-Poedit-Country: Italy\n" #: src/ani.c:647 msgid "Animation Preview" msgstr "Anteprima Animazione" #: src/ani.c:650 src/shifter.c:275 msgid "Play" msgstr "Riproduci" #: src/ani.c:654 msgid "Fix" msgstr "Correggi" #: src/ani.c:655 src/ani.c:1005 src/font.c:1624 src/font.c:1643 #: src/shifter.c:286 src/viewer.c:97 msgid "Close" msgstr "Chiudi" #: src/ani.c:709 src/ani.c:812 src/ani.c:1022 src/ani.c:1028 src/canvas.c:356 #: src/canvas.c:708 src/canvas.c:989 src/canvas.c:1353 src/canvas.c:1383 #: src/canvas.c:1470 src/canvas.c:1545 src/canvas.c:1988 src/canvas.c:1994 #: src/canvas.c:2077 src/canvas.c:2217 src/canvas.c:2240 src/font.c:1352 #: src/fpick.c:636 src/fpick.c:754 src/layer.c:524 src/layer.c:815 #: src/layer.c:970 src/mainwindow.c:341 src/mainwindow.c:370 #: src/mainwindow.c:534 src/mainwindow.c:578 src/mainwindow.c:604 #: src/mainwindow.c:3797 src/mainwindow.c:4045 src/otherwindow.c:931 #: src/otherwindow.c:980 src/otherwindow.c:982 src/prefs.c:459 src/spawn.c:924 #: src/spawn.c:978 src/spawn.c:1017 src/thread.c:360 src/vcode.c:9912 #: src/viewer.c:1161 src/viewer.c:1179 msgid "Error" msgstr "Errore" #: src/ani.c:709 msgid "Unable to create output directory" msgstr "Impossibile creare la cartella di destinazione" #: src/ani.c:759 msgid "Creating Animation Frames" msgstr "Creazione anteprima fotogrammi" #: src/ani.c:812 msgid "Unable to save image" msgstr "Impossibile salvare l'immagine" #: src/ani.c:840 src/canvas.c:1171 src/fpick.c:731 src/layer.c:311 #: src/layer.c:379 src/layer.c:826 src/layer.c:840 src/mainwindow.c:375 #: src/mainwindow.c:1026 src/png.c:8794 src/prefs.c:464 msgid "Warning" msgstr "Attenzione!" #: src/ani.c:840 msgid "" "Do you really want to clear all of the position and cycle data for all of " "the layers?" msgstr "Vuoi veramente cancellare tutto e i dati relativi agli altri livelli?" #: src/ani.c:841 src/fpick.c:731 src/layer.c:311 src/layer.c:842 #: src/mainwindow.c:375 msgid "No" msgstr "No" #: src/ani.c:841 src/fpick.c:731 src/layer.c:311 src/layer.c:842 #: src/mainwindow.c:375 msgid "Yes" msgstr "Sì" #: src/ani.c:954 msgid "Set Key Frame" msgstr "Imposta fotogramma chiave" #: src/ani.c:961 msgid "Configure Animation" msgstr "Configura animazione" #: src/ani.c:964 msgid "Output Files" msgstr "File di destinazione" #: src/ani.c:967 msgid "Start frame" msgstr "Fotogramma iniziale" #: src/ani.c:969 msgid "End frame" msgstr "Fotogramma finale" #: src/ani.c:971 src/shifter.c:267 msgid "Delay" msgstr "Ritardo" #: src/ani.c:973 msgid "Output path" msgstr "Percorso di destinazione" #: src/ani.c:973 src/font.c:1637 src/spawn.c:664 msgid "Select Directory" msgstr "Seleziona cartella" #: src/ani.c:976 msgid "File prefix" msgstr "Prefisso file" #: src/ani.c:978 src/canvas.c:2096 msgid "File Format" msgstr "Formato File" #: src/ani.c:982 msgid "Positions" msgstr "Posizioni" #: src/ani.c:997 msgid "Cycling" msgstr "Ripetizione" #: src/ani.c:1006 msgid "Save" msgstr "Salva" #: src/ani.c:1007 src/font.c:1577 src/otherwindow.c:868 src/otherwindow.c:1615 #: src/otherwindow.c:1728 src/otherwindow.c:2938 src/otherwindow.c:3071 #: src/otherwindow.c:3170 msgid "Preview" msgstr "Anteprima" #: src/ani.c:1008 src/shifter.c:285 msgid "Create Frames" msgstr "Crea fotogrammi" #: src/ani.c:1022 msgid "You must have at least 2 layers to create an animation" msgstr "Devi avere almeno due livelli per creare un'animazione" #: src/ani.c:1028 msgid "You must save your layers file before creating an animation" msgstr "Devi salvare il tuo file coi livelli prima di creare un'animazione" #: src/canvas.c:357 msgid "The image is too large to transform." msgstr "l'immagine è troppo grande per trasformarla" #: src/canvas.c:393 src/canvas.c:430 src/otherwindow.c:1613 #: src/otherwindow.c:2524 src/otherwindow.c:2583 src/otherwindow.c:3179 msgid "Gradient" msgstr "Gradiente" #: src/canvas.c:393 src/otherwindow.c:840 src/otherwindow.c:842 #: src/otherwindow.c:2074 src/otherwindow.c:3180 msgid "Palette" msgstr "Tavolozza" #: src/canvas.c:393 src/info.c:265 src/otherwindow.c:847 src/otherwindow.c:2757 #: src/otherwindow.c:3180 src/png.c:781 src/png.c:995 msgid "Clipboard" msgstr "Appunti" #: src/canvas.c:394 src/cpick.c:831 src/toolbar.c:299 msgid "Value" msgstr "Valore" #: src/canvas.c:394 src/cpick.c:811 src/otherwindow.c:575 src/otherwindow.c:859 #: src/otherwindow.c:3053 src/toolbar.c:318 msgid "Red" msgstr "Rosso" #: src/canvas.c:394 src/cpick.c:815 src/otherwindow.c:575 src/otherwindow.c:860 #: src/otherwindow.c:3053 src/toolbar.c:319 msgid "Green" msgstr "Verde" #: src/canvas.c:394 src/cpick.c:819 src/otherwindow.c:575 src/otherwindow.c:861 #: src/otherwindow.c:3053 src/toolbar.c:320 msgid "Blue" msgstr "Blu" #: src/canvas.c:399 msgid "From " msgstr "" #: src/canvas.c:403 msgid "To " msgstr "" #: src/canvas.c:410 msgid "Map" msgstr "" #: src/canvas.c:429 msgid "MT" msgstr "MT" #: src/canvas.c:429 msgid "Sobel" msgstr "Sobel" #: src/canvas.c:429 msgid "Prewitt" msgstr "Prewitt" #: src/canvas.c:429 msgid "Kirsch" msgstr "Kirsch" #: src/canvas.c:430 msgid "Roberts" msgstr "Roberts" #: src/canvas.c:430 msgid "Laplace" msgstr "Laplace" #: src/canvas.c:430 msgid "Morphological" msgstr "Morfologico" #: src/canvas.c:442 msgid "Edge Detect" msgstr "Trova bordi" #: src/canvas.c:464 msgid "Edge Sharpen" msgstr "Affina bordi" #: src/canvas.c:472 msgid "Edge Soften" msgstr "Ammorbidisci bordi" #: src/canvas.c:521 msgid "Different X/Y" msgstr "X/Y differenti" #: src/canvas.c:522 src/canvas.c:562 src/canvas.c:603 src/canvas.c:637 #: src/canvas.c:722 src/otherwindow.c:1037 src/otherwindow.c:2685 msgid "Gamma corrected" msgstr "Gamma corretto" #: src/canvas.c:530 src/memory.c:8219 msgid "Gaussian Blur" msgstr "Sfocatura gaussiana" #: src/canvas.c:558 msgid "Radius" msgstr "Raggio" #: src/canvas.c:559 msgid "Amount" msgstr "Ammontare" #: src/canvas.c:560 msgid "Threshold " msgstr "Soglia " #: src/canvas.c:570 src/memory.c:8360 msgid "Unsharp Mask" msgstr "Maschera sfocata" #: src/canvas.c:599 msgid "Outer radius" msgstr "Raggio esterno" #: src/canvas.c:600 msgid "Inner radius" msgstr "Raggio interno" #: src/canvas.c:602 src/info.c:280 msgid "Normalize" msgstr "Normalizza" #: src/canvas.c:611 src/memory.c:8512 msgid "Difference of Gaussians" msgstr "Differenza di gaussiani" #: src/canvas.c:636 msgid "Protect details" msgstr "Proteggi dettagli" #: src/canvas.c:645 msgid "Kuwahara-Nagao Blur" msgstr "Sfocatura di Kuwahara-Nagao" #: src/canvas.c:709 msgid "The image is too large for this rotation." msgstr "L'immagine è troppo grande per questa rotazione." #: src/canvas.c:723 msgid "Smooth" msgstr "Liscia" #: src/canvas.c:732 msgid "Free Rotate" msgstr "Rotazione libera" #: src/canvas.c:989 src/viewer.c:1161 msgid "Not enough memory to create clipboard" msgstr "Memoria insufficiente per creare gli appunti" #: src/canvas.c:1172 msgid "" "You have not allocated enough memory in the Preferences window to undo this " "action." msgstr "" #: src/canvas.c:1353 msgid "Invalid palette file" msgstr "File della tavolozza non valido" #: src/canvas.c:1383 msgid "Invalid channel file." msgstr "Canale file non valido" #: src/canvas.c:1401 msgid "Raw frames" msgstr "Fotogrammi grezzi" #: src/canvas.c:1401 msgid "Composited frames" msgstr "Fotogrammi compositi" #: src/canvas.c:1402 msgid "Composited frames with nonzero delay" msgstr "Fotogrammi compositi con ritardo diverso da zero" #: src/canvas.c:1406 msgid "Load Frames" msgstr "Carica fotogrammi" #: src/canvas.c:1409 msgid "Load into Layers" msgstr "Carica nei livelli" #: src/canvas.c:1415 msgid "Load First Frame" msgstr "Carica il primo fotogramma" #: src/canvas.c:1416 msgid "Explode Frames" msgstr "Esplodi fotogrammi" #: src/canvas.c:1418 msgid "View Animation" msgstr "Vedi animazione" #: src/canvas.c:1434 #, c-format msgid "This is an animated %s file." msgstr "Questo è un file %s animato" #: src/canvas.c:1435 #, c-format msgid "This is a multipage %s file." msgstr "Questo è un file %s multipagina" #: src/canvas.c:1459 #, c-format msgid "File is too big, must be <= to width=%i height=%i" msgstr "File troppo grande, dev'essere <= di larghezza=%i altezza=%i" #: src/canvas.c:1461 msgid "Unable to explode frames" msgstr "Impossibile esplodere fotogrammi" #: src/canvas.c:1463 msgid "Unable to load file" msgstr "Impossibile caricare il file" #: src/canvas.c:1465 msgid "" "The file import library had to terminate due to a problem with the file " "(possibly corrupt image data or a truncated file). I have managed to load " "some data as the header seemed fine, but I would suggest you save this image " "to a new file to ensure this does not happen again." msgstr "" "Il processo d'importazione è stato interrotto a causa di problemi col file " "alcuni dati come l'intestazione sembravano integri, ma suggerirei di salvare " "questa immagine in un nuovo file, per esser certi che ciò non avvenga ancora." #: src/canvas.c:1467 msgid "The animation is too long to load all of it into layers." msgstr "L'animazione è troppo lunga per caricarla in tutti i suoi livelli" #: src/canvas.c:1469 msgid "Could not explode all the frames in the animation." msgstr "Impossibile esplodere tutti i fotogrammi dell'animazione" #: src/canvas.c:1481 src/font.c:1556 src/fpick.c:937 src/otherwindow.c:2765 #: src/prefs.c:321 src/toolbar.c:451 msgid "Size" msgstr "Dimensione" #: src/canvas.c:1484 src/otherwindow.c:244 msgid "Width" msgstr "Larghezza" #: src/canvas.c:1485 src/otherwindow.c:245 msgid "Height" msgstr "Altezza" #: src/canvas.c:1489 src/channels.c:253 src/channels.c:317 src/fpick.c:666 #: src/fpick.c:957 src/mainwindow.c:3990 src/otherwindow.c:255 #: src/otherwindow.c:517 src/otherwindow.c:591 src/otherwindow.c:867 #: src/otherwindow.c:1058 src/otherwindow.c:1727 src/otherwindow.c:2101 #: src/otherwindow.c:2336 src/otherwindow.c:2538 src/otherwindow.c:2691 #: src/otherwindow.c:2776 src/otherwindow.c:2937 src/otherwindow.c:3070 #: src/otherwindow.c:3169 src/prefs.c:338 src/prefs.c:464 src/prefs.c:538 #: src/spawn.c:666 src/viewer.c:1258 msgid "Cancel" msgstr "Cancella" #: src/canvas.c:1490 src/channels.c:253 src/channels.c:317 src/fpick.c:956 #: src/info.c:297 src/mainwindow.c:3992 src/mygtk.c:233 src/mygtk.c:535 #: src/otherwindow.c:591 src/otherwindow.c:871 src/otherwindow.c:1058 #: src/otherwindow.c:1729 src/otherwindow.c:2101 src/otherwindow.c:2336 #: src/otherwindow.c:2538 src/otherwindow.c:2691 src/otherwindow.c:2776 #: src/otherwindow.c:3072 src/otherwindow.c:3171 src/prefs.c:338 #: src/prefs.c:538 src/spawn.c:666 msgid "OK" msgstr "OK" #: src/canvas.c:1504 #, c-format msgid "This is a scalable %s file." msgstr "" #: src/canvas.c:1545 msgid "Cannot open file" msgstr "Impossibile aprire il file" #: src/canvas.c:1546 msgid "Unsupported file format" msgstr "Formato file non supportato" #: src/canvas.c:1673 #, c-format msgid "File: %s already exists. Do you want to overwrite it?" msgstr "Il file: %s è gia presente. Vuoi sovrascriverlo?" #: src/canvas.c:1674 msgid "File Found" msgstr "File trovato" #: src/canvas.c:1674 src/mainwindow.c:1095 msgid "NO" msgstr "NO" #: src/canvas.c:1674 src/mainwindow.c:1095 msgid "YES" msgstr "SÃŒ" #: src/canvas.c:1988 msgid "Unable to export undo images" msgstr "Impossibile esportare immagini annullate" #: src/canvas.c:1994 msgid "Unable to export ASCII file" msgstr "Impossibile esportare in file ASCII" #: src/canvas.c:2076 src/layer.c:814 src/mainwindow.c:529 #, c-format msgid "Unable to save file: %s" msgstr "Impossibile salvare file: %s" #: src/canvas.c:2101 src/prefs.c:222 msgid "Transparency index" msgstr "Indice Trasparenza" #: src/canvas.c:2103 msgid "TIFF Compression" msgstr "" #: src/canvas.c:2105 src/prefs.c:225 msgid "JPEG Save Quality (100=High)" msgstr "Qualità di salvataggio JPEG (100=alta)" #: src/canvas.c:2107 msgid "ZIP Compression (0=None)" msgstr "" #: src/canvas.c:2108 src/prefs.c:227 msgid "PNG Compression (0=None)" msgstr "Compressione PNG (0=Nessuna)" #: src/canvas.c:2111 src/prefs.c:249 msgid "LZMA2 Compression (0=None)" msgstr "" #: src/canvas.c:2113 src/prefs.c:252 msgid "ZSTD Compression Level" msgstr "" #: src/canvas.c:2115 src/prefs.c:231 msgid "TGA RLE Compression" msgstr "Compressione TGA RLE" #: src/canvas.c:2117 msgid "LBM PackBits Compression" msgstr "" #: src/canvas.c:2118 src/prefs.c:226 msgid "JPEG2000 Compression (0=Lossless)" msgstr "Compressione JPEG2000 (0=senza perdita)" #: src/canvas.c:2120 msgid "WebP Compression" msgstr "" #: src/canvas.c:2122 msgid "WebP Save Quality (100=High)" msgstr "" #: src/canvas.c:2123 src/prefs.c:263 msgid "V8 Save Quality (100=High)" msgstr "" #: src/canvas.c:2125 src/prefs.c:264 msgid "V8L Compression (0=None)" msgstr "" #: src/canvas.c:2127 msgid "Hotspot at X =" msgstr "Punto a X =" #: src/canvas.c:2129 msgid "Y =" msgstr "Y =" #: src/canvas.c:2133 msgid "Animation delay" msgstr "Ritardo animazione" #: src/canvas.c:2136 src/otherwindow.c:253 msgid "Undoable" msgstr "Annullabile" #: src/canvas.c:2138 src/prefs.c:236 msgid "Apply colour profile" msgstr "Applica profilo colore" #: src/canvas.c:2176 src/toolbar.c:543 msgid "Load Image File" msgstr "Carica File Immagine" #: src/canvas.c:2191 src/toolbar.c:544 msgid "Save Image File" msgstr "Salva File Immagine" #: src/canvas.c:2196 msgid "Load Palette File" msgstr "Carica tavolozza file" #: src/canvas.c:2202 msgid "Save Palette File" msgstr "Salva tavolozza file" #: src/canvas.c:2207 msgid "Export Undo Images" msgstr "Esporta immagini annullate" #: src/canvas.c:2212 msgid "Export Undo Images (reversed)" msgstr "Esporta immagini annullate (invertito)" #: src/canvas.c:2217 msgid "You must have 16 or fewer palette colours to export ASCII art." msgstr "Devi avere 16 colori o di meno per l'esportazione in ASCII art." #: src/canvas.c:2220 msgid "Export ASCII Art" msgstr "Esporta in ASCII Art" #: src/canvas.c:2224 msgid "Save Layer Files" msgstr "Salva livelli del file" #: src/canvas.c:2234 msgid "Choose frames directory" msgstr "Selezione cartella per i fotogrammi" #: src/canvas.c:2240 msgid "You must save at least one frame to create an animated GIF." msgstr "Devi salvare almeno un fotogramma per creare un'animazione GIF" #: src/canvas.c:2243 msgid "Export GIF animation" msgstr "Esporta animazione GIF" #: src/canvas.c:2247 msgid "Load Channel" msgstr "Carica Canale" #: src/canvas.c:2255 msgid "Save Channel" msgstr "Salva canale" #: src/canvas.c:2260 msgid "Save Composite Image" msgstr "Salva immagine composita" #: src/channels.c:243 msgid "Create Channel" msgstr "Crea Canale" #: src/channels.c:244 msgid "Channel Type" msgstr "Tipo canale" #: src/channels.c:247 msgid "Initial Channel State" msgstr "Stato iniziale canale" #: src/channels.c:251 msgid "Inverted" msgstr "Invertito" #: src/channels.c:265 msgid "Cleared" msgstr "Pulito" #: src/channels.c:266 msgid "Set" msgstr "Imposta" #: src/channels.c:267 msgid "Set colour A radius B" msgstr "Imposta colore A con raggio B" #: src/channels.c:268 msgid "Set blend A to B" msgstr "Imposta trasparenza A a B" #: src/channels.c:269 msgid "Image Red" msgstr "Rosso immagine" #: src/channels.c:270 msgid "Image Green" msgstr "Verde immagine" #: src/channels.c:271 msgid "Image Blue" msgstr "Blu immagine" #: src/channels.c:273 src/channels.c:313 src/mainwindow.c:67 #: src/otherwindow.c:1679 msgid "Alpha" msgstr "Alfa" #: src/channels.c:274 src/channels.c:314 src/mainwindow.c:67 #: src/otherwindow.c:1683 msgid "Selection" msgstr "Selezione" #: src/channels.c:275 src/channels.c:315 src/mainwindow.c:67 #: src/otherwindow.c:1687 msgid "Mask" msgstr "Maschera" #: src/channels.c:312 msgid "Delete Channels" msgstr "Elimina canali" #: src/channels.c:367 msgid "Threshold Channel" msgstr "Canale soglia" #: src/cpick.c:823 src/otherwindow.c:573 src/otherwindow.c:820 #: src/toolbar.c:299 msgid "Hue" msgstr "Tonalità" #: src/cpick.c:827 src/otherwindow.c:573 src/otherwindow.c:818 #: src/toolbar.c:299 msgid "Saturation" msgstr "Saturazione" #: src/cpick.c:835 msgid "Hex" msgstr "Esadecimale" #: src/cpick.c:840 src/layer.c:1109 src/otherwindow.c:2530 src/prefs.c:323 #: src/toolbar.c:457 msgid "Opacity" msgstr "Opacità" #: src/font.c:982 msgid "Creating Font Index" msgstr "Creazione indice dei caratteri in corso" #: src/font.c:1353 msgid "You must select at least one directory to search for fonts." msgstr "Devi selezionare almeno una cartella in cui cercare caratteri" #: src/font.c:1529 src/font.c:1624 src/toolbar.c:609 src/viewer.c:1213 #: src/viewer.c:1258 msgid "Paste Text" msgstr "Incolla testo" #: src/font.c:1533 src/font.c:1572 src/png.c:3578 msgid "Text" msgstr "Testo" #: src/font.c:1540 msgid "Font" msgstr "Carattere" #: src/font.c:1548 msgid "Style" msgstr "Stile" #: src/font.c:1566 msgid "Filename" msgstr "Nome del file" #: src/font.c:1567 msgid "Face" msgstr "Tipo" #: src/font.c:1587 src/viewer.c:1222 msgid "Antialias" msgstr "Antiscalettatura" #: src/font.c:1590 src/viewer.c:1224 msgid "Invert" msgstr "Inverti" #: src/font.c:1593 src/viewer.c:1226 msgid "Background colour =" msgstr "Colore di sfondo =" #: src/font.c:1601 src/viewer.c:1233 msgid "DPI =" msgstr "" #: src/font.c:1610 msgid "Oblique" msgstr "Obliquo" #: src/font.c:1612 src/viewer.c:1244 msgid "Angle of rotation =" msgstr "Angolo di rotazione =" #: src/font.c:1617 src/viewer.c:1248 msgid "Align" msgstr "" #: src/font.c:1620 src/viewer.c:1253 msgid "Spacing" msgstr "" #: src/font.c:1629 msgid "Font Directories" msgstr "Cartella dei caratteri" #: src/font.c:1634 src/spawn.c:664 msgid "Directory" msgstr "Cartella" #: src/font.c:1637 msgid "New Directory" msgstr "Nuova cartella" #: src/font.c:1644 src/prefs.c:532 msgid "Add" msgstr "Aggiungi" #: src/font.c:1645 src/prefs.c:533 msgid "Remove" msgstr "Rimuovi" #: src/font.c:1646 msgid "Create Index" msgstr "Crea indice" #: src/font.c:1660 src/viewer.c:1267 msgid "Enter Text Here" msgstr "Inserisci il testo qui" #: src/fpick.c:635 #, c-format msgid "Could not access directory %s" msgstr "Impossibile accedere alla cartella %s" #: src/fpick.c:668 src/fpick.c:698 msgid "Delete" msgstr "Elimina" #: src/fpick.c:669 src/fpick.c:698 msgid "Rename" msgstr "Rinomina" #: src/fpick.c:672 src/otherwindow.c:255 src/otherwindow.c:1666 msgid "Create" msgstr "Crea" #: src/fpick.c:699 msgid "Enter the new filename" msgstr "Inserisci un nuovo nome file" #: src/fpick.c:704 msgid "Create Directory" msgstr "Crea Cartella" #: src/fpick.c:705 msgid "Enter the name of the new directory" msgstr "Inserisci il nome della nuova cartella" #: src/fpick.c:729 #, c-format msgid "Do you really want to delete \"%s\" ?" msgstr "Sei sicuro di voler eliminare \"%s\" ?" #: src/fpick.c:735 msgid "Unable to delete" msgstr "Impossibile eliminare" #: src/fpick.c:741 msgid "Unable to rename" msgstr "Impossibile rinominare" #: src/fpick.c:750 msgid "Unable to create directory" msgstr "Impossibile creare cartella" #: src/fpick.c:924 msgid "Up" msgstr "Sù" #: src/fpick.c:925 msgid "Home" msgstr "Home" #: src/fpick.c:926 msgid "Create New Directory" msgstr "Crea nuova cartella" #: src/fpick.c:927 msgid "Show Hidden Files" msgstr "Mostra file nascosti" #: src/fpick.c:929 msgid "Case Insensitive Sort" msgstr "Ordina senza distinzioni tra maiuscole e minuscole" #: src/fpick.c:936 msgid "Name" msgstr "Nome" #: src/fpick.c:938 msgid "Type" msgstr "Tipo" #: src/fpick.c:939 msgid "Modified" msgstr "Modificato" #: src/help.c:25 src/prefs.c:160 msgid "General" msgstr "Generale" #: src/help.c:26 msgid "Keyboard shortcuts" msgstr "Scorciatoie da tastiera" #: src/help.c:27 msgid "Mouse shortcuts" msgstr "Scorciatoie da mouse" #: src/help.c:28 msgid "Credits" msgstr "Riconoscimenti" #: src/help.c:32 msgid "mtPaint 3.51 - Copyright (C) 2004-2021 The Authors\n" msgstr "mtPaint 3.51 - Copyright (C) 2004-2021 Gli autori\n" #: src/help.c:33 msgid "See 'Credits' section for a list of the authors.\n" msgstr "Vedi la sezione 'Riconoscimenti' per una lista degli autori.\n" #: src/help.c:34 msgid "" "mtPaint 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.\n" msgstr "" "mtPaint è software libero; puoi redistribuirlo e/o modificarlo secondo i " "termini della GNU General Public License come pubblicato dalla Free Software " "Foundation; o della versione 3 della licenza, o (a tua discrezione) di ogni " "successiva versione.\n" #: src/help.c:35 msgid "" "mtPaint 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.\n" msgstr "" "mtPaint è distribuito con la speranza che sia utile, ma SENZA ALCUNA " "GARANZIA; senza neppure la garanzia implicita di COMMERCIABILITÀ o IDONEITÀ " "PER UNO SCOPO PARTICOLARE. Vedi la GNU General Public License per maggiori " "dettagli\n" #: src/help.c:36 msgid "" "mtPaint is a simple GTK+1/2/3 painting program designed for creating icons " "and pixel based artwork. It can edit indexed palette or 24 bit RGB images " "and offers basic painting and palette manipulation tools. It also has " "several other more powerful features such as channels, layers and animation. " "Due to its simplicity and lack of dependencies it runs well on GNU/Linux, " "Windows and older PC hardware.\n" msgstr "" "mtPaint è un semplice programma di disegno (GTK 1/2) progettato per la " "creazione di icone ed arte pixellistica. Può modificare tavolozze " "indicizzate o immagini a 24 bit RGB ed offre strumenti di base per il " "disegno e la manipolazione di tavolozze. Ha anche diverse altre " "caratteristiche più avanzate come i canali, i livelli e l'animazione. In " "virtù della sua semplicità e mancanza di dipendenze, può essere eseguito su " "ogni sistema GNU/Linux, Windows e sui PC datati.\n" #: src/help.c:37 msgid "" "There is full documentation of mtPaint's features contained in a handbook. " "If you don't already have this, you can download it from the mtPaint " "website.\n" msgstr "" "esiste una documentazione completa delle funzioni di mtPaint, contenuta in " "un manuale.Se non l'hai già, puoi scaricarlo dal sito di mtPaint.\n" #: src/help.c:38 msgid "" "If you like mtPaint and you want to keep up to date with new releases, or " "you want to give some feedback, then the mailing lists may be of interest to " "you:\n" msgstr "" "Se ti piace mtpaint e vuoi tenerti aggiornato sulle nuove versioni, o " "inviare qualche riscontro, allora la mailing list può interessarti.\n" #: src/help.c:39 msgid "http://sourceforge.net/mail/?group_id=155874" msgstr "http://sourceforge.net/mail/?group_id=155874" #: src/help.c:42 msgid " Ctrl-N Create new image" msgstr " Ctrl-N Crea una nuova immagine" #: src/help.c:43 msgid " Ctrl-O Open Image" msgstr " Ctrl-O Apri immagine" #: src/help.c:44 msgid " Ctrl-S Save Image" msgstr " Ctrl-S Salva immagine" #: src/help.c:45 msgid " Ctrl-Shift-S Save layers file" msgstr "" #: src/help.c:46 msgid " Ctrl-Q Quit program\n" msgstr " Ctrl-Q Esci dal programma\n" #: src/help.c:47 msgid " Ctrl-A Select whole image" msgstr " Ctrl-A Seleziona l'intera immagine" #: src/help.c:48 msgid " Escape Select nothing, cancel paste box" msgstr "" " Escape Non selezionare nulla, cancella il riquadro di copia" #: src/help.c:49 msgid " J Lasso selection\n" msgstr "" #: src/help.c:50 msgid " Ctrl-C Copy selection to clipboard" msgstr " Ctrl-C Copia la selezione negli appunti" #: src/help.c:51 msgid "" " Ctrl-X Copy selection to clipboard, and then paint current " "pattern to selection area" msgstr "" " Ctrl-X Copia la selezione negli appunti, e quindi copia il " "motivo corrente nell'area di selezione" #: src/help.c:52 msgid " Ctrl-V Paste clipboard to centre of current view" msgstr "" " Ctrl-V Incolla il contenuto degli appunti al centro della View " "corrente" #: src/help.c:53 msgid " Ctrl-K Paste clipboard to location it was copied from" msgstr "" " Ctrl-K Incolla il contenuto degli appunti nell'area d'origine" #: src/help.c:54 msgid " Ctrl-Shift-V Paste clipboard to new layer" msgstr "" #: src/help.c:55 msgid " Enter/Return Commit paste to canvas" msgstr " Enter/Return/Invio Incolla sulla tela" #: src/help.c:56 msgid " Shift+Enter/Return Commit paste and swap canvas into the clipboard\n" msgstr "" #: src/help.c:57 msgid " Arrow keys Paint Mode - Move the mouse pointer" msgstr " Tasti freccia Modalità disegno - Muovi il puntatore del mouse" #: src/help.c:58 msgid "" " Arrow keys Selection Mode - Nudge selection box or paste box by one " "pixel" msgstr "" " Tasti freccia Modalità selezione - Sposta la finestra di selezione o " "incolla casella di un pixel" #: src/help.c:59 msgid "" " Shift+Arrow keys Nudge mouse pointer, selection box or paste box by x " "pixels - x is defined by the Preferences window" msgstr "" " Maiusc+ Tasti freccia Sposta il puntatore del mouse, la finestra di " "selezione o incolla casella di x pixel - x è definito dalla finestra di " "preferenze" #: src/help.c:60 msgid " Ctrl+Arrows Move layer or resize selection box" msgstr "" " Ctrl+Tasti freccia Muovi livello o ridimensiona il riquadro di selezione" #: src/help.c:61 msgid " Ctrl+Shift+Arrows Move layer or resize selection box by x pixels\n" msgstr "" #: src/help.c:62 msgid " Enter/Return Paint Mode - Simulate left click" msgstr "" #: src/help.c:63 msgid " Backspace Paint Mode - Simulate right click\n" msgstr "" #: src/help.c:64 msgid "" " [ or ] Change colour A to the next or previous palette item" msgstr "" " [ or ] Cambia colore A con il successivo o con il precedente " "elemento della tavolozza" #: src/help.c:65 msgid "" " Shift+[ or ] Change colour B to the next or previous palette item\n" msgstr "" " Maiusc+[ or ] Cambia colore B con il successivo o con il precedente " "elemento della tavolozza\n" #: src/help.c:66 msgid " Delete Crop image to selection" msgstr " Elimina Ritaglia immagine in base alla selezione" #: src/help.c:67 msgid "" " Insert Transform colours - i.e. Brightness, Contrast, " "Saturation, Posterize, Gamma" msgstr "" " Inserisci Trasforma colori - ovvero. Luminosità, Contrasto, " "Saturazione, Posterizza, Gamma" #: src/help.c:68 msgid " Ctrl-G Greyscale the image" msgstr " Ctrl-G Converti immagine in scala di Grigio" #: src/help.c:69 msgid " Shift-Ctrl-G Greyscale the image (Gamma corrected)" msgstr "" " Maiusc-Ctrl-G Converti immagine in scala di Grigio (con correzione " "Gamma)" #: src/help.c:70 msgid " Ctrl+M Mirror the image" msgstr "" #: src/help.c:71 msgid " Shift-Ctrl-I Invert the image\n" msgstr "" #: src/help.c:72 msgid "" " Ctrl-T Draw a rectangle around the selection area with the " "current fill" msgstr "" " Ctrl-T Disegna un rettangolo intorno all'area di selezione con " "ilriempimento corrente" #: src/help.c:73 msgid " Ctrl-Shift-T Fill in the selection area with the current fill" msgstr "" " Ctrl-Maiusc-T Riempi l'area selezionata con il riempimento corrente" #: src/help.c:74 msgid " Ctrl-L Draw an ellipse spanning the selection area" msgstr "" " Ctrl-L Disegna un'ellisse che attraversi l'area di selezione" #: src/help.c:75 msgid " Ctrl-Shift-L Draw a filled ellipse spanning the selection area\n" msgstr "" " Ctrl-Maiusc-L Disegna un'ellisse piena che attraversi l'area di " "selezione\n" #: src/help.c:76 msgid " Ctrl-E Edit the RGB values for colours A & B" msgstr " Ctrl-E Modifica i valori RGB per i colori A & B" #: src/help.c:77 msgid " Ctrl-W Edit all palette colours\n" msgstr " Ctrl-W Modifica tutte le tavolozze colori\n" #: src/help.c:78 msgid " Ctrl-P Preferences" msgstr " Ctrl-P Preferenze" #: src/help.c:79 msgid " Ctrl-I Information\n" msgstr " Ctrl-I Informazioni\n" #: src/help.c:80 msgid " Ctrl-Z Undo last action" msgstr " Ctrl-Z Annulla l'ultima azione" #: src/help.c:81 msgid " Ctrl-R Redo an undone action\n" msgstr " Ctrl-R Ripristina un'azione annullata\n" #: src/help.c:82 msgid " Shift-T Text Tool (GTK+)" msgstr "" #: src/help.c:83 msgid " T Text Tool (FreeType)\n" msgstr "" #: src/help.c:84 msgid " V View Window" msgstr " V Finestra Vista" #: src/help.c:85 msgid " L Layers Window\n" msgstr " L Finestra livelli\n" #: src/help.c:86 msgid " Ctrl-H Toggle Hide Image mode" msgstr "" #: src/help.c:87 msgid " B Toggle Snap to Tile Grid mode\n" msgstr "" #: src/help.c:88 msgid " X Swap Colours A & B" msgstr "" #: src/help.c:89 msgid " E Choose Colour\n" msgstr "" #: src/help.c:90 msgid "" " A Draw open arrow head when using the line tool (size set " "by flow setting)" msgstr "" " A Disegna una freccia aperta quando si utilizza lo " "strumento linea (imposta dimensioni attraverso i settaggi di flusso)" #: src/help.c:91 msgid "" " S Draw closed arrow head when using the line tool (size " "set by flow setting)\n" msgstr "" " S Disegna una freccia chiusa quando si utilizza lo " "strumento linea (impostadimensioni attraverso i settaggi di flusso)\n" #: src/help.c:92 msgid " D Line Tool" msgstr "" #: src/help.c:93 msgid " F Flood Fill Tool\n" msgstr "" #: src/help.c:94 msgid " +,= Main edit window - Zoom in" msgstr " +,= Finestra principale - Zoom in" #: src/help.c:95 msgid " - Main edit window - Zoom out" msgstr " - Finestra principale - Zoom out" #: src/help.c:96 msgid " Shift +,= View window - Zoom in" msgstr " Maiusc +,= Finestra Vista - Zoom in" #: src/help.c:97 msgid " Shift - View window - Zoom out\n" msgstr " Maiusc - Finestra Vista - Zoom out\n" #: src/help.c:98 #, c-format msgid " 1 10% zoom" msgstr " 1 10% zoom" #: src/help.c:99 #, c-format msgid " 2 25% zoom" msgstr " 2 25% zoom" #: src/help.c:100 #, c-format msgid " 3 50% zoom" msgstr " 3 50% zoom" #: src/help.c:101 #, c-format msgid " 4 100% zoom" msgstr " 4 100% zoom" #: src/help.c:102 #, c-format msgid " 5 400% zoom" msgstr " 5 400% zoom" #: src/help.c:103 #, c-format msgid " 6 800% zoom" msgstr " 6 800% zoom" #: src/help.c:104 #, c-format msgid " 7 1200% zoom" msgstr " 7 1200% zoom" #: src/help.c:105 #, c-format msgid " 8 1600% zoom" msgstr " 8 1600% zoom" #: src/help.c:106 #, c-format msgid " 9 2000% zoom\n" msgstr " 9 2000% zoom\n" #: src/help.c:107 msgid " Shift + 1 Edit image channel" msgstr " Maiusc + 1 Modifica canale immagine" #: src/help.c:108 msgid " Shift + 2 Edit alpha channel" msgstr " Maiusc + 2 Modifica canale alfa" #: src/help.c:109 msgid " Shift + 3 Edit selection channel" msgstr " Maiusc + 3 Modifica canale selezione" #: src/help.c:110 msgid " Shift + 4 Edit mask channel\n" msgstr " Maiusc + 4 Modifica maschera canale\n" #: src/help.c:111 msgid " F1 Help" msgstr " F1 Aiuto" #: src/help.c:112 msgid " F2 Choose Pattern" msgstr " F2 Scegli motivo" #: src/help.c:113 msgid " F3 Choose Brush" msgstr " F3 Scegli pennello" #: src/help.c:114 msgid " F4 Paint Tool" msgstr " F4 Strumento di disegno" #: src/help.c:115 msgid " F5 Toggle Main Toolbar" msgstr " F5 Passa alla barra principale" #: src/help.c:116 msgid " F6 Toggle Tools Toolbar" msgstr " F6 Passa a barra strumenti principale" #: src/help.c:117 msgid " F7 Toggle Settings Toolbar" msgstr " F7 Passa a barra impostazioni" #: src/help.c:118 msgid " F8 Toggle Palette" msgstr " F8 Passa a tavolozza" #: src/help.c:119 msgid " F9 Selection Tool" msgstr " F9 Strumento selezione" #: src/help.c:120 msgid " F12 Toggle Dock Area\n" msgstr " F12 Passa ad area di lavoro\n" #: src/help.c:121 msgid " Ctrl + F1 - F12 Save current clipboard to file 1-12" msgstr "" " Ctrl + F1 - F12 Salva il contenuto corrente degli appunti nei file 1-12" #: src/help.c:122 msgid " Shift + F1 - F12 Load clipboard from file 1-12\n" msgstr "" " Maiusc + F1 - F12 Carica il contenuto degli appunti dai file 1-12\n" #: src/help.c:123 msgid "" " Ctrl + 1, 2, ... , 0 Set opacity to 10%, 20%, ... , 100% (main or keypad " "numbers)" msgstr "" " Ctrl + 1, 2, ... , 0 Imposta opacità al 10%, 20%, ... , 100% (finestra " "principale o tastierino numerico" #: src/help.c:124 msgid " Ctrl + + or = Increase opacity by 1" msgstr " Ctrl + + or = Incrementa opacità di 1" #: src/help.c:125 msgid " Ctrl + - Decrease opacity by 1\n" msgstr " Ctrl + - Decrementa opacità di 1\n" #: src/help.c:126 msgid "" " Home Show or hide main window menu/toolbar/status bar/palette" msgstr "" " Home Mostra o nascondi la finestra principale menu/barra " "strumenti/barra di stato/tavolozza" #: src/help.c:127 msgid " Page Up Scale Image" msgstr " Pagina sù Scala Immagine" #: src/help.c:128 msgid " Page Down Resize Image canvas" msgstr " Pagina giù Ridimensiona tela immagine" #: src/help.c:129 msgid " End Pan Window" msgstr " Fine Finestra panoramica" #: src/help.c:132 msgid " Left button Paint to canvas using the current tool" msgstr " Tasto sinistro Disegna sulla tela usando lo strumento corrente" #: src/help.c:133 msgid "" " Middle button Selects the point which will be the centre of the " "image after the next zoom" msgstr "" " Tasto centrale Seleziona il punto che sarà il centro della immagine " "dopo il successivo zoom" #: src/help.c:134 msgid "" " Right button Commit paste to canvas / Stop drawing current line / " "Cancel selection\n" msgstr "" " Tasto destro Incolla sulla tela / arresta il disegno della linea " "corrente / Cancella selezione\n" #: src/help.c:135 msgid "" " Scroll Wheel In GTK+2/3 the user can have the scroll wheel zoom in " "or out via the Preferences window\n" msgstr "" " Rotellina di scorrimento del mouse In GTK+2/3 l'utente può avere la " "rotellina per lo zoom attraverso la finestra di preferenze\n" #: src/help.c:136 msgid " Ctrl+Left button Choose colour A from under mouse pointer" msgstr " Ctrl+tasto sinistro Scegli un colore A dal puntatore del mouse" #: src/help.c:137 msgid " Ctrl+Left button Clone tool - Select source" msgstr "" #: src/help.c:138 msgid "" " Ctrl+Middle button Create colour A/B and pattern based on the RGB colour " "in A (RGB images only)" msgstr "" " Ctrl+tasto centrale Crea colore A/B e motivo basato su colori RGB in A " "(solo immagini RGB)" #: src/help.c:139 msgid " Ctrl+Right button Choose colour B from under mouse pointer" msgstr " Ctrl+tasto destro Scegli colore B dal puntatore del mouse" #: src/help.c:140 msgid "" " Ctrl+Right button Polygon tool - Delete last point / Delete nearest " "point" msgstr "" #: src/help.c:141 msgid " Ctrl+Scroll Wheel Scroll the main edit window left or right\n" msgstr "" " Ctrl+rotellina di scorrimento Sposta la finestra principale a destra o " "a sinistra\n" #: src/help.c:142 msgid "" " Ctrl+Double click Set colour A or B to average colour under brush " "square or selection marquee (RGB only)\n" msgstr "" " Ctrl + doppio clic Imposta colore A o B operando una media del colore " "selezionato dal pennello quadrato o linea di selezione (solo RGB)\n" #: src/help.c:143 msgid "" " Shift+Right button Selects the point which will be the centre of the " "image after the next zoom\n" "\n" msgstr "" " Maiusc + tasto destro Seleziona il punto che sarà al centro della " "immagine dopo il prossimo zoom\n" "\n" #: src/help.c:144 msgid "You can fixate the X/Y co-ordinates while moving the mouse:\n" msgstr "È possibile fissare le coordinate X / Y mentre si sposta il mouse:\n" #: src/help.c:145 msgid " Shift Constrain mouse movements to vertical line" msgstr "" " Maiusc Vincola i movimenti del mouse alla linea verticale" #: src/help.c:146 msgid " Shift+Ctrl Constrain mouse movements to horizontal line" msgstr "" " Maiusc+Ctrl Vincola i movimenti del mouse alla linea orizzontale" #: src/help.c:149 msgid "mtPaint is maintained by Dmitry Groshev.\n" msgstr "mtPaint è mantenuto da Dmitry Groshev.\n" #: src/help.c:150 msgid "wjaguar@users.sourceforge.net" msgstr "wjaguar@users.sourceforge.net" #: src/help.c:151 msgid "http://mtpaint.sourceforge.net/\n" msgstr "http://mtpaint.sourceforge.net/\n" #: src/help.c:152 msgid "" "The following people (in alphabetical order) have contributed directly to " "the project, and are therefore worthy of gracious thanks for their " "generosity and hard work:\n" "\n" msgstr "" "Le seguenti persone (in ordine alfabetico) hanno contribuito direttamente al " "progetto, e sono pertanto meritevoli di un sentito ringraziamento per la " "loro generosità e duro lavoro\n" "\n" #: src/help.c:153 msgid "Authors\n" msgstr "Autori\n" #: src/help.c:154 msgid "" "Dmitry Groshev - Contributing developer for version 2.30. Lead developer and " "maintainer from version 3.00 to the present." msgstr "" "Dmitry Groshev - che ha contribuito allo sviluppo per la versione 2.30, capo " "sviluppatore egestore progetto dalla versione 3.00 ad oggi." #: src/help.c:155 msgid "" "Mark Tyler - Original author and maintainer up to version 3.00, occasional " "contributor thereafter." msgstr "" "Mark Tyler - autore originale e gestore fino alla versione 3.00, " "occasionalecontributore dopo questa versione" #: src/help.c:156 msgid "" "Xiaolin Wu - Wrote the Wu quantizing method - see wu.c for more " "information.\n" "\n" msgstr "" "Xiaolin Wu - ha scritto il metodo di quantizzazione Wu - vedi wu.c per " "ulteriori informazioni.\n" "\n" #: src/help.c:157 msgid "" "General Contributions (Feedback and Ideas for improvements unless otherwise " "stated)\n" msgstr "" "Contributi generali (riscontri e idee per il miglioramento, salvo diversa " "rettifica\n" #: src/help.c:158 msgid "Abdulla Al Muhairi - Website redesign April 2005" msgstr "Abdulla Al Muhair - ha ridisegnato il sito web nell'aprile del 2005" #: src/help.c:159 msgid "Alan Horkan" msgstr "Alan Horkan" #: src/help.c:160 msgid "Alexandre Prokoudine" msgstr "Alexandre Prokoudine" #: src/help.c:161 msgid "Antonio Andrea Bianco" msgstr "Antonio Andrea Bianco" #: src/help.c:162 msgid "Charlie Ledocq" msgstr "" #: src/help.c:163 msgid "Dennis Lee" msgstr "Dennis Lee" #: src/help.c:164 msgid "Donald White" msgstr "" #: src/help.c:165 msgid "Ed Jason" msgstr "Ed Jason" #: src/help.c:166 msgid "" "Eddie Kohler - Created Gifsicle which is needed for the creation and viewing " "of animated GIF files http://www.lcdf.org/gifsicle/" msgstr "" "Eddie Kohler - che ha creato Gifsicle, necessario per creare e visualizzare " "o animare file GIF - http://www.lcdf.org/gifsicle/" #: src/help.c:167 msgid "" "Guadalinex Team (Junta de Andalucia) - man page, Launchpad/Rosetta " "registration" msgstr "" "Guadalinex Team (Junta de Andalucia)- man page, Launchpad/Rosetta " "registrazione" #: src/help.c:168 msgid "Lou Afonso" msgstr "Lou Afonso" #: src/help.c:169 msgid "Magnus Hjorth" msgstr "Magnus Hjorth" #: src/help.c:170 msgid "Martin Zelaia" msgstr "Martin Zelaia" #: src/help.c:171 msgid "Pasi Kallinen" msgstr "" #: src/help.c:172 msgid "Pavel Ruzicka" msgstr "Pavel Ruzicka" #: src/help.c:173 msgid "Puppy Linux (Barry Kauler)" msgstr "Puppy Linux (Barry Kauler)" #: src/help.c:174 msgid "Victor Copovi" msgstr "" #: src/help.c:175 msgid "Vlastimil Krejcir" msgstr "Vlastimil Krejcir" #: src/help.c:176 msgid "" "William Kern\n" "\n" msgstr "" "William Kern\n" "\n" #: src/help.c:177 msgid "Translations\n" msgstr "Traduzioni\n" #: src/help.c:178 msgid "Brazilian Portuguese - Paulo Trevizan, Valter Nazianzeno" msgstr "Brasiliano Portoghese - Paulo Trevizan, Valter Nazianzeno" #: src/help.c:179 msgid "Czech - Pavel Ruzicka, Martin Petricek, Roman Hornik, Pavel Fric" msgstr "" "Cecoslovacco - Pavel Ruzicka, Martin Petricek, Roman Hornik, Pavel Fric" #: src/help.c:180 msgid "Dutch - Hans Strijards, Pjotr" msgstr "Olandese - Hans Strijards, Pjotr" #: src/help.c:181 msgid "" "French - Nicolas Velin, Pascal Billard, Sylvain Cresto, Johan Serre, " "Philippe Etienne, Victor Copovi" msgstr "" "Francese - Nicolas Velin, Pascal Billard, Sylvain Cresto, Johan Serre, " "Philippe Etienne, Victor Copovi" #: src/help.c:182 msgid "Galician - Miguel Anxo Bouzada" msgstr "Galiziano - Miguel Anxo Bouzada" #: src/help.c:183 msgid "German - Oliver Frommel, B. Clausius, Ulrich Ringel, Simon Brixel" msgstr "Tedesco - Oliver Frommel, B. Clausius, Ulrich Ringel, Simon Brixel" #: src/help.c:184 msgid "Hungarian - Ur Balazs" msgstr "" #: src/help.c:185 msgid "Italian - Angelo Gemmi" msgstr "Italiano - Angelo Gemmi" #: src/help.c:186 msgid "Japanese - Norihiro YONEDA" msgstr "Giapponese - Norihiro YONEDA" #: src/help.c:187 msgid "Kabyle - Yacine Bouklif" msgstr "" #: src/help.c:188 msgid "Polish - Bartosz Kaszubowski, LucaS" msgstr "Polacco - Bartosz Kaszubowski, LucaS" #: src/help.c:189 msgid "Portuguese - Israel G. Lugo, Tiago Silva" msgstr "Portoghese - Israel G. Lugo, Tiago Silva" #: src/help.c:190 msgid "Russian - Sergey Irupin, Dmitry Groshev" msgstr "Russo - Sergey Irupin, Dmitry Groshev" #: src/help.c:191 msgid "Simplified Chinese - Cecc" msgstr "Cinese semplificato - Cecc" #: src/help.c:192 msgid "Slovak - Jozef Riha" msgstr "Slovacco - Jozef Riha" #: src/help.c:193 msgid "" "Spanish - Guadalinex Team (Junta de Andalucia), Antonio Sanchez Leon, Miguel " "Anxo Bouzada, Francisco Jose Rey, Adolfo Jayme" msgstr "" "Spagnolo - Guadalinex Team (Junta de Andalucia), Antonio Sanchez Leon, " "Miguel Anxo Bouzada, Francisco Jose Rey, Adolfo Jayme" #: src/help.c:194 msgid "Swedish - Daniel Nylander, Daniel Eriksson" msgstr "Svedese - Daniel Nylander, Daniel Eriksson" #: src/help.c:195 msgid "Tagalog - Anjelo delCarmen" msgstr "" #: src/help.c:196 msgid "Taiwanese Chinese - Wei-Lun Chao" msgstr "Cinese di Taiwan - Wei-Lun Chao" #: src/help.c:197 msgid "Turkish - Muhammet Kara, Tutku Dalmaz" msgstr "Turco - Muhammet Kara, Tutku Dalmaz" #: src/info.c:258 msgid "Information" msgstr "Informazioni" #: src/info.c:260 msgid "Memory" msgstr "Memoria" #: src/info.c:261 msgid "Total memory for main + undo images" msgstr "Memoria totale per l'applicazione principale + annullamenti immagini" #: src/info.c:263 msgid "Undo / Redo / Max levels used" msgstr "Annulla / Ripristina / Livello massimo di annullamenti" #: src/info.c:265 msgid "Unused" msgstr "Inutilizzato" #: src/info.c:269 msgid "Unique RGB pixels" msgstr "Pixel unici RGB" #: src/info.c:272 src/layer.c:121 msgid "Layers" msgstr "Livelli" #: src/info.c:273 msgid "Total layer memory usage" msgstr "Memoria totale in uso" #: src/info.c:277 msgid "Colour Histogram" msgstr "Istogramma colore" #: src/info.c:289 src/otherwindow.c:1614 msgid "Index" msgstr "Indice" #: src/info.c:290 msgid "Canvas pixels" msgstr "Pixel della tela" #: src/info.c:328 #, c-format msgid "Clipboard = %i x %i" msgstr "Appunti = %i x %i" #: src/info.c:328 #, c-format msgid "Clipboard = %i x %i x RGB" msgstr "Appunti = %i x %i x RGB" #: src/info.c:377 msgid "Orphans" msgstr "Orfani" #: src/info.c:383 #, c-format msgid "Colour index totals - %i of %i used" msgstr "Indice complessivo dei colori - %i di %i usati" #: src/inifile.c:966 msgid "" "Could not find home directory. Using current directory as home directory." msgstr "" "Impossibile trovare la cartella home. Utilizzo cartella corrente come " "cartella Home" #: src/layer.c:63 msgid "Background" msgstr "Sfondo" #: src/layer.c:122 src/mainwindow.c:5931 msgid "(Modified)" msgstr "(Modificato)" #: src/layer.c:123 src/mainwindow.c:5932 msgid "Untitled" msgstr "Senza nome" #: src/layer.c:308 #, c-format msgid "Do you really want to delete layer %i (%s) ?" msgstr "Vuoi davvero eliminare il livello %i (%s)" #: src/layer.c:380 msgid "" "One or more of the layers contains changes that have not been saved. Do you " "really want to lose these changes?" msgstr "" "Uno o più livelli contengono modifiche che non sono state salvate. Vuoi " "davvero non tenere traccia di queste modifiche?" #: src/layer.c:381 src/mainwindow.c:1028 msgid "Cancel Operation" msgstr "Cancella operazione" #: src/layer.c:381 src/mainwindow.c:1028 msgid "Lose Changes" msgstr "Non salvare le modifiche" #: src/layer.c:523 #, c-format msgid "%d layers failed to load" msgstr "%d impossibile caricare livello" #: src/layer.c:826 msgid "" "One or more of the image layers has not been saved. You must save each " "image individually before saving the layers text file in order to load this " "composite image in the future." msgstr "" "Uno o più livelli dell'immagine non sono stati salvati. Devi salvare ogni " "immagine individualmente prima di salvare il file di testo coi livelli per " "caricare questa imagine composita in futuro" #: src/layer.c:841 msgid "Do you really want to delete all of the layers?" msgstr "Vuoi davvero cancellare tutti i livelli?" #: src/layer.c:970 msgid "You cannot add any more layers." msgstr "Non puoi aggiungere più livelli" #: src/layer.c:1083 src/otherwindow.c:241 msgid "New Layer" msgstr "Nuovo livello" #: src/layer.c:1085 msgid "Raise" msgstr "Porta sù" #: src/layer.c:1087 msgid "Lower" msgstr "Porta giù" #: src/layer.c:1089 msgid "Duplicate Layer" msgstr "Duplica livello" #: src/layer.c:1091 msgid "Centralise Layer" msgstr "Centra livello" #: src/layer.c:1093 msgid "Delete Layer" msgstr "Elimina livello" #: src/layer.c:1095 msgid "Close Layers Window" msgstr "Chiudi finestra dei livelli" #: src/layer.c:1101 msgid "Layer Name" msgstr "Nome livello" #: src/layer.c:1104 src/toolbar.c:209 msgid "Position" msgstr "Posizione" #: src/layer.c:1112 msgid "Transparent Colour" msgstr "Colore trasparente" #: src/layer.c:1117 msgid "Show all layers in main window" msgstr "Mostra tutti i livelli nella finestra principale" #: src/mainwindow.c:67 src/otherwindow.c:844 src/otherwindow.c:2756 #: src/toolbar.c:342 msgid "Image" msgstr "Immagine" #: src/mainwindow.c:69 src/mainwindow.c:489 src/otherwindow.c:1613 #: src/otherwindow.c:2302 msgid "RGB" msgstr "RGB" #: src/mainwindow.c:69 src/otherwindow.c:1613 src/otherwindow.c:2302 msgid "sRGB" msgstr "sRGB" #: src/mainwindow.c:342 msgid "There were no unused colours to remove!" msgstr "Non ci sono colori inutilizzati da rimuovere!" #: src/mainwindow.c:371 msgid "The palette does not contain 2 colours that have identical RGB values" msgstr "La tavolozza non contiene 2 colori che abbiano gli stessi valori RGB" #: src/mainwindow.c:374 #, c-format msgid "" "The palette contains %i colours that have identical RGB values. Do you " "really want to merge them into one index and realign the canvas?" msgstr "" "La tavolozza contiene %i colori che hanno identici valori RGB. Vuoi davvero " "fonderli in uno e riallineare le tele?" #: src/mainwindow.c:492 msgid "indexed" msgstr "Indicizzato" #: src/mainwindow.c:498 #, c-format msgid "" "You are trying to save an %s image to an %s file which is not possible. I " "would suggest you save with a PNG extension." msgstr "" "Si sta tentando di salvare un immagine %s su un file %s per il quale " "l'operazione non è permessa. Suggerisco di salvare con estensione png" #: src/mainwindow.c:500 #, c-format msgid "" "You are trying to save an %s file with a palette of more than %d colours. " "Either use another format or reduce the palette to %d colours." msgstr "" "Si sta tentando di salvare un file %s con una tavolozza di più di %d colori " "utilizzare un altro formato o ridurre la tavolozza a %d colori" #: src/mainwindow.c:578 msgid "Unable to load clipboard" msgstr "Impossibile caricare gli appunti" #: src/mainwindow.c:604 msgid "Unable to save clipboard" msgstr "Impossibile salvare gli appunti" #: src/mainwindow.c:775 msgid "Zoom in" msgstr "" #: src/mainwindow.c:777 msgid "Zoom out" msgstr "" #: src/mainwindow.c:779 #, c-format msgid "10% zoom" msgstr "" #: src/mainwindow.c:781 #, c-format msgid "25% zoom" msgstr "" #: src/mainwindow.c:783 #, c-format msgid "50% zoom" msgstr "" #: src/mainwindow.c:785 #, c-format msgid "100% zoom" msgstr "" #: src/mainwindow.c:787 #, c-format msgid "400% zoom" msgstr "" #: src/mainwindow.c:789 #, c-format msgid "600% zoom" msgstr "" #: src/mainwindow.c:791 #, c-format msgid "800% zoom" msgstr "" #: src/mainwindow.c:793 #, c-format msgid "1000% zoom" msgstr "" #: src/mainwindow.c:795 #, c-format msgid "1200% zoom" msgstr "" #: src/mainwindow.c:797 #, c-format msgid "1600% zoom" msgstr "" #: src/mainwindow.c:799 #, c-format msgid "2000% zoom" msgstr "" #: src/mainwindow.c:801 #, c-format msgid "4000% zoom" msgstr "" #: src/mainwindow.c:803 #, c-format msgid "8000% zoom" msgstr "" #: src/mainwindow.c:805 #, c-format msgid "10% opacity" msgstr "" #: src/mainwindow.c:807 #, c-format msgid "20% opacity" msgstr "" #: src/mainwindow.c:809 #, c-format msgid "30% opacity" msgstr "" #: src/mainwindow.c:811 #, c-format msgid "40% opacity" msgstr "" #: src/mainwindow.c:813 #, c-format msgid "50% opacity" msgstr "" #: src/mainwindow.c:815 #, c-format msgid "60% opacity" msgstr "" #: src/mainwindow.c:817 #, c-format msgid "70% opacity" msgstr "" #: src/mainwindow.c:819 #, c-format msgid "80% opacity" msgstr "" #: src/mainwindow.c:821 #, c-format msgid "90% opacity" msgstr "" #: src/mainwindow.c:823 #, c-format msgid "100% opacity" msgstr "" #: src/mainwindow.c:825 msgid "Increase opacity" msgstr "" #: src/mainwindow.c:827 msgid "Decrease opacity" msgstr "" #: src/mainwindow.c:829 msgid "Draw open arrow head" msgstr "" #: src/mainwindow.c:831 msgid "Draw closed arrow head" msgstr "" #: src/mainwindow.c:833 msgid "Previous colour A" msgstr "" #: src/mainwindow.c:835 msgid "Next colour A" msgstr "" #: src/mainwindow.c:837 msgid "Previous colour B" msgstr "" #: src/mainwindow.c:839 msgid "Next colour B" msgstr "" #: src/mainwindow.c:841 msgid "Previous pattern" msgstr "" #: src/mainwindow.c:843 msgid "Next pattern" msgstr "" #: src/mainwindow.c:845 msgid "Larger brush" msgstr "" #: src/mainwindow.c:847 msgid "Smaller brush" msgstr "" #: src/mainwindow.c:849 msgid "View window - Zoom in" msgstr "" #: src/mainwindow.c:851 msgid "View window - Zoom out" msgstr "" #: src/mainwindow.c:1027 msgid "" "This canvas/palette contains changes that have not been saved. Do you " "really want to lose these changes?" msgstr "" "Questa tela / tavolozza contiene modifiche che non sono state salvate. Vuoi " "davvero perdere questi cambiamenti?" #: src/mainwindow.c:1094 msgid "Do you really want to quit?" msgstr "Vuoi davvero uscire?" #: src/mainwindow.c:3754 msgid "Empty string or broken quoting" msgstr "" #: src/mainwindow.c:3755 msgid "Script must begin with a command" msgstr "" #: src/mainwindow.c:3756 msgid "Script nesting limit exceeded" msgstr "" #: src/mainwindow.c:3765 #, c-format msgid "'%s' does not match any item" msgstr "" #: src/mainwindow.c:3767 #, c-format msgid "'%s' matches a non-scriptable item" msgstr "" #: src/mainwindow.c:3769 #, c-format msgid "'%s' matches a disabled item" msgstr "" #: src/mainwindow.c:3788 #, c-format msgid "'%s' value does not fit item" msgstr "" #: src/mainwindow.c:3969 msgid "Script" msgstr "" #: src/mainwindow.c:3982 src/spawn.c:656 src/spawn.c:662 msgid "Action" msgstr "Azione" #: src/mainwindow.c:3991 src/spawn.c:666 msgid "Execute" msgstr "Esegui" #: src/mainwindow.c:4045 msgid "Unable to load script" msgstr "" #: src/mainwindow.c:5182 msgid "/_File" msgstr "" #: src/mainwindow.c:5184 msgid "//New" msgstr "//Nuovo" #: src/mainwindow.c:5186 msgid "//Open ..." msgstr "//Apri ..." #: src/mainwindow.c:5188 src/mainwindow.c:5669 msgid "//Save" msgstr "//Salva" #: src/mainwindow.c:5190 src/mainwindow.c:5549 src/mainwindow.c:5627 #: src/mainwindow.c:5671 msgid "//Save As ..." msgstr "//Salva come ..." #: src/mainwindow.c:5192 msgid "//Export Undo Images ..." msgstr "//Esporta Immagini annullate ..." #: src/mainwindow.c:5194 msgid "//Export Undo Images (reversed) ..." msgstr "//Esporta Immagini annullate (invertito) ..." #: src/mainwindow.c:5196 msgid "//Export ASCII Art ..." msgstr "//Esporta in ASCII Art ..." #: src/mainwindow.c:5198 msgid "//Export Animated GIF ..." msgstr "//Esporta GIF animata ..." #: src/mainwindow.c:5201 msgid "//Actions" msgstr "//Azioni" #: src/mainwindow.c:5235 src/mainwindow.c:5488 msgid "///Configure" msgstr "///Configura" #: src/mainwindow.c:5290 msgid "//Quit" msgstr "//Esci" #: src/mainwindow.c:5293 msgid "/_Edit" msgstr "/_Modifica" #: src/mainwindow.c:5295 msgid "//Undo" msgstr "//Annulla" #: src/mainwindow.c:5297 msgid "//Redo" msgstr "//Ripristina" #: src/mainwindow.c:5300 msgid "//Cut" msgstr "//Taglia" #: src/mainwindow.c:5302 msgid "//Copy" msgstr "//Copia" #: src/mainwindow.c:5304 msgid "//Copy To Palette" msgstr "//Copia nella tavolozza" #: src/mainwindow.c:5306 msgid "//Paste To Centre" msgstr "//Incolla al centro" #: src/mainwindow.c:5308 msgid "//Paste To New Layer" msgstr "//Incolla su un nuovo livello" #: src/mainwindow.c:5310 msgid "//Paste" msgstr "//Incolla" #: src/mainwindow.c:5312 msgid "//Paste Text" msgstr "//Incolla testo" #: src/mainwindow.c:5318 msgid "//Paste Text (FreeType)" msgstr "//Incolla testo (FreeType)" #: src/mainwindow.c:5321 msgid "//Paste Palette" msgstr "//Incolla tavolozza" #: src/mainwindow.c:5323 msgid "//Load Clipboard" msgstr "//Carica appunti" #: src/mainwindow.c:5350 msgid "//Save Clipboard" msgstr "//Salva negli appunti" #: src/mainwindow.c:5377 msgid "//Import Clipboard from System" msgstr "//Importa appunti dal sistema" #: src/mainwindow.c:5378 msgid "//Export Clipboard to System" msgstr "//Esporta appunti sul sistema" #: src/mainwindow.c:5381 msgid "//Choose Pattern ..." msgstr "//Scegli motivo ..." #: src/mainwindow.c:5383 msgid "//Choose Brush ..." msgstr "//Scegli pennello ..." #: src/mainwindow.c:5385 msgid "//Choose Colour ..." msgstr "" #: src/mainwindow.c:5392 msgid "/_View" msgstr "/_Vista" #: src/mainwindow.c:5394 msgid "//Show Main Toolbar" msgstr "//Mostra barra principale" #: src/mainwindow.c:5396 msgid "//Show Tools Toolbar" msgstr "//Mostra barra strumenti" #: src/mainwindow.c:5399 msgid "//Show Settings Toolbar" msgstr "//Mostra impostazioni barra strumenti" #: src/mainwindow.c:5402 msgid "//Show Dock" msgstr "//Mostra area di lavoro" #: src/mainwindow.c:5404 msgid "//Show Palette" msgstr "//Mostra tavolozza" #: src/mainwindow.c:5406 msgid "//Show Status Bar" msgstr "//Mostra barra di stato" #: src/mainwindow.c:5409 msgid "//Toggle Image View" msgstr "//Passa a vista immagine" #: src/mainwindow.c:5413 msgid "//Centralize Image" msgstr "//Centra immagine" #: src/mainwindow.c:5414 msgid "//Show Zoom Grid" msgstr "//Mostra zoom griglia" #: src/mainwindow.c:5415 msgid "//Snap To Tile Grid" msgstr "" #: src/mainwindow.c:5417 msgid "//Configure Grid ..." msgstr "//Configura Griglia ..." #: src/mainwindow.c:5418 msgid "//Tracing Image ..." msgstr "//Tracciatura immagine ..." #: src/mainwindow.c:5421 msgid "//View Window" msgstr "//Mostra finestre" #: src/mainwindow.c:5423 msgid "//Horizontal Split" msgstr "//Dividi in orizzontale" #: src/mainwindow.c:5425 msgid "//Focus View Window" msgstr "//Finestra di anteprima" #: src/mainwindow.c:5427 msgid "//Pan Window" msgstr "//Finestra panoramica" #: src/mainwindow.c:5430 msgid "//Layers Window" msgstr "//Finestra livelli" #: src/mainwindow.c:5433 msgid "/_Image" msgstr "/_Immagine" #: src/mainwindow.c:5436 msgid "//Convert To RGB" msgstr "//Converti in RGB" #: src/mainwindow.c:5438 msgid "//Convert To Indexed ..." msgstr "//Converti in scala di colore ..." #: src/mainwindow.c:5441 msgid "//Scale Canvas ..." msgstr "//Scala tela ..." #: src/mainwindow.c:5443 msgid "//Resize Canvas ..." msgstr "//Ridimensiona tela ..." #: src/mainwindow.c:5445 msgid "//Crop" msgstr "//Ritaglia" #: src/mainwindow.c:5448 src/mainwindow.c:5517 msgid "//Flip Vertically" msgstr "//Ribalta in verticale" #: src/mainwindow.c:5449 src/mainwindow.c:5519 msgid "//Flip Horizontally" msgstr "//Ribalta in orizzontale" #: src/mainwindow.c:5452 src/mainwindow.c:5521 msgid "//Rotate Clockwise" msgstr "//Ruota in senso orario" #: src/mainwindow.c:5453 src/mainwindow.c:5523 msgid "//Rotate Anti-Clockwise" msgstr "//Ruota in senso antiorario" #: src/mainwindow.c:5454 msgid "//Free Rotate ..." msgstr "//Rotazione libera ..." #: src/mainwindow.c:5455 msgid "//Skew ..." msgstr "//Deforma ..." #: src/mainwindow.c:5458 msgid "//Segment ..." msgstr "" #: src/mainwindow.c:5462 msgid "//Script ..." msgstr "" #: src/mainwindow.c:5464 msgid "//Scripts" msgstr "" #: src/mainwindow.c:5491 msgid "//Information ..." msgstr "//Informazioni ..." #: src/mainwindow.c:5494 msgid "//Preferences ..." msgstr "//Preferenze ..." #: src/mainwindow.c:5497 msgid "/_Selection" msgstr "/_Selezione" #: src/mainwindow.c:5499 msgid "//Select All" msgstr "//Seleziona tutto" #: src/mainwindow.c:5501 msgid "//Select None (Esc)" msgstr "//Nessuna selezione (Esc)" #: src/mainwindow.c:5503 msgid "//Lasso Selection" msgstr "//Selezione laccio" #: src/mainwindow.c:5505 msgid "//Lasso Selection Cut" msgstr "//Taglia selezione laccio" #: src/mainwindow.c:5508 msgid "//Outline Selection" msgstr "//Selezione bordo" #: src/mainwindow.c:5510 msgid "//Fill Selection" msgstr "//Riempi selezione" #: src/mainwindow.c:5512 msgid "//Outline Ellipse" msgstr "//Ellisse contornata" #: src/mainwindow.c:5514 msgid "//Fill Ellipse" msgstr "//Ellisse piena" #: src/mainwindow.c:5526 msgid "//Horizontal Ramp" msgstr "//Rampa orizzontale" #: src/mainwindow.c:5528 msgid "//Vertical Ramp" msgstr "//Rampa verticale" #: src/mainwindow.c:5531 msgid "//Alpha Blend A,B" msgstr "//Trasparenza alfa A,B" #: src/mainwindow.c:5533 msgid "//Move Alpha to Mask" msgstr "//Porta alfa a maschera" #: src/mainwindow.c:5535 msgid "//Mask Colour A,B" msgstr "//Maschera colore A,B" #: src/mainwindow.c:5537 msgid "//Unmask Colour A,B" msgstr "//Elimina maschera colore A,B" #: src/mainwindow.c:5539 msgid "//Mask All Colours" msgstr "//Maschera tutti i colori" #: src/mainwindow.c:5541 msgid "//Clear Mask" msgstr "//Cancella maschera" #: src/mainwindow.c:5544 msgid "/_Palette" msgstr "/_Tavolozza" #: src/mainwindow.c:5548 src/mainwindow.c:5626 msgid "//Load ..." msgstr "//Carica ..." #: src/mainwindow.c:5550 msgid "//Load Default" msgstr "//Carica predefinita" #: src/mainwindow.c:5552 msgid "//Mask All" msgstr "//Maschera tutto" #: src/mainwindow.c:5553 msgid "//Mask None" msgstr "//Nessuna maschera" #: src/mainwindow.c:5555 msgid "//Swap A & B" msgstr "//Scambia colori A & B" #: src/mainwindow.c:5557 msgid "//Edit Colour A & B ..." msgstr "//Modifica colore A & B ..." #: src/mainwindow.c:5559 msgid "//Dither A" msgstr "//Retino A" #: src/mainwindow.c:5561 msgid "//Palette Editor ..." msgstr "//Modifica tavolozza ..." #: src/mainwindow.c:5563 msgid "//Set Palette Size ..." msgstr "//Imposta dimensioni tavolozza ..." #: src/mainwindow.c:5564 msgid "//Merge Duplicate Colours" msgstr "//Fondi colori duplicati" #: src/mainwindow.c:5566 msgid "//Remove Unused Colours" msgstr "//Rimuovi colori non in uso" #: src/mainwindow.c:5569 msgid "//Create Quantized ..." msgstr "//Crea Quantizzato ..." #: src/mainwindow.c:5572 msgid "//Sort Colours ..." msgstr "//Ordina colori ..." #: src/mainwindow.c:5573 msgid "//Palette Shifter ..." msgstr "//Cicla ..." #: src/mainwindow.c:5574 msgid "//Pick Gradient ..." msgstr "" #: src/mainwindow.c:5576 msgid "/Effe_cts" msgstr "/Effetti" #: src/mainwindow.c:5578 msgid "//Transform Colour ..." msgstr "//Trasforma colore ..." #: src/mainwindow.c:5580 msgid "//Invert" msgstr "//Inverti" #: src/mainwindow.c:5582 msgid "//Greyscale" msgstr "//Scala di grigio" #: src/mainwindow.c:5584 msgid "//Greyscale (Gamma corrected)" msgstr "//Scala di grigio (con correzione gamma)" #: src/mainwindow.c:5586 msgid "//Normalize" msgstr "" #: src/mainwindow.c:5587 src/mainwindow.c:5658 msgid "//Threshold ..." msgstr "//Soglia ..." #: src/mainwindow.c:5588 msgid "//Map ..." msgstr "" #: src/mainwindow.c:5590 msgid "//Isometric Transformation" msgstr "//Trasformazione isometrica" #: src/mainwindow.c:5592 msgid "///Left Side Down" msgstr "///Sinistra verso il basso" #: src/mainwindow.c:5593 msgid "///Right Side Down" msgstr "///Destra verso il basso" #: src/mainwindow.c:5594 msgid "///Top Side Right" msgstr "///Lato superiore destro" #: src/mainwindow.c:5595 msgid "///Bottom Side Right" msgstr "///Lato inferiore destro" #: src/mainwindow.c:5598 msgid "//Edge Detect ..." msgstr "//Trova bordi ..." #: src/mainwindow.c:5600 msgid "//Difference of Gaussians ..." msgstr "//Differenza di Gaussiani ..." #: src/mainwindow.c:5602 msgid "//Sharpen ..." msgstr "//Nitidezza ..." #: src/mainwindow.c:5604 msgid "//Unsharp Mask ..." msgstr "//Maschera sfocata ..." #: src/mainwindow.c:5606 msgid "//Soften ..." msgstr "//Amorbidisci ..." #: src/mainwindow.c:5608 msgid "//Gaussian Blur ..." msgstr "//Sfocatura Gaussiana ..." #: src/mainwindow.c:5610 msgid "//Kuwahara-Nagao Blur ..." msgstr "//Sfocatura Kuwahara-Nagao ..." #: src/mainwindow.c:5612 msgid "//Emboss" msgstr "//Rilievo" #: src/mainwindow.c:5614 msgid "//Dilate" msgstr "//Dilata" #: src/mainwindow.c:5616 msgid "//Erode" msgstr "//Erodi" #: src/mainwindow.c:5619 msgid "//Solid Noise ..." msgstr "" #: src/mainwindow.c:5620 msgid "//Bacteria ..." msgstr "" #: src/mainwindow.c:5623 msgid "/Cha_nnels" msgstr "/Canali" #: src/mainwindow.c:5625 msgid "//New ..." msgstr "//Nuovo ..." #: src/mainwindow.c:5628 msgid "//Delete ..." msgstr "//Elimina ..." #: src/mainwindow.c:5632 msgid "//Edit Image" msgstr "//Modifica immagine" #: src/mainwindow.c:5635 msgid "//Edit Alpha" msgstr "//Modifica alfa" #: src/mainwindow.c:5638 msgid "//Edit Selection" msgstr "//Modifica selezione" #: src/mainwindow.c:5641 msgid "//Edit Mask" msgstr "//Modifica maschera" #: src/mainwindow.c:5645 msgid "//Hide Image" msgstr "//Nascondi immagine" #: src/mainwindow.c:5648 msgid "//Disable Alpha" msgstr "//Disabilita alfa" #: src/mainwindow.c:5651 msgid "//Disable Selection" msgstr "//Disabilita Selezione" #: src/mainwindow.c:5654 msgid "//Disable Mask" msgstr "//Disabilita maschera" #: src/mainwindow.c:5657 msgid "//Couple RGBA Operations" msgstr "//Operazioni RGBA" #: src/mainwindow.c:5659 msgid "//Unassociate Alpha" msgstr "//Disassocia alfa" #: src/mainwindow.c:5663 msgid "//View Alpha as an Overlay" msgstr "//Vedi alfa come sovrapposizione" #: src/mainwindow.c:5664 msgid "//Configure Overlays ..." msgstr "//Configura sovrapposizione ..." #: src/mainwindow.c:5666 msgid "/_Layers" msgstr "/_Livelli" #: src/mainwindow.c:5668 msgid "//New Layer" msgstr "//Nuovo livello" #: src/mainwindow.c:5672 msgid "//Save Composite Image ..." msgstr "//Salva immagine composita ..." #: src/mainwindow.c:5673 msgid "//Composite to New Layer" msgstr "//Composita su un nuovo livello" #: src/mainwindow.c:5674 msgid "//Remove All Layers" msgstr "//Rimuovi tutti i livelli" #: src/mainwindow.c:5676 msgid "//Configure Animation ..." msgstr "//Configura animazione ..." #: src/mainwindow.c:5677 msgid "//Preview Animation ..." msgstr "//Anteprima animazione ..." #: src/mainwindow.c:5678 msgid "//Set Key Frame ..." msgstr "//Imposta fotogramma chiave ..." #: src/mainwindow.c:5679 msgid "//Remove All Key Frames ..." msgstr "//Rimuovi tutti i fotogrammi chiave ..." #: src/mainwindow.c:5681 msgid "/More..." msgstr "/Ulteriori informazioni..." #: src/mainwindow.c:5683 msgid "/_Help" msgstr "/_Aiuto" #: src/mainwindow.c:5684 msgid "//Documentation" msgstr "//Documentazione" #: src/mainwindow.c:5686 msgid "//About" msgstr "//A proposito di..." #: src/mainwindow.c:5689 msgid "//Keyboard Shortcuts ..." msgstr "" #: src/mainwindow.c:5690 msgid "//Rebind Shortcut Keycodes" msgstr "//Riassegna scorciatoie da tastiera" #: src/memory.c:2800 msgid "Quantize Pass 1" msgstr "" #: src/memory.c:2854 msgid "Quantize Pass 2" msgstr "" #: src/memory.c:3073 src/memory.c:3458 msgid "Converting to Indexed Palette" msgstr "Conversione in scala di colore" #: src/memory.c:5135 src/otherwindow.c:540 msgid "Bacteria Effect" msgstr "Effetto bacteria" #: src/memory.c:5170 msgid "Rotating" msgstr "Rotazione" #: src/memory.c:5511 msgid "Free Rotation" msgstr "Rotazione libera" #: src/memory.c:6096 msgid "Scaling Image" msgstr "Scalatura immagine" #: src/memory.c:7560 msgid "Counting Unique RGB Pixels" msgstr "Conta pixel RGB unici" #: src/memory.c:7608 msgid "Applying Effect" msgstr "Applicazione effetto" #: src/memory.c:8792 msgid "Kuwahara-Nagao Filter" msgstr "Filtro Kuwahara-Nagao" #: src/memory.c:10456 src/otherwindow.c:2665 msgid "Skew" msgstr "Deforma" #: src/memory.c:10630 msgid "Segmentation Pass 1" msgstr "" #: src/memory.c:10757 msgid "Segmentation Pass 2" msgstr "" #: src/memory.c:11019 src/otherwindow.c:3156 msgid "Solid Noise" msgstr "" #: src/mygtk.c:134 src/mygtk.c:163 msgid "Please Wait ..." msgstr "Attendere prego ..." #: src/mygtk.c:141 msgid "STOP" msgstr "STOP" #: src/mygtk.c:504 msgid "Disabled" msgstr "" #: src/mygtk.c:504 src/toolbar.c:301 msgid "Screen" msgstr "Scherma" #: src/mygtk.c:504 msgid "Window" msgstr "" #: src/mygtk.c:508 msgid "Input" msgstr "" #: src/mygtk.c:512 msgid "Device:" msgstr "" #: src/mygtk.c:514 msgid "Mode:" msgstr "" #: src/mygtk.c:519 msgid "Axes" msgstr "" #: src/mygtk.c:524 msgid "X:" msgstr "" #: src/mygtk.c:525 msgid "Y:" msgstr "" #: src/mygtk.c:526 msgid "Pressure:" msgstr "" #: src/mygtk.c:527 msgid "X tilt:" msgstr "" #: src/mygtk.c:528 msgid "Y tilt:" msgstr "" #: src/mygtk.c:529 msgid "Wheel:" msgstr "" #: src/mygtk.c:579 msgid "none" msgstr "" #: src/otherwindow.c:236 msgid "24 bit RGB" msgstr "24 bit RGB" #: src/otherwindow.c:236 src/otherwindow.c:3179 msgid "Greyscale" msgstr "Scala di Grigio" #: src/otherwindow.c:237 msgid "Indexed Palette" msgstr "Scala di colore" #: src/otherwindow.c:237 msgid "From Clipboard" msgstr "Dagli appunti" #: src/otherwindow.c:237 msgid "Grab Screenshot" msgstr "Cattura schermata" #: src/otherwindow.c:242 src/toolbar.c:542 msgid "New Image" msgstr "Nuova immagine" #: src/otherwindow.c:246 src/otherwindow.c:3164 msgid "Colours" msgstr "Colori" #: src/otherwindow.c:409 msgid "Pattern Chooser" msgstr "Selezionatore motivi" #: src/otherwindow.c:497 msgid "Set Palette Size" msgstr "Imposta dimensioni tavolozza" #: src/otherwindow.c:517 src/otherwindow.c:591 src/otherwindow.c:870 #: src/otherwindow.c:2538 src/otherwindow.c:2776 src/otherwindow.c:2939 #: src/prefs.c:338 src/prefs.c:538 msgid "Apply" msgstr "Applica" #: src/otherwindow.c:573 msgid "Luminance" msgstr "Luminanza" #: src/otherwindow.c:573 src/otherwindow.c:814 msgid "Brightness" msgstr "Luminosità" #: src/otherwindow.c:574 msgid "Distance to A" msgstr "Distanza ad A" #: src/otherwindow.c:575 msgid "Projection to A->B" msgstr "Proiezione ad A->B" #: src/otherwindow.c:576 msgid "Frequency" msgstr "Frequenza" #: src/otherwindow.c:580 msgid "Sort Palette Colours" msgstr "Ordina colori tavolozza" #: src/otherwindow.c:582 msgid "Start Index" msgstr "Inizio scala" #: src/otherwindow.c:583 msgid "End Index" msgstr "Fine scala" #: src/otherwindow.c:589 msgid "Reverse Order" msgstr "Ordine inverso" #: src/otherwindow.c:805 msgid "Bitwise" msgstr "Bit a bit" #: src/otherwindow.c:805 msgid "Truncated" msgstr "Troncato" #: src/otherwindow.c:805 msgid "Rounded" msgstr "Arrotondato" #: src/otherwindow.c:809 src/toolbar.c:311 src/toolbar.c:558 msgid "Transform Colour" msgstr "Trasforma colore" #: src/otherwindow.c:812 msgid "Gamma" msgstr "Gamma" #: src/otherwindow.c:816 msgid "Contrast" msgstr "Contrasto" #: src/otherwindow.c:822 src/otherwindow.c:1674 msgid "Posterize" msgstr "Posterizza" #: src/otherwindow.c:831 msgid "Show Detail" msgstr "Mostra dettagli" #: src/otherwindow.c:836 msgid "Posterize type" msgstr "Tipo di posterizzazione" #: src/otherwindow.c:857 msgid "Auto-Preview" msgstr "Anteprima automatica" #: src/otherwindow.c:869 msgid "Reset" msgstr "Resetta" #: src/otherwindow.c:931 msgid "New geometry is the same as now - nothing to do." msgstr "" "La nuova geometria è la stessa attuale - nessuna trasformazione effettuata" #: src/otherwindow.c:980 msgid "The operating system cannot allocate the memory for this operation." msgstr "Il sistema operativo non può allocare memoria per questa operazione" #: src/otherwindow.c:982 msgid "" "You have not allocated enough memory in the Preferences window for this " "operation." msgstr "" "Non hai abbastanza memoria assegnata nella finestra delle preferenze per " "questa operazione" #: src/otherwindow.c:993 src/otherwindow.c:2495 msgid "Mirror" msgstr "Rispecchia" #: src/otherwindow.c:993 src/otherwindow.c:994 msgid "Tile" msgstr "Piastrella" #: src/otherwindow.c:993 msgid "Void" msgstr "Vuoto" #: src/otherwindow.c:994 src/shifter.c:283 msgid "Clear" msgstr "Cancella" #: src/otherwindow.c:994 msgid "Mirror tile" msgstr "Rispecchia piastrella" #: src/otherwindow.c:996 msgid "Nearest Neighbour" msgstr "Più vicino" #: src/otherwindow.c:997 msgid "Bilinear / Area Mapping" msgstr "Bilineare / Mappatura area" #: src/otherwindow.c:998 msgid "Bicubic" msgstr "Bicubico" #: src/otherwindow.c:999 msgid "Bicubic edged" msgstr "Bicubico edged" #: src/otherwindow.c:1000 msgid "Bicubic better" msgstr "Bicubico migliore" #: src/otherwindow.c:1001 msgid "Bicubic sharper" msgstr "Bicubico più nitido" #: src/otherwindow.c:1002 msgid "Blackman-Harris" msgstr "Blackman-Harris" #: src/otherwindow.c:1008 msgid "Scale Canvas" msgstr "Scala tela" #: src/otherwindow.c:1009 msgid "Resize Canvas" msgstr "Ridimensiona tela" #: src/otherwindow.c:1012 msgid "Original " msgstr "Originale " #: src/otherwindow.c:1013 msgid "New" msgstr "Nuovo" #: src/otherwindow.c:1014 msgid "Width " msgstr "Larghezza " #: src/otherwindow.c:1018 msgid "Height " msgstr "Altezza " #: src/otherwindow.c:1023 src/otherwindow.c:2514 src/otherwindow.c:2672 #: src/toolbar.c:212 msgid "Offset" msgstr "Spostamento" #: src/otherwindow.c:1026 src/otherwindow.c:1615 src/viewer.c:1209 msgid "Centre" msgstr "Centra" #: src/otherwindow.c:1033 src/otherwindow.c:1052 msgid "Fix Aspect Ratio" msgstr "Mantieni proporzioni" #: src/otherwindow.c:1039 src/otherwindow.c:2070 src/toolbar.c:312 msgid "Settings" msgstr "Impostazioni" #: src/otherwindow.c:1046 msgid "Sharper image reduction" msgstr "Netta riduzione immagine" #: src/otherwindow.c:1047 msgid "Boundary extension" msgstr "" #: src/otherwindow.c:1613 src/otherwindow.c:2302 msgid "HSV" msgstr "HSV" #: src/otherwindow.c:1614 msgid "Highlight" msgstr "" #: src/otherwindow.c:1615 msgid "Limit" msgstr "Limite" #: src/otherwindow.c:1616 msgid "Sphere" msgstr "Sfera" #: src/otherwindow.c:1616 src/otherwindow.c:2670 msgid "Angle" msgstr "Angolo" #: src/otherwindow.c:1616 msgid "Cube" msgstr "Cubo" #: src/otherwindow.c:1617 msgid "Opaque" msgstr "Opaco" #: src/otherwindow.c:1617 msgid "Border" msgstr "Bordo" #: src/otherwindow.c:1618 msgid "Transparent" msgstr "Trasparente" #: src/otherwindow.c:1618 msgid "Tile " msgstr "Piastrella " #: src/otherwindow.c:1618 msgid "Segment" msgstr "" #: src/otherwindow.c:1656 msgid "Scale" msgstr "Scala" #: src/otherwindow.c:1657 src/otherwindow.c:3059 msgid "From" msgstr "Da" #: src/otherwindow.c:1659 src/otherwindow.c:3061 msgid "To" msgstr "A" #: src/otherwindow.c:1699 msgid "Range" msgstr "Gamma" #: src/otherwindow.c:1702 msgid "Inverse" msgstr "Inverso" #: src/otherwindow.c:1710 msgid "Smart grid" msgstr "Gliglia intelligente" #: src/otherwindow.c:1712 msgid "Tile grid" msgstr "Griglia piastrella" #: src/otherwindow.c:1714 msgid "Minimum grid zoom" msgstr "Zoom minimo griglio" #: src/otherwindow.c:1717 msgid "Tile width" msgstr "Larghezza piastrella" #: src/otherwindow.c:1720 msgid "Tile height" msgstr "Altezza piastrella" #: src/otherwindow.c:1744 msgid "Palette Editor" msgstr "Modifica tavolozza" #: src/otherwindow.c:1763 msgid "Configure Overlays" msgstr "Configura sovrapposizione" #: src/otherwindow.c:1782 msgid "Colour Editor" msgstr "Modifica colore" #: src/otherwindow.c:1818 src/toolbar.c:430 msgid "Colour-Selective Mode" msgstr "Modalità Colore-selettivo" #: src/otherwindow.c:1843 msgid "Configure Grid" msgstr "Configura griglia" #: src/otherwindow.c:2045 msgid "Exact Conversion" msgstr "Conversione esatta" #: src/otherwindow.c:2045 msgid "Use Current Palette" msgstr "Usa la tavolozza corrente" #: src/otherwindow.c:2046 msgid "PNN Quantize (slow, better quality)" msgstr "Quantizza PNN (lento, qualità superiore)" #: src/otherwindow.c:2047 msgid "Wu Quantize (fast)" msgstr "Quantizza Wu (veloce)" #: src/otherwindow.c:2048 msgid "Max-Min Quantize (best for small palettes and dithering)" msgstr "Quantizza massimo-minimo (migliore per piccole tavolozze e retinatura)" #: src/otherwindow.c:2049 src/otherwindow.c:2495 src/otherwindow.c:2756 #: src/png.c:2794 src/prefs.c:377 msgid "None" msgstr "Nessuno" #: src/otherwindow.c:2049 msgid "Floyd-Steinberg" msgstr "Floyd-Steinberg" #: src/otherwindow.c:2049 msgid "Stucki" msgstr "Stucki" #: src/otherwindow.c:2052 msgid "Floyd-Steinberg (quick)" msgstr "Floyd-Steinberg (veloce)" #: src/otherwindow.c:2052 msgid "Dithered (effect)" msgstr "Retinato (effetto)" #: src/otherwindow.c:2053 msgid "Scattered (effect)" msgstr "Diffuso (effetto)" #: src/otherwindow.c:2054 msgid "Gamut" msgstr "Gamut" #: src/otherwindow.c:2054 msgid "Weakly" msgstr "Debole" #: src/otherwindow.c:2054 msgid "Strongly" msgstr "Forte" #: src/otherwindow.c:2055 msgid "Off" msgstr "Disattivato" #: src/otherwindow.c:2055 msgid "Separate/Sum" msgstr "Separa/Somma" #: src/otherwindow.c:2055 msgid "Separate/Split" msgstr "Separa/Dividi" #: src/otherwindow.c:2056 msgid "Length/Sum" msgstr "Lunghezza / Somma" #: src/otherwindow.c:2056 msgid "Length/Split" msgstr "Lunghezza/Dividi" #: src/otherwindow.c:2057 msgid "Largest (Linf)" msgstr "Il più larga (Linf)" #: src/otherwindow.c:2057 msgid "Sum (L1)" msgstr "Somma" #: src/otherwindow.c:2057 msgid "Euclidean (L2)" msgstr "Euclideo" #: src/otherwindow.c:2061 msgid "Create Quantized" msgstr "Crea quantizzato" #: src/otherwindow.c:2062 msgid "Convert To Indexed" msgstr "Converti a scala di colore" #: src/otherwindow.c:2065 msgid "Indexed Colours To Use" msgstr "Scala di colori da usare" #: src/otherwindow.c:2078 msgid "Truncate palette" msgstr "Tronca tavolozza" #: src/otherwindow.c:2079 msgid "Diameter based weighting" msgstr "Peso basato su diametro" #: src/otherwindow.c:2084 msgid "Dither" msgstr "Retino" #: src/otherwindow.c:2087 src/otherwindow.c:2584 src/otherwindow.c:2928 msgid "Colour space" msgstr "Spazio colore" #: src/otherwindow.c:2088 src/otherwindow.c:2929 msgid "Difference measure" msgstr "Differenza misura" #: src/otherwindow.c:2089 msgid "Reduce colour bleed" msgstr "Riduci trasparenza colore" #: src/otherwindow.c:2090 msgid "Serpentine scan" msgstr "Serpentine scan" #: src/otherwindow.c:2092 msgid "Error propagation, %" msgstr "Diffusione d'errore" #: src/otherwindow.c:2093 msgid "Selective error propagation" msgstr "Diffusione d'errore selettiva" #: src/otherwindow.c:2097 msgid "Full error precision" msgstr "Precisione completa di errore" #: src/otherwindow.c:2302 msgid "Backward HSV" msgstr "HSV inverso" #: src/otherwindow.c:2303 src/otherwindow.c:2326 msgid "Constant" msgstr "Costante" #: src/otherwindow.c:2307 msgid "Edit Gradient" msgstr "Modifica gradiente" #: src/otherwindow.c:2329 msgid "Points:" msgstr "Punti" #: src/otherwindow.c:2493 msgid "Linear" msgstr "Lineare" #: src/otherwindow.c:2493 src/otherwindow.c:2703 msgid "Bilinear" msgstr "Bilineare" #: src/otherwindow.c:2493 msgid "Radial" msgstr "Radiale" #: src/otherwindow.c:2494 msgid "Square" msgstr "Quadrato" #: src/otherwindow.c:2494 msgid "Angular" msgstr "Angolare" #: src/otherwindow.c:2494 msgid "Conical" msgstr "Conico" #: src/otherwindow.c:2495 msgid "Level " msgstr "" #: src/otherwindow.c:2495 msgid "Repeat" msgstr "Ripeti" #: src/otherwindow.c:2496 msgid "A to B" msgstr "A su B" #: src/otherwindow.c:2496 msgid "A to B (RGB)" msgstr "A su B (RGB)" #: src/otherwindow.c:2497 msgid "A to B (sRGB)" msgstr "A su B (sRGB)" #: src/otherwindow.c:2497 msgid "A to B (HSV)" msgstr "A su B (HSV)" #: src/otherwindow.c:2497 msgid "A to B (backward HSV)" msgstr "A su B (HSV invertito)" #: src/otherwindow.c:2498 msgid "A only" msgstr "A soltanto" #: src/otherwindow.c:2498 src/otherwindow.c:2500 msgid "Custom" msgstr "Personalizzato" #: src/otherwindow.c:2499 msgid "Current to 0" msgstr "Corrente a 0" #: src/otherwindow.c:2499 msgid "Current only" msgstr "Solo corrente" #: src/otherwindow.c:2504 msgid "Configure Gradient" msgstr "Configura gradiente" #: src/otherwindow.c:2507 src/png.c:1001 msgid "Channel" msgstr "Canale" #: src/otherwindow.c:2512 msgid "Length" msgstr "Lunghezza" #: src/otherwindow.c:2513 msgid "Repeat length" msgstr "Ripeti lunghezza" #: src/otherwindow.c:2515 msgid "Gradient type" msgstr "Tipo di gradiente" #: src/otherwindow.c:2516 msgid "Extension type" msgstr "Tipo di estensione" #: src/otherwindow.c:2517 msgid "Distance type" msgstr "" #: src/otherwindow.c:2518 msgid "Preview opacity" msgstr "Anteprima opacità" #: src/otherwindow.c:2527 src/otherwindow.c:2533 src/toolbar.c:309 msgid "Reverse" msgstr "Inverti" #: src/otherwindow.c:2528 src/otherwindow.c:2534 msgid "Edit Custom" msgstr "Edita personalizzato" #: src/otherwindow.c:2592 msgid "Pick Gradient" msgstr "Seleziona gradiente" #: src/otherwindow.c:2668 msgid "Horizontal " msgstr "Orizzontale " #: src/otherwindow.c:2674 msgid "At distance" msgstr "A distanza" #: src/otherwindow.c:2675 msgid "Vertical" msgstr "Verticale" #: src/otherwindow.c:2756 msgid "Unchanged" msgstr "Immutato" #: src/otherwindow.c:2761 msgid "Tracing Image" msgstr "Tracciatura immagine" #: src/otherwindow.c:2763 src/toolbar.c:315 msgid "Source" msgstr "Fonte" #: src/otherwindow.c:2768 msgid "Origin" msgstr "Origine" #: src/otherwindow.c:2771 msgid "Relative scale" msgstr "Scala relativa" #: src/otherwindow.c:2774 msgid "Display" msgstr "Mostra" #: src/otherwindow.c:2926 msgid "Segment Image" msgstr "" #: src/otherwindow.c:2931 src/toolbar.c:304 msgid "Threshold" msgstr "" #: src/otherwindow.c:2933 msgid "Level" msgstr "Livello" #: src/otherwindow.c:2934 msgid "Minimum size" msgstr "" #: src/otherwindow.c:3053 msgid "Max" msgstr "" #: src/otherwindow.c:3053 msgid "Min" msgstr "" #: src/otherwindow.c:3057 msgid "Threshold Image" msgstr "" #: src/otherwindow.c:3158 msgid "Seed" msgstr "" #: src/otherwindow.c:3160 msgid "X span" msgstr "" #: src/otherwindow.c:3161 msgid "Y span" msgstr "" #: src/otherwindow.c:3162 msgid "Octaves" msgstr "" #: src/png.c:620 #, c-format msgid "Saving %s image" msgstr "Salvataggio %s immagine" #: src/png.c:620 #, c-format msgid "Loading %s image" msgstr "Caricamento %s immagine" #: src/png.c:998 msgid "Layer" msgstr "Livello" #: src/png.c:3577 msgid "Lossless" msgstr "" #: src/png.c:3577 msgid "Default" msgstr "" #: src/png.c:3577 msgid "Picture" msgstr "" #: src/png.c:3577 msgid "Photo" msgstr "" #: src/png.c:3578 msgid "Drawing" msgstr "" #: src/png.c:3578 msgid "Icon" msgstr "" #: src/png.c:8370 msgid "Applying colour profile" msgstr "Applicazione profilo colore" #: src/png.c:8792 #, c-format msgid "%d out of %d frames could not be saved as %s - saved as PNG instead" msgstr "" "%d su %d fotogrammi non potevano essere salvati come %s - salvati come PNG " "invece" #: src/png.c:8809 msgid "Explode frames" msgstr "Esplodi fotogrammi" #: src/prefs.c:56 msgid "Default System Language" msgstr "Lingua predefinita del sistema" #: src/prefs.c:57 msgid "Chinese (Simplified)" msgstr "Cinese" #: src/prefs.c:57 msgid "Chinese (Taiwanese)" msgstr "Cinese (di Taiwan)" #: src/prefs.c:57 msgid "Czech" msgstr "Cecoslovacco" #: src/prefs.c:58 msgid "Dutch" msgstr "Olandese" #: src/prefs.c:58 msgid "English (UK)" msgstr "Inglese (regno unito)" #: src/prefs.c:58 msgid "French" msgstr "Francese" #: src/prefs.c:58 msgid "Galician" msgstr "Galiziano" #: src/prefs.c:58 msgid "German" msgstr "Tedesco" #: src/prefs.c:59 msgid "Hungarian" msgstr "" #: src/prefs.c:59 msgid "Italian" msgstr "Italiano" #: src/prefs.c:59 msgid "Japanese" msgstr "Giapponese" #: src/prefs.c:59 msgid "Kabyle" msgstr "" #: src/prefs.c:59 msgid "Polish" msgstr "Polacco" #: src/prefs.c:60 msgid "Portuguese" msgstr "Portoghese" #: src/prefs.c:60 msgid "Portuguese (Brazilian)" msgstr "Portoghese (Brasiliano)" #: src/prefs.c:60 msgid "Russian" msgstr "Russo" #: src/prefs.c:60 msgid "Slovak" msgstr "Slovacco" #: src/prefs.c:61 msgid "Spanish" msgstr "Spagnolo" #: src/prefs.c:61 msgid "Swedish" msgstr "Svedese" #: src/prefs.c:61 msgid "Tagalog" msgstr "" #: src/prefs.c:61 msgid "Turkish" msgstr "Turco" #: src/prefs.c:81 msgid "Current Device" msgstr "Periferica attuale" #: src/prefs.c:135 msgid "Pressure" msgstr "Pressione" #: src/prefs.c:149 msgid "Preferences" msgstr "Preferenze" #: src/prefs.c:163 msgid "Max threads (0 to autodetect)" msgstr "Numero massimo di thread (0 per rilevarli in automatico)" #: src/prefs.c:164 msgid "Min kpixels per render thread" msgstr "" #: src/prefs.c:171 msgid "Max memory used for undo (MB)" msgstr "Memoria massima in uso per annullamenti" #: src/prefs.c:172 msgid "Max undo levels" msgstr "Massimi livelli di annullamento" #: src/prefs.c:173 msgid "Communal layer undo space (%)" msgstr "Annulla spazio su livello comune (%)" #: src/prefs.c:175 msgid "Bayer master pattern" msgstr "" #: src/prefs.c:178 msgid "Use gamma correction by default" msgstr "Usa correzione gamma come impostazione predefinita" #: src/prefs.c:179 msgid "Use gamma correction when painting" msgstr "" #: src/prefs.c:180 msgid "Separate patterns for A & B" msgstr "" #: src/prefs.c:183 msgid "Optimize alpha chequers" msgstr "Ottimizza scacchiera di trasparenza" #: src/prefs.c:184 msgid "Disable view window transparencies" msgstr "Disabilita trasparenze nella finestra Vista" #: src/prefs.c:185 msgid "Enable overlays by layer" msgstr "" #: src/prefs.c:189 msgid "Language" msgstr "Lingua" #: src/prefs.c:191 msgid "" "Select preferred language translation\n" "\n" "You will need to restart mtPaint\n" "for this to take full effect" msgstr "" "Seleziona la tua lingua preferita\n" "\n" "Devi riavviare mtpaint perché questo cambiamento divenga effettivo" #: src/prefs.c:198 msgid "Interface" msgstr "Interfaccia" #: src/prefs.c:200 msgid "Greyscale backdrop" msgstr "Sfondo in scala di grigi" #: src/prefs.c:201 msgid "Selection nudge pixels" msgstr "Sposta pixel nella selezione" #: src/prefs.c:202 msgid "Max Pan Window Size" msgstr "Dimensioni massime della finestra panoramica" #: src/prefs.c:204 msgid "Display clipboard while pasting" msgstr "Mostra il contenuto degli appunti mentre incolli" #: src/prefs.c:205 msgid "Mouse cursor = Tool" msgstr "Cursore mouse = Strumento" #: src/prefs.c:206 msgid "Confirm Exit" msgstr "Conferma uscita" #: src/prefs.c:207 msgid "Q key quits mtPaint" msgstr "Il tasto Q chiude Mtpaint" #: src/prefs.c:208 msgid "Arrow keys scroll canvas" msgstr "" #: src/prefs.c:209 msgid "Changing tool commits paste" msgstr "Cambio strumento per incollare" #: src/prefs.c:210 msgid "Centre tool settings dialogs" msgstr "Centra la finestra d'impostazioni strumenti" #: src/prefs.c:211 msgid "New image sets zoom to 100%" msgstr "La nuova immagine imposta lo zoom al 100%" #: src/prefs.c:212 msgid "Zoom on cursor position" msgstr "" #: src/prefs.c:214 msgid "Mouse Scroll Wheel = Zoom" msgstr "Rotellina di scorrimento del mouse=Zoom" #: src/prefs.c:215 msgid "Use menu icons" msgstr "Usa icone menu" #: src/prefs.c:220 msgid "Files" msgstr "File" #: src/prefs.c:223 msgid "XBM X hotspot" msgstr "Punto d'ascissa (x) XBM" #: src/prefs.c:224 msgid "XBM Y hotspot" msgstr "Punto d'ordinata (y) XBM" #: src/prefs.c:228 msgid "Recently Used Files" msgstr "File aperti di recente" #: src/prefs.c:229 msgid "Progress bar silence limit" msgstr "Limite della barra d'avanzamento" #: src/prefs.c:232 msgid "Read 16-bit TGAs as 5:6:5 BGR" msgstr "Leggi TGA a 16 bit come BGR 5:6:5" #: src/prefs.c:233 msgid "Write TGAs in bottom-up row order" msgstr "Scrivi TGA dal basso in alto" #: src/prefs.c:234 msgid "Undoable image loading" msgstr "Caricamento in corso d'immagine annullabile" #: src/prefs.c:245 msgid "Compression (RGB)" msgstr "" #: src/prefs.c:246 msgid "Compression (indexed)" msgstr "" #: src/prefs.c:247 msgid "Compression (monochrome)" msgstr "" #: src/prefs.c:255 msgid "Enable predictor" msgstr "" #: src/prefs.c:262 msgid "Compression mode" msgstr "" #: src/prefs.c:271 msgid "Channel for Mask Plane" msgstr "" #: src/prefs.c:273 msgid "Ignore Transparent Colour" msgstr "" #: src/prefs.c:274 msgid "PackBits Compression" msgstr "" #: src/prefs.c:275 msgid "Write Indexed as Planar Bitmap (PBM)" msgstr "" #: src/prefs.c:280 msgid "Paths" msgstr "Percorsi" #: src/prefs.c:281 msgid "Clipboard Files" msgstr "File degli appunti" #: src/prefs.c:281 msgid "Select Clipboard File" msgstr "Seleziona il file dagli appunti" #: src/prefs.c:283 msgid "HTML Browser Program" msgstr "Browser HTML" #: src/prefs.c:283 msgid "Select Browser Program" msgstr "Seleziona il browser" #: src/prefs.c:285 msgid "Location of Handbook index" msgstr "Locazione dell'indice del manuale" #: src/prefs.c:285 msgid "Select Handbook Index File" msgstr "Seleziona indice del manuale" #: src/prefs.c:287 msgid "Default Palette" msgstr "Tavolozza predefinita" #: src/prefs.c:287 msgid "Select Default Palette" msgstr "Seleziona la tavolozza predefinita" #: src/prefs.c:289 msgid "Default Patterns" msgstr "Motivi predefiniti" #: src/prefs.c:289 msgid "Select Default Patterns File" msgstr "Seleziona il file coi motivi predefiniti" #: src/prefs.c:292 msgid "Default CSS" msgstr "" #: src/prefs.c:292 msgid "Select Default CSS File" msgstr "" #: src/prefs.c:295 msgid "Default Theme" msgstr "Tema preimpostato" #: src/prefs.c:295 msgid "Select Default Theme File" msgstr "Seleziona il file del tema preimpostato" #: src/prefs.c:300 msgid "Status Bar" msgstr "Barra di stato" #: src/prefs.c:301 msgid "Canvas Geometry" msgstr "Geometria tela" #: src/prefs.c:302 msgid "Cursor X,Y" msgstr "Cursore X,Y" #: src/prefs.c:303 msgid "Pixel [I] {RGB}" msgstr "Pixel" #: src/prefs.c:304 msgid "Selection Geometry" msgstr "Seleziona geometria" #: src/prefs.c:305 msgid "Undo / Redo" msgstr "Annulla / Ripristina" #: src/prefs.c:308 msgid "Tablet" msgstr "Tavoletta" #: src/prefs.c:309 msgid "Device Settings" msgstr "Impostazioni periferica" #: src/prefs.c:313 msgid "Configure Device" msgstr "Configura periferica" #: src/prefs.c:319 msgid "Tool Variable" msgstr "Variabili del dispositivo" #: src/prefs.c:322 src/toolbar.c:454 msgid "Flow" msgstr "Flusso" #: src/prefs.c:330 msgid "Test Area" msgstr "Area di prova" #: src/prefs.c:373 msgid "Factor" msgstr "Fattore" #: src/prefs.c:459 msgid "This key is builtin" msgstr "" #: src/prefs.c:462 #, c-format msgid "" "This key is mapped to:\n" "\"%s\"" msgstr "" #: src/prefs.c:465 msgid "Remap" msgstr "" #: src/prefs.c:510 msgid "Keyboard Shortcuts" msgstr "" #: src/shifter.c:147 msgid "Frames" msgstr "Fotogrammi" #: src/shifter.c:258 msgid "Palette Shifter" msgstr "Cicla tavolozza" #: src/shifter.c:263 msgid "Start" msgstr "Avvia" #: src/shifter.c:265 msgid "Finish" msgstr "Termina" #: src/shifter.c:284 msgid "Fix Palette" msgstr "Correggi tavolozza" #: src/spawn.c:651 msgid "Configure File Actions" msgstr "Configura le azioni file" #: src/spawn.c:657 src/spawn.c:663 msgid "Command" msgstr "Comando" #: src/spawn.c:922 #, c-format msgid "Error %i reported when trying to run %s" msgstr "Errore %i segnalato nel tentativo di avviare %s" #: src/spawn.c:979 msgid "" "I am unable to find the documentation. Either you need to download the " "mtPaint Handbook from the web site and install it, or you need to set the " "correct location in the Preferences window." msgstr "" "Non riesco a trovare la documentazione. O devi scaricare il manuale di " "mtpaint dal sito web ed installarlo, oppure impostare la corretta locazione " "nella finestra delle preferenze" #: src/spawn.c:1018 msgid "" "There was a problem running the HTML browser. You need to set the correct " "program name in the Preferences window." msgstr "" "C'è stato un problema nell'avviare il browser HTML. Devi impostare il nome " "correttodel programma nella finestra delle preferenze" #: src/thread.c:361 msgid "Helper thread is not responding. Save your work and exit the program." msgstr "Il thread helper non risponde. Salva il lavoro ed esci dal programma." #: src/toolbar.c:147 msgid "RGB Cube" msgstr "Cubo RGB" #: src/toolbar.c:148 msgid "By image channel" msgstr "Per canale immagine" #: src/toolbar.c:149 msgid "Gradient-driven" msgstr "Gradient-driven" #: src/toolbar.c:157 msgid "Fill settings" msgstr "Impostazioni riempimento" #: src/toolbar.c:170 msgid "Respect opacity mode" msgstr "Preserva opacità" #: src/toolbar.c:176 msgid "Smudge settings" msgstr "Impostazioni sfumino" #: src/toolbar.c:215 msgid "Aligned" msgstr "" #: src/toolbar.c:222 msgid "Clone settings" msgstr "" #: src/toolbar.c:228 msgid "By selection channel" msgstr "" #: src/toolbar.c:234 msgid "Lasso settings" msgstr "" #: src/toolbar.c:252 msgid "Brush spacing" msgstr "Spaziatura pennello" #: src/toolbar.c:299 src/toolbar.c:341 msgid "Normal" msgstr "Normale" #: src/toolbar.c:300 msgid "Colour" msgstr "Colore" #: src/toolbar.c:300 msgid "Saturate More" msgstr "Più saturato" #: src/toolbar.c:301 msgid "Multiply" msgstr "Moltiplica" #: src/toolbar.c:301 msgid "Divide" msgstr "Dividi" #: src/toolbar.c:301 msgid "Dodge" msgstr "Scherma" #: src/toolbar.c:302 msgid "Burn" msgstr "Brucia" #: src/toolbar.c:302 msgid "Hard Light" msgstr "Alte luci" #: src/toolbar.c:302 msgid "Soft Light" msgstr "Basse luci" #: src/toolbar.c:302 msgid "Difference" msgstr "Differenza" #: src/toolbar.c:303 msgid "Darken" msgstr "Scurisci" #: src/toolbar.c:303 msgid "Lighten" msgstr "Schiarisci" #: src/toolbar.c:303 msgid "Grain Extract" msgstr "Estrai grana" #: src/toolbar.c:304 msgid "Grain Merge" msgstr "Fondi grana" #: src/toolbar.c:330 msgid "Blend mode" msgstr "Modalità trasparente" #: src/toolbar.c:417 msgid "Continuous Mode" msgstr "Modalità continua" #: src/toolbar.c:421 msgid "Opacity Mode" msgstr "Modalità opacità" #: src/toolbar.c:424 msgid "Tint Mode" msgstr "Modalità colore" #: src/toolbar.c:427 msgid "Tint +-" msgstr "Colore +-" #: src/toolbar.c:434 msgid "Blend Mode" msgstr "Modalità trasparente" #: src/toolbar.c:438 msgid "Disable All Masks" msgstr "Disabilita tutte le maschere" #: src/toolbar.c:441 msgid "Gradient Mode" msgstr "Modalità gradiente" #: src/toolbar.c:486 msgid "Settings Toolbar" msgstr "Barra impostazioni" #: src/toolbar.c:546 msgid "Cut" msgstr "Taglia" #: src/toolbar.c:548 msgid "Copy" msgstr "Copia" #: src/toolbar.c:550 msgid "Paste" msgstr "Incolla" #: src/toolbar.c:553 msgid "Undo" msgstr "Annulla" #: src/toolbar.c:555 msgid "Redo" msgstr "Ripristina" #: src/toolbar.c:559 src/viewer.c:328 msgid "Pan Window" msgstr "Finestra panoramica" #: src/toolbar.c:560 src/toolbar.c:640 msgid "More..." msgstr "" #: src/toolbar.c:574 msgid "Paint" msgstr "Disegno" #: src/toolbar.c:580 msgid "Shuffle" msgstr "Mix" #: src/toolbar.c:583 msgid "Flood Fill" msgstr "Secchiello" #: src/toolbar.c:587 msgid "Straight Line" msgstr "Linea retta" #: src/toolbar.c:590 msgid "Smudge" msgstr "Sfuma" #: src/toolbar.c:594 msgid "Clone" msgstr "Clona" #: src/toolbar.c:597 msgid "Make Selection" msgstr "Crea selezione" #: src/toolbar.c:600 msgid "Polygon Selection" msgstr "Selezione poligonale" #: src/toolbar.c:603 msgid "Place Gradient" msgstr "Applica gradiente" #: src/toolbar.c:606 msgid "Lasso Selection" msgstr "Selezione laccio" #: src/toolbar.c:614 msgid "Ellipse Outline" msgstr "Ellisse contornata" #: src/toolbar.c:617 msgid "Filled Ellipse" msgstr "Ellisse piena" #: src/toolbar.c:620 msgid "Outline Selection" msgstr "Contorna selezione" #: src/toolbar.c:623 msgid "Fill Selection" msgstr "Riempi selezione" #: src/toolbar.c:627 msgid "Flip Selection Vertically" msgstr "Ribalta selezione in verticale" #: src/toolbar.c:630 msgid "Flip Selection Horizontally" msgstr "Ribalta selezione in orizzontale" #: src/toolbar.c:633 msgid "Rotate Selection Clockwise" msgstr "Ruota selezione in senso orario" #: src/toolbar.c:636 msgid "Rotate Selection Anti-Clockwise" msgstr "Ruota selezione in senso antiorario" #: src/vcode.c:5201 msgid "Browse" msgstr "Sfoglia" #: src/vcode.c:7886 msgid "New key ..." msgstr "" #: src/vcode.c:9909 #, c-format msgid "'%s' does not match any widget" msgstr "" #: src/vcode.c:9910 #, c-format msgid "'%s' value does not fit '%s' widget" msgstr "" #: src/viewer.c:115 msgid "About" msgstr "Informazioni su" #: src/viewer.c:1179 msgid "No font selected" msgstr "" #: src/viewer.c:1209 msgid "Left" msgstr "" #: src/viewer.c:1209 msgid "Right" msgstr "" #~ msgid "Create GIF frames" #~ msgstr "Crea fotogrammi GIF" #~ msgid "" #~ "You are trying to save an XPM file with more than 4096 colours. Either " #~ "use another format or posterize the image to 4 bits, or otherwise reduce " #~ "the number of colours." #~ msgstr "" #~ "Si sta tentando di salvare un file XPM con più di 4.096 colori. usa un " #~ "altro formato o posterizza l'immagine a 4 bit, altrimenti riduci il " #~ "numero di colori " #~ msgid "Store Values" #~ msgstr "Memorizza valori" #~ msgid "Distance to A+B" #~ msgstr "Distanza ad A+B" #~ msgid "File: %s invalid - palette not updated" #~ msgstr "File: %s non valido - tavolozza non aggiornata" #~ msgid "Import GIF animation - Choose frames directory" #~ msgstr "Importa animazione GIF - Seleziona la cartella dei fotogrammi" #~ msgid "This is an animated GIF file. What do you want to do?" #~ msgstr "Questa è una GIF animata. Cosa vuoi farci?" #~ msgid "Edit Frames" #~ msgstr "Modifica fotogrammi" mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/po/ja.po000066400000000000000000003161651471325446300215370ustar00rootroot00000000000000# Japanese translation for mtpaint # This file is distributed under the same license as the mtpaint package. # Norihiro YONEDA , 2007. # msgid "" msgstr "" "Project-Id-Version: mtpaint\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-01-04 21:31+0200\n" "PO-Revision-Date: 2009-06-09 12:48+0900\n" "Last-Translator: YoN \n" "Language-Team: Puppy Linux Japanese\n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Rosetta-Version: 0.1\n" #: src/ani.c:647 msgid "Animation Preview" msgstr "アニメーションプレビュー" #: src/ani.c:650 src/shifter.c:275 msgid "Play" msgstr "å†ç”Ÿ" #: src/ani.c:654 msgid "Fix" msgstr "固定" #: src/ani.c:655 src/ani.c:1005 src/font.c:1624 src/font.c:1643 #: src/shifter.c:286 src/viewer.c:97 msgid "Close" msgstr "é–‰ã˜ã‚‹" #: src/ani.c:709 src/ani.c:812 src/ani.c:1022 src/ani.c:1028 src/canvas.c:356 #: src/canvas.c:708 src/canvas.c:989 src/canvas.c:1353 src/canvas.c:1383 #: src/canvas.c:1470 src/canvas.c:1545 src/canvas.c:1988 src/canvas.c:1994 #: src/canvas.c:2077 src/canvas.c:2217 src/canvas.c:2240 src/font.c:1352 #: src/fpick.c:636 src/fpick.c:754 src/layer.c:524 src/layer.c:815 #: src/layer.c:970 src/mainwindow.c:341 src/mainwindow.c:370 #: src/mainwindow.c:534 src/mainwindow.c:578 src/mainwindow.c:604 #: src/mainwindow.c:3797 src/mainwindow.c:4045 src/otherwindow.c:931 #: src/otherwindow.c:980 src/otherwindow.c:982 src/prefs.c:459 src/spawn.c:924 #: src/spawn.c:978 src/spawn.c:1017 src/thread.c:360 src/vcode.c:9912 #: src/viewer.c:1161 src/viewer.c:1179 msgid "Error" msgstr "エラー" #: src/ani.c:709 msgid "Unable to create output directory" msgstr "出力ディレクトリを作æˆã§ãã¾ã›ã‚“" #: src/ani.c:759 msgid "Creating Animation Frames" msgstr "アニメーションフレームを作æˆä¸­" #: src/ani.c:812 msgid "Unable to save image" msgstr "イメージをä¿å­˜ã§ãã¾ã›ã‚“" #: src/ani.c:840 src/canvas.c:1171 src/fpick.c:731 src/layer.c:311 #: src/layer.c:379 src/layer.c:826 src/layer.c:840 src/mainwindow.c:375 #: src/mainwindow.c:1026 src/png.c:8794 src/prefs.c:464 msgid "Warning" msgstr "警告" #: src/ani.c:840 msgid "" "Do you really want to clear all of the position and cycle data for all of " "the layers?" msgstr "本当ã«ã€å…¨ãƒ¬ã‚¤ãƒ¤ã®ä½ç½®ã¨ã‚µã‚¤ã‚¯ãƒ«ãƒ‡ãƒ¼ã‚¿ã‚’ã™ã¹ã¦ã‚¯ãƒªã‚¢ã—ã¾ã™ã‹ï¼Ÿ" #: src/ani.c:841 src/fpick.c:731 src/layer.c:311 src/layer.c:842 #: src/mainwindow.c:375 msgid "No" msgstr "ã„ã„ãˆ" #: src/ani.c:841 src/fpick.c:731 src/layer.c:311 src/layer.c:842 #: src/mainwindow.c:375 msgid "Yes" msgstr "ã¯ã„" #: src/ani.c:954 msgid "Set Key Frame" msgstr "キーフレームã®è¨­å®š" #: src/ani.c:961 msgid "Configure Animation" msgstr "アニメーション設定" #: src/ani.c:964 msgid "Output Files" msgstr "出力ファイル" #: src/ani.c:967 msgid "Start frame" msgstr "フレームã®é–‹å§‹" #: src/ani.c:969 msgid "End frame" msgstr "フレームã®çµ‚了" #: src/ani.c:971 src/shifter.c:267 msgid "Delay" msgstr "é…å»¶" #: src/ani.c:973 msgid "Output path" msgstr "出力パス" #: src/ani.c:973 src/font.c:1637 src/spawn.c:664 msgid "Select Directory" msgstr "è¾žæ›¸ã‚’é¸æŠž" #: src/ani.c:976 msgid "File prefix" msgstr "ファイル プレフィックス" #: src/ani.c:978 src/canvas.c:2096 msgid "File Format" msgstr "ファイル フォーマット" #: src/ani.c:982 msgid "Positions" msgstr "ä½ç½®" #: src/ani.c:997 msgid "Cycling" msgstr "循環" #: src/ani.c:1006 msgid "Save" msgstr "ä¿å­˜" #: src/ani.c:1007 src/font.c:1577 src/otherwindow.c:868 src/otherwindow.c:1615 #: src/otherwindow.c:1728 src/otherwindow.c:2938 src/otherwindow.c:3071 #: src/otherwindow.c:3170 msgid "Preview" msgstr "プレビュー" #: src/ani.c:1008 src/shifter.c:285 msgid "Create Frames" msgstr "フレームã®ä½œæˆ" #: src/ani.c:1022 msgid "You must have at least 2 layers to create an animation" msgstr "アニメーションを作るã«ã¯ï¼’ã¤ä»¥ä¸Šã®ãƒ¬ã‚¤ãƒ¤ãŒå¿…è¦ã§ã™" #: src/ani.c:1028 msgid "You must save your layers file before creating an animation" msgstr "アニメーションを作るå‰ã«ãƒ¬ã‚¤ãƒ¤ã‚’ä¿å­˜ã—ã¦ä¸‹ã•ã„" #: src/canvas.c:357 msgid "The image is too large to transform." msgstr "イメージã¯å¤‰æ›ã™ã‚‹ã«ã¯å¤§ãã™ãŽã¾ã™ã€‚" #: src/canvas.c:393 src/canvas.c:430 src/otherwindow.c:1613 #: src/otherwindow.c:2524 src/otherwindow.c:2583 src/otherwindow.c:3179 msgid "Gradient" msgstr "グラデーション" #: src/canvas.c:393 src/otherwindow.c:840 src/otherwindow.c:842 #: src/otherwindow.c:2074 src/otherwindow.c:3180 msgid "Palette" msgstr "パレット" #: src/canvas.c:393 src/info.c:265 src/otherwindow.c:847 src/otherwindow.c:2757 #: src/otherwindow.c:3180 src/png.c:781 src/png.c:995 msgid "Clipboard" msgstr "クリップボード" #: src/canvas.c:394 src/cpick.c:831 src/toolbar.c:299 msgid "Value" msgstr "値" #: src/canvas.c:394 src/cpick.c:811 src/otherwindow.c:575 src/otherwindow.c:859 #: src/otherwindow.c:3053 src/toolbar.c:318 msgid "Red" msgstr "赤色" #: src/canvas.c:394 src/cpick.c:815 src/otherwindow.c:575 src/otherwindow.c:860 #: src/otherwindow.c:3053 src/toolbar.c:319 msgid "Green" msgstr "綠色" #: src/canvas.c:394 src/cpick.c:819 src/otherwindow.c:575 src/otherwindow.c:861 #: src/otherwindow.c:3053 src/toolbar.c:320 msgid "Blue" msgstr "é’色" #: src/canvas.c:399 msgid "From " msgstr "" #: src/canvas.c:403 msgid "To " msgstr "" #: src/canvas.c:410 msgid "Map" msgstr "" #: src/canvas.c:429 msgid "MT" msgstr "MT" #: src/canvas.c:429 msgid "Sobel" msgstr "Sobel" #: src/canvas.c:429 msgid "Prewitt" msgstr "Prewitt" #: src/canvas.c:429 msgid "Kirsch" msgstr "Kirsch" #: src/canvas.c:430 msgid "Roberts" msgstr "Roberts" #: src/canvas.c:430 msgid "Laplace" msgstr "Laplace" #: src/canvas.c:430 msgid "Morphological" msgstr "形態学的" #: src/canvas.c:442 msgid "Edge Detect" msgstr "境界検出" #: src/canvas.c:464 msgid "Edge Sharpen" msgstr "ç¸ã‚’シャープã«ã™ã‚‹" #: src/canvas.c:472 msgid "Edge Soften" msgstr "ç¸ã‚’ã¼ã‹ã™" #: src/canvas.c:521 msgid "Different X/Y" msgstr "X/Yã®é•ã„" #: src/canvas.c:522 src/canvas.c:562 src/canvas.c:603 src/canvas.c:637 #: src/canvas.c:722 src/otherwindow.c:1037 src/otherwindow.c:2685 msgid "Gamma corrected" msgstr "ガンマ補正" #: src/canvas.c:530 src/memory.c:8219 msgid "Gaussian Blur" msgstr "ガウスã¼ã‹ã—" #: src/canvas.c:558 msgid "Radius" msgstr "放射状" #: src/canvas.c:559 msgid "Amount" msgstr "é‡" #: src/canvas.c:560 msgid "Threshold " msgstr "ã—ãã„値" #: src/canvas.c:570 src/memory.c:8360 msgid "Unsharp Mask" msgstr "アンシャープマスク" #: src/canvas.c:599 msgid "Outer radius" msgstr "外åŠå¾„" #: src/canvas.c:600 msgid "Inner radius" msgstr "内åŠå¾„" #: src/canvas.c:602 src/info.c:280 msgid "Normalize" msgstr "標準化" #: src/canvas.c:611 src/memory.c:8512 msgid "Difference of Gaussians" msgstr "ガウスã®å·®ç•°" #: src/canvas.c:636 msgid "Protect details" msgstr "" #: src/canvas.c:645 msgid "Kuwahara-Nagao Blur" msgstr "Kuwahara-Nagaoã¼ã‹ã—" #: src/canvas.c:709 msgid "The image is too large for this rotation." msgstr "イメージã¯ã“ã®å›žè»¢ã«ã¯å¤§ãã™ãŽã¾ã™ã€‚" #: src/canvas.c:723 msgid "Smooth" msgstr "平滑" #: src/canvas.c:732 msgid "Free Rotate" msgstr "自由回転" #: src/canvas.c:989 src/viewer.c:1161 msgid "Not enough memory to create clipboard" msgstr "クリップボードを作æˆã™ã‚‹ã«ãƒ¡ãƒ¢ãƒªãŒè¶³ã‚Šã¾ã›ã‚“" #: src/canvas.c:1172 msgid "" "You have not allocated enough memory in the Preferences window to undo this " "action." msgstr "" #: src/canvas.c:1353 msgid "Invalid palette file" msgstr "" #: src/canvas.c:1383 msgid "Invalid channel file." msgstr "無効ãªãƒãƒ£ãƒ³ãƒãƒ«ãƒ•ァイルã§ã™ã€‚" #: src/canvas.c:1401 msgid "Raw frames" msgstr "" #: src/canvas.c:1401 msgid "Composited frames" msgstr "" #: src/canvas.c:1402 msgid "Composited frames with nonzero delay" msgstr "" #: src/canvas.c:1406 msgid "Load Frames" msgstr "" #: src/canvas.c:1409 msgid "Load into Layers" msgstr "" #: src/canvas.c:1415 msgid "Load First Frame" msgstr "" #: src/canvas.c:1416 msgid "Explode Frames" msgstr "" #: src/canvas.c:1418 msgid "View Animation" msgstr "アニメーションを表示" #: src/canvas.c:1434 #, c-format msgid "This is an animated %s file." msgstr "ã“れã¯%sアニメファイルã§ã™ã€‚" #: src/canvas.c:1435 #, c-format msgid "This is a multipage %s file." msgstr "" #: src/canvas.c:1459 #, c-format msgid "File is too big, must be <= to width=%i height=%i" msgstr "フィルãŒå¤§ãã™ãŽã¾ã™ã€‚å¹…=%i 高ã•=%i 以下ã«ã—ã¦ä¸‹ã•ã„" #: src/canvas.c:1461 msgid "Unable to explode frames" msgstr "" #: src/canvas.c:1463 msgid "Unable to load file" msgstr "ファイルを読ã¿è¾¼ã‚ã¾ã›ã‚“" #: src/canvas.c:1465 msgid "" "The file import library had to terminate due to a problem with the file " "(possibly corrupt image data or a truncated file). I have managed to load " "some data as the header seemed fine, but I would suggest you save this image " "to a new file to ensure this does not happen again." msgstr "" "ファイルã«å•題ãŒã‚ã‚‹ã®ã§ãƒ•ァイルインãƒãƒ¼ãƒˆãƒ©ã‚¤ãƒ–ラリã¯çµ‚了ã—ã¾ã™ï¼ˆãŸã¶ã‚“䏿­£" "ãªç”»åƒãƒ‡ãƒ¼ã‚¿ã¾ãŸã¯ä¸å®Œå…¨ãªãƒ•ァイルã§ã™ï¼‰ã€‚ヘッダãŒé–“é•ã„ãªã„よã†ã§ã—ãŸã®ã§ã€" "ã„ãã¤ã‹ã®ãƒ‡ãƒ¼ã‚¿ã‚’ロードã§ãã¾ã—ãŸã€‚ã—ã‹ã—二度ã¨èµ·ã“らãªã„よã†ã«ã€ã“ã®ã‚¤ãƒ¡ãƒ¼" "ジを新ã—ã„ファイルã«ä¿å­˜ã—ã¦ä¸‹ã•ã„。" #: src/canvas.c:1467 msgid "The animation is too long to load all of it into layers." msgstr "" #: src/canvas.c:1469 msgid "Could not explode all the frames in the animation." msgstr "" #: src/canvas.c:1481 src/font.c:1556 src/fpick.c:937 src/otherwindow.c:2765 #: src/prefs.c:321 src/toolbar.c:451 msgid "Size" msgstr "サイズ" #: src/canvas.c:1484 src/otherwindow.c:244 msgid "Width" msgstr "å¹…" #: src/canvas.c:1485 src/otherwindow.c:245 msgid "Height" msgstr "高ã•" #: src/canvas.c:1489 src/channels.c:253 src/channels.c:317 src/fpick.c:666 #: src/fpick.c:957 src/mainwindow.c:3990 src/otherwindow.c:255 #: src/otherwindow.c:517 src/otherwindow.c:591 src/otherwindow.c:867 #: src/otherwindow.c:1058 src/otherwindow.c:1727 src/otherwindow.c:2101 #: src/otherwindow.c:2336 src/otherwindow.c:2538 src/otherwindow.c:2691 #: src/otherwindow.c:2776 src/otherwindow.c:2937 src/otherwindow.c:3070 #: src/otherwindow.c:3169 src/prefs.c:338 src/prefs.c:464 src/prefs.c:538 #: src/spawn.c:666 src/viewer.c:1258 msgid "Cancel" msgstr "キャンセル" #: src/canvas.c:1490 src/channels.c:253 src/channels.c:317 src/fpick.c:956 #: src/info.c:297 src/mainwindow.c:3992 src/mygtk.c:233 src/mygtk.c:535 #: src/otherwindow.c:591 src/otherwindow.c:871 src/otherwindow.c:1058 #: src/otherwindow.c:1729 src/otherwindow.c:2101 src/otherwindow.c:2336 #: src/otherwindow.c:2538 src/otherwindow.c:2691 src/otherwindow.c:2776 #: src/otherwindow.c:3072 src/otherwindow.c:3171 src/prefs.c:338 #: src/prefs.c:538 src/spawn.c:666 msgid "OK" msgstr "OK" #: src/canvas.c:1504 #, c-format msgid "This is a scalable %s file." msgstr "" #: src/canvas.c:1545 msgid "Cannot open file" msgstr "ファイルを開ã‘ã¾ã›ã‚“" #: src/canvas.c:1546 msgid "Unsupported file format" msgstr "サãƒãƒ¼ãƒˆã•れã¦ã„ãªã„ファイルフォーマットã§ã™" #: src/canvas.c:1673 #, c-format msgid "File: %s already exists. Do you want to overwrite it?" msgstr "ファイル:%s ã¯ã™ã§ã«å­˜åœ¨ã—ã¾ã™ã€‚上書ãã—ã¾ã™ã‹ï¼Ÿ" #: src/canvas.c:1674 msgid "File Found" msgstr "ファイルãŒè¦‹ã¤ã‹ã‚Šã¾ã—ãŸ" #: src/canvas.c:1674 src/mainwindow.c:1095 msgid "NO" msgstr "ã„ã„ãˆ" #: src/canvas.c:1674 src/mainwindow.c:1095 msgid "YES" msgstr "ã¯ã„" #: src/canvas.c:1988 msgid "Unable to export undo images" msgstr "アンドゥイメージをエクスãƒãƒ¼ãƒˆã§ãã¾ã›ã‚“" #: src/canvas.c:1994 msgid "Unable to export ASCII file" msgstr "ASCIIファイルをエクスãƒãƒ¼ãƒˆã§ãã¾ã›ã‚“" #: src/canvas.c:2076 src/layer.c:814 src/mainwindow.c:529 #, c-format msgid "Unable to save file: %s" msgstr "ファイルをä¿å­˜ã§ãã¾ã›ã‚“:%s" #: src/canvas.c:2101 src/prefs.c:222 msgid "Transparency index" msgstr "逿˜Žåº¦æŒ‡æ•°" #: src/canvas.c:2103 msgid "TIFF Compression" msgstr "" #: src/canvas.c:2105 src/prefs.c:225 msgid "JPEG Save Quality (100=High)" msgstr "JPEG ä¿å­˜å“質 (100=高ã„)" #: src/canvas.c:2107 msgid "ZIP Compression (0=None)" msgstr "" #: src/canvas.c:2108 src/prefs.c:227 msgid "PNG Compression (0=None)" msgstr "PNG 圧縮 (0=ãªã—)" #: src/canvas.c:2111 src/prefs.c:249 msgid "LZMA2 Compression (0=None)" msgstr "" #: src/canvas.c:2113 src/prefs.c:252 msgid "ZSTD Compression Level" msgstr "" #: src/canvas.c:2115 src/prefs.c:231 msgid "TGA RLE Compression" msgstr "TGA RLE 圧縮" #: src/canvas.c:2117 msgid "LBM PackBits Compression" msgstr "" #: src/canvas.c:2118 src/prefs.c:226 msgid "JPEG2000 Compression (0=Lossless)" msgstr "JPEG2000 圧縮 (0=å¯é€†)" #: src/canvas.c:2120 msgid "WebP Compression" msgstr "" #: src/canvas.c:2122 msgid "WebP Save Quality (100=High)" msgstr "" #: src/canvas.c:2123 src/prefs.c:263 msgid "V8 Save Quality (100=High)" msgstr "" #: src/canvas.c:2125 src/prefs.c:264 msgid "V8L Compression (0=None)" msgstr "" #: src/canvas.c:2127 msgid "Hotspot at X =" msgstr "X = ã®ãƒ›ãƒƒãƒˆã‚¹ãƒãƒƒãƒˆ" #: src/canvas.c:2129 msgid "Y =" msgstr "Y =" #: src/canvas.c:2133 msgid "Animation delay" msgstr "アニメーションé…å»¶" #: src/canvas.c:2136 src/otherwindow.c:253 msgid "Undoable" msgstr "å–り消ã—å¯èƒ½" #: src/canvas.c:2138 src/prefs.c:236 msgid "Apply colour profile" msgstr "" #: src/canvas.c:2176 src/toolbar.c:543 msgid "Load Image File" msgstr "イメージファイルをロード" #: src/canvas.c:2191 src/toolbar.c:544 msgid "Save Image File" msgstr "イメージファイルをä¿å­˜" #: src/canvas.c:2196 msgid "Load Palette File" msgstr "パレットをロード" #: src/canvas.c:2202 msgid "Save Palette File" msgstr "パレットファイルをä¿å­˜" #: src/canvas.c:2207 msgid "Export Undo Images" msgstr "アンドゥイメージã®ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ" #: src/canvas.c:2212 msgid "Export Undo Images (reversed)" msgstr "アンドゥイメージを(å転ã—ã¦ï¼‰ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ" #: src/canvas.c:2217 msgid "You must have 16 or fewer palette colours to export ASCII art." msgstr "ASCIIアートã«ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã™ã‚‹ã«ã¯16色以下ã®ãƒ‘レット色ãŒå¿…è¦ã§ã™ã€‚" #: src/canvas.c:2220 msgid "Export ASCII Art" msgstr "ASCIIアートをエクスãƒãƒ¼ãƒˆ" #: src/canvas.c:2224 msgid "Save Layer Files" msgstr "レイヤファイルをä¿å­˜" #: src/canvas.c:2234 msgid "Choose frames directory" msgstr "ãƒ•ãƒ¬ãƒ¼ãƒ ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‚’é¸æŠž" #: src/canvas.c:2240 msgid "You must save at least one frame to create an animated GIF." msgstr "アニメGIFを作るã«ã¯å°‘ãªãã¨ã‚‚1ã¤ã®ãƒ•レームをä¿å­˜ã—ã¦ä¸‹ã•ã„。" #: src/canvas.c:2243 msgid "Export GIF animation" msgstr "GIFアニメをエクスãƒãƒ¼ãƒˆ" #: src/canvas.c:2247 msgid "Load Channel" msgstr "ãƒãƒ£ãƒ³ãƒãƒ«ã‚’ロード" #: src/canvas.c:2255 msgid "Save Channel" msgstr "ãƒãƒ£ãƒ³ãƒãƒ«ã‚’ä¿å­˜" #: src/canvas.c:2260 msgid "Save Composite Image" msgstr "åˆæˆã‚¤ãƒ¡ãƒ¼ã‚¸ã‚’ä¿å­˜" #: src/channels.c:243 msgid "Create Channel" msgstr "ãƒãƒ£ãƒ³ãƒãƒ«ã‚’作æˆ" #: src/channels.c:244 msgid "Channel Type" msgstr "ãƒãƒ£ãƒ³ãƒãƒ«ã‚¿ã‚¤ãƒ—" #: src/channels.c:247 msgid "Initial Channel State" msgstr "åˆæœŸãƒãƒ£ãƒ³ãƒãƒ«çжæ³" #: src/channels.c:251 msgid "Inverted" msgstr "å転" #: src/channels.c:265 msgid "Cleared" msgstr "クリア" #: src/channels.c:266 msgid "Set" msgstr "設定" #: src/channels.c:267 msgid "Set colour A radius B" msgstr "色 A åŠå¾„ B ã§è¨­å®š" #: src/channels.c:268 msgid "Set blend A to B" msgstr "A ã‚’ B ã«ãƒ–レンド" #: src/channels.c:269 msgid "Image Red" msgstr "赤色イメージ" #: src/channels.c:270 msgid "Image Green" msgstr "綠色イメージ" #: src/channels.c:271 msgid "Image Blue" msgstr "é’色イメージ" #: src/channels.c:273 src/channels.c:313 src/mainwindow.c:67 #: src/otherwindow.c:1679 msgid "Alpha" msgstr "アルファ" #: src/channels.c:274 src/channels.c:314 src/mainwindow.c:67 #: src/otherwindow.c:1683 msgid "Selection" msgstr "é¸æŠž" #: src/channels.c:275 src/channels.c:315 src/mainwindow.c:67 #: src/otherwindow.c:1687 msgid "Mask" msgstr "マスク" #: src/channels.c:312 msgid "Delete Channels" msgstr "ãƒãƒ£ãƒ³ãƒãƒ«ã‚’削除" #: src/channels.c:367 msgid "Threshold Channel" msgstr "ã—ãã„ãƒãƒ£ãƒ³ãƒãƒ«" #: src/cpick.c:823 src/otherwindow.c:573 src/otherwindow.c:820 #: src/toolbar.c:299 msgid "Hue" msgstr "色相" #: src/cpick.c:827 src/otherwindow.c:573 src/otherwindow.c:818 #: src/toolbar.c:299 msgid "Saturation" msgstr "彩度" #: src/cpick.c:835 msgid "Hex" msgstr "Hex" #: src/cpick.c:840 src/layer.c:1109 src/otherwindow.c:2530 src/prefs.c:323 #: src/toolbar.c:457 msgid "Opacity" msgstr "ä¸é€æ˜Žåº¦" #: src/font.c:982 msgid "Creating Font Index" msgstr "フォントインデックスを作æˆ" #: src/font.c:1353 msgid "You must select at least one directory to search for fonts." msgstr "ãƒ•ã‚©ãƒ³ãƒˆã®æ¤œç´¢ã«ã¯å°‘ãªãã¨ã‚‚1ã¤ã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‚’é¸æŠžã—ã¦ä¸‹ã•ã„。" #: src/font.c:1529 src/font.c:1624 src/toolbar.c:609 src/viewer.c:1213 #: src/viewer.c:1258 msgid "Paste Text" msgstr "テキストを貼り付ã‘" #: src/font.c:1533 src/font.c:1572 src/png.c:3578 msgid "Text" msgstr "テキスト" #: src/font.c:1540 msgid "Font" msgstr "フォント" #: src/font.c:1548 msgid "Style" msgstr "スタイル" #: src/font.c:1566 msgid "Filename" msgstr "ファイルå" #: src/font.c:1567 msgid "Face" msgstr "書体" #: src/font.c:1587 src/viewer.c:1222 msgid "Antialias" msgstr "アンãƒã‚¨ã‚¤ãƒªã‚¢ã‚¹" #: src/font.c:1590 src/viewer.c:1224 msgid "Invert" msgstr "å転" #: src/font.c:1593 src/viewer.c:1226 msgid "Background colour =" msgstr "背景色 =" #: src/font.c:1601 src/viewer.c:1233 msgid "DPI =" msgstr "" #: src/font.c:1610 msgid "Oblique" msgstr "斜体" #: src/font.c:1612 src/viewer.c:1244 msgid "Angle of rotation =" msgstr "回転角度 =" #: src/font.c:1617 src/viewer.c:1248 msgid "Align" msgstr "" #: src/font.c:1620 src/viewer.c:1253 msgid "Spacing" msgstr "" #: src/font.c:1629 msgid "Font Directories" msgstr "フォントディレクトリ" #: src/font.c:1634 src/spawn.c:664 msgid "Directory" msgstr "辞書" #: src/font.c:1637 msgid "New Directory" msgstr "æ–°è¦ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒª" #: src/font.c:1644 src/prefs.c:532 msgid "Add" msgstr "追加" #: src/font.c:1645 src/prefs.c:533 msgid "Remove" msgstr "削除" #: src/font.c:1646 msgid "Create Index" msgstr "インデックスを作æˆ" #: src/font.c:1660 src/viewer.c:1267 msgid "Enter Text Here" msgstr "ã“ã“ã«ãƒ†ã‚­ã‚¹ãƒˆã‚’入力" #: src/fpick.c:635 #, c-format msgid "Could not access directory %s" msgstr "ディレクトリ %s ã«ã‚¢ã‚¯ã‚»ã‚¹ã§ãã¾ã›ã‚“" #: src/fpick.c:668 src/fpick.c:698 msgid "Delete" msgstr "削除" #: src/fpick.c:669 src/fpick.c:698 msgid "Rename" msgstr "リãƒãƒ¼ãƒ " #: src/fpick.c:672 src/otherwindow.c:255 src/otherwindow.c:1666 msgid "Create" msgstr "作æˆ" #: src/fpick.c:699 msgid "Enter the new filename" msgstr "æ–°è¦ãƒ•ァイルåを入力" #: src/fpick.c:704 msgid "Create Directory" msgstr "ディレクトリを作æˆ" #: src/fpick.c:705 msgid "Enter the name of the new directory" msgstr "æ–°è¦ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªåを入力" #: src/fpick.c:729 #, c-format msgid "Do you really want to delete \"%s\" ?" msgstr "本当㫠\"%s\" を削除ã—ã¾ã™ã‹ï¼Ÿ" #: src/fpick.c:735 msgid "Unable to delete" msgstr "削除ã§ãã¾ã›ã‚“" #: src/fpick.c:741 msgid "Unable to rename" msgstr "リãƒãƒ¼ãƒ ã§ãã¾ã›ã‚“" #: src/fpick.c:750 msgid "Unable to create directory" msgstr "ディレクトリを作æˆã§ãã¾ã›ã‚“" #: src/fpick.c:924 msgid "Up" msgstr "上" #: src/fpick.c:925 msgid "Home" msgstr "ホーム" #: src/fpick.c:926 msgid "Create New Directory" msgstr "æ–°è¦ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‚’作æˆ" #: src/fpick.c:927 msgid "Show Hidden Files" msgstr "éš ã—ファイルを表示" #: src/fpick.c:929 msgid "Case Insensitive Sort" msgstr "å¤§æ–‡å­—å°æ–‡å­—を区別ã—ã¦ä¸¦ã³æ›¿ãˆ" #: src/fpick.c:936 msgid "Name" msgstr "åå‰" #: src/fpick.c:938 msgid "Type" msgstr "タイプ" #: src/fpick.c:939 msgid "Modified" msgstr "修正" #: src/help.c:25 src/prefs.c:160 msgid "General" msgstr "一般" #: src/help.c:26 msgid "Keyboard shortcuts" msgstr "キーボードショートカット" #: src/help.c:27 msgid "Mouse shortcuts" msgstr "マウスショートカット" #: src/help.c:28 msgid "Credits" msgstr "クレジット" #: src/help.c:32 msgid "mtPaint 3.51 - Copyright (C) 2004-2021 The Authors\n" msgstr "mtPaint 3.51 - 著作権 (C) 2004-2021 作者ãŸã¡\n" #: src/help.c:33 msgid "See 'Credits' section for a list of the authors.\n" msgstr "作者リストã¯ã€Œã‚¯ãƒ¬ã‚¸ãƒƒãƒˆã€ã‚’ã”覧下ã•ã„。\n" #: src/help.c:34 msgid "" "mtPaint 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.\n" msgstr "" "mtPaintã¯ã€ç„¡æ–™ã‚½ãƒ•トã§ã™; フリーソフトウェア財団ã«ã‚ˆã£ã¦ç™ºè¡¨ã•れãŸGNU一般公" "有使用許諾(GPL)ã®æ¡ä»¶ã®ä¸‹ã§ã€ã‚ãªãŸã¯ãれをå†é…布ã™ã‚‹äº‹ã‚‚ã€ãれを修正ã™ã‚‹äº‹ã‚‚" "ã§ãã¾ã™; ãƒãƒ¼ã‚¸ãƒ§ãƒ³ï¼“ã®ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã€ã¾ãŸã¯ï¼ˆã‚ãªãŸã®ã‚ªãƒ—ションã§ï¼‰ã©ã®æœ€æ–°" "ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã§ã‚‚。\n" #: src/help.c:35 msgid "" "mtPaint 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.\n" msgstr "" "mtPaintã¯ã€å½¹ã«ç«‹ã¤äº‹ã‚’希望ã—ã¦é…布ã•れã¾ã™ãŒã€Œç„¡ä¿è¨¼ã€ã§ã™;商å“驿 ¼æ€§ã¾ãŸã¯" "特定目的ã¸ã®é©åˆæ€§ã®é»™ç¤ºä¿è¨¼ã‚‚ã‚りã¾ã›ã‚“。詳細ã¯GNU一般公有使用許諾を見ã¦ä¸‹ã•" "ã„。\n" #: src/help.c:36 msgid "" "mtPaint is a simple GTK+1/2/3 painting program designed for creating icons " "and pixel based artwork. It can edit indexed palette or 24 bit RGB images " "and offers basic painting and palette manipulation tools. It also has " "several other more powerful features such as channels, layers and animation. " "Due to its simplicity and lack of dependencies it runs well on GNU/Linux, " "Windows and older PC hardware.\n" msgstr "" "mtPaintã¯ã‚¢ã‚¤ã‚³ãƒ³ã¨ãƒ”クセルベースã®ã‚¢ãƒ¼ãƒˆãƒ¯ãƒ¼ã‚¯ã‚’作æˆã™ã‚‹ãŸã‚ã«è¨­è¨ˆã•れãŸã‚·ãƒ³" "プルãªGTK+1/2ペイントプログラムã§ã™ã€‚ãれã¯ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ã‚’付ã‘られãŸãƒ‘レットã¾" "ãŸã¯24ビットã®RGBイメージを編集ã§ãã€åŸºæœ¬çš„ãªçµµã¨ãƒ‘レットæ“作ツールをæä¾›ã—ã¾" "ã™ã€‚ã¾ãŸã€ã„ãã¤ã‹ã®å¼·åŠ›ãªç‰¹å¾´ã€ä¾‹ãˆã°ãƒãƒ£ãƒ³ãƒãƒ«ã€ãƒ¬ã‚¤ãƒ¤ã€ã‚¢ãƒ‹ãƒ¡ãƒ¼ã‚·ãƒ§ãƒ³ã‚‚ã‚" "りã¾ã™ã€‚ãã®å˜ç´”ã•ã¨ä¾å­˜æ€§ãŒãªã„ãŸã‚ã€GNU/Linuxã€Windowsã¨å¤ã„PCãƒãƒ¼ãƒ‰ã‚¦ã‚§ã‚¢" "ã§ã‚‚å‹•ãã¾ã™ã€‚\n" #: src/help.c:37 msgid "" "There is full documentation of mtPaint's features contained in a handbook. " "If you don't already have this, you can download it from the mtPaint " "website.\n" msgstr "" "ãƒãƒ³ãƒ‰ãƒ–ックã«å«ã¾ã‚Œã‚‹mtPaintã®ç‰¹å¾´ã®å®Œå…¨ãªãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆãŒã‚りã¾ã™ã€‚ã‚ãªãŸãŒã¾" "ã æŒã£ã¦ã„ãªã„ãªã‚‰ã°ã€mtPaintã®ã‚¦ã‚§ãƒ–サイトã‹ã‚‰ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰ã§ãã¾ã™ã€‚\n" #: src/help.c:38 msgid "" "If you like mtPaint and you want to keep up to date with new releases, or " "you want to give some feedback, then the mailing lists may be of interest to " "you:\n" msgstr "" "ã‚ãªãŸãŒmtPaintãŒå¥½ãã§ã€æ–°ã—ã„リリースをアップデートã—ã¦ã„ãŸã„ã€ã‚ã‚‹ã„ã¯" "フィードãƒãƒƒã‚¯ã‚’ã—ãŸã„ãªã‚‰ã€ãƒ¡ãƒ¼ãƒªãƒ³ã‚°ãƒªã‚¹ãƒˆãŒèˆˆå‘³æ·±ã„ã‹ã‚‚知れã¾ã›ã‚“:\n" #: src/help.c:39 msgid "http://sourceforge.net/mail/?group_id=155874" msgstr "http://sourceforge.net/mail/?group_id=155874" #: src/help.c:42 msgid " Ctrl-N Create new image" msgstr " Ctrl-N æ–°è¦ã‚¤ãƒ¡ãƒ¼ã‚¸ã‚’作æˆ" #: src/help.c:43 msgid " Ctrl-O Open Image" msgstr " Ctrl-O イメージを開ã" #: src/help.c:44 msgid " Ctrl-S Save Image" msgstr " Ctrl-S イメージをä¿å­˜" #: src/help.c:45 msgid " Ctrl-Shift-S Save layers file" msgstr "" #: src/help.c:46 msgid " Ctrl-Q Quit program\n" msgstr " Ctrl-Q プログラムを終了\n" #: src/help.c:47 msgid " Ctrl-A Select whole image" msgstr " Ctrl-A ã‚¤ãƒ¡ãƒ¼ã‚¸å…¨ä½“ã‚’é¸æŠž" #: src/help.c:48 msgid " Escape Select nothing, cancel paste box" msgstr " Escape ä½•ã‚‚é¸æŠžã›ãšã€è²¼ã‚Šä»˜ã‘をキャンセル" #: src/help.c:49 msgid " J Lasso selection\n" msgstr "" #: src/help.c:50 msgid " Ctrl-C Copy selection to clipboard" msgstr " Ctrl-C é¸æŠžç¯„å›²ã‚’ã‚¯ãƒªãƒƒãƒ—ãƒœãƒ¼ãƒ‰ã¸ã‚³ãƒ”ー" #: src/help.c:51 msgid "" " Ctrl-X Copy selection to clipboard, and then paint current " "pattern to selection area" msgstr "" " Ctrl-X é¸æŠžç¯„å›²ã‚’ã‚¯ãƒªãƒƒãƒ—ãƒœãƒ¼ãƒ‰ã¸ã‚³ãƒ”ーã—ã¦ã€ç¾åœ¨ã®ãƒ‘ターンã§é¸æŠžé ˜" "域を塗りã¤ã¶ã™" #: src/help.c:52 msgid " Ctrl-V Paste clipboard to centre of current view" msgstr " Ctrl-V クリップボードをç¾åœ¨ã®è¡¨ç¤ºã®ä¸­å¤®ã¸è²¼ã‚Šä»˜ã‘" #: src/help.c:53 msgid " Ctrl-K Paste clipboard to location it was copied from" msgstr " Ctrl-K クリップボードをコピーã—ãŸä½ç½®ã¸è²¼ã‚Šä»˜ã‘" #: src/help.c:54 msgid " Ctrl-Shift-V Paste clipboard to new layer" msgstr "" #: src/help.c:55 msgid " Enter/Return Commit paste to canvas" msgstr " Enter/Return キャンãƒã‚¹ã«è²¼ã‚Šä»˜ã‘" #: src/help.c:56 msgid " Shift+Enter/Return Commit paste and swap canvas into the clipboard\n" msgstr "" #: src/help.c:57 msgid " Arrow keys Paint Mode - Move the mouse pointer" msgstr " 矢å°ã‚­ãƒ¼ 塗りã¤ã¶ã—モード - マウスカーソルを移動" #: src/help.c:58 msgid "" " Arrow keys Selection Mode - Nudge selection box or paste box by one " "pixel" msgstr "" " 矢å°ã‚­ãƒ¼ é¸æŠžãƒ¢ãƒ¼ãƒ‰ - é¸æŠžãƒœãƒƒã‚¯ã‚¹ã€è²¼ã‚Šä»˜ã‘ボックスを1ピクセルå˜ä½" "ã§ç§»å‹•" #: src/help.c:59 msgid "" " Shift+Arrow keys Nudge mouse pointer, selection box or paste box by x " "pixels - x is defined by the Preferences window" msgstr "" " Shift+矢å°ã‚­ãƒ¼ マウスãƒã‚¤ãƒ³ã‚¿ã€é¸æŠžãƒœãƒƒã‚¯ã‚¹ã€è²¼ã‚Šä»˜ã‘ボックスを x ピクセル" "å˜ä½ã§ç§»å‹• - x ã¯è¨­å®šã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã§æ±ºã‚られã¾ã™" #: src/help.c:60 msgid " Ctrl+Arrows Move layer or resize selection box" msgstr " Ctrl+矢å°ã‚­ãƒ¼ レイヤã®ç§»å‹•ã€é¸æŠžãƒœãƒƒã‚¯ã‚¹ã®ãƒªã‚µã‚¤ã‚º" #: src/help.c:61 msgid " Ctrl+Shift+Arrows Move layer or resize selection box by x pixels\n" msgstr "" #: src/help.c:62 msgid " Enter/Return Paint Mode - Simulate left click" msgstr "" #: src/help.c:63 msgid " Backspace Paint Mode - Simulate right click\n" msgstr "" #: src/help.c:64 msgid "" " [ or ] Change colour A to the next or previous palette item" msgstr " [ ã‹ ] 色A を次ã®ã€ã¾ãŸã¯å‰ã®ãƒ‘レットアイテムã«å¤‰æ›´" #: src/help.c:65 msgid "" " Shift+[ or ] Change colour B to the next or previous palette item\n" msgstr " Shift+[ ã‹ ] 色B を次ã®ã€ã¾ãŸã¯å‰ã®ãƒ‘レットアイテムã«å¤‰æ›´\n" #: src/help.c:66 msgid " Delete Crop image to selection" msgstr " Delete ã‚¤ãƒ¡ãƒ¼ã‚¸ã‚’é¸æŠžç¯„å›²ã«ãƒˆãƒªãƒŸãƒ³ã‚°" #: src/help.c:67 msgid "" " Insert Transform colours - i.e. Brightness, Contrast, " "Saturation, Posterize, Gamma" msgstr "" " Insert è‰²ã‚’å¤‰æ› - ã™ãªã‚ã¡ã€æ˜Žã‚‹ã•ã€ã‚³ãƒ³ãƒˆãƒ©ã‚¹ãƒˆã€å½©åº¦ã€ãƒã‚¹ã‚¿ãƒ©ã‚¤" "ズã€ã‚¬ãƒ³ãƒž" #: src/help.c:68 msgid " Ctrl-G Greyscale the image" msgstr " Ctrl-G イメージをグレースケール" #: src/help.c:69 msgid " Shift-Ctrl-G Greyscale the image (Gamma corrected)" msgstr " Shift-Ctrl-G イメージをグレースケール(ガンマ補正)" #: src/help.c:70 msgid " Ctrl+M Mirror the image" msgstr "" #: src/help.c:71 msgid " Shift-Ctrl-I Invert the image\n" msgstr "" #: src/help.c:72 msgid "" " Ctrl-T Draw a rectangle around the selection area with the " "current fill" msgstr " Ctrl-T é¸æŠžé ˜åŸŸã«ç¾åœ¨ã®è‰²ã§é•·æ–¹å½¢ã‚’æã" #: src/help.c:73 msgid " Ctrl-Shift-T Fill in the selection area with the current fill" msgstr " Ctrl-Shift-T é¸æŠžé ˜åŸŸã‚’ç¾åœ¨ã®è‰²ã§å¡—りã¤ã¶ã™" #: src/help.c:74 msgid " Ctrl-L Draw an ellipse spanning the selection area" msgstr " Ctrl-L 楕円ã®é¸æŠžé ˜åŸŸã‚’æã" #: src/help.c:75 msgid " Ctrl-Shift-L Draw a filled ellipse spanning the selection area\n" msgstr " Ctrl-Shift-L é¸æŠžé ˜åŸŸå†…ã«æ¥•円をæã\n" #: src/help.c:76 msgid " Ctrl-E Edit the RGB values for colours A & B" msgstr " Ctrl-E 色A 㨠色B ã®RGB値を編集" #: src/help.c:77 msgid " Ctrl-W Edit all palette colours\n" msgstr " Ctrl-W 全パレット色を編集\n" #: src/help.c:78 msgid " Ctrl-P Preferences" msgstr " Ctrl-P 設定" #: src/help.c:79 msgid " Ctrl-I Information\n" msgstr " Ctrl-I 情報\n" #: src/help.c:80 msgid " Ctrl-Z Undo last action" msgstr " Ctrl-Z æœ€å¾Œã®æ“ä½œã‚’å…ƒã«æˆ»ã™" #: src/help.c:81 msgid " Ctrl-R Redo an undone action\n" msgstr " Ctrl-R 未完æˆã®æ“作をやり直ã™\n" #: src/help.c:82 msgid " Shift-T Text Tool (GTK+)" msgstr "" #: src/help.c:83 msgid " T Text Tool (FreeType)\n" msgstr "" #: src/help.c:84 msgid " V View Window" msgstr " V 表示ウィンドウ" #: src/help.c:85 msgid " L Layers Window\n" msgstr " L レイヤウィンドウ\n" #: src/help.c:86 msgid " Ctrl-H Toggle Hide Image mode" msgstr "" #: src/help.c:87 msgid " B Toggle Snap to Tile Grid mode\n" msgstr "" #: src/help.c:88 msgid " X Swap Colours A & B" msgstr "" #: src/help.c:89 msgid " E Choose Colour\n" msgstr "" #: src/help.c:90 msgid "" " A Draw open arrow head when using the line tool (size set " "by flow setting)" msgstr "" " A 線引ããƒ„ãƒ¼ãƒ«ã‚’ä½¿ã†æ™‚ã€é–‹ã„ãŸçŸ¢å°ã‚’æã (フロー設定ã§ã‚µã‚¤" "ズを設定)" #: src/help.c:91 msgid "" " S Draw closed arrow head when using the line tool (size " "set by flow setting)\n" msgstr "" " S 線引ããƒ„ãƒ¼ãƒ«ã‚’ä½¿ã†æ™‚ã€é–‰ã˜ãŸçŸ¢å°ã‚’æã (フロー設定ã§ã‚µã‚¤" "ズを設定)\n" #: src/help.c:92 msgid " D Line Tool" msgstr "" #: src/help.c:93 msgid " F Flood Fill Tool\n" msgstr "" #: src/help.c:94 msgid " +,= Main edit window - Zoom in" msgstr " +,= メイン編集ウィンドウ - 拡大" #: src/help.c:95 msgid " - Main edit window - Zoom out" msgstr " - メイン編集ウィンド - 縮å°" #: src/help.c:96 msgid " Shift +,= View window - Zoom in" msgstr " Shift +,= 表示ウィンドウ - 拡大" #: src/help.c:97 msgid " Shift - View window - Zoom out\n" msgstr " Shift - 表示ウィンドウ - 縮å°\n" #: src/help.c:98 #, fuzzy, c-format msgid " 1 10% zoom" msgstr " 1 10% ズーム" #: src/help.c:99 #, fuzzy, c-format msgid " 2 25% zoom" msgstr " 2 25% ズーム" #: src/help.c:100 #, fuzzy, c-format msgid " 3 50% zoom" msgstr " 3 50% ズーム" #: src/help.c:101 #, fuzzy, c-format msgid " 4 100% zoom" msgstr " 4 100% ズーム" #: src/help.c:102 #, fuzzy, c-format msgid " 5 400% zoom" msgstr " 5 400% ズーム" #: src/help.c:103 #, fuzzy, c-format msgid " 6 800% zoom" msgstr " 6 800% ズーム" #: src/help.c:104 #, fuzzy, c-format msgid " 7 1200% zoom" msgstr " 7 1200% ズーム" #: src/help.c:105 #, fuzzy, c-format msgid " 8 1600% zoom" msgstr " 8 1600% ズーム" #: src/help.c:106 #, fuzzy, c-format msgid " 9 2000% zoom\n" msgstr " 9 2000% ズーム\n" #: src/help.c:107 msgid " Shift + 1 Edit image channel" msgstr " Shift + 1 イメージãƒãƒ£ãƒ³ãƒãƒ«ã‚’編集" #: src/help.c:108 msgid " Shift + 2 Edit alpha channel" msgstr " Shift + 2 アルファãƒãƒ£ãƒ³ãƒãƒ«ã‚’編集" #: src/help.c:109 msgid " Shift + 3 Edit selection channel" msgstr " Shift + 3 é¸æŠžãƒãƒ£ãƒ³ãƒãƒ«ã‚’編集" #: src/help.c:110 msgid " Shift + 4 Edit mask channel\n" msgstr " Shift + 4 マスクãƒãƒ£ãƒ³ãƒãƒ«ã‚’編集\n" #: src/help.c:111 msgid " F1 Help" msgstr " F1 ヘルプ" #: src/help.c:112 msgid " F2 Choose Pattern" msgstr " F2 ãƒ‘ã‚¿ãƒ¼ãƒ³ã‚’é¸æŠž" #: src/help.c:113 msgid " F3 Choose Brush" msgstr " F3 ãƒ–ãƒ©ã‚·ã‚’é¸æŠž" #: src/help.c:114 msgid " F4 Paint Tool" msgstr " F4 ペイントツール" #: src/help.c:115 msgid " F5 Toggle Main Toolbar" msgstr " F5 メインツールãƒãƒ¼ã‚’切り替ãˆ" #: src/help.c:116 msgid " F6 Toggle Tools Toolbar" msgstr " F6 ツールã®ãƒ„ールãƒãƒ¼ã‚’切り替ãˆ" #: src/help.c:117 msgid " F7 Toggle Settings Toolbar" msgstr " F7 設定ツールãƒãƒ¼ã‚’切り替ãˆ" #: src/help.c:118 msgid " F8 Toggle Palette" msgstr " F8 パレットを切り替ãˆ" #: src/help.c:119 msgid " F9 Selection Tool" msgstr " F9 ツールã®é¸æŠž" #: src/help.c:120 msgid " F12 Toggle Dock Area\n" msgstr " F12 ドックエリアを切り替ãˆ\n" #: src/help.c:121 msgid " Ctrl + F1 - F12 Save current clipboard to file 1-12" msgstr " Ctrl + F1 - F12 ç¾åœ¨ã®ã‚¯ãƒªãƒƒãƒ—ボードをファイル 1-12 ã«ä¿å­˜" #: src/help.c:122 msgid " Shift + F1 - F12 Load clipboard from file 1-12\n" msgstr " Shift + F1 - F12 ファイル 1-12 ã‹ã‚‰ã‚¯ãƒªãƒƒãƒ—ボードを読ã¿è¾¼ã¿\n" #: src/help.c:123 msgid "" " Ctrl + 1, 2, ... , 0 Set opacity to 10%, 20%, ... , 100% (main or keypad " "numbers)" msgstr "" " Ctrl + 1, 2, ... , 0 ä¸é€æ˜Žåº¦ã‚’ 10%ã€20%ã€... , 100%ã«è¨­å®šï¼ˆãƒ¡ã‚¤ãƒ³ã‚ã‚‹ã„ã¯" "キーパッドã®ç•ªå·ï¼‰" #: src/help.c:124 msgid " Ctrl + + or = Increase opacity by 1" msgstr " Ctrl + + or = ä¸é€æ˜Žåº¦ã‚’ 1 ã¥ã¤å¢—ã‚„ã™" #: src/help.c:125 msgid " Ctrl + - Decrease opacity by 1\n" msgstr " Ctrl + - ä¸é€æ˜Žåº¦ã‚’ 1 ã¥ã¤æ¸›ã‚‰ã™\n" #: src/help.c:126 msgid "" " Home Show or hide main window menu/toolbar/status bar/palette" msgstr "" " Home メインウィンドウã®ãƒ¡ãƒ‹ãƒ¥ãƒ¼/ツールãƒãƒ¼/ステータスãƒãƒ¼/パレットã®" "表示・éžè¡¨ç¤º" #: src/help.c:127 msgid " Page Up Scale Image" msgstr " Page Up ã‚¤ãƒ¡ãƒ¼ã‚¸ã‚’ç¸®å°æ‹¡å¤§" #: src/help.c:128 msgid " Page Down Resize Image canvas" msgstr " Page Down イメージキャンãƒã‚¹ã®ã‚µã‚¤ã‚ºã‚’変更" #: src/help.c:129 msgid " End Pan Window" msgstr " End ウィンドウをパンã™ã‚‹" #: src/help.c:132 msgid " Left button Paint to canvas using the current tool" msgstr " 左ボタン ç¾åœ¨ä½¿ç”¨ä¸­ã®ãƒ„ールã§ã‚­ãƒ£ãƒ³ãƒã‚¹ã‚’å¡—ã‚‹" #: src/help.c:133 msgid "" " Middle button Selects the point which will be the centre of the " "image after the next zoom" msgstr " 中央ボタン 次ã®ã‚ºãƒ¼ãƒ å¾Œã€ã‚¤ãƒ¡ãƒ¼ã‚¸ã®ä¸­å¤®ã«ãªã‚‹ãƒã‚¤ãƒ³ãƒˆã‚’é¸æŠž" #: src/help.c:134 msgid "" " Right button Commit paste to canvas / Stop drawing current line / " "Cancel selection\n" msgstr "" " å³ãƒœã‚¿ãƒ³ キャンãƒã‚¹ã«è²¼ã‚Šä»˜ã‘ã‚‹ / ç¾åœ¨ã®ç·šã®æç”»ã‚’中止 / é¸æŠžã‚’ã‚­ãƒ£" "ンセル\n" #: src/help.c:135 msgid "" " Scroll Wheel In GTK+2/3 the user can have the scroll wheel zoom in " "or out via the Preferences window\n" msgstr "" " スクロールボタン GTK+2/3 ã§ã¯è¨­å®šã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã‹ã‚‰ã‚¹ã‚¯ãƒ­ãƒ¼ãƒ«ãƒœã‚¿" "ンã§ã‚ºãƒ¼ãƒ ã® + - を使ãˆã‚‹ã‚ˆã†ã«ã§ãã¾ã™\n" #: src/help.c:136 msgid " Ctrl+Left button Choose colour A from under mouse pointer" msgstr " Ctrl+左ボタン マウスãƒã‚¤ãƒ³ã‚¿ä¸Šã®è‰² A ã‚’é¸æŠž" #: src/help.c:137 msgid " Ctrl+Left button Clone tool - Select source" msgstr "" #: src/help.c:138 msgid "" " Ctrl+Middle button Create colour A/B and pattern based on the RGB colour " "in A (RGB images only)" msgstr "" " Ctrl+中央ボタン A/B 色を作æˆã—㦠A ã® RGB 色ベースã§ãƒ‘ターン化ã™ã‚‹(RGB イ" "メージã®ã¿)" #: src/help.c:139 msgid " Ctrl+Right button Choose colour B from under mouse pointer" msgstr " Ctrl+å³ãƒœã‚¿ãƒ³ マウスãƒã‚¤ãƒ³ã‚¿ä¸Šã®è‰²Bã‚’é¸æŠž" #: src/help.c:140 msgid "" " Ctrl+Right button Polygon tool - Delete last point / Delete nearest " "point" msgstr "" #: src/help.c:141 msgid " Ctrl+Scroll Wheel Scroll the main edit window left or right\n" msgstr "" " Ctrl+スクロールボタン メイン編集ウィンドウを左ã‹ã‚‰å³ã¸ã‚¹ã‚¯ãƒ­ãƒ¼ãƒ«\n" #: src/help.c:142 msgid "" " Ctrl+Double click Set colour A or B to average colour under brush " "square or selection marquee (RGB only)\n" msgstr "" " Ctrl+ダブルクリック 色A ã¾ãŸã¯ Bをブラシ四角ã‹é¸æŠžãƒžãƒ¼ã‚­ãƒ¼ã§å¹³å‡è‰²ã«ã™" "ã‚‹ (RGB ã®ã¿)\n" #: src/help.c:143 msgid "" " Shift+Right button Selects the point which will be the centre of the " "image after the next zoom\n" "\n" msgstr "" " Shift+å³ãƒœã‚¿ãƒ³ 次ã®ã‚ºãƒ¼ãƒ å¾Œãƒã‚¤ãƒ³ãƒˆãŒã‚¤ãƒ¡ãƒ¼ã‚¸ã®ä¸­å¤®ã«ãªã‚‹ã‚ˆã†ã«é¸æŠž\n" "\n" #: src/help.c:144 msgid "You can fixate the X/Y co-ordinates while moving the mouse:\n" msgstr "X/Y 座標をマウスã®ç§»å‹•ã—ã¦ã„ã‚‹é–“ã€å›ºå®šã§ãã¾ã™:\n" #: src/help.c:145 msgid " Shift Constrain mouse movements to vertical line" msgstr " Shift マウスã®åž‚直移動を抑制" #: src/help.c:146 msgid " Shift+Ctrl Constrain mouse movements to horizontal line" msgstr " Shift+Ctrl ãƒžã‚¦ã‚¹ã®æ°´å¹³ç§»å‹•を抑制" #: src/help.c:149 msgid "mtPaint is maintained by Dmitry Groshev.\n" msgstr "mtPaint 㯠Dmitry Groshev ã«ã‚ˆã£ã¦ãƒ¡ãƒ³ãƒ†ãƒŠãƒ³ã‚¹ã•れã¦ã„ã¾ã™ã€‚\n" #: src/help.c:150 msgid "wjaguar@users.sourceforge.net" msgstr "wjaguar@users.sourceforge.net" #: src/help.c:151 msgid "http://mtpaint.sourceforge.net/\n" msgstr "http://mtpaint.sourceforge.net/\n" #: src/help.c:152 msgid "" "The following people (in alphabetical order) have contributed directly to " "the project, and are therefore worthy of gracious thanks for their " "generosity and hard work:\n" "\n" msgstr "" "ä»¥ä¸‹ã®æ–¹ã€…(アルファベット順)ãŒãƒ—ロジェクトã«ç›´æŽ¥ã€è²¢çŒ®ã—ã¾ã—ãŸã€‚従ã£ã¦ã€ã" "ã®æ–¹ã€…ã®å¯›å¤§ã•ã¨ãã¤ã„仕事ã«å¯¾ã—ã¦ä¸é‡ãªãŠç¤¼ã‚’ã™ã‚‹ã«å€¤ã—ã¾ã™ã€‚:\n" "\n" #: src/help.c:153 msgid "Authors\n" msgstr "作者ãŸã¡\n" #: src/help.c:154 msgid "" "Dmitry Groshev - Contributing developer for version 2.30. Lead developer and " "maintainer from version 3.00 to the present." msgstr "" "Dmitry Groshev - ãƒãƒ¼ã‚¸ãƒ§ãƒ³ 2.30ã®è²¢çŒ®é–‹ç™ºè€…。ãƒãƒ¼ã‚¸ãƒ§ãƒ³ 3.00 ã‹ã‚‰ä»Šã¾ã§ã«ã„" "ãŸã‚‹æŒ‡å°Žçš„開発者ã§ã‚りメンテナー。" #: src/help.c:155 msgid "" "Mark Tyler - Original author and maintainer up to version 3.00, occasional " "contributor thereafter." msgstr "" "Mark Tyler - ãƒãƒ¼ã‚¸ãƒ§ãƒ³ 3.00 ã¾ã§ã®ã‚ªãƒªã‚¸ãƒŠãƒ«ä½œè€…ã§ãƒ¡ãƒ³ãƒ†ãƒŠãƒ¼ã€‚ãã®å¾Œã¯æ™‚折ã®" "貢献者。" #: src/help.c:156 msgid "" "Xiaolin Wu - Wrote the Wu quantizing method - see wu.c for more " "information.\n" "\n" msgstr "" "Xiaolin Wu - Wu é‡å­åŒ–方法を書ã„㟠- 詳細㯠wu.c ã‚’ã”覧下ã•ã„。\n" "\n" #: src/help.c:157 msgid "" "General Contributions (Feedback and Ideas for improvements unless otherwise " "stated)\n" msgstr "" "一般貢献(ãã®ä»–記載ã•れã¦ã„ãªã„改良ã®ãŸã‚ã®ã‚¢ã‚¤ãƒ‡ã‚¢ã¨ãƒ•ィードãƒãƒƒã‚¯ï¼‰\n" #: src/help.c:158 msgid "Abdulla Al Muhairi - Website redesign April 2005" msgstr "Abdulla Al Muhairi - 2005å¹´4月ã«ã‚¦ã‚§ãƒ–サイトã®ãƒªãƒ‡ã‚¶ã‚¤ãƒ³" #: src/help.c:159 msgid "Alan Horkan" msgstr "Alan Horkan" #: src/help.c:160 msgid "Alexandre Prokoudine" msgstr "Alexandre Prokoudine" #: src/help.c:161 msgid "Antonio Andrea Bianco" msgstr "Antonio Andrea Bianco" #: src/help.c:162 msgid "Charlie Ledocq" msgstr "" #: src/help.c:163 msgid "Dennis Lee" msgstr "Dennis Lee" #: src/help.c:164 msgid "Donald White" msgstr "" #: src/help.c:165 msgid "Ed Jason" msgstr "Ed Jason" #: src/help.c:166 msgid "" "Eddie Kohler - Created Gifsicle which is needed for the creation and viewing " "of animated GIF files http://www.lcdf.org/gifsicle/" msgstr "" "Eddie Kohler - アニメGIFファイルã®ä½œæˆã¨è¡¨ç¤ºã«å¿…è¦ãª Gifsicle ã®ä½œæˆ http://" "www.lcdf.org/gifsicle/" #: src/help.c:167 msgid "" "Guadalinex Team (Junta de Andalucia) - man page, Launchpad/Rosetta " "registration" msgstr "" "Guadalinex Team (Junta de Andalucia) - マニュアルページã€Launchpad/Rosetta ã®" "登録" #: src/help.c:168 msgid "Lou Afonso" msgstr "Lou Afonso" #: src/help.c:169 msgid "Magnus Hjorth" msgstr "Magnus Hjorth" #: src/help.c:170 msgid "Martin Zelaia" msgstr "Martin Zelaia" #: src/help.c:171 msgid "Pasi Kallinen" msgstr "" #: src/help.c:172 msgid "Pavel Ruzicka" msgstr "Pavel Ruzicka" #: src/help.c:173 msgid "Puppy Linux (Barry Kauler)" msgstr "Puppy Linux (Barry Kauler)" #: src/help.c:174 msgid "Victor Copovi" msgstr "" #: src/help.c:175 msgid "Vlastimil Krejcir" msgstr "Vlastimil Krejcir" #: src/help.c:176 msgid "" "William Kern\n" "\n" msgstr "" "William Kern\n" "\n" #: src/help.c:177 msgid "Translations\n" msgstr "翻訳\n" #: src/help.c:178 msgid "Brazilian Portuguese - Paulo Trevizan, Valter Nazianzeno" msgstr "ブラジル ãƒãƒ«ãƒˆã‚¬ãƒ«èªž - Paulo Trevizan, Valter Nazianzeno" #: src/help.c:179 msgid "Czech - Pavel Ruzicka, Martin Petricek, Roman Hornik, Pavel Fric" msgstr "ãƒã‚§ã‚³èªž - Pavel Ruzicka, Martin Petricek, Roman Hornik, Pavel Fric" #: src/help.c:180 msgid "Dutch - Hans Strijards, Pjotr" msgstr "オランダ語 - Hans Strijards, Pjotr" #: src/help.c:181 msgid "" "French - Nicolas Velin, Pascal Billard, Sylvain Cresto, Johan Serre, " "Philippe Etienne, Victor Copovi" msgstr "" "フランス語 - Nicolas Velin, Pascal Billard, Sylvain Cresto, Johan Serre, " "Philippe Etienne, Victor Copovi" #: src/help.c:182 msgid "Galician - Miguel Anxo Bouzada" msgstr "ガリシア語 - Miguel Anxo Bouzada" #: src/help.c:183 msgid "German - Oliver Frommel, B. Clausius, Ulrich Ringel, Simon Brixel" msgstr "ドイツ語 - Oliver Frommel, B. Clausius, Ulrich Ringel, Simon Brixel" #: src/help.c:184 msgid "Hungarian - Ur Balazs" msgstr "" #: src/help.c:185 msgid "Italian - Angelo Gemmi" msgstr "イタリア語 - Angelo Gemmi" #: src/help.c:186 msgid "Japanese - Norihiro YONEDA" msgstr "日本語 - 米田 憲弘" #: src/help.c:187 msgid "Kabyle - Yacine Bouklif" msgstr "" #: src/help.c:188 msgid "Polish - Bartosz Kaszubowski, LucaS" msgstr "ãƒãƒ¼ãƒ©ãƒ³ãƒ‰èªž - Bartosz Kaszubowski, LucaS" #: src/help.c:189 msgid "Portuguese - Israel G. Lugo, Tiago Silva" msgstr "ãƒãƒ«ãƒˆã‚¬ãƒ«èªž - Israel G. Lugo, Tiago Silva" #: src/help.c:190 msgid "Russian - Sergey Irupin, Dmitry Groshev" msgstr "ロシア語 - Sergey Irupin, Dmitry Groshev" #: src/help.c:191 msgid "Simplified Chinese - Cecc" msgstr "簡体字中国語 - Cecc" #: src/help.c:192 msgid "Slovak - Jozef Riha" msgstr "スロãƒã‚­ã‚¢èªž - Jozef Riha" #: src/help.c:193 msgid "" "Spanish - Guadalinex Team (Junta de Andalucia), Antonio Sanchez Leon, Miguel " "Anxo Bouzada, Francisco Jose Rey, Adolfo Jayme" msgstr "" "スペイン語 - Guadalinex Team (Junta de Andalucia), Antonio Sanchez Leon, " "Miguel Anxo Bouzada, Francisco Jose Rey, Adolfo Jayme" #: src/help.c:194 msgid "Swedish - Daniel Nylander, Daniel Eriksson" msgstr "スウェーデン語 - Daniel Nylander, Daniel Eriksson" #: src/help.c:195 msgid "Tagalog - Anjelo delCarmen" msgstr "" #: src/help.c:196 msgid "Taiwanese Chinese - Wei-Lun Chao" msgstr "å°æ¹¾ä¸­å›½èªž - Wei-Lun Chao" #: src/help.c:197 msgid "Turkish - Muhammet Kara, Tutku Dalmaz" msgstr "トルコ語 - Muhammet Kara, Tutku Dalmaz" #: src/info.c:258 msgid "Information" msgstr "情報" #: src/info.c:260 msgid "Memory" msgstr "メモリ" #: src/info.c:261 msgid "Total memory for main + undo images" msgstr "メイン + ã‚¤ãƒ¡ãƒ¼ã‚¸ã‚’å…ƒã«æˆ»ã™ãŸã‚ã®åˆè¨ˆãƒ¡ãƒ¢ãƒª" #: src/info.c:263 msgid "Undo / Redo / Max levels used" msgstr "å…ƒã«æˆ»ã™ / やり直㗠/ 最高レベルを使用" #: src/info.c:265 msgid "Unused" msgstr "未使用" #: src/info.c:269 msgid "Unique RGB pixels" msgstr "ä¸€æ„ RGB ピクセル" #: src/info.c:272 src/layer.c:121 msgid "Layers" msgstr "レイヤ" #: src/info.c:273 msgid "Total layer memory usage" msgstr "レイヤメモリ使用é‡åˆè¨ˆ" #: src/info.c:277 msgid "Colour Histogram" msgstr "カラーヒストグラム" #: src/info.c:289 src/otherwindow.c:1614 msgid "Index" msgstr "インデックス" #: src/info.c:290 msgid "Canvas pixels" msgstr "キャンãƒã‚¹ ピクセル" #: src/info.c:328 #, c-format msgid "Clipboard = %i x %i" msgstr "クリップボード = %i x %i" #: src/info.c:328 #, c-format msgid "Clipboard = %i x %i x RGB" msgstr "クリップボード = %i x %i x RGB" #: src/info.c:377 msgid "Orphans" msgstr "最åˆã®è¡Œ" #: src/info.c:383 #, c-format msgid "Colour index totals - %i of %i used" msgstr "カラーインデックスåˆè¨ˆ - %i ã®å†… %i 使用" #: src/inifile.c:966 msgid "" "Could not find home directory. Using current directory as home directory." msgstr "" "ホームディレクトリãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。ç¾åœ¨ã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‚’ホームã¨ã—ã¦ä½¿ã„ã¾" "ã™ã€‚" #: src/layer.c:63 msgid "Background" msgstr "背景" #: src/layer.c:122 src/mainwindow.c:5931 msgid "(Modified)" msgstr "(変更済ã¿)" #: src/layer.c:123 src/mainwindow.c:5932 msgid "Untitled" msgstr "無題" #: src/layer.c:308 #, c-format msgid "Do you really want to delete layer %i (%s) ?" msgstr "本当ã«ãƒ¬ã‚¤ãƒ¤ %i (%s) を削除ã—ã¦ã‚‚ã„ã„ã§ã™ã‹ï¼Ÿ" #: src/layer.c:380 msgid "" "One or more of the layers contains changes that have not been saved. Do you " "really want to lose these changes?" msgstr "" "1ã¤ä»¥ä¸Šã®ãƒ¬ã‚¤ãƒ¤ã«ä¿å­˜ã•れã¦ã„ãªã„変更ãŒã‚りã¾ã™ã€‚本当ã«å¤‰æ›´ã‚’破棄ã—ã¾ã™ã‹ï¼Ÿ" #: src/layer.c:381 src/mainwindow.c:1028 msgid "Cancel Operation" msgstr "キャンセル" #: src/layer.c:381 src/mainwindow.c:1028 msgid "Lose Changes" msgstr "変更を破棄" #: src/layer.c:523 #, c-format msgid "%d layers failed to load" msgstr "%d レイヤã®èª­ã¿è¾¼ã¿ã«å¤±æ•—" #: src/layer.c:826 msgid "" "One or more of the image layers has not been saved. You must save each " "image individually before saving the layers text file in order to load this " "composite image in the future." msgstr "" "一ã¤ä»¥ä¸Šã®ãƒ¬ã‚¤ãƒ¤ãŒä¿å­˜ã•れã¦ã„ã¾ã›ã‚“。将æ¥ã“ã®åˆæˆã‚¤ãƒ¡ãƒ¼ã‚¸ã‚’読ã¿è¾¼ã‚€ãŸã‚ã«ã€" "レイヤテキストをä¿å­˜ã™ã‚‹å‰ã«ã‚¤ãƒ¡ãƒ¼ã‚¸ã‚’個々ã«ä¿å­˜ã—ã¦ä¸‹ã•ã„。" #: src/layer.c:841 msgid "Do you really want to delete all of the layers?" msgstr "本当ã«ã™ã¹ã¦ã®ãƒ¬ã‚¤ãƒ¤ã‚’削除ã—ã¾ã™ã‹ï¼Ÿ" #: src/layer.c:970 msgid "You cannot add any more layers." msgstr "ã“れ以上レイヤを追加ã§ãã¾ã›ã‚“。" #: src/layer.c:1083 src/otherwindow.c:241 msgid "New Layer" msgstr "æ–°è¦ãƒ¬ã‚¤ãƒ¤" #: src/layer.c:1085 msgid "Raise" msgstr "上ã’ã‚‹" #: src/layer.c:1087 msgid "Lower" msgstr "下ã’ã‚‹" #: src/layer.c:1089 msgid "Duplicate Layer" msgstr "レイヤを複製" #: src/layer.c:1091 msgid "Centralise Layer" msgstr "レイヤを中央ã¸" #: src/layer.c:1093 msgid "Delete Layer" msgstr "レイヤを削除" #: src/layer.c:1095 msgid "Close Layers Window" msgstr "レイヤウィンドウを閉ã˜ã‚‹" #: src/layer.c:1101 msgid "Layer Name" msgstr "レイヤå" #: src/layer.c:1104 src/toolbar.c:209 msgid "Position" msgstr "ä½ç½®" #: src/layer.c:1112 msgid "Transparent Colour" msgstr "é€éŽè‰²" #: src/layer.c:1117 msgid "Show all layers in main window" msgstr "メインウィンドウã«å…¨ãƒ¬ã‚¤ãƒ¤ã‚’表示" #: src/mainwindow.c:67 src/otherwindow.c:844 src/otherwindow.c:2756 #: src/toolbar.c:342 msgid "Image" msgstr "イメージ" #: src/mainwindow.c:69 src/mainwindow.c:489 src/otherwindow.c:1613 #: src/otherwindow.c:2302 msgid "RGB" msgstr "RGB" #: src/mainwindow.c:69 src/otherwindow.c:1613 src/otherwindow.c:2302 msgid "sRGB" msgstr "" #: src/mainwindow.c:342 msgid "There were no unused colours to remove!" msgstr "削除ã™ã‚‹æœªä½¿ç”¨ã®è‰²ã¯ã‚りã¾ã›ã‚“ï¼" #: src/mainwindow.c:371 msgid "The palette does not contain 2 colours that have identical RGB values" msgstr "パレットã¯åŒã˜RGB値ã®ï¼’ã¤ã®è‰²ãŒã‚りã¾ã›ã‚“" #: src/mainwindow.c:374 #, c-format msgid "" "The palette contains %i colours that have identical RGB values. Do you " "really want to merge them into one index and realign the canvas?" msgstr "" "パレットã¯åŒã˜RGB値ã®è‰² %i ã‚’å«ã¿ã¾ã™ã€‚本当ã«ï¼‘ã¤ã®ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ã«ãƒžãƒ¼ã‚¸ã—ã¦" "キャンãƒã‚¹ã‚’冿§‹æˆã—ã¾ã™ã‹ï¼Ÿ" #: src/mainwindow.c:492 msgid "indexed" msgstr "インデックス済ã¿" #: src/mainwindow.c:498 #, c-format msgid "" "You are trying to save an %s image to an %s file which is not possible. I " "would suggest you save with a PNG extension." msgstr "%s イメージを %s ファイルã§ä¿å­˜ã§ãã¾ã›ã‚“。PNGæ‹¡å¼µå­ã§ä¿å­˜ã—ã¦ä¸‹ã•ã„。" #: src/mainwindow.c:500 #, c-format msgid "" "You are trying to save an %s file with a palette of more than %d colours. " "Either use another format or reduce the palette to %d colours." msgstr "" "ファイル %s ã‚’ %d 色以上ã®ãƒ‘レットã§ä¿å­˜ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚別ã®ãƒ•ォーマット" "を使ã†ã‹ã€ãƒ‘レットを %d è‰²ã«æ¸›è‰²ã—ã¦ä¸‹ã•ã„。" #: src/mainwindow.c:578 msgid "Unable to load clipboard" msgstr "クリップボードを読ã¿è¾¼ã‚ã¾ã›ã‚“" #: src/mainwindow.c:604 msgid "Unable to save clipboard" msgstr "クリップボードをä¿å­˜ã§ãã¾ã›ã‚“" #: src/mainwindow.c:775 msgid "Zoom in" msgstr "" #: src/mainwindow.c:777 msgid "Zoom out" msgstr "" #: src/mainwindow.c:779 #, c-format msgid "10% zoom" msgstr "" #: src/mainwindow.c:781 #, c-format msgid "25% zoom" msgstr "" #: src/mainwindow.c:783 #, c-format msgid "50% zoom" msgstr "" #: src/mainwindow.c:785 #, c-format msgid "100% zoom" msgstr "" #: src/mainwindow.c:787 #, c-format msgid "400% zoom" msgstr "" #: src/mainwindow.c:789 #, c-format msgid "600% zoom" msgstr "" #: src/mainwindow.c:791 #, c-format msgid "800% zoom" msgstr "" #: src/mainwindow.c:793 #, c-format msgid "1000% zoom" msgstr "" #: src/mainwindow.c:795 #, c-format msgid "1200% zoom" msgstr "" #: src/mainwindow.c:797 #, c-format msgid "1600% zoom" msgstr "" #: src/mainwindow.c:799 #, c-format msgid "2000% zoom" msgstr "" #: src/mainwindow.c:801 #, c-format msgid "4000% zoom" msgstr "" #: src/mainwindow.c:803 #, c-format msgid "8000% zoom" msgstr "" #: src/mainwindow.c:805 #, c-format msgid "10% opacity" msgstr "" #: src/mainwindow.c:807 #, c-format msgid "20% opacity" msgstr "" #: src/mainwindow.c:809 #, c-format msgid "30% opacity" msgstr "" #: src/mainwindow.c:811 #, c-format msgid "40% opacity" msgstr "" #: src/mainwindow.c:813 #, c-format msgid "50% opacity" msgstr "" #: src/mainwindow.c:815 #, c-format msgid "60% opacity" msgstr "" #: src/mainwindow.c:817 #, c-format msgid "70% opacity" msgstr "" #: src/mainwindow.c:819 #, c-format msgid "80% opacity" msgstr "" #: src/mainwindow.c:821 #, c-format msgid "90% opacity" msgstr "" #: src/mainwindow.c:823 #, c-format msgid "100% opacity" msgstr "" #: src/mainwindow.c:825 msgid "Increase opacity" msgstr "" #: src/mainwindow.c:827 msgid "Decrease opacity" msgstr "" #: src/mainwindow.c:829 msgid "Draw open arrow head" msgstr "" #: src/mainwindow.c:831 msgid "Draw closed arrow head" msgstr "" #: src/mainwindow.c:833 msgid "Previous colour A" msgstr "" #: src/mainwindow.c:835 msgid "Next colour A" msgstr "" #: src/mainwindow.c:837 msgid "Previous colour B" msgstr "" #: src/mainwindow.c:839 msgid "Next colour B" msgstr "" #: src/mainwindow.c:841 msgid "Previous pattern" msgstr "" #: src/mainwindow.c:843 msgid "Next pattern" msgstr "" #: src/mainwindow.c:845 msgid "Larger brush" msgstr "" #: src/mainwindow.c:847 msgid "Smaller brush" msgstr "" #: src/mainwindow.c:849 msgid "View window - Zoom in" msgstr "" #: src/mainwindow.c:851 msgid "View window - Zoom out" msgstr "" #: src/mainwindow.c:1027 msgid "" "This canvas/palette contains changes that have not been saved. Do you " "really want to lose these changes?" msgstr "" "ã“ã®ã‚­ãƒ£ãƒ³ãƒã‚¹/パレットã«ã¯æœªä¿å­˜ã®å¤‰æ›´ãŒã‚りã¾ã™ã€‚ã“ã®å¤‰æ›´ã‚’破棄ã—ã¾ã™ã‹ï¼Ÿ" #: src/mainwindow.c:1094 msgid "Do you really want to quit?" msgstr "本当ã«çµ‚了ã—ã¾ã™ã‹ï¼Ÿ" #: src/mainwindow.c:3754 msgid "Empty string or broken quoting" msgstr "" #: src/mainwindow.c:3755 msgid "Script must begin with a command" msgstr "" #: src/mainwindow.c:3756 msgid "Script nesting limit exceeded" msgstr "" #: src/mainwindow.c:3765 #, c-format msgid "'%s' does not match any item" msgstr "" #: src/mainwindow.c:3767 #, c-format msgid "'%s' matches a non-scriptable item" msgstr "" #: src/mainwindow.c:3769 #, c-format msgid "'%s' matches a disabled item" msgstr "" #: src/mainwindow.c:3788 #, c-format msgid "'%s' value does not fit item" msgstr "" #: src/mainwindow.c:3969 msgid "Script" msgstr "" #: src/mainwindow.c:3982 src/spawn.c:656 src/spawn.c:662 msgid "Action" msgstr "アクション" #: src/mainwindow.c:3991 src/spawn.c:666 msgid "Execute" msgstr "実行" #: src/mainwindow.c:4045 msgid "Unable to load script" msgstr "" #: src/mainwindow.c:5182 msgid "/_File" msgstr "/ファイル(_F)" #: src/mainwindow.c:5184 msgid "//New" msgstr "//æ–°è¦" #: src/mainwindow.c:5186 msgid "//Open ..." msgstr "//é–‹ã …" #: src/mainwindow.c:5188 src/mainwindow.c:5669 msgid "//Save" msgstr "//ä¿å­˜" #: src/mainwindow.c:5190 src/mainwindow.c:5549 src/mainwindow.c:5627 #: src/mainwindow.c:5671 msgid "//Save As ..." msgstr "//åå‰ã‚’付ã‘ã¦ä¿å­˜â€¦" #: src/mainwindow.c:5192 msgid "//Export Undo Images ..." msgstr "//アンドゥイメージをエクスãƒãƒ¼ãƒˆâ€¦" #: src/mainwindow.c:5194 msgid "//Export Undo Images (reversed) ..." msgstr "//アンドゥイメージをエクスãƒãƒ¼ãƒˆï¼ˆå転)…" #: src/mainwindow.c:5196 msgid "//Export ASCII Art ..." msgstr "//ASCIIアートをエクスãƒãƒ¼ãƒˆâ€¦" #: src/mainwindow.c:5198 msgid "//Export Animated GIF ..." msgstr "//GIFアニメをエクスãƒãƒ¼ãƒˆâ€¦" #: src/mainwindow.c:5201 msgid "//Actions" msgstr "//アクション" #: src/mainwindow.c:5235 src/mainwindow.c:5488 msgid "///Configure" msgstr "///設定" #: src/mainwindow.c:5290 msgid "//Quit" msgstr "//終了" #: src/mainwindow.c:5293 msgid "/_Edit" msgstr "/編集(_E)" #: src/mainwindow.c:5295 msgid "//Undo" msgstr "//å…ƒã«æˆ»ã™" #: src/mainwindow.c:5297 msgid "//Redo" msgstr "//やり直ã—" #: src/mainwindow.c:5300 msgid "//Cut" msgstr "//切å–り" #: src/mainwindow.c:5302 msgid "//Copy" msgstr "//コピー" #: src/mainwindow.c:5304 msgid "//Copy To Palette" msgstr "//パレットã«ã‚³ãƒ”ー" #: src/mainwindow.c:5306 msgid "//Paste To Centre" msgstr "//中央ã«è²¼ã‚Šä»˜ã‘" #: src/mainwindow.c:5308 msgid "//Paste To New Layer" msgstr "//æ–°ã—ã„レイヤã¨ã—ã¦è²¼ã‚Šä»˜ã‘" #: src/mainwindow.c:5310 msgid "//Paste" msgstr "//貼り付ã‘" #: src/mainwindow.c:5312 msgid "//Paste Text" msgstr "//文字を貼り付ã‘" #: src/mainwindow.c:5318 msgid "//Paste Text (FreeType)" msgstr "//文字を貼り付㑠(FreeType)" #: src/mainwindow.c:5321 msgid "//Paste Palette" msgstr "//パレットを貼り付ã‘" #: src/mainwindow.c:5323 msgid "//Load Clipboard" msgstr "//クリップボードをロード" #: src/mainwindow.c:5350 msgid "//Save Clipboard" msgstr "//クリップボードをä¿å­˜" #: src/mainwindow.c:5377 msgid "//Import Clipboard from System" msgstr "//クリップボードをシステムã‹ã‚‰ã‚¤ãƒ³ãƒãƒ¼ãƒˆ" #: src/mainwindow.c:5378 msgid "//Export Clipboard to System" msgstr "//クリップボードをシステムã«ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ" #: src/mainwindow.c:5381 msgid "//Choose Pattern ..." msgstr "//ãƒ‘ã‚¿ãƒ¼ãƒ³ã‚’é¸æŠžâ€¦" #: src/mainwindow.c:5383 msgid "//Choose Brush ..." msgstr "//ãƒ–ãƒ©ã‚·ã‚’é¸æŠžâ€¦" #: src/mainwindow.c:5385 msgid "//Choose Colour ..." msgstr "" #: src/mainwindow.c:5392 msgid "/_View" msgstr "/表示(_V)" #: src/mainwindow.c:5394 msgid "//Show Main Toolbar" msgstr "//メインツールãƒãƒ¼ã‚’表示" #: src/mainwindow.c:5396 msgid "//Show Tools Toolbar" msgstr "//ツールã®ãƒ„ールãƒãƒ¼ã‚’表示" #: src/mainwindow.c:5399 msgid "//Show Settings Toolbar" msgstr "//ツールãƒãƒ¼ã®è¨­å®šã‚’表示" #: src/mainwindow.c:5402 msgid "//Show Dock" msgstr "//ドックを表示" #: src/mainwindow.c:5404 msgid "//Show Palette" msgstr "//パレットを表示" #: src/mainwindow.c:5406 msgid "//Show Status Bar" msgstr "//ステータスãƒãƒ¼ã‚’表示" #: src/mainwindow.c:5409 msgid "//Toggle Image View" msgstr "//イメージ表示を切æ›" #: src/mainwindow.c:5413 msgid "//Centralize Image" msgstr "//イメージを中央ã«ç½®ã" #: src/mainwindow.c:5414 msgid "//Show Zoom Grid" msgstr "//ズームグリッドを表示" #: src/mainwindow.c:5415 msgid "//Snap To Tile Grid" msgstr "" #: src/mainwindow.c:5417 msgid "//Configure Grid ..." msgstr "//グリッドを設定…" #: src/mainwindow.c:5418 msgid "//Tracing Image ..." msgstr "//イメージをトレース…" #: src/mainwindow.c:5421 msgid "//View Window" msgstr "//ウィンドウを表示" #: src/mainwindow.c:5423 msgid "//Horizontal Split" msgstr "//水平分割" #: src/mainwindow.c:5425 msgid "//Focus View Window" msgstr "//表示ウィンドウをフォーカス" #: src/mainwindow.c:5427 msgid "//Pan Window" msgstr "//ウィンドウをパンã™ã‚‹" #: src/mainwindow.c:5430 msgid "//Layers Window" msgstr "//レイヤウィンドウ" #: src/mainwindow.c:5433 msgid "/_Image" msgstr "/イメージ(_I)" #: src/mainwindow.c:5436 msgid "//Convert To RGB" msgstr "//RGBã«å¤‰æ›" #: src/mainwindow.c:5438 msgid "//Convert To Indexed ..." msgstr "//インデックスã«å¤‰æ›â€¦" #: src/mainwindow.c:5441 msgid "//Scale Canvas ..." msgstr "//キャンãƒã‚¹ã®ã‚µã‚¤ã‚ºã‚’拡大縮å°â€¦" #: src/mainwindow.c:5443 msgid "//Resize Canvas ..." msgstr "//キャンãƒã‚¹ã®ã‚µã‚¤ã‚ºã‚’変更…" #: src/mainwindow.c:5445 msgid "//Crop" msgstr "//トリミング" #: src/mainwindow.c:5448 src/mainwindow.c:5517 msgid "//Flip Vertically" msgstr "//垂直ã«å転" #: src/mainwindow.c:5449 src/mainwindow.c:5519 msgid "//Flip Horizontally" msgstr "//æ°´å¹³ã«å転" #: src/mainwindow.c:5452 src/mainwindow.c:5521 msgid "//Rotate Clockwise" msgstr "//時計方å‘ã«å›žè»¢" #: src/mainwindow.c:5453 src/mainwindow.c:5523 msgid "//Rotate Anti-Clockwise" msgstr "//åæ™‚計方å‘ã«å›žè»¢" #: src/mainwindow.c:5454 msgid "//Free Rotate ..." msgstr "//自由ã«å›žè»¢â€¦" #: src/mainwindow.c:5455 msgid "//Skew ..." msgstr "//æ­ªã¿â€¦" #: src/mainwindow.c:5458 msgid "//Segment ..." msgstr "" #: src/mainwindow.c:5462 msgid "//Script ..." msgstr "" #: src/mainwindow.c:5464 msgid "//Scripts" msgstr "" #: src/mainwindow.c:5491 msgid "//Information ..." msgstr "//情報…" #: src/mainwindow.c:5494 msgid "//Preferences ..." msgstr "//設定…" #: src/mainwindow.c:5497 msgid "/_Selection" msgstr "/é¸æŠž(_S)" #: src/mainwindow.c:5499 msgid "//Select All" msgstr "//å…¨é¸æŠž" #: src/mainwindow.c:5501 msgid "//Select None (Esc)" msgstr "//é¸æŠžã—ãªã„ (Esc)" #: src/mainwindow.c:5503 msgid "//Lasso Selection" msgstr "//投ã’縄ツールã§é¸æŠž" #: src/mainwindow.c:5505 msgid "//Lasso Selection Cut" msgstr "//投ã’縄ツールã§åˆ‡å–り" #: src/mainwindow.c:5508 msgid "//Outline Selection" msgstr "//ã‚¢ã‚¦ãƒˆãƒ©ã‚¤ãƒ³é¸æŠž" #: src/mainwindow.c:5510 msgid "//Fill Selection" msgstr "//é¸æŠžç¯„å›²ã®å¡—りã¤ã¶ã—" #: src/mainwindow.c:5512 msgid "//Outline Ellipse" msgstr "//楕円ã®è¼ªéƒ­" #: src/mainwindow.c:5514 msgid "//Fill Ellipse" msgstr "//楕円ã®å¡—りã¤ã¶ã—" #: src/mainwindow.c:5526 msgid "//Horizontal Ramp" msgstr "//水平色勾é…" #: src/mainwindow.c:5528 msgid "//Vertical Ramp" msgstr "//垂直色勾é…" #: src/mainwindow.c:5531 msgid "//Alpha Blend A,B" msgstr "//アルファãƒãƒ£ãƒ³ãƒãƒ«Aã€Bã‚’æ··ãœã‚‹" #: src/mainwindow.c:5533 msgid "//Move Alpha to Mask" msgstr "//アルファãƒãƒ£ãƒ³ãƒãƒ«ã‚’マスクã«ç§»å‹•" #: src/mainwindow.c:5535 msgid "//Mask Colour A,B" msgstr "//色Aã€Bをマスクã™ã‚‹" #: src/mainwindow.c:5537 msgid "//Unmask Colour A,B" msgstr "//色Aã€Bをアンマスクã™ã‚‹" #: src/mainwindow.c:5539 msgid "//Mask All Colours" msgstr "//ã™ã¹ã¦ã®è‰²ã‚’マスクã™ã‚‹" #: src/mainwindow.c:5541 msgid "//Clear Mask" msgstr "//マスクをクリア" #: src/mainwindow.c:5544 msgid "/_Palette" msgstr "/パレット(_P)" #: src/mainwindow.c:5548 src/mainwindow.c:5626 msgid "//Load ..." msgstr "//ロード…" #: src/mainwindow.c:5550 msgid "//Load Default" msgstr "//デフォルトをロード" #: src/mainwindow.c:5552 msgid "//Mask All" msgstr "//ã™ã¹ã¦ãƒžã‚¹ã‚¯" #: src/mainwindow.c:5553 msgid "//Mask None" msgstr "//マスクã—ãªã„" #: src/mainwindow.c:5555 msgid "//Swap A & B" msgstr "//Aã¨Bを入れæ›ãˆã‚‹" #: src/mainwindow.c:5557 msgid "//Edit Colour A & B ..." msgstr "//色Aã¨Bを編集…" #: src/mainwindow.c:5559 msgid "//Dither A" msgstr "//Aをディザ" #: src/mainwindow.c:5561 msgid "//Palette Editor ..." msgstr "//パレット編集…" #: src/mainwindow.c:5563 msgid "//Set Palette Size ..." msgstr "//パレットサイズを設定…" #: src/mainwindow.c:5564 msgid "//Merge Duplicate Colours" msgstr "//複製ã—ãŸè‰²ã‚’çµåˆ" #: src/mainwindow.c:5566 msgid "//Remove Unused Colours" msgstr "//未使用ã®è‰²ã‚’削除" #: src/mainwindow.c:5569 msgid "//Create Quantized ..." msgstr "//é‡å­åŒ–ã®ä½œæˆâ€¦" #: src/mainwindow.c:5572 msgid "//Sort Colours ..." msgstr "//色ã®ä¸¦ã³æ›¿ãˆâ€¦" #: src/mainwindow.c:5573 msgid "//Palette Shifter ..." msgstr "//パレットシフタ…" #: src/mainwindow.c:5574 msgid "//Pick Gradient ..." msgstr "" #: src/mainwindow.c:5576 msgid "/Effe_cts" msgstr "/効果(_C)" #: src/mainwindow.c:5578 msgid "//Transform Colour ..." msgstr "//色ã®å¤‰æ›â€¦" #: src/mainwindow.c:5580 msgid "//Invert" msgstr "//å転" #: src/mainwindow.c:5582 msgid "//Greyscale" msgstr "//グレースケール" #: src/mainwindow.c:5584 msgid "//Greyscale (Gamma corrected)" msgstr "//グレースケール(ガンマ補正)" #: src/mainwindow.c:5586 msgid "//Normalize" msgstr "" #: src/mainwindow.c:5587 src/mainwindow.c:5658 msgid "//Threshold ..." msgstr "//ã—ãã„値…" #: src/mainwindow.c:5588 msgid "//Map ..." msgstr "" #: src/mainwindow.c:5590 msgid "//Isometric Transformation" msgstr "//ç­‰é‡å¤‰æ›" #: src/mainwindow.c:5592 msgid "///Left Side Down" msgstr "///å·¦å´ä¸‹" #: src/mainwindow.c:5593 msgid "///Right Side Down" msgstr "///å³å´ä¸‹" #: src/mainwindow.c:5594 msgid "///Top Side Right" msgstr "///上å³" #: src/mainwindow.c:5595 msgid "///Bottom Side Right" msgstr "///下å³" #: src/mainwindow.c:5598 msgid "//Edge Detect ..." msgstr "//ç¸ã‚’検出…" #: src/mainwindow.c:5600 msgid "//Difference of Gaussians ..." msgstr "//ガウスã®å·®ç•°â€¦" #: src/mainwindow.c:5602 msgid "//Sharpen ..." msgstr "//シャープã«ã™ã‚‹â€¦" #: src/mainwindow.c:5604 msgid "//Unsharp Mask ..." msgstr "//マスクをã¼ã‹ã™â€¦" #: src/mainwindow.c:5606 msgid "//Soften ..." msgstr "//ã¼ã‹ã—…" #: src/mainwindow.c:5608 msgid "//Gaussian Blur ..." msgstr "//ガウスã¼ã‹ã—…" #: src/mainwindow.c:5610 msgid "//Kuwahara-Nagao Blur ..." msgstr "//Kuwahara-Nagaoã¼ã‹ã—…" #: src/mainwindow.c:5612 msgid "//Emboss" msgstr "//エンボス" #: src/mainwindow.c:5614 msgid "//Dilate" msgstr "//æ‹¡å¼µ" #: src/mainwindow.c:5616 msgid "//Erode" msgstr "//è…食" #: src/mainwindow.c:5619 msgid "//Solid Noise ..." msgstr "" #: src/mainwindow.c:5620 msgid "//Bacteria ..." msgstr "//ãƒã‚¯ãƒ†ãƒªã‚¢â€¦" #: src/mainwindow.c:5623 msgid "/Cha_nnels" msgstr "/ãƒãƒ£ãƒ³ãƒãƒ«(_N)" #: src/mainwindow.c:5625 msgid "//New ..." msgstr "//æ–°è¦â€¦" #: src/mainwindow.c:5628 msgid "//Delete ..." msgstr "//削除…" #: src/mainwindow.c:5632 msgid "//Edit Image" msgstr "//イメージを編集" #: src/mainwindow.c:5635 msgid "//Edit Alpha" msgstr "//アルファãƒãƒ£ãƒ³ãƒãƒ«ã‚’編集" #: src/mainwindow.c:5638 msgid "//Edit Selection" msgstr "//é¸æŠžã‚’ç·¨é›†" #: src/mainwindow.c:5641 msgid "//Edit Mask" msgstr "//マスクを編集" #: src/mainwindow.c:5645 msgid "//Hide Image" msgstr "//イメージを隠ã™" #: src/mainwindow.c:5648 msgid "//Disable Alpha" msgstr "//アルファãƒãƒ£ãƒ³ãƒãƒ«ã‚’無効ã«ã™ã‚‹" #: src/mainwindow.c:5651 msgid "//Disable Selection" msgstr "//é¸æŠžã‚’ç„¡åŠ¹ã«ã™ã‚‹" #: src/mainwindow.c:5654 msgid "//Disable Mask" msgstr "//マスクを無効ã«ã™ã‚‹" #: src/mainwindow.c:5657 msgid "//Couple RGBA Operations" msgstr "//RGBAæ“作をçµåˆ" #: src/mainwindow.c:5659 msgid "//Unassociate Alpha" msgstr "//アルファãƒãƒ£ãƒ³ãƒãƒ«ã‚’çµåˆã—ãªã„" #: src/mainwindow.c:5663 msgid "//View Alpha as an Overlay" msgstr "//アルファãƒãƒ£ãƒ³ãƒãƒ«ã‚’オーãƒãƒ¼ãƒ¬ã‚¤ã¨ã—ã¦è¡¨ç¤º" #: src/mainwindow.c:5664 msgid "//Configure Overlays ..." msgstr "//オーãƒãƒ¼ãƒ¬ã‚¤ã‚’設定…" #: src/mainwindow.c:5666 msgid "/_Layers" msgstr "/レイヤ(_L)" #: src/mainwindow.c:5668 msgid "//New Layer" msgstr "//æ–°è¦ãƒ¬ã‚¤ãƒ¤" #: src/mainwindow.c:5672 msgid "//Save Composite Image ..." msgstr "//åˆæˆã‚¤ãƒ¡ãƒ¼ã‚¸ã‚’ä¿å­˜â€¦" #: src/mainwindow.c:5673 msgid "//Composite to New Layer" msgstr "//æ–°è¦ãƒ¬ã‚¤ãƒ¤ã«åˆæˆ" #: src/mainwindow.c:5674 msgid "//Remove All Layers" msgstr "//全レイヤを削除" #: src/mainwindow.c:5676 msgid "//Configure Animation ..." msgstr "//アニメを設定…" #: src/mainwindow.c:5677 msgid "//Preview Animation ..." msgstr "//アニメをプレビュー…" #: src/mainwindow.c:5678 msgid "//Set Key Frame ..." msgstr "//キーフレームを設定…" #: src/mainwindow.c:5679 msgid "//Remove All Key Frames ..." msgstr "//全キーフレームを削除…" #: src/mainwindow.c:5681 msgid "/More..." msgstr "/ã•らã«..." #: src/mainwindow.c:5683 msgid "/_Help" msgstr "/ヘルプ(_H)" #: src/mainwindow.c:5684 msgid "//Documentation" msgstr "//文書" #: src/mainwindow.c:5686 msgid "//About" msgstr "//mtPaintã«ã¤ã„ã¦" #: src/mainwindow.c:5689 msgid "//Keyboard Shortcuts ..." msgstr "" #: src/mainwindow.c:5690 msgid "//Rebind Shortcut Keycodes" msgstr "//ショートカットキーコードã®ã‚„り直ã—" #: src/memory.c:2800 msgid "Quantize Pass 1" msgstr "" #: src/memory.c:2854 msgid "Quantize Pass 2" msgstr "" #: src/memory.c:3073 src/memory.c:3458 msgid "Converting to Indexed Palette" msgstr "インデックスパレットã«å¤‰æ›" #: src/memory.c:5135 src/otherwindow.c:540 msgid "Bacteria Effect" msgstr "ãƒã‚¯ãƒ†ãƒªã‚¢åŠ¹æžœ" #: src/memory.c:5170 msgid "Rotating" msgstr "回転" #: src/memory.c:5511 msgid "Free Rotation" msgstr "自由回転" #: src/memory.c:6096 msgid "Scaling Image" msgstr "ã‚¤ãƒ¡ãƒ¼ã‚¸ã‚’ç¸®å°æ‹¡å¤§" #: src/memory.c:7560 msgid "Counting Unique RGB Pixels" msgstr "一æ„RGBピクセルを計算" #: src/memory.c:7608 msgid "Applying Effect" msgstr "効果をé©ç”¨" #: src/memory.c:8792 msgid "Kuwahara-Nagao Filter" msgstr "Kuwahara-Nagaoフィルタ" #: src/memory.c:10456 src/otherwindow.c:2665 msgid "Skew" msgstr "æ­ªã¿" #: src/memory.c:10630 msgid "Segmentation Pass 1" msgstr "" #: src/memory.c:10757 msgid "Segmentation Pass 2" msgstr "" #: src/memory.c:11019 src/otherwindow.c:3156 msgid "Solid Noise" msgstr "" #: src/mygtk.c:134 src/mygtk.c:163 msgid "Please Wait ..." msgstr "ãŠå¾…ã¡ä¸‹ã•ã„…" #: src/mygtk.c:141 msgid "STOP" msgstr "åœæ­¢" #: src/mygtk.c:504 msgid "Disabled" msgstr "" #: src/mygtk.c:504 src/toolbar.c:301 msgid "Screen" msgstr "スクリーン" #: src/mygtk.c:504 msgid "Window" msgstr "" #: src/mygtk.c:508 msgid "Input" msgstr "" #: src/mygtk.c:512 msgid "Device:" msgstr "" #: src/mygtk.c:514 msgid "Mode:" msgstr "" #: src/mygtk.c:519 msgid "Axes" msgstr "" #: src/mygtk.c:524 msgid "X:" msgstr "" #: src/mygtk.c:525 msgid "Y:" msgstr "" #: src/mygtk.c:526 msgid "Pressure:" msgstr "" #: src/mygtk.c:527 msgid "X tilt:" msgstr "" #: src/mygtk.c:528 msgid "Y tilt:" msgstr "" #: src/mygtk.c:529 msgid "Wheel:" msgstr "" #: src/mygtk.c:579 msgid "none" msgstr "" #: src/otherwindow.c:236 msgid "24 bit RGB" msgstr "24ビット RGB" #: src/otherwindow.c:236 src/otherwindow.c:3179 msgid "Greyscale" msgstr "グレースケール" #: src/otherwindow.c:237 msgid "Indexed Palette" msgstr "インデックスパレット" #: src/otherwindow.c:237 msgid "From Clipboard" msgstr "クリップボードã‹ã‚‰" #: src/otherwindow.c:237 msgid "Grab Screenshot" msgstr "スクリーンショットをã¨ã‚‹" #: src/otherwindow.c:242 src/toolbar.c:542 msgid "New Image" msgstr "æ–°è¦ã‚¤ãƒ¡ãƒ¼ã‚¸" #: src/otherwindow.c:246 src/otherwindow.c:3164 msgid "Colours" msgstr "色" #: src/otherwindow.c:409 msgid "Pattern Chooser" msgstr "ãƒ‘ã‚¿ãƒ¼ãƒ³é¸æŠž" #: src/otherwindow.c:497 msgid "Set Palette Size" msgstr "パレットサイズを設定" #: src/otherwindow.c:517 src/otherwindow.c:591 src/otherwindow.c:870 #: src/otherwindow.c:2538 src/otherwindow.c:2776 src/otherwindow.c:2939 #: src/prefs.c:338 src/prefs.c:538 msgid "Apply" msgstr "é©ç”¨" #: src/otherwindow.c:573 msgid "Luminance" msgstr "è¼åº¦" #: src/otherwindow.c:573 src/otherwindow.c:814 msgid "Brightness" msgstr "明るã•" #: src/otherwindow.c:574 msgid "Distance to A" msgstr "Aã¾ã§ã®è·é›¢" #: src/otherwindow.c:575 msgid "Projection to A->B" msgstr "A->Bã¸ã®æŠ•å½±" #: src/otherwindow.c:576 msgid "Frequency" msgstr "頻度" #: src/otherwindow.c:580 msgid "Sort Palette Colours" msgstr "ãƒ‘ãƒ¬ãƒƒãƒˆè‰²ã‚’ä¸¦ã³æ›¿ãˆ" #: src/otherwindow.c:582 msgid "Start Index" msgstr "インデックスを開始" #: src/otherwindow.c:583 msgid "End Index" msgstr "インデックスを終了" #: src/otherwindow.c:589 msgid "Reverse Order" msgstr "逆順" #: src/otherwindow.c:805 msgid "Bitwise" msgstr "" #: src/otherwindow.c:805 msgid "Truncated" msgstr "" #: src/otherwindow.c:805 msgid "Rounded" msgstr "" #: src/otherwindow.c:809 src/toolbar.c:311 src/toolbar.c:558 msgid "Transform Colour" msgstr "色ã®å¤‰æ›" #: src/otherwindow.c:812 msgid "Gamma" msgstr "ガンマ" #: src/otherwindow.c:816 msgid "Contrast" msgstr "コントラスト" #: src/otherwindow.c:822 src/otherwindow.c:1674 msgid "Posterize" msgstr "ãƒã‚¹ã‚¿ãƒªã‚¼ãƒ¼ã‚·ãƒ§ãƒ³" #: src/otherwindow.c:831 msgid "Show Detail" msgstr "詳細表示" #: src/otherwindow.c:836 msgid "Posterize type" msgstr "" #: src/otherwindow.c:857 msgid "Auto-Preview" msgstr "自動プレビュー" #: src/otherwindow.c:869 msgid "Reset" msgstr "リセット" #: src/otherwindow.c:931 msgid "New geometry is the same as now - nothing to do." msgstr "æ–°ã—ã„é…ä½ã¯ç¾åœ¨ã¨åŒã˜ã§ã™ - ã™ã‚‹äº‹ã¯ã‚りã¾ã›ã‚“。" #: src/otherwindow.c:980 msgid "The operating system cannot allocate the memory for this operation." msgstr "OSã¯ã“ã®æ“作ã«ãƒ¡ãƒ¢ãƒªã‚’割り当ã¦ã‚‹äº‹ãŒã§ãã¾ã›ã‚“。" #: src/otherwindow.c:982 msgid "" "You have not allocated enough memory in the Preferences window for this " "operation." msgstr "ã“ã®æ“作ã®è¨­å®šã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã«å¿…è¦ãªãƒ¡ãƒ¢ãƒªã‚’割り当ã¦ã‚‹äº‹ãŒã§ãã¾ã›ã‚“。" #: src/otherwindow.c:993 src/otherwindow.c:2495 msgid "Mirror" msgstr "ミラー" #: src/otherwindow.c:993 src/otherwindow.c:994 msgid "Tile" msgstr "タイル" #: src/otherwindow.c:993 msgid "Void" msgstr "" #: src/otherwindow.c:994 src/shifter.c:283 msgid "Clear" msgstr "クリア" #: src/otherwindow.c:994 msgid "Mirror tile" msgstr "ミラー タイル" #: src/otherwindow.c:996 msgid "Nearest Neighbour" msgstr "最近隣法" #: src/otherwindow.c:997 msgid "Bilinear / Area Mapping" msgstr "åŒç·šå½¢/エリアマッピング" #: src/otherwindow.c:998 msgid "Bicubic" msgstr "åŒä¸‰æ¬¡" #: src/otherwindow.c:999 msgid "Bicubic edged" msgstr "åŒä¸‰æ¬¡å¢ƒç•Œ" #: src/otherwindow.c:1000 msgid "Bicubic better" msgstr "ãƒã‚¤ã‚­ãƒ¥ãƒ¼ãƒ“ック(良)" #: src/otherwindow.c:1001 msgid "Bicubic sharper" msgstr "ãƒã‚¤ã‚­ãƒ¥ãƒ¼ãƒ“ック(鮮明)" #: src/otherwindow.c:1002 msgid "Blackman-Harris" msgstr "Blackman-Harris" #: src/otherwindow.c:1008 msgid "Scale Canvas" msgstr "キャンãƒã‚¹ã®ç¸®å°æ‹¡å¤§" #: src/otherwindow.c:1009 msgid "Resize Canvas" msgstr "キャンãƒã‚¹ã®ã‚µã‚¤ã‚ºå¤‰æ›´" #: src/otherwindow.c:1012 msgid "Original " msgstr "å…ƒ " #: src/otherwindow.c:1013 msgid "New" msgstr "æ–°è¦" #: src/otherwindow.c:1014 msgid "Width " msgstr "å¹… " #: src/otherwindow.c:1018 msgid "Height " msgstr "高㕠" #: src/otherwindow.c:1023 src/otherwindow.c:2514 src/otherwindow.c:2672 #: src/toolbar.c:212 msgid "Offset" msgstr "オフセット" #: src/otherwindow.c:1026 src/otherwindow.c:1615 src/viewer.c:1209 msgid "Centre" msgstr "中央" #: src/otherwindow.c:1033 src/otherwindow.c:1052 msgid "Fix Aspect Ratio" msgstr "アスペクトレシオを固定" #: src/otherwindow.c:1039 src/otherwindow.c:2070 src/toolbar.c:312 msgid "Settings" msgstr "設定" #: src/otherwindow.c:1046 msgid "Sharper image reduction" msgstr "シャープ化イメージã®ç¸®å°" #: src/otherwindow.c:1047 msgid "Boundary extension" msgstr "" #: src/otherwindow.c:1613 src/otherwindow.c:2302 msgid "HSV" msgstr "HSV" #: src/otherwindow.c:1614 msgid "Highlight" msgstr "" #: src/otherwindow.c:1615 msgid "Limit" msgstr "é™ç•Œ" #: src/otherwindow.c:1616 msgid "Sphere" msgstr "çƒ" #: src/otherwindow.c:1616 src/otherwindow.c:2670 msgid "Angle" msgstr "角度" #: src/otherwindow.c:1616 msgid "Cube" msgstr "立方体" #: src/otherwindow.c:1617 msgid "Opaque" msgstr "ä¸é€æ˜Ž" #: src/otherwindow.c:1617 msgid "Border" msgstr "ç¸" #: src/otherwindow.c:1618 msgid "Transparent" msgstr "é€éŽ" #: src/otherwindow.c:1618 msgid "Tile " msgstr "タイル" #: src/otherwindow.c:1618 msgid "Segment" msgstr "" #: src/otherwindow.c:1656 msgid "Scale" msgstr "スケール" #: src/otherwindow.c:1657 src/otherwindow.c:3059 msgid "From" msgstr "ã‹ã‚‰" #: src/otherwindow.c:1659 src/otherwindow.c:3061 msgid "To" msgstr "ã¸" #: src/otherwindow.c:1699 msgid "Range" msgstr "範囲" #: src/otherwindow.c:1702 msgid "Inverse" msgstr "å転" #: src/otherwindow.c:1710 msgid "Smart grid" msgstr "スマートグリッド" #: src/otherwindow.c:1712 msgid "Tile grid" msgstr "タイルグリッド" #: src/otherwindow.c:1714 msgid "Minimum grid zoom" msgstr "最å°ã‚°ãƒªãƒƒãƒ‰ã‚ºãƒ¼ãƒ " #: src/otherwindow.c:1717 msgid "Tile width" msgstr "タイル幅" #: src/otherwindow.c:1720 msgid "Tile height" msgstr "タイル高ã•" #: src/otherwindow.c:1744 msgid "Palette Editor" msgstr "パレット編集" #: src/otherwindow.c:1763 msgid "Configure Overlays" msgstr "オーãƒãƒ¼ãƒ¬ã‚¤ã®è¨­å®š" #: src/otherwindow.c:1782 msgid "Colour Editor" msgstr "色編集" #: src/otherwindow.c:1818 src/toolbar.c:430 msgid "Colour-Selective Mode" msgstr "è‰²é¸æŠžãƒ¢ãƒ¼ãƒ‰" #: src/otherwindow.c:1843 msgid "Configure Grid" msgstr "グリッドを設定" #: src/otherwindow.c:2045 msgid "Exact Conversion" msgstr "正確ãªå¤‰æ›" #: src/otherwindow.c:2045 msgid "Use Current Palette" msgstr "ç¾åœ¨ã®ãƒ‘レットを使用" #: src/otherwindow.c:2046 msgid "PNN Quantize (slow, better quality)" msgstr "PNN é‡å­åŒ– (é…ã„ãŒè‰¯ã„画質)" #: src/otherwindow.c:2047 msgid "Wu Quantize (fast)" msgstr "Wu é‡å­åŒ– (速ã„)" #: src/otherwindow.c:2048 msgid "Max-Min Quantize (best for small palettes and dithering)" msgstr "最大最å°é‡å­åŒ– (å°ã•ãªãƒ‘レットã¨ãƒ‡ã‚£ã‚¶ã«æœ€é©)" #: src/otherwindow.c:2049 src/otherwindow.c:2495 src/otherwindow.c:2756 #: src/png.c:2794 src/prefs.c:377 msgid "None" msgstr "ãªã—" #: src/otherwindow.c:2049 msgid "Floyd-Steinberg" msgstr "Floyd-Steinberg" #: src/otherwindow.c:2049 msgid "Stucki" msgstr "Stucki" #: src/otherwindow.c:2052 msgid "Floyd-Steinberg (quick)" msgstr "Floyd-Steinberg (速ã„)" #: src/otherwindow.c:2052 msgid "Dithered (effect)" msgstr "ディザ(効果)" #: src/otherwindow.c:2053 msgid "Scattered (effect)" msgstr "æ‹¡æ•£(効果)" #: src/otherwindow.c:2054 msgid "Gamut" msgstr "色域" #: src/otherwindow.c:2054 msgid "Weakly" msgstr "å¼±ã" #: src/otherwindow.c:2054 msgid "Strongly" msgstr "å¼·ã" #: src/otherwindow.c:2055 msgid "Off" msgstr "オフ" #: src/otherwindow.c:2055 msgid "Separate/Sum" msgstr "分離/åˆè¨ˆ" #: src/otherwindow.c:2055 msgid "Separate/Split" msgstr "分離/分割" #: src/otherwindow.c:2056 msgid "Length/Sum" msgstr "é•·ã•/åˆè¨ˆ" #: src/otherwindow.c:2056 msgid "Length/Split" msgstr "é•·ã•/分割" #: src/otherwindow.c:2057 msgid "Largest (Linf)" msgstr "最大(Linf)" #: src/otherwindow.c:2057 msgid "Sum (L1)" msgstr "åˆè¨ˆ(L1)" #: src/otherwindow.c:2057 msgid "Euclidean (L2)" msgstr "ユークリッド(L2)" #: src/otherwindow.c:2061 msgid "Create Quantized" msgstr "é‡å­åŒ–ã®ä½œæˆ" #: src/otherwindow.c:2062 msgid "Convert To Indexed" msgstr "インデックスã«å¤‰æ›" #: src/otherwindow.c:2065 msgid "Indexed Colours To Use" msgstr "使用ã™ã‚‹ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ã‚«ãƒ©ãƒ¼" #: src/otherwindow.c:2078 msgid "Truncate palette" msgstr "切りå–りパレット" #: src/otherwindow.c:2079 msgid "Diameter based weighting" msgstr "ロードé‡ã«åŸºã¥ã直径" #: src/otherwindow.c:2084 msgid "Dither" msgstr "ディザ" #: src/otherwindow.c:2087 src/otherwindow.c:2584 src/otherwindow.c:2928 msgid "Colour space" msgstr "色空間" #: src/otherwindow.c:2088 src/otherwindow.c:2929 msgid "Difference measure" msgstr "差異測定" #: src/otherwindow.c:2089 msgid "Reduce colour bleed" msgstr "色ã®ã«ã˜ã¿ã‚’減らã™" #: src/otherwindow.c:2090 msgid "Serpentine scan" msgstr "蛇行スキャン" #: src/otherwindow.c:2092 msgid "Error propagation, %" msgstr "ã‚¨ãƒ©ãƒ¼ä¼æ¬ã€ %" #: src/otherwindow.c:2093 msgid "Selective error propagation" msgstr "é¸æŠžã§ãるエラーä¼é”" #: src/otherwindow.c:2097 msgid "Full error precision" msgstr "全エラー予測" #: src/otherwindow.c:2302 msgid "Backward HSV" msgstr "HSVを逆ã«" #: src/otherwindow.c:2303 src/otherwindow.c:2326 msgid "Constant" msgstr "定数" #: src/otherwindow.c:2307 msgid "Edit Gradient" msgstr "グラデーションを編集" #: src/otherwindow.c:2329 msgid "Points:" msgstr "点:" #: src/otherwindow.c:2493 msgid "Linear" msgstr "ç·šå½¢" #: src/otherwindow.c:2493 src/otherwindow.c:2703 msgid "Bilinear" msgstr "二本線" #: src/otherwindow.c:2493 msgid "Radial" msgstr "放射状" #: src/otherwindow.c:2494 msgid "Square" msgstr "四角" #: src/otherwindow.c:2494 msgid "Angular" msgstr "角度" #: src/otherwindow.c:2494 msgid "Conical" msgstr "円éŒ" #: src/otherwindow.c:2495 msgid "Level " msgstr "" #: src/otherwindow.c:2495 msgid "Repeat" msgstr "ç¹°è¿”ã—" #: src/otherwindow.c:2496 msgid "A to B" msgstr "Aã‚’Bã¸" #: src/otherwindow.c:2496 msgid "A to B (RGB)" msgstr "Aã‚’Bã¸(RGB)" #: src/otherwindow.c:2497 msgid "A to B (sRGB)" msgstr "" #: src/otherwindow.c:2497 msgid "A to B (HSV)" msgstr "Aã‚’Bã¸(HSV)" #: src/otherwindow.c:2497 msgid "A to B (backward HSV)" msgstr "Aã‚’Bã¸(HSVを逆ã«)" #: src/otherwindow.c:2498 msgid "A only" msgstr "Aã ã‘" #: src/otherwindow.c:2498 src/otherwindow.c:2500 msgid "Custom" msgstr "カスタム" #: src/otherwindow.c:2499 msgid "Current to 0" msgstr "ç¾åœ¨ã‚’ 0 ã«" #: src/otherwindow.c:2499 msgid "Current only" msgstr "ç¾åœ¨ã ã‘" #: src/otherwindow.c:2504 msgid "Configure Gradient" msgstr "グラデーションを設定" #: src/otherwindow.c:2507 src/png.c:1001 msgid "Channel" msgstr "ãƒãƒ£ãƒ³ãƒãƒ«" #: src/otherwindow.c:2512 msgid "Length" msgstr "é•·ã•" #: src/otherwindow.c:2513 msgid "Repeat length" msgstr "é•·ã•を繰り返ã™" #: src/otherwindow.c:2515 msgid "Gradient type" msgstr "グラデーション形å¼" #: src/otherwindow.c:2516 msgid "Extension type" msgstr "æ‹¡å¼µå­å½¢å¼" #: src/otherwindow.c:2517 msgid "Distance type" msgstr "" #: src/otherwindow.c:2518 msgid "Preview opacity" msgstr "ä¸é€æ˜Žåº¦ã‚’プレビュー" #: src/otherwindow.c:2527 src/otherwindow.c:2533 src/toolbar.c:309 msgid "Reverse" msgstr "逆" #: src/otherwindow.c:2528 src/otherwindow.c:2534 msgid "Edit Custom" msgstr "カスタムを編集" #: src/otherwindow.c:2592 msgid "Pick Gradient" msgstr "" #: src/otherwindow.c:2668 msgid "Horizontal " msgstr "æ°´å¹³" #: src/otherwindow.c:2674 msgid "At distance" msgstr "離れã¦" #: src/otherwindow.c:2675 msgid "Vertical" msgstr "垂直" #: src/otherwindow.c:2756 msgid "Unchanged" msgstr "変更ã—ãªã„" #: src/otherwindow.c:2761 msgid "Tracing Image" msgstr "イメージをトレース" #: src/otherwindow.c:2763 src/toolbar.c:315 msgid "Source" msgstr "ソース" #: src/otherwindow.c:2768 msgid "Origin" msgstr "起点" #: src/otherwindow.c:2771 msgid "Relative scale" msgstr "相対スケール" #: src/otherwindow.c:2774 msgid "Display" msgstr "表示" #: src/otherwindow.c:2926 msgid "Segment Image" msgstr "" #: src/otherwindow.c:2931 src/toolbar.c:304 msgid "Threshold" msgstr "" #: src/otherwindow.c:2933 msgid "Level" msgstr "æ°´å¹³" #: src/otherwindow.c:2934 msgid "Minimum size" msgstr "" #: src/otherwindow.c:3053 msgid "Max" msgstr "" #: src/otherwindow.c:3053 msgid "Min" msgstr "" #: src/otherwindow.c:3057 msgid "Threshold Image" msgstr "" #: src/otherwindow.c:3158 msgid "Seed" msgstr "" #: src/otherwindow.c:3160 msgid "X span" msgstr "" #: src/otherwindow.c:3161 msgid "Y span" msgstr "" #: src/otherwindow.c:3162 msgid "Octaves" msgstr "" #: src/png.c:620 #, c-format msgid "Saving %s image" msgstr "%s イメージをä¿å­˜ä¸­" #: src/png.c:620 #, c-format msgid "Loading %s image" msgstr "%s イメージを読ã¿è¾¼ã¿ä¸­" #: src/png.c:998 msgid "Layer" msgstr "レイヤ" #: src/png.c:3577 msgid "Lossless" msgstr "" #: src/png.c:3577 msgid "Default" msgstr "" #: src/png.c:3577 msgid "Picture" msgstr "" #: src/png.c:3577 msgid "Photo" msgstr "" #: src/png.c:3578 msgid "Drawing" msgstr "" #: src/png.c:3578 msgid "Icon" msgstr "" #: src/png.c:8370 msgid "Applying colour profile" msgstr "" #: src/png.c:8792 #, c-format msgid "%d out of %d frames could not be saved as %s - saved as PNG instead" msgstr "" "%d フレームã®ã†ã¡ %d 㯠%s ã¨ã—ã¦ä¿å­˜ã§ãã¾ã›ã‚“ã§ã—㟠- ã‹ã‚りã«PNGã§ä¿å­˜ã—ã¾" "ã—ãŸ" #: src/png.c:8809 msgid "Explode frames" msgstr "" #: src/prefs.c:56 msgid "Default System Language" msgstr "デフォルトシステム言語" #: src/prefs.c:57 msgid "Chinese (Simplified)" msgstr "簡体字中国語" #: src/prefs.c:57 msgid "Chinese (Taiwanese)" msgstr "中国語(å°æ¹¾)" #: src/prefs.c:57 msgid "Czech" msgstr "ãƒã‚§ã‚³èªž" #: src/prefs.c:58 msgid "Dutch" msgstr "オランダ語" #: src/prefs.c:58 msgid "English (UK)" msgstr "英語 (英国)" #: src/prefs.c:58 msgid "French" msgstr "フランス語" #: src/prefs.c:58 msgid "Galician" msgstr "ガリシア語" #: src/prefs.c:58 msgid "German" msgstr "ドイツ語" #: src/prefs.c:59 msgid "Hungarian" msgstr "" #: src/prefs.c:59 msgid "Italian" msgstr "イタリア語" #: src/prefs.c:59 msgid "Japanese" msgstr "日本語" #: src/prefs.c:59 msgid "Kabyle" msgstr "" #: src/prefs.c:59 msgid "Polish" msgstr "ãƒãƒ¼ãƒ©ãƒ³ãƒ‰èªž" #: src/prefs.c:60 msgid "Portuguese" msgstr "ãƒãƒ«ãƒˆã‚¬ãƒ«èªž" #: src/prefs.c:60 msgid "Portuguese (Brazilian)" msgstr "ãƒãƒ«ãƒˆã‚¬ãƒ«èªž (ブラジル)" #: src/prefs.c:60 msgid "Russian" msgstr "ロシア語" #: src/prefs.c:60 msgid "Slovak" msgstr "スロãƒã‚­ã‚¢èªž" #: src/prefs.c:61 msgid "Spanish" msgstr "スペイン語" #: src/prefs.c:61 msgid "Swedish" msgstr "スウェーデン語" #: src/prefs.c:61 msgid "Tagalog" msgstr "" #: src/prefs.c:61 msgid "Turkish" msgstr "トルコ語" #: src/prefs.c:81 msgid "Current Device" msgstr "ç¾åœ¨ã®ãƒ‡ãƒã‚¤ã‚¹" #: src/prefs.c:135 msgid "Pressure" msgstr "圧力" #: src/prefs.c:149 msgid "Preferences" msgstr "設定" #: src/prefs.c:163 msgid "Max threads (0 to autodetect)" msgstr "" #: src/prefs.c:164 msgid "Min kpixels per render thread" msgstr "" #: src/prefs.c:171 msgid "Max memory used for undo (MB)" msgstr "å…ƒã«æˆ»ã™ãŸã‚ã«ä½¿ç”¨ã•れる最大メモリ(MB)" #: src/prefs.c:172 msgid "Max undo levels" msgstr "å…ƒã«æˆ»ã™æœ€é«˜å›žæ•°" #: src/prefs.c:173 msgid "Communal layer undo space (%)" msgstr "共有レイヤ アンドゥ スペース (%)" #: src/prefs.c:175 msgid "Bayer master pattern" msgstr "" #: src/prefs.c:178 msgid "Use gamma correction by default" msgstr "ガンマ補正をデフォルトã§ä½¿ç”¨" #: src/prefs.c:179 msgid "Use gamma correction when painting" msgstr "" #: src/prefs.c:180 msgid "Separate patterns for A & B" msgstr "" #: src/prefs.c:183 msgid "Optimize alpha chequers" msgstr "アルファãƒã‚§ãƒƒã‚¯ã‚’最é©åŒ–" #: src/prefs.c:184 msgid "Disable view window transparencies" msgstr "表示ウィンドウã®é€æ˜Žåº¦ã‚’無効ã«ã™ã‚‹" #: src/prefs.c:185 msgid "Enable overlays by layer" msgstr "" #: src/prefs.c:189 msgid "Language" msgstr "言語" #: src/prefs.c:191 msgid "" "Select preferred language translation\n" "\n" "You will need to restart mtPaint\n" "for this to take full effect" msgstr "" "翻訳ã•れãŸé©åˆ‡ãªè¨€èªžã‚’é¸æŠžã—ã¦ä¸‹ã•ã„\n" "\n" "設定を有効ã«ã™ã‚‹ã«ã¯ mtPaint ã‚’\n" "リスタートã™ã‚‹å¿…è¦ãŒã‚りã¾ã™" #: src/prefs.c:198 msgid "Interface" msgstr "インターフェース" #: src/prefs.c:200 msgid "Greyscale backdrop" msgstr "グレースケール背景" #: src/prefs.c:201 msgid "Selection nudge pixels" msgstr "å¾®èª¿æ•´ãƒ”ã‚¯ã‚»ãƒ«ã‚’é¸æŠž" #: src/prefs.c:202 msgid "Max Pan Window Size" msgstr "パンã™ã‚‹æœ€å¤§ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã‚µã‚¤ã‚º" #: src/prefs.c:204 msgid "Display clipboard while pasting" msgstr "è²¼ã‚Šä»˜ã‘æ™‚ã«ã‚¯ãƒªãƒƒãƒ—ボードを表示" #: src/prefs.c:205 msgid "Mouse cursor = Tool" msgstr "マウスカーソル = ツール" #: src/prefs.c:206 msgid "Confirm Exit" msgstr "終了を確èª" #: src/prefs.c:207 msgid "Q key quits mtPaint" msgstr "Qキーã§mtPaintを終了" #: src/prefs.c:208 msgid "Arrow keys scroll canvas" msgstr "" #: src/prefs.c:209 msgid "Changing tool commits paste" msgstr "貼り付ã‘ツールを変更" #: src/prefs.c:210 msgid "Centre tool settings dialogs" msgstr "ツール設定ダイアログを中央ã«" #: src/prefs.c:211 msgid "New image sets zoom to 100%" msgstr "æ–°ã—ã„イメージを100%ズームã«è¨­å®š" #: src/prefs.c:212 msgid "Zoom on cursor position" msgstr "" #: src/prefs.c:214 msgid "Mouse Scroll Wheel = Zoom" msgstr "マウススクロールボタン = ズーム" #: src/prefs.c:215 msgid "Use menu icons" msgstr "メニューアイコンを使ã†" #: src/prefs.c:220 msgid "Files" msgstr "ファイル" #: src/prefs.c:223 msgid "XBM X hotspot" msgstr "XBM X ホットスãƒãƒƒãƒˆ" #: src/prefs.c:224 msgid "XBM Y hotspot" msgstr "XBM Y ホットスãƒãƒƒãƒˆ" #: src/prefs.c:228 msgid "Recently Used Files" msgstr "最近使ã£ãŸãƒ•ァイル" #: src/prefs.c:229 msgid "Progress bar silence limit" msgstr "プログレスãƒãƒ¼ サイレンス 制é™" #: src/prefs.c:232 msgid "Read 16-bit TGAs as 5:6:5 BGR" msgstr "16ビットTGAã‚’ 5:6:5 BGRã¨ã—ã¦èª­ã¿è¾¼ã‚€" #: src/prefs.c:233 msgid "Write TGAs in bottom-up row order" msgstr "TGAを下ã‹ã‚‰ä¸Šã¸ã®è¡Œé †åºã§æ›¸ã" #: src/prefs.c:234 msgid "Undoable image loading" msgstr "å…ƒã«æˆ»ã›ã‚‹ã‚¤ãƒ¡ãƒ¼ã‚¸ã‚’ロード中" #: src/prefs.c:245 msgid "Compression (RGB)" msgstr "" #: src/prefs.c:246 msgid "Compression (indexed)" msgstr "" #: src/prefs.c:247 msgid "Compression (monochrome)" msgstr "" #: src/prefs.c:255 msgid "Enable predictor" msgstr "" #: src/prefs.c:262 msgid "Compression mode" msgstr "" #: src/prefs.c:271 msgid "Channel for Mask Plane" msgstr "" #: src/prefs.c:273 msgid "Ignore Transparent Colour" msgstr "" #: src/prefs.c:274 msgid "PackBits Compression" msgstr "" #: src/prefs.c:275 msgid "Write Indexed as Planar Bitmap (PBM)" msgstr "" #: src/prefs.c:280 msgid "Paths" msgstr "パス" #: src/prefs.c:281 msgid "Clipboard Files" msgstr "クリップボードファイル" #: src/prefs.c:281 msgid "Select Clipboard File" msgstr "ã‚¯ãƒªãƒƒãƒ—ãƒœãƒ¼ãƒ‰ãƒ•ã‚¡ã‚¤ãƒ«ã‚’é¸æŠž" #: src/prefs.c:283 msgid "HTML Browser Program" msgstr "HTMLブラウザ" #: src/prefs.c:283 msgid "Select Browser Program" msgstr "ブラウザã®é¸æŠž" #: src/prefs.c:285 msgid "Location of Handbook index" msgstr "ãƒãƒ³ãƒ‰ãƒ–ックインデックスã®å ´æ‰€" #: src/prefs.c:285 msgid "Select Handbook Index File" msgstr "ãƒãƒ³ãƒ‰ãƒ–ックインデックスファイルã®é¸æŠž" #: src/prefs.c:287 msgid "Default Palette" msgstr "デフォルトパレット" #: src/prefs.c:287 msgid "Select Default Palette" msgstr "ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆãƒ‘ãƒ¬ãƒƒãƒˆã‚’é¸æŠž" #: src/prefs.c:289 msgid "Default Patterns" msgstr "デフォルトパターン" #: src/prefs.c:289 msgid "Select Default Patterns File" msgstr "ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆãƒ‘ã‚¿ãƒ¼ãƒ³ãƒ•ã‚¡ã‚¤ãƒ«ã‚’é¸æŠž" #: src/prefs.c:292 msgid "Default CSS" msgstr "" #: src/prefs.c:292 msgid "Select Default CSS File" msgstr "" #: src/prefs.c:295 msgid "Default Theme" msgstr "" #: src/prefs.c:295 msgid "Select Default Theme File" msgstr "" #: src/prefs.c:300 msgid "Status Bar" msgstr "ステータスãƒãƒ¼" #: src/prefs.c:301 msgid "Canvas Geometry" msgstr "キャンãƒã‚¹åº§æ¨™" #: src/prefs.c:302 msgid "Cursor X,Y" msgstr "カーソル X,Y" #: src/prefs.c:303 msgid "Pixel [I] {RGB}" msgstr "ピクセル [I] {RGB}" #: src/prefs.c:304 msgid "Selection Geometry" msgstr "åº§æ¨™ã‚’é¸æŠž" #: src/prefs.c:305 msgid "Undo / Redo" msgstr "å…ƒã«æˆ»ã™ / やり直ã—" #: src/prefs.c:308 msgid "Tablet" msgstr "タブレット" #: src/prefs.c:309 msgid "Device Settings" msgstr "デãƒã‚¤ã‚¹ã®è¨­å®š" #: src/prefs.c:313 msgid "Configure Device" msgstr "デãƒã‚¤ã‚¹ã‚’設定" #: src/prefs.c:319 msgid "Tool Variable" msgstr "ツール変数" #: src/prefs.c:322 src/toolbar.c:454 msgid "Flow" msgstr "フロー" #: src/prefs.c:330 msgid "Test Area" msgstr "テスト領域" #: src/prefs.c:373 msgid "Factor" msgstr "ä¿‚æ•°" #: src/prefs.c:459 msgid "This key is builtin" msgstr "" #: src/prefs.c:462 #, c-format msgid "" "This key is mapped to:\n" "\"%s\"" msgstr "" #: src/prefs.c:465 msgid "Remap" msgstr "" #: src/prefs.c:510 msgid "Keyboard Shortcuts" msgstr "" #: src/shifter.c:147 msgid "Frames" msgstr "フレーム" #: src/shifter.c:258 msgid "Palette Shifter" msgstr "パレットシフタ" #: src/shifter.c:263 msgid "Start" msgstr "é–‹å§‹" #: src/shifter.c:265 msgid "Finish" msgstr "完了" #: src/shifter.c:284 msgid "Fix Palette" msgstr "パレットを固定" #: src/spawn.c:651 msgid "Configure File Actions" msgstr "ファイルアクションを設定" #: src/spawn.c:657 src/spawn.c:663 msgid "Command" msgstr "コマンド" #: src/spawn.c:922 #, c-format msgid "Error %i reported when trying to run %s" msgstr "エラー %i ãŒå ±å‘Šã•れã¾ã—㟠(%s を実行ã—よã†ã¨ã—ã¦)" #: src/spawn.c:979 msgid "" "I am unable to find the documentation. Either you need to download the " "mtPaint Handbook from the web site and install it, or you need to set the " "correct location in the Preferences window." msgstr "" "ドキュメントãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。インターãƒãƒƒãƒˆã‹ã‚‰mtPaintãƒãƒ³ãƒ‰ãƒ–ックをダウン" "ロードã—ã¦ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã™ã‚‹ã‹ã€è¨­å®šã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã§æ­£ã—ã„ロケーションを設定ã™ã‚‹å¿…" "è¦ãŒã‚りã¾ã™ã€‚" #: src/spawn.c:1018 msgid "" "There was a problem running the HTML browser. You need to set the correct " "program name in the Preferences window." msgstr "" "HTMLブラウザを実行中ã«å•題ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚設定ウィンドウã§ãƒ—ログラムåã‚’æ­£ã—" "ã設定ã™ã‚‹å¿…è¦ãŒã‚りã¾ã™ã€‚" #: src/thread.c:361 msgid "Helper thread is not responding. Save your work and exit the program." msgstr "" #: src/toolbar.c:147 msgid "RGB Cube" msgstr "RGB 立方体" #: src/toolbar.c:148 msgid "By image channel" msgstr "イメージãƒãƒ£ãƒ³ãƒãƒ«ã«ã‚ˆã‚‹" #: src/toolbar.c:149 msgid "Gradient-driven" msgstr "グラデーション指å‘" #: src/toolbar.c:157 msgid "Fill settings" msgstr "塗りã¤ã¶ã—設定" #: src/toolbar.c:170 msgid "Respect opacity mode" msgstr "ä¸é€æ˜Žåº¦ãƒ¢ãƒ¼ãƒ‰ã‚’é‡è¦–" #: src/toolbar.c:176 msgid "Smudge settings" msgstr "ã«ã˜ã¿è¨­å®š" #: src/toolbar.c:215 msgid "Aligned" msgstr "" #: src/toolbar.c:222 msgid "Clone settings" msgstr "" #: src/toolbar.c:228 msgid "By selection channel" msgstr "" #: src/toolbar.c:234 msgid "Lasso settings" msgstr "" #: src/toolbar.c:252 msgid "Brush spacing" msgstr "ブラシ間隔" #: src/toolbar.c:299 src/toolbar.c:341 msgid "Normal" msgstr "標準" #: src/toolbar.c:300 msgid "Colour" msgstr "色" #: src/toolbar.c:300 msgid "Saturate More" msgstr "ã‚‚ã£ã¨æŸ“ã¿è¾¼ã¾ã›ã‚‹" #: src/toolbar.c:301 msgid "Multiply" msgstr "掛ã‘ç®—" #: src/toolbar.c:301 msgid "Divide" msgstr "ã‚り算" #: src/toolbar.c:301 msgid "Dodge" msgstr "覆ã„焼ã" #: src/toolbar.c:302 msgid "Burn" msgstr "焼ãè¾¼ã¿" #: src/toolbar.c:302 msgid "Hard Light" msgstr "å¼·ã„å…‰" #: src/toolbar.c:302 msgid "Soft Light" msgstr "柔らã‹ãªå…‰" #: src/toolbar.c:302 msgid "Difference" msgstr "相é•" #: src/toolbar.c:303 msgid "Darken" msgstr "æš—ã" #: src/toolbar.c:303 msgid "Lighten" msgstr "明るãã™ã‚‹" #: src/toolbar.c:303 msgid "Grain Extract" msgstr "ç²’å­æŠ½å‡º" #: src/toolbar.c:304 msgid "Grain Merge" msgstr "ç²’å­çµåˆ" #: src/toolbar.c:330 msgid "Blend mode" msgstr "ブレンドモード" #: src/toolbar.c:417 msgid "Continuous Mode" msgstr "連続モード" #: src/toolbar.c:421 msgid "Opacity Mode" msgstr "ä¸é€æ˜Žåº¦ãƒ¢ãƒ¼ãƒ‰" #: src/toolbar.c:424 msgid "Tint Mode" msgstr "色調モード" #: src/toolbar.c:427 msgid "Tint +-" msgstr "色調 +-" #: src/toolbar.c:434 msgid "Blend Mode" msgstr "ブレンドモード" #: src/toolbar.c:438 msgid "Disable All Masks" msgstr "全マスクを無効ã«ã™ã‚‹" #: src/toolbar.c:441 msgid "Gradient Mode" msgstr "グラデーションモード" #: src/toolbar.c:486 msgid "Settings Toolbar" msgstr "ツールãƒãƒ¼ã‚’設定" #: src/toolbar.c:546 msgid "Cut" msgstr "切りå–り" #: src/toolbar.c:548 msgid "Copy" msgstr "コピー" #: src/toolbar.c:550 msgid "Paste" msgstr "貼り付ã‘" #: src/toolbar.c:553 msgid "Undo" msgstr "å…ƒã«æˆ»ã™" #: src/toolbar.c:555 msgid "Redo" msgstr "やり直ã—" #: src/toolbar.c:559 src/viewer.c:328 msgid "Pan Window" msgstr "ウィンドウをパンã™ã‚‹" #: src/toolbar.c:560 src/toolbar.c:640 msgid "More..." msgstr "" #: src/toolbar.c:574 msgid "Paint" msgstr "å¡—ã‚‹" #: src/toolbar.c:580 msgid "Shuffle" msgstr "æ··ãœã‚‹" #: src/toolbar.c:583 msgid "Flood Fill" msgstr "塗りã¤ã¶ã™" #: src/toolbar.c:587 msgid "Straight Line" msgstr "ç›´ç·š" #: src/toolbar.c:590 msgid "Smudge" msgstr "ã«ã˜ã¿" #: src/toolbar.c:594 msgid "Clone" msgstr "クローン" #: src/toolbar.c:597 msgid "Make Selection" msgstr "é¸æŠž" #: src/toolbar.c:600 msgid "Polygon Selection" msgstr "ãƒãƒªã‚´ãƒ³é¸æŠž" #: src/toolbar.c:603 msgid "Place Gradient" msgstr "グラデーションを置ã" #: src/toolbar.c:606 msgid "Lasso Selection" msgstr "投ã’ç¸„ãƒ„ãƒ¼ãƒ«é¸æŠž" #: src/toolbar.c:614 msgid "Ellipse Outline" msgstr "楕円アウトライン" #: src/toolbar.c:617 msgid "Filled Ellipse" msgstr "楕円を塗りã¤ã¶ã—" #: src/toolbar.c:620 msgid "Outline Selection" msgstr "ã‚¢ã‚¦ãƒˆãƒ©ã‚¤ãƒ³é¸æŠž" #: src/toolbar.c:623 msgid "Fill Selection" msgstr "é¸æŠžã‚’å¡—ã‚Šã¤ã¶ã™" #: src/toolbar.c:627 msgid "Flip Selection Vertically" msgstr "é¸æŠžã‚’åž‚ç›´ã«å転" #: src/toolbar.c:630 msgid "Flip Selection Horizontally" msgstr "é¸æŠžã‚’æ°´å¹³ã«å転" #: src/toolbar.c:633 msgid "Rotate Selection Clockwise" msgstr "é¸æŠžã‚’æ™‚è¨ˆæ–¹å‘ã«å›žè»¢" #: src/toolbar.c:636 msgid "Rotate Selection Anti-Clockwise" msgstr "é¸æŠžã‚’åæ™‚計方å‘ã«å›žè»¢" #: src/vcode.c:5201 msgid "Browse" msgstr "ブラウズ" #: src/vcode.c:7886 msgid "New key ..." msgstr "" #: src/vcode.c:9909 #, c-format msgid "'%s' does not match any widget" msgstr "" #: src/vcode.c:9910 #, c-format msgid "'%s' value does not fit '%s' widget" msgstr "" #: src/viewer.c:115 msgid "About" msgstr "mtPaintã«ã¤ã„ã¦" #: src/viewer.c:1179 msgid "No font selected" msgstr "" #: src/viewer.c:1209 msgid "Left" msgstr "" #: src/viewer.c:1209 msgid "Right" msgstr "" #~ msgid "Create GIF frames" #~ msgstr "GIFフレームを作æˆ" #~ msgid "" #~ "You are trying to save an XPM file with more than 4096 colours. Either " #~ "use another format or posterize the image to 4 bits, or otherwise reduce " #~ "the number of colours." #~ msgstr "" #~ "XPM ファイルを4096色以上ã§ä¿å­˜ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚別ã®ãƒ•ォーマットを使ã†ã‹" #~ "イメージを4ビットã«ãƒã‚¹ã‚¿ãƒªã‚¼ãƒ¼ã‚·ãƒ§ãƒ³ã™ã‚‹ã‹ã€è‰²æ•°ã‚’減色ã—ã¦ä¸‹ã•ã„。" #~ msgid "Store Values" #~ msgstr "値を格ç´" #~ msgid "File: %s invalid - palette not updated" #~ msgstr "ファイル:%s ã¯ç„¡åйã§ã™ - ãƒ‘ãƒ¬ãƒƒãƒˆã¯æ›´æ–°ã•れã¾ã›ã‚“" #~ msgid "Distance to A+B" #~ msgstr "A+Bã¾ã§ã®è·é›¢" #~ msgid "Edit Frames" #~ msgstr "フレームを編集" #~ msgid " C Command Line Window" #~ msgstr " C コマンドラインウィンドウ" #~ msgid "The palette does not contain enough colours to do a merge" #~ msgstr "パレットã¯çµåˆã™ã‚‹ã«å分ãªè‰²ãŒã‚りã¾ã›ã‚“。" #~ msgid "There are too many identical palette items to be reduced." #~ msgstr "減らã™åŒã˜ãƒ‘レットアイテムãŒå¤šã™ãŽã¾ã™ã€‚" #~ msgid "/View/Command Line Window" #~ msgstr "/表示(V)/コマンドラインウィンドウ" #~ msgid "Grid colour RGB" #~ msgstr "グリッドカラーRGB" #~ msgid "Zoom" #~ msgstr "ズーム" #~ msgid "%i Files on Command Line" #~ msgstr "コマンドライン㮠%i ファイル" #~ msgid "" #~ "Dennis Lee - Wrote the two quantizing methods DL1 & 3 - see quantizer.c " #~ "for more information." #~ msgstr "" #~ "Dennis Lee - DL1 㨠3 ã®ï¼’ã¤ã®é‡å­åŒ–方法を書ãã¾ã—㟠- 詳細ã¯quantizer.c " #~ "ã‚’ã”覧下ã•ã„。" #~ msgid "Magnus Hjorth - Wrote inifile.c/h, from mhWaveEdit 1.3.0." #~ msgstr "Magnus Hjorth - mhWaveEdit 1.3.0 ã‹ã‚‰ inifile.c/h を書ã„ãŸã€‚" #~ msgid "DL1 Quantize (fastest)" #~ msgstr "DL1 é‡å­åŒ–(最速)" #~ msgid "DL3 Quantize (very slow, better quality)" #~ msgstr "DL3 é‡å­åŒ– (ã¨ã¦ã‚‚é…ã„ãŒé«˜å“質)" #~ msgid "Wu Quantize (best method for small palettes)" #~ msgstr "Wu é‡å­åŒ– (å°ã•ã„パレットå‘ãã®æ–¹æ³•)" #~ msgid "Max-Min Quantize (best with dithering)" #~ msgstr "Max-Min é‡å­åŒ– (ãƒ‡ã‚£ã‚¶ãƒªãƒ³ã‚°ã«æœ€é«˜)" #~ msgid "Not enough memory to rotate image" #~ msgstr "イメージを回転ã™ã‚‹ã«ã¯ãƒ¡ãƒ¢ãƒªãŒè¶³ã‚Šã¾ã›ã‚“" #~ msgid "Not enough memory to rotate clipboard" #~ msgstr "クリップボードを回転ã™ã‚‹ã«ã¯ãƒ¡ãƒ¢ãƒªãŒè¶³ã‚Šã¾ã›ã‚“" #~ msgid "File is too big, must be <= to width=%i height=%i : %s" #~ msgstr "ファイルãŒå¤§ãã™ãŽã¾ã™ã€‚ã“れ以下ã«ã—ã¦ä¸‹ã•ã„<= å¹…=%i 高ã•=%i:%s" #~ msgid "Could not open %s: %s" #~ msgstr "%s ã‚’é–‹ã‘ã¾ã›ã‚“:%s" #~ msgid "Error closing %s: %s" #~ msgstr "%s ã‚’é–‰ã˜ã‚‹æ™‚ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸï¼š%s" #~ msgid "Could not write to %s: %s" #~ msgstr "%s ã«æ›¸ãè¾¼ã‚ã¾ã›ã‚“:%s" #~ msgid "patterns_user.c could not be opened in current directory" #~ msgstr "patterns_user.c ã¯ç¾åœ¨ã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã«é–‹ã‘ã¾ã›ã‚“" #~ msgid "Done" #~ msgstr "完了" #~ msgid "patterns_user.c created in current directory" #~ msgstr "patterns_user.c ã¯ç¾åœ¨ã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã«ä½œæˆã•れã¾ã—ãŸ" #~ msgid "Current image is not 94x94x3 so I cannot create patterns_user.c" #~ msgstr "" #~ "ç¾åœ¨ã®ã‚¤ãƒ¡ãƒ¼ã‚¸ã¯ 94x94x3 ã§ã¯ã‚りã¾ã›ã‚“。patterns_user.c を作æˆã§ãã¾ã›ã‚“" #~ msgid "" #~ "You are trying to save an RGB image to an XPM file which is not " #~ "possible. I would suggest you save with a PNG extension." #~ msgstr "" #~ "RGBイメージをä¸å¯èƒ½ãªXPMファイルã«ä¿å­˜ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚PNGæ‹¡å¼µå­ã§ä¿å­˜" #~ "ã—ã¦ä¸‹ã•ã„。" #~ msgid "" #~ "You are trying to save an RGB image to a GIF file which is not possible. " #~ "I would suggest you save with a PNG extension." #~ msgstr "" #~ "RGBイメージをä¸å¯èƒ½ãªGIFファイルã«ä¿å­˜ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚PNGæ‹¡å¼µå­ã§ä¿å­˜" #~ "ã—ã¦ä¸‹ã•ã„。" #~ msgid "" #~ "You are trying to save an XBM file with a palette of more than 2 " #~ "colours. Either use another format or reduce the palette to 2 colours." #~ msgstr "" #~ "XBMファイルを2色以上ã®ãƒ‘レットã§ä¿å­˜ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚ä»–ã®ãƒ•ォーマットã«" #~ "ã™ã‚‹ã‹ã€ãƒ‘レットを2è‰²ã«æ¸›ã‚‰ã—ã¦ä¸‹ã•ã„。" #~ msgid "" #~ "You are trying to save an indexed canvas to a JPEG file which is not " #~ "possible. I would suggest you save with a PNG extension." #~ msgstr "" #~ "インデックスキャンãƒã‚¹ã‚’ä¸å¯èƒ½ãªJPEGファイルã§ä¿å­˜ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚PNG" #~ "æ‹¡å¼µå­ã§ä¿å­˜ã—ã¦ä¸‹ã•ã„。" #~ msgid "/File/Actions/sep2" #~ msgstr "/ファイル(F)/アクション/sep2" #~ msgid "/Edit/Create Patterns" #~ msgstr "/編集(E)/パターンを作æˆ" #~ msgid "/Palette/Create Quantized (DL1)" #~ msgstr "/パレット(P)/é‡å­åŒ–ã®ä½œæˆ (DL1)" #~ msgid "/Palette/Create Quantized (DL3)" #~ msgstr "/パレット(P)/é‡å­åŒ–ã®ä½œæˆ (DL3)" #~ msgid "/Palette/Create Quantized (Wu)" #~ msgstr "/パレット(P)/é‡å­åŒ–ã®ä½œæˆ (Wu)" #~ msgid "/Frames" #~ msgstr "/フレーム" #~ msgid "/File/%i" #~ msgstr "/ファイル(F)/%i" #~ msgid "/File/Actions/%i" #~ msgstr "/ファイル(F)/アクション/%i" #~ msgid "Loading PNG image" #~ msgstr "PNGイメージをロード" #~ msgid "Loading clipboard image" #~ msgstr "クリップボードイメージをロード" #~ msgid "Saving PNG image" #~ msgstr "PNGイメージをä¿å­˜" #~ msgid "Saving Clipboard image" #~ msgstr "クリップボードイメージをä¿å­˜" #~ msgid "Saving Layer image" #~ msgstr "レイヤイメージをä¿å­˜" #~ msgid "Saving Channel image" #~ msgstr "ãƒãƒ£ãƒ³ãƒãƒ«ã‚¤ãƒ¡ãƒ¼ã‚¸ã‚’ä¿å­˜" #~ msgid "Loading GIF image" #~ msgstr "GIFイメージをロード" #~ msgid "Saving GIF image" #~ msgstr "GIFイメージをä¿å­˜" #~ msgid "Loading JPEG image" #~ msgstr "JPEGイメージをロード" #~ msgid "Saving JPEG image" #~ msgstr "JPEGイメージをä¿å­˜" #~ msgid "Loading TIFF image" #~ msgstr "TIFFイメージをロード" #~ msgid "Saving TIFF image" #~ msgstr "TIFFイメージをä¿å­˜" #~ msgid "Loading BMP image" #~ msgstr "BMPイメージをロード" #~ msgid "Saving BMP image" #~ msgstr "BMPイメージをä¿å­˜" #~ msgid "Loading XPM image" #~ msgstr "XPMイメージをロード" #~ msgid "Saving XPM image" #~ msgstr "XPMイメージをä¿å­˜" #~ msgid "Loading XBM image" #~ msgstr "XBMイメージをロード" #~ msgid "Saving XBM image" #~ msgstr "XBMイメージをä¿å­˜" #~ msgid "Loading LSS16 image" #~ msgstr "LSS16イメージをロード" #~ msgid "Saving LSS16 image" #~ msgstr "LSS16イメージをä¿å­˜" #~ msgid "Saving UNDO images" #~ msgstr "アンドゥイメージをä¿å­˜" #~ msgid "JPEG Save Quality (100=High) " #~ msgstr "JPEGã®ä¿å­˜å“質 (100=高ã„) " mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/po/kab.po000066400000000000000000002515471471325446300217040ustar00rootroot00000000000000# kabyle translation for mtpaint # Copyright (c) 2020 Rosetta Contributors and Canonical Ltd 2020 # This file is distributed under the same license as the mtpaint package. # FIRST AUTHOR , 2020. # msgid "" msgstr "" "Project-Id-Version: mtpaint\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-01-04 21:31+0200\n" "PO-Revision-Date: 2020-11-06 10:11+0000\n" "Last-Translator: Yacine Bouklif \n" "Language-Team: Kabyle \n" "Language: kab\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Launchpad-Export-Date: 2021-01-04 08:36+0000\n" "X-Generator: Launchpad (build 34b3ffd45c9543b7f7aa5aa313925241e9e7ca3f)\n" #: src/ani.c:647 msgid "Animation Preview" msgstr "TamuÉ£li n usmussu" #: src/ani.c:650 src/shifter.c:275 msgid "Play" msgstr "Urar" #: src/ani.c:654 msgid "Fix" msgstr "Seggem" #: src/ani.c:655 src/ani.c:1005 src/font.c:1624 src/font.c:1643 #: src/shifter.c:286 src/viewer.c:97 msgid "Close" msgstr "Mdel" #: src/ani.c:709 src/ani.c:812 src/ani.c:1022 src/ani.c:1028 src/canvas.c:356 #: src/canvas.c:708 src/canvas.c:989 src/canvas.c:1353 src/canvas.c:1383 #: src/canvas.c:1470 src/canvas.c:1545 src/canvas.c:1988 src/canvas.c:1994 #: src/canvas.c:2077 src/canvas.c:2217 src/canvas.c:2240 src/font.c:1352 #: src/fpick.c:636 src/fpick.c:754 src/layer.c:524 src/layer.c:815 #: src/layer.c:970 src/mainwindow.c:341 src/mainwindow.c:370 #: src/mainwindow.c:534 src/mainwindow.c:578 src/mainwindow.c:604 #: src/mainwindow.c:3797 src/mainwindow.c:4045 src/otherwindow.c:931 #: src/otherwindow.c:980 src/otherwindow.c:982 src/prefs.c:459 src/spawn.c:924 #: src/spawn.c:978 src/spawn.c:1017 src/thread.c:360 src/vcode.c:9912 #: src/viewer.c:1161 src/viewer.c:1179 msgid "Error" msgstr "Tuccá¸a" #: src/ani.c:709 msgid "Unable to create output directory" msgstr "D awezÉ£i asnulfu n ukaram n tuffÉ£a" #: src/ani.c:759 msgid "Creating Animation Frames" msgstr "Asnulfu n yikataren n usmussu" #: src/ani.c:812 msgid "Unable to save image" msgstr "D awezÉ£i asekles n tugna" #: src/ani.c:840 src/canvas.c:1171 src/fpick.c:731 src/layer.c:311 #: src/layer.c:379 src/layer.c:826 src/layer.c:840 src/mainwindow.c:375 #: src/mainwindow.c:1026 src/png.c:8794 src/prefs.c:464 msgid "Warning" msgstr "AlÉ£u" #: src/ani.c:840 msgid "" "Do you really want to clear all of the position and cycle data for all of " "the layers?" msgstr "D tidet tebÉ£iḠad tsefá¸eḠakk isefka n usmusu n tissiyin meṛṛ ?" #: src/ani.c:841 src/fpick.c:731 src/layer.c:311 src/layer.c:842 #: src/mainwindow.c:375 msgid "No" msgstr "Ala" #: src/ani.c:841 src/fpick.c:731 src/layer.c:311 src/layer.c:842 #: src/mainwindow.c:375 msgid "Yes" msgstr "Ih" #: src/ani.c:954 msgid "Set Key Frame" msgstr "Sbadu uá¸á¸un n ukatar" #: src/ani.c:961 msgid "Configure Animation" msgstr "Swel asmussu" #: src/ani.c:964 msgid "Output Files" msgstr "Ifuyla n tuffÉ£a" #: src/ani.c:967 msgid "Start frame" msgstr "Akatar n tazwara" #: src/ani.c:969 msgid "End frame" msgstr "Akatar n taggara" #: src/ani.c:971 src/shifter.c:267 msgid "Delay" msgstr "Amená¸ar" #: src/ani.c:973 msgid "Output path" msgstr "Abrid n tuffÉ£a" #: src/ani.c:973 src/font.c:1637 src/spawn.c:664 msgid "Select Directory" msgstr "Fren akaram" #: src/ani.c:976 msgid "File prefix" msgstr "Azwir n yifuyla" #: src/ani.c:978 src/canvas.c:2096 msgid "File Format" msgstr "Amasal n ufylu" #: src/ani.c:982 msgid "Positions" msgstr "Idegan" #: src/ani.c:997 msgid "Cycling" msgstr "Allus" #: src/ani.c:1006 msgid "Save" msgstr "Sekles" #: src/ani.c:1007 src/font.c:1577 src/otherwindow.c:868 src/otherwindow.c:1615 #: src/otherwindow.c:1728 src/otherwindow.c:2938 src/otherwindow.c:3071 #: src/otherwindow.c:3170 msgid "Preview" msgstr "TamuÉ£li" #: src/ani.c:1008 src/shifter.c:285 msgid "Create Frames" msgstr "Snulfu-d ikataren" #: src/ani.c:1022 msgid "You must have at least 2 layers to create an animation" msgstr "Isefk ad ilin ma drus snat n tissiyin akken ad d-tesnulfuḠasmussu" #: src/ani.c:1028 msgid "You must save your layers file before creating an animation" msgstr "Isefk ad teskelseḠqbel tissiyin akken ad d-tesnulfuḠasmussu" #: src/canvas.c:357 msgid "The image is too large to transform." msgstr "Tugna temqqer aá¹­as akken ad tettwabedel." #: src/canvas.c:393 src/canvas.c:430 src/otherwindow.c:1613 #: src/otherwindow.c:2524 src/otherwindow.c:2583 src/otherwindow.c:3179 msgid "Gradient" msgstr "Afesnaw" #: src/canvas.c:393 src/otherwindow.c:840 src/otherwindow.c:842 #: src/otherwindow.c:2074 src/otherwindow.c:3180 msgid "Palette" msgstr "Tapaliá¸t" #: src/canvas.c:393 src/info.c:265 src/otherwindow.c:847 src/otherwindow.c:2757 #: src/otherwindow.c:3180 src/png.c:781 src/png.c:995 msgid "Clipboard" msgstr "Tacfawit" #: src/canvas.c:394 src/cpick.c:831 src/toolbar.c:299 msgid "Value" msgstr "Azal" #: src/canvas.c:394 src/cpick.c:811 src/otherwindow.c:575 src/otherwindow.c:859 #: src/otherwindow.c:3053 src/toolbar.c:318 msgid "Red" msgstr "AzeggaÉ£" #: src/canvas.c:394 src/cpick.c:815 src/otherwindow.c:575 src/otherwindow.c:860 #: src/otherwindow.c:3053 src/toolbar.c:319 msgid "Green" msgstr "Azegzaw" #: src/canvas.c:394 src/cpick.c:819 src/otherwindow.c:575 src/otherwindow.c:861 #: src/otherwindow.c:3053 src/toolbar.c:320 msgid "Blue" msgstr "Anili" #: src/canvas.c:399 msgid "From " msgstr "" #: src/canvas.c:403 msgid "To " msgstr "" #: src/canvas.c:410 msgid "Map" msgstr "" #: src/canvas.c:429 msgid "MT" msgstr "" #: src/canvas.c:429 msgid "Sobel" msgstr "" #: src/canvas.c:429 msgid "Prewitt" msgstr "" #: src/canvas.c:429 msgid "Kirsch" msgstr "" #: src/canvas.c:430 msgid "Roberts" msgstr "" #: src/canvas.c:430 msgid "Laplace" msgstr "" #: src/canvas.c:430 msgid "Morphological" msgstr "" #: src/canvas.c:442 msgid "Edge Detect" msgstr "Tifin n yiran" #: src/canvas.c:464 msgid "Edge Sharpen" msgstr "Asemsed n yiran" #: src/canvas.c:472 msgid "Edge Soften" msgstr "SilwiÉ£ iran" #: src/canvas.c:521 msgid "Different X/Y" msgstr "" #: src/canvas.c:522 src/canvas.c:562 src/canvas.c:603 src/canvas.c:637 #: src/canvas.c:722 src/otherwindow.c:1037 src/otherwindow.c:2685 msgid "Gamma corrected" msgstr "AseÉ£ti gama" #: src/canvas.c:530 src/memory.c:8219 msgid "Gaussian Blur" msgstr "AluÉ£u n Gauss" #: src/canvas.c:558 msgid "Radius" msgstr "Aqqar" #: src/canvas.c:559 msgid "Amount" msgstr "Tasmekta" #: src/canvas.c:560 msgid "Threshold " msgstr "Amnar: " #: src/canvas.c:570 src/memory.c:8360 msgid "Unsharp Mask" msgstr "" #: src/canvas.c:599 msgid "Outer radius" msgstr "Aqqar n beṛṛa" #: src/canvas.c:600 msgid "Inner radius" msgstr "Aqqar n daxel" #: src/canvas.c:602 src/info.c:280 msgid "Normalize" msgstr "Normaliser" #: src/canvas.c:611 src/memory.c:8512 msgid "Difference of Gaussians" msgstr "" #: src/canvas.c:636 msgid "Protect details" msgstr "Talqayt n umesten" #: src/canvas.c:645 msgid "Kuwahara-Nagao Blur" msgstr "AluÉ£u n Kuwahara-Nagao" #: src/canvas.c:709 msgid "The image is too large for this rotation." msgstr "Tugna temeqqer aá¹­as i tuzzya-agi." #: src/canvas.c:723 msgid "Smooth" msgstr "SilwiÉ£" #: src/canvas.c:732 msgid "Free Rotate" msgstr "Tuzzya tilellit" #: src/canvas.c:989 src/viewer.c:1161 msgid "Not enough memory to create clipboard" msgstr "Ulac ddeqs n tkatut i wesnulfu n tecfawit" #: src/canvas.c:1172 msgid "" "You have not allocated enough memory in the Preferences window to undo this " "action." msgstr "" #: src/canvas.c:1353 msgid "Invalid palette file" msgstr "Afaylu n tpaliá¸t armeÉ£tu" #: src/canvas.c:1383 msgid "Invalid channel file." msgstr "Afaylu n ubadu d armeÉ£tu." #: src/canvas.c:1401 msgid "Raw frames" msgstr "Ikataren n wadur" #: src/canvas.c:1401 msgid "Composited frames" msgstr "" #: src/canvas.c:1402 msgid "Composited frames with nonzero delay" msgstr "" #: src/canvas.c:1406 msgid "Load Frames" msgstr "Sali-d ikataren" #: src/canvas.c:1409 msgid "Load into Layers" msgstr "Sali-d daxel n tissiyin" #: src/canvas.c:1415 msgid "Load First Frame" msgstr "Sali-d akatar amezwaru" #: src/canvas.c:1416 msgid "Explode Frames" msgstr "" #: src/canvas.c:1418 msgid "View Animation" msgstr "TamuÉ£li n usmussu" #: src/canvas.c:1434 #, c-format msgid "This is an animated %s file." msgstr "Tagi d tugna %s tasmussant." #: src/canvas.c:1435 #, c-format msgid "This is a multipage %s file." msgstr "" #: src/canvas.c:1459 #, c-format msgid "File is too big, must be <= to width=%i height=%i" msgstr "Afaylu meqqr aá¹­as, isefk ad yili <= largeur=%i hauteur=%i" #: src/canvas.c:1461 msgid "Unable to explode frames" msgstr "" #: src/canvas.c:1463 msgid "Unable to load file" msgstr "D awezÉ£i asali n ufaylu" #: src/canvas.c:1465 msgid "" "The file import library had to terminate due to a problem with the file " "(possibly corrupt image data or a truncated file). I have managed to load " "some data as the header seemed fine, but I would suggest you save this image " "to a new file to ensure this does not happen again." msgstr "" #: src/canvas.c:1467 msgid "The animation is too long to load all of it into layers." msgstr "Asmussu meqqeá¹› aá¹­as akken ad d-yali akk di tissiyin." #: src/canvas.c:1469 msgid "Could not explode all the frames in the animation." msgstr "" #: src/canvas.c:1481 src/font.c:1556 src/fpick.c:937 src/otherwindow.c:2765 #: src/prefs.c:321 src/toolbar.c:451 msgid "Size" msgstr "Tiddi" #: src/canvas.c:1484 src/otherwindow.c:244 msgid "Width" msgstr "Tehri" #: src/canvas.c:1485 src/otherwindow.c:245 msgid "Height" msgstr "TeÉ£zi" #: src/canvas.c:1489 src/channels.c:253 src/channels.c:317 src/fpick.c:666 #: src/fpick.c:957 src/mainwindow.c:3990 src/otherwindow.c:255 #: src/otherwindow.c:517 src/otherwindow.c:591 src/otherwindow.c:867 #: src/otherwindow.c:1058 src/otherwindow.c:1727 src/otherwindow.c:2101 #: src/otherwindow.c:2336 src/otherwindow.c:2538 src/otherwindow.c:2691 #: src/otherwindow.c:2776 src/otherwindow.c:2937 src/otherwindow.c:3070 #: src/otherwindow.c:3169 src/prefs.c:338 src/prefs.c:464 src/prefs.c:538 #: src/spawn.c:666 src/viewer.c:1258 msgid "Cancel" msgstr "Sefsex" #: src/canvas.c:1490 src/channels.c:253 src/channels.c:317 src/fpick.c:956 #: src/info.c:297 src/mainwindow.c:3992 src/mygtk.c:233 src/mygtk.c:535 #: src/otherwindow.c:591 src/otherwindow.c:871 src/otherwindow.c:1058 #: src/otherwindow.c:1729 src/otherwindow.c:2101 src/otherwindow.c:2336 #: src/otherwindow.c:2538 src/otherwindow.c:2691 src/otherwindow.c:2776 #: src/otherwindow.c:3072 src/otherwindow.c:3171 src/prefs.c:338 #: src/prefs.c:538 src/spawn.c:666 msgid "OK" msgstr "Ih" #: src/canvas.c:1504 #, c-format msgid "This is a scalable %s file." msgstr "" #: src/canvas.c:1545 msgid "Cannot open file" msgstr "Ulamek aldau n ufaylu" #: src/canvas.c:1546 msgid "Unsupported file format" msgstr "Amasal n ufaylu ur yettwadhel ara" #: src/canvas.c:1673 #, c-format msgid "File: %s already exists. Do you want to overwrite it?" msgstr "Afaylu %s yella yakan. TebÉ£iḠad t-tesemselsiḠ?" #: src/canvas.c:1674 msgid "File Found" msgstr "Afaylu yettwaf" #: src/canvas.c:1674 src/mainwindow.c:1095 msgid "NO" msgstr "ALA" #: src/canvas.c:1674 src/mainwindow.c:1095 msgid "YES" msgstr "IH" #: src/canvas.c:1988 msgid "Unable to export undo images" msgstr "" #: src/canvas.c:1994 msgid "Unable to export ASCII file" msgstr "Tuccá¸a deg usifeḠn ufaylu ASCII" #: src/canvas.c:2076 src/layer.c:814 src/mainwindow.c:529 #, c-format msgid "Unable to save file: %s" msgstr "D awezÉ£i asekles n ufaylu: %s" #: src/canvas.c:2101 src/prefs.c:222 msgid "Transparency index" msgstr "Amatar n tefrawant" #: src/canvas.c:2103 msgid "TIFF Compression" msgstr "" #: src/canvas.c:2105 src/prefs.c:225 msgid "JPEG Save Quality (100=High)" msgstr "TaÉ£ara n tugna JPEG (100=Afellay)" #: src/canvas.c:2107 msgid "ZIP Compression (0=None)" msgstr "" #: src/canvas.c:2108 src/prefs.c:227 msgid "PNG Compression (0=None)" msgstr "Asekkusem PNG (0=Ulac)" #: src/canvas.c:2111 src/prefs.c:249 msgid "LZMA2 Compression (0=None)" msgstr "" #: src/canvas.c:2113 src/prefs.c:252 msgid "ZSTD Compression Level" msgstr "" #: src/canvas.c:2115 src/prefs.c:231 msgid "TGA RLE Compression" msgstr "Asekkussem TGA RLE" #: src/canvas.c:2117 msgid "LBM PackBits Compression" msgstr "" #: src/canvas.c:2118 src/prefs.c:226 msgid "JPEG2000 Compression (0=Lossless)" msgstr "Asekkussem JPEG2000 (0= war asá¹›uḥu)" #: src/canvas.c:2120 msgid "WebP Compression" msgstr "" #: src/canvas.c:2122 msgid "WebP Save Quality (100=High)" msgstr "" #: src/canvas.c:2123 src/prefs.c:263 msgid "V8 Save Quality (100=High)" msgstr "" #: src/canvas.c:2125 src/prefs.c:264 msgid "V8L Compression (0=None)" msgstr "" #: src/canvas.c:2127 msgid "Hotspot at X =" msgstr "" #: src/canvas.c:2129 msgid "Y =" msgstr "Y =" #: src/canvas.c:2133 msgid "Animation delay" msgstr "Amená¸ar n usmussu" #: src/canvas.c:2136 src/otherwindow.c:253 msgid "Undoable" msgstr "" #: src/canvas.c:2138 src/prefs.c:236 msgid "Apply colour profile" msgstr "Snes amaÉ£nu n yini" #: src/canvas.c:2176 src/toolbar.c:543 msgid "Load Image File" msgstr "Sali-d afaylu n tugna" #: src/canvas.c:2191 src/toolbar.c:544 msgid "Save Image File" msgstr "Sekles afaylu n tugna" #: src/canvas.c:2196 msgid "Load Palette File" msgstr "Sali-d afaylu n tpaliá¸t" #: src/canvas.c:2202 msgid "Save Palette File" msgstr "Sekles afaylu n tpaliá¸t" #: src/canvas.c:2207 msgid "Export Undo Images" msgstr "" #: src/canvas.c:2212 msgid "Export Undo Images (reversed)" msgstr "" #: src/canvas.c:2217 msgid "You must have 16 or fewer palette colours to export ASCII art." msgstr "" "Isefk ad tesÉ›uḠ16 n yinitenn tpaliá¸t neÉ£ drus akken ad tsifá¸eḠtaẓuri ASCII." #: src/canvas.c:2220 msgid "Export ASCII Art" msgstr "SifeḠs umasal n tẓuri ASCII" #: src/canvas.c:2224 msgid "Save Layer Files" msgstr "Sekles ifuyla n tissi" #: src/canvas.c:2234 msgid "Choose frames directory" msgstr "Fren akaram n yikataren" #: src/canvas.c:2240 msgid "You must save at least one frame to create an animated GIF." msgstr "" "Akken ad d-tesnulfuḠasmussu n GIF isefk ad teskelseḠma drus yiwen n ukatar." #: src/canvas.c:2243 msgid "Export GIF animation" msgstr "SifeḠasmussu GIF" #: src/canvas.c:2247 msgid "Load Channel" msgstr "Sali-d abadu" #: src/canvas.c:2255 msgid "Save Channel" msgstr "Sekles abadu" #: src/canvas.c:2260 msgid "Save Composite Image" msgstr "Sekles tugna tuddist" #: src/channels.c:243 msgid "Create Channel" msgstr "Snulfu-d abadu" #: src/channels.c:244 msgid "Channel Type" msgstr "Anaw b ubadu" #: src/channels.c:247 msgid "Initial Channel State" msgstr "Addad n tazwara n ubadu" #: src/channels.c:251 msgid "Inverted" msgstr "Yetti" #: src/channels.c:265 msgid "Cleared" msgstr "Yettwasfeá¸" #: src/channels.c:266 msgid "Set" msgstr "Wennez" #: src/channels.c:267 msgid "Set colour A radius B" msgstr "Sbadu ini A aqqar B" #: src/channels.c:268 msgid "Set blend A to B" msgstr "Sbadu amyezdi n A akked B" #: src/channels.c:269 msgid "Image Red" msgstr "AzeggaÉ£" #: src/channels.c:270 msgid "Image Green" msgstr "Azegzaw" #: src/channels.c:271 msgid "Image Blue" msgstr "Anili" #: src/channels.c:273 src/channels.c:313 src/mainwindow.c:67 #: src/otherwindow.c:1679 msgid "Alpha" msgstr "Alfa" #: src/channels.c:274 src/channels.c:314 src/mainwindow.c:67 #: src/otherwindow.c:1683 msgid "Selection" msgstr "Tafrayt" #: src/channels.c:275 src/channels.c:315 src/mainwindow.c:67 #: src/otherwindow.c:1687 msgid "Mask" msgstr "Tagelmust" #: src/channels.c:312 msgid "Delete Channels" msgstr "Kkes ibuda" #: src/channels.c:367 msgid "Threshold Channel" msgstr "Amnaá¹› n ubadu" #: src/cpick.c:823 src/otherwindow.c:573 src/otherwindow.c:820 #: src/toolbar.c:299 msgid "Hue" msgstr "TiÉ£mi" #: src/cpick.c:827 src/otherwindow.c:573 src/otherwindow.c:818 #: src/toolbar.c:299 msgid "Saturation" msgstr "Tawant" #: src/cpick.c:835 msgid "Hex" msgstr "" #: src/cpick.c:840 src/layer.c:1109 src/otherwindow.c:2530 src/prefs.c:323 #: src/toolbar.c:457 msgid "Opacity" msgstr "Tiá¸ullest" #: src/font.c:982 msgid "Creating Font Index" msgstr "Asnulfu n umatar n tsefsit" #: src/font.c:1353 msgid "You must select at least one directory to search for fonts." msgstr "Isefk ad tferneḠxerá¹£um yiwen n ukaram anida ara tnadiḠtisefsa." #: src/font.c:1529 src/font.c:1624 src/toolbar.c:609 src/viewer.c:1213 #: src/viewer.c:1258 msgid "Paste Text" msgstr "Sená¹­eḠaá¸ris" #: src/font.c:1533 src/font.c:1572 src/png.c:3578 msgid "Text" msgstr "Aá¸ris" #: src/font.c:1540 msgid "Font" msgstr "Tasefsit" #: src/font.c:1548 msgid "Style" msgstr "AÉ£anib" #: src/font.c:1566 msgid "Filename" msgstr "Isem n ufaylu" #: src/font.c:1567 msgid "Face" msgstr "" #: src/font.c:1587 src/viewer.c:1222 msgid "Antialias" msgstr "Amzay" #: src/font.c:1590 src/viewer.c:1224 msgid "Invert" msgstr "Tti" #: src/font.c:1593 src/viewer.c:1226 msgid "Background colour =" msgstr "Ini n ugilal =" #: src/font.c:1601 src/viewer.c:1233 msgid "DPI =" msgstr "" #: src/font.c:1610 msgid "Oblique" msgstr "Yekna" #: src/font.c:1612 src/viewer.c:1244 msgid "Angle of rotation =" msgstr "TiÉ£mert n tuzzya =" #: src/font.c:1617 src/viewer.c:1248 msgid "Align" msgstr "" #: src/font.c:1620 src/viewer.c:1253 msgid "Spacing" msgstr "" #: src/font.c:1629 msgid "Font Directories" msgstr "Ikaramen n tsefsa" #: src/font.c:1634 src/spawn.c:664 msgid "Directory" msgstr "Akaram" #: src/font.c:1637 msgid "New Directory" msgstr "Akaram amaynut" #: src/font.c:1644 src/prefs.c:532 msgid "Add" msgstr "Rnu" #: src/font.c:1645 src/prefs.c:533 msgid "Remove" msgstr "Kkes" #: src/font.c:1646 msgid "Create Index" msgstr "Snulfu-d amatar" #: src/font.c:1660 src/viewer.c:1267 msgid "Enter Text Here" msgstr "Aru aá¸ris dagi" #: src/fpick.c:635 #, c-format msgid "Could not access directory %s" msgstr "Ur yezmir ara ad yaddef É£er ukaram %s" #: src/fpick.c:668 src/fpick.c:698 msgid "Delete" msgstr "Kkes" #: src/fpick.c:669 src/fpick.c:698 msgid "Rename" msgstr "Beddel isem" #: src/fpick.c:672 src/otherwindow.c:255 src/otherwindow.c:1666 msgid "Create" msgstr "Snulfu-d" #: src/fpick.c:699 msgid "Enter the new filename" msgstr "Sekcem isem amaynut n ufaylu" #: src/fpick.c:704 msgid "Create Directory" msgstr "Snulfu-d akaram" #: src/fpick.c:705 msgid "Enter the name of the new directory" msgstr "Sekcem isem amaynut n ukaram" #: src/fpick.c:729 #, c-format msgid "Do you really want to delete \"%s\" ?" msgstr "D tidet tebÉ£iḠad tekkseḠ\"%s\" ?" #: src/fpick.c:735 msgid "Unable to delete" msgstr "D awezÉ£i tukksa" #: src/fpick.c:741 msgid "Unable to rename" msgstr "D awezÉ£i abeddel n yisem" #: src/fpick.c:750 msgid "Unable to create directory" msgstr "D awezÉ£i asnulfu n ukaram" #: src/fpick.c:924 msgid "Up" msgstr "Uksawen" #: src/fpick.c:925 msgid "Home" msgstr "Asebter agejdan" #: src/fpick.c:926 msgid "Create New Directory" msgstr "Snulfu-d akaram amaynut" #: src/fpick.c:927 msgid "Show Hidden Files" msgstr "BeqqeḠifuyla uffiren" #: src/fpick.c:929 msgid "Case Insensitive Sort" msgstr "Afran ur nettḥulfu ara i tejá¹›ut n usekkil" #: src/fpick.c:936 msgid "Name" msgstr "Isem" #: src/fpick.c:938 msgid "Type" msgstr "Anaw" #: src/fpick.c:939 msgid "Modified" msgstr "Yettwabeddel" #: src/help.c:25 src/prefs.c:160 msgid "General" msgstr "Amatu" #: src/help.c:26 msgid "Keyboard shortcuts" msgstr "Inegzumen n unasiw" #: src/help.c:27 msgid "Mouse shortcuts" msgstr "Inegzumen n umumed" #: src/help.c:28 msgid "Credits" msgstr "Imttekkiyen" #: src/help.c:32 msgid "mtPaint 3.51 - Copyright (C) 2004-2021 The Authors\n" msgstr "mtPaint 3.51 - Copyright (C) 2004-2021 Imeskaren\n" #: src/help.c:33 msgid "See 'Credits' section for a list of the authors.\n" msgstr "" #: src/help.c:34 msgid "" "mtPaint 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.\n" msgstr "" #: src/help.c:35 msgid "" "mtPaint 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.\n" msgstr "" #: src/help.c:36 msgid "" "mtPaint is a simple GTK+1/2/3 painting program designed for creating icons " "and pixel based artwork. It can edit indexed palette or 24 bit RGB images " "and offers basic painting and palette manipulation tools. It also has " "several other more powerful features such as channels, layers and animation. " "Due to its simplicity and lack of dependencies it runs well on GNU/Linux, " "Windows and older PC hardware.\n" msgstr "" #: src/help.c:37 msgid "" "There is full documentation of mtPaint's features contained in a handbook. " "If you don't already have this, you can download it from the mtPaint " "website.\n" msgstr "" #: src/help.c:38 msgid "" "If you like mtPaint and you want to keep up to date with new releases, or " "you want to give some feedback, then the mailing lists may be of interest to " "you:\n" msgstr "" #: src/help.c:39 msgid "http://sourceforge.net/mail/?group_id=155874" msgstr "http://sourceforge.net/mail/?group_id=155874" #: src/help.c:42 msgid " Ctrl-N Create new image" msgstr " Ctrl-N Snulfu-d tugna tamaynutt" #: src/help.c:43 msgid " Ctrl-O Open Image" msgstr " Ctrl-O Ldi tugna" #: src/help.c:44 msgid " Ctrl-S Save Image" msgstr " Ctrl-S Sekles tugna" #: src/help.c:45 msgid " Ctrl-Shift-S Save layers file" msgstr " Ctrl-Shift-S Sekles afaylu n tissiyin" #: src/help.c:46 msgid " Ctrl-Q Quit program\n" msgstr " Ctrl-Q FfeÉ£ seg wahil\n" #: src/help.c:47 msgid " Ctrl-A Select whole image" msgstr " Ctrl-A Fren akk tugna" #: src/help.c:48 msgid " Escape Select nothing, cancel paste box" msgstr " Escape Ur ferren ara, sefsex taÉ£zut n usená¹­eá¸" #: src/help.c:49 msgid " J Lasso selection\n" msgstr "" #: src/help.c:50 msgid " Ctrl-C Copy selection to clipboard" msgstr " Ctrl-C NÉ£el tafrayt É£er tecfawit" #: src/help.c:51 msgid "" " Ctrl-X Copy selection to clipboard, and then paint current " "pattern to selection area" msgstr "" " Ctrl-X NÉ£el tafrayt É£er tacfawit, sakin aÄÄar tafrayt s wudlif" #: src/help.c:52 msgid " Ctrl-V Paste clipboard to centre of current view" msgstr " Ctrl-V Sená¹­eḠtacfawit di tlemmast n tmuÉ£li tamirant" #: src/help.c:53 msgid " Ctrl-K Paste clipboard to location it was copied from" msgstr " Ctrl-K Sená¹­eḠtacfawit deg umá¸iq ansi d-tettwanÉ£el" #: src/help.c:54 msgid " Ctrl-Shift-V Paste clipboard to new layer" msgstr " Ctrl-Shift-V Sená¹­eḠtacfawit di tissi tamaynutt" #: src/help.c:55 msgid " Enter/Return Commit paste to canvas" msgstr "" #: src/help.c:56 msgid " Shift+Enter/Return Commit paste and swap canvas into the clipboard\n" msgstr "" #: src/help.c:57 msgid " Arrow keys Paint Mode - Move the mouse pointer" msgstr " Tineccabin Smutti unuÉ£ - Smutti taḥnacaá¸t n umumed" #: src/help.c:58 msgid "" " Arrow keys Selection Mode - Nudge selection box or paste box by one " "pixel" msgstr "" #: src/help.c:59 msgid "" " Shift+Arrow keys Nudge mouse pointer, selection box or paste box by x " "pixels - x is defined by the Preferences window" msgstr "" #: src/help.c:60 msgid " Ctrl+Arrows Move layer or resize selection box" msgstr "" " Ctrl+Tineccabin Smutti tissi neÉ£ ales tiddi n tenkult n tefrayt" #: src/help.c:61 msgid " Ctrl+Shift+Arrows Move layer or resize selection box by x pixels\n" msgstr "" #: src/help.c:62 msgid " Enter/Return Paint Mode - Simulate left click" msgstr "" #: src/help.c:63 msgid " Backspace Paint Mode - Simulate right click\n" msgstr "" #: src/help.c:64 msgid "" " [ or ] Change colour A to the next or previous palette item" msgstr " [ neÉ£ ] Beddel ini A É£er uferdis uzwir neÉ£ uá¸fir n tpaliá¸t" #: src/help.c:65 msgid "" " Shift+[ or ] Change colour B to the next or previous palette item\n" msgstr " Shift+[ neÉ£ ] Semselsi ini B s yini uzwir neÉ£ uá¸fir n tpaliá¸t\n" #: src/help.c:66 msgid " Delete Crop image to selection" msgstr " Kkes Æ”eẓ tugna alama tafrayt" #: src/help.c:67 msgid "" " Insert Transform colours - i.e. Brightness, Contrast, " "Saturation, Posterize, Gamma" msgstr "" #: src/help.c:68 msgid " Ctrl-G Greyscale the image" msgstr " Ctrl-G Err tugna É£er yiswiren n umelliÉ£di" #: src/help.c:69 msgid " Shift-Ctrl-G Greyscale the image (Gamma corrected)" msgstr " Shift-Ctrl-G Err tugna s yiswiren n umelliÉ£di (aseÉ£ti n gama)" #: src/help.c:70 msgid " Ctrl+M Mirror the image" msgstr "" #: src/help.c:71 msgid " Shift-Ctrl-I Invert the image\n" msgstr " Shift-Ctrl-I Tti tugna\n" #: src/help.c:72 msgid "" " Ctrl-T Draw a rectangle around the selection area with the " "current fill" msgstr " Ctrl-T SuneÉ£ asrem yezzin i teÉ£zut n tefrayt s wudlif amiran" #: src/help.c:73 msgid " Ctrl-Shift-T Fill in the selection area with the current fill" msgstr " Ctrl-Shift-T AÄÄar taÉ£zut n tefrayt s wudlif amiran" #: src/help.c:74 msgid " Ctrl-L Draw an ellipse spanning the selection area" msgstr " Ctrl-L SuneÉ£ taglayt di teÉ£zut n tefrayt" #: src/help.c:75 msgid " Ctrl-Shift-L Draw a filled ellipse spanning the selection area\n" msgstr " Ctrl-Shift-L SuneÉ£ taglayt yeÄÄuren di teÉ£zut n tefrayt\n" #: src/help.c:76 msgid " Ctrl-E Edit the RGB values for colours A & B" msgstr " Ctrl-E Ẓreg azalen RVB n yiniten A & B" #: src/help.c:77 msgid " Ctrl-W Edit all palette colours\n" msgstr " Ctrl-W Ẓreg tapaliá¸t n yiniten\n" #: src/help.c:78 msgid " Ctrl-P Preferences" msgstr " Ctrl-P Ismenyifen" #: src/help.c:79 msgid " Ctrl-I Information\n" msgstr " Ctrl-I TalÉ£ut\n" #: src/help.c:80 msgid " Ctrl-Z Undo last action" msgstr " Ctrl-Z Sefsex tigawt taneggarut" #: src/help.c:81 msgid " Ctrl-R Redo an undone action\n" msgstr " Ctrl-R Err-d tigawt yettwasfesxen\n" #: src/help.c:82 msgid " Shift-T Text Tool (GTK+)" msgstr " Shift-T Afrcku Aá¸ris (GTK+)" #: src/help.c:83 msgid " T Text Tool (FreeType)\n" msgstr " T Afecku Aá¸ris (FreeType)\n" #: src/help.c:84 msgid " V View Window" msgstr " V Asfaylu n tmuÉ£li" #: src/help.c:85 msgid " L Layers Window\n" msgstr " L Asfaylu n tissiyin\n" #: src/help.c:86 msgid " Ctrl-H Toggle Hide Image mode" msgstr "" #: src/help.c:87 msgid " B Toggle Snap to Tile Grid mode\n" msgstr "" #: src/help.c:88 msgid " X Swap Colours A & B" msgstr " X Semselsi initen A & B" #: src/help.c:89 msgid " E Choose Colour\n" msgstr " E Fren ini\n" #: src/help.c:90 msgid "" " A Draw open arrow head when using the line tool (size set " "by flow setting)" msgstr "" " A SuneÉ£ taqamumt yeldin n tneccabt mi ara yettwaseqdec ufecku " "izirig (tiddi yesbadu-tt \"flow setting\")" #: src/help.c:91 msgid "" " S Draw closed arrow head when using the line tool (size " "set by flow setting)\n" msgstr "" " S SuneÉ£ taqamumt imedlen n tneccabt mi ara yettwaseqdec " "ufecku izirig (tiddi yesbadu-tt \"flow setting\")\n" #: src/help.c:92 msgid " D Line Tool" msgstr " D Afecku Izirig" #: src/help.c:93 msgid " F Flood Fill Tool\n" msgstr "" #: src/help.c:94 msgid " +,= Main edit window - Zoom in" msgstr " +,= Asfaylu n usiẓreg agejdan - Zoom +" #: src/help.c:95 msgid " - Main edit window - Zoom out" msgstr " - Asfaylu n usiẓreg agejdan - Zoom -" #: src/help.c:96 msgid " Shift +,= View window - Zoom in" msgstr " Shift +,= Asfaylu n tmuÉ£li - Zoom +" #: src/help.c:97 msgid " Shift - View window - Zoom out\n" msgstr " Shift - Asfaylu n tmuÉ£li - Zoom -\n" #: src/help.c:98 #, c-format msgid " 1 10% zoom" msgstr " 1 10% zoom" #: src/help.c:99 #, c-format msgid " 2 25% zoom" msgstr " 2 25% zoom" #: src/help.c:100 #, c-format msgid " 3 50% zoom" msgstr " 3 50% zoom" #: src/help.c:101 #, c-format msgid " 4 100% zoom" msgstr " 4 100% zoom" #: src/help.c:102 #, c-format msgid " 5 400% zoom" msgstr " 5 400% zoom" #: src/help.c:103 #, c-format msgid " 6 800% zoom" msgstr " 6 800% zoom" #: src/help.c:104 #, c-format msgid " 7 1200% zoom" msgstr " 7 1200% zoom" #: src/help.c:105 #, c-format msgid " 8 1600% zoom" msgstr " 8 1600% zoom" #: src/help.c:106 #, c-format msgid " 9 2000% zoom\n" msgstr " 9 2000% zoom\n" #: src/help.c:107 msgid " Shift + 1 Edit image channel" msgstr " Shift + 1 Ẓreg abadu n tugna" #: src/help.c:108 msgid " Shift + 2 Edit alpha channel" msgstr " Shift + 2 Ẓreg abadu alfa" #: src/help.c:109 msgid " Shift + 3 Edit selection channel" msgstr " Shift + 3 Ẓreg tafrayt" #: src/help.c:110 msgid " Shift + 4 Edit mask channel\n" msgstr " Shift + 4 Ẓreg abadu n teglmust\n" #: src/help.c:111 msgid " F1 Help" msgstr " F1 Tallelt" #: src/help.c:112 msgid " F2 Choose Pattern" msgstr " F2 Fren udlif" #: src/help.c:113 msgid " F3 Choose Brush" msgstr " F3 Fren amfezzu" #: src/help.c:114 msgid " F4 Paint Tool" msgstr " F4 Allal n teklut" #: src/help.c:115 msgid " F5 Toggle Main Toolbar" msgstr "" #: src/help.c:116 msgid " F6 Toggle Tools Toolbar" msgstr "" #: src/help.c:117 msgid " F7 Toggle Settings Toolbar" msgstr "" #: src/help.c:118 msgid " F8 Toggle Palette" msgstr "" #: src/help.c:119 msgid " F9 Selection Tool" msgstr " F9 Afecku Tafrayt" #: src/help.c:120 msgid " F12 Toggle Dock Area\n" msgstr "" #: src/help.c:121 msgid " Ctrl + F1 - F12 Save current clipboard to file 1-12" msgstr " Ctrl + F1 - F12 Sekles tacfawit tamirant deg ufaylu 1-12" #: src/help.c:122 msgid " Shift + F1 - F12 Load clipboard from file 1-12\n" msgstr " Shift + F1 - F12 Sali-d tacfawit seg ufaylu 1-12\n" #: src/help.c:123 msgid "" " Ctrl + 1, 2, ... , 0 Set opacity to 10%, 20%, ... , 100% (main or keypad " "numbers)" msgstr "" #: src/help.c:124 msgid " Ctrl + + or = Increase opacity by 1" msgstr " Ctrl + + or = Sali tiá¸ullest s 1" #: src/help.c:125 msgid " Ctrl + - Decrease opacity by 1\n" msgstr " Ctrl + - Sader tiá¸ullest s1\n" #: src/help.c:126 msgid "" " Home Show or hide main window menu/toolbar/status bar/palette" msgstr "" #: src/help.c:127 msgid " Page Up Scale Image" msgstr " Asebter d asawen Beddel taskala n tugna" #: src/help.c:128 msgid " Page Down Resize Image canvas" msgstr "" #: src/help.c:129 msgid " End Pan Window" msgstr "" #: src/help.c:132 msgid " Left button Paint to canvas using the current tool" msgstr " Taqeffalt tazelmaá¸t Klu di teÉ£zut n usuneÉ£ s ufecku amiran" #: src/help.c:133 msgid "" " Middle button Selects the point which will be the centre of the " "image after the next zoom" msgstr "" #: src/help.c:134 msgid "" " Right button Commit paste to canvas / Stop drawing current line / " "Cancel selection\n" msgstr "" " Taqeffalt tayfust Sentem tamhelt / Seḥbes asuneÉ£ amiranl / Sefsex " "tafrayt\n" #: src/help.c:135 msgid "" " Scroll Wheel In GTK+2/3 the user can have the scroll wheel zoom in " "or out via the Preferences window\n" msgstr "" #: src/help.c:136 msgid " Ctrl+Left button Choose colour A from under mouse pointer" msgstr "" #: src/help.c:137 msgid " Ctrl+Left button Clone tool - Select source" msgstr "" #: src/help.c:138 msgid "" " Ctrl+Middle button Create colour A/B and pattern based on the RGB colour " "in A (RGB images only)" msgstr "" " Ctrl+Taqeffalt talemmast Snulfu-d ini A/B yebnan É£ef yini RGB di A " "(tugniwin n RGB kan)" #: src/help.c:139 msgid " Ctrl+Right button Choose colour B from under mouse pointer" msgstr "" #: src/help.c:140 msgid "" " Ctrl+Right button Polygon tool - Delete last point / Delete nearest " "point" msgstr "" #: src/help.c:141 msgid " Ctrl+Scroll Wheel Scroll the main edit window left or right\n" msgstr "" " Ctrl+Ṛṛuda n udrurem Smutti asfaylu n usiẓreg É£er zelmaḠneÉ£ É£er " "yefus\n" #: src/help.c:142 msgid "" " Ctrl+Double click Set colour A or B to average colour under brush " "square or selection marquee (RGB only)\n" msgstr "" #: src/help.c:143 msgid "" " Shift+Right button Selects the point which will be the centre of the " "image after the next zoom\n" "\n" msgstr "" #: src/help.c:144 msgid "You can fixate the X/Y co-ordinates while moving the mouse:\n" msgstr "TzemreḠad tesweḥleḠamutti X/Y mi ara yettmutti umumed:\n" #: src/help.c:145 msgid " Shift Constrain mouse movements to vertical line" msgstr " Shift Ḥettem amutti n umumed É£er yizirig ubdid" #: src/help.c:146 msgid " Shift+Ctrl Constrain mouse movements to horizontal line" msgstr " Shift+Ctrl Ḥettem amutti n umumed É£er yizirig aglawan" #: src/help.c:149 msgid "mtPaint is maintained by Dmitry Groshev.\n" msgstr "" #: src/help.c:150 msgid "wjaguar@users.sourceforge.net" msgstr "wjaguar@users.sourceforge.net" #: src/help.c:151 msgid "http://mtpaint.sourceforge.net/\n" msgstr "http://mtpaint.sourceforge.net/\n" #: src/help.c:152 msgid "" "The following people (in alphabetical order) have contributed directly to " "the project, and are therefore worthy of gracious thanks for their " "generosity and hard work:\n" "\n" msgstr "" #: src/help.c:153 msgid "Authors\n" msgstr "Imeskaren\n" #: src/help.c:154 msgid "" "Dmitry Groshev - Contributing developer for version 2.30. Lead developer and " "maintainer from version 3.00 to the present." msgstr "" #: src/help.c:155 msgid "" "Mark Tyler - Original author and maintainer up to version 3.00, occasional " "contributor thereafter." msgstr "" #: src/help.c:156 msgid "" "Xiaolin Wu - Wrote the Wu quantizing method - see wu.c for more " "information.\n" "\n" msgstr "" #: src/help.c:157 msgid "" "General Contributions (Feedback and Ideas for improvements unless otherwise " "stated)\n" msgstr "" #: src/help.c:158 msgid "Abdulla Al Muhairi - Website redesign April 2005" msgstr "" #: src/help.c:159 msgid "Alan Horkan" msgstr "Alan Horkan" #: src/help.c:160 msgid "Alexandre Prokoudine" msgstr "Alexandre Prokoudine" #: src/help.c:161 msgid "Antonio Andrea Bianco" msgstr "Antonio Andrea Bianco" #: src/help.c:162 msgid "Charlie Ledocq" msgstr "" #: src/help.c:163 msgid "Dennis Lee" msgstr "Dennis Lee" #: src/help.c:164 msgid "Donald White" msgstr "" #: src/help.c:165 msgid "Ed Jason" msgstr "Ed Jason" #: src/help.c:166 msgid "" "Eddie Kohler - Created Gifsicle which is needed for the creation and viewing " "of animated GIF files http://www.lcdf.org/gifsicle/" msgstr "" #: src/help.c:167 msgid "" "Guadalinex Team (Junta de Andalucia) - man page, Launchpad/Rosetta " "registration" msgstr "" #: src/help.c:168 msgid "Lou Afonso" msgstr "Lou Afonso" #: src/help.c:169 msgid "Magnus Hjorth" msgstr "Magnus Hjorth" #: src/help.c:170 msgid "Martin Zelaia" msgstr "Martin Zelaia" #: src/help.c:171 msgid "Pasi Kallinen" msgstr "" #: src/help.c:172 msgid "Pavel Ruzicka" msgstr "Pavel Ruzicka" #: src/help.c:173 msgid "Puppy Linux (Barry Kauler)" msgstr "Puppy Linux (Barry Kauler)" #: src/help.c:174 msgid "Victor Copovi" msgstr "" #: src/help.c:175 msgid "Vlastimil Krejcir" msgstr "Vlastimil Krejcir" #: src/help.c:176 msgid "" "William Kern\n" "\n" msgstr "" "William Kern\n" "\n" #: src/help.c:177 msgid "Translations\n" msgstr "Tisuqilin\n" #: src/help.c:178 msgid "Brazilian Portuguese - Paulo Trevizan, Valter Nazianzeno" msgstr "Tapurtugalit n Brizil - Paulo Trevizan, Valter Nazianzeno" #: src/help.c:179 msgid "Czech - Pavel Ruzicka, Martin Petricek, Roman Hornik, Pavel Fric" msgstr "TaÄikit - Pavel Ruzicka, Martin Petricek, Roman Hornik, Pavel Fric" #: src/help.c:180 msgid "Dutch - Hans Strijards, Pjotr" msgstr "Tahulandit - Hans Strijards, Pjotr" #: src/help.c:181 msgid "" "French - Nicolas Velin, Pascal Billard, Sylvain Cresto, Johan Serre, " "Philippe Etienne, Victor Copovi" msgstr "" "Tafransist - Nicolas Velin, Pascal Billard, Sylvain Cresto, Johan Serre, " "Philippe Etienne, Victor Copovi" #: src/help.c:182 msgid "Galician - Miguel Anxo Bouzada" msgstr "Tagalikant - Miguel Anxo Bouzada" #: src/help.c:183 msgid "German - Oliver Frommel, B. Clausius, Ulrich Ringel, Simon Brixel" msgstr "Talmanit - Oliver Frommel, B. Clausius, Ulrich Ringel, Simon Brixel" #: src/help.c:184 msgid "Hungarian - Ur Balazs" msgstr "Tahungarit - Ur Balazs" #: src/help.c:185 msgid "Italian - Angelo Gemmi" msgstr "Taá¹­elyanit - Angelo Gemmi" #: src/help.c:186 msgid "Japanese - Norihiro YONEDA" msgstr "Tajapunit - Norihiro YONEDA" #: src/help.c:187 msgid "Kabyle - Yacine Bouklif" msgstr "" #: src/help.c:188 msgid "Polish - Bartosz Kaszubowski, LucaS" msgstr "Tapulunit - Bartosz Kaszubowski, LucaS" #: src/help.c:189 msgid "Portuguese - Israel G. Lugo, Tiago Silva" msgstr "Tapurtugalit - Israel G. Lugo, Tiago Silva" #: src/help.c:190 msgid "Russian - Sergey Irupin, Dmitry Groshev" msgstr "Tarusit - Sergey Irupin, Dmitry Groshev" #: src/help.c:191 msgid "Simplified Chinese - Cecc" msgstr "Tacinwat taḥerfit - Cecc" #: src/help.c:192 msgid "Slovak - Jozef Riha" msgstr "Tasluvakit - Jozef Riha" #: src/help.c:193 msgid "" "Spanish - Guadalinex Team (Junta de Andalucia), Antonio Sanchez Leon, Miguel " "Anxo Bouzada, Francisco Jose Rey, Adolfo Jayme" msgstr "" "Taspenyulit - Guadalinex Team (Junta de Andalucia), Antonio Sanchez Leon, " "Miguel Anxo Bouzada, Francisco Jose Rey, Adolfo Jayme" #: src/help.c:194 msgid "Swedish - Daniel Nylander, Daniel Eriksson" msgstr "Taswidit - Daniel Nylander, Daniel Eriksson" #: src/help.c:195 msgid "Tagalog - Anjelo delCarmen" msgstr "Taá¹­agalugt - Anjelo delCarmen" #: src/help.c:196 msgid "Taiwanese Chinese - Wei-Lun Chao" msgstr "Tacinwat n Ṭaywan - Wei-Lun Chao" #: src/help.c:197 msgid "Turkish - Muhammet Kara, Tutku Dalmaz" msgstr "Taá¹­urkit - Muhammet Kara, Tutku Dalmaz" #: src/info.c:258 msgid "Information" msgstr "TalÉ£ut" #: src/info.c:260 msgid "Memory" msgstr "Takatut" #: src/info.c:261 msgid "Total memory for main + undo images" msgstr "" #: src/info.c:263 msgid "Undo / Redo / Max levels used" msgstr "" #: src/info.c:265 msgid "Unused" msgstr "Ur yettwaseqdec ar" #: src/info.c:269 msgid "Unique RGB pixels" msgstr "Ipikselen RVB isufen" #: src/info.c:272 src/layer.c:121 msgid "Layers" msgstr "Tissiyin" #: src/info.c:273 msgid "Total layer memory usage" msgstr "Aseqdec n tkatut n tissi" #: src/info.c:277 msgid "Colour Histogram" msgstr "" #: src/info.c:289 src/otherwindow.c:1614 msgid "Index" msgstr "Amatar" #: src/info.c:290 msgid "Canvas pixels" msgstr "Ipikslen n teÉ£zut n usuneÉ£" #: src/info.c:328 #, c-format msgid "Clipboard = %i x %i" msgstr "Tacfawit = %i x %i" #: src/info.c:328 #, c-format msgid "Clipboard = %i x %i x RGB" msgstr "Tacfawit = %i x %i x RVB" #: src/info.c:377 msgid "Orphans" msgstr "" #: src/info.c:383 #, c-format msgid "Colour index totals - %i of %i used" msgstr "" #: src/inifile.c:966 msgid "" "Could not find home directory. Using current directory as home directory." msgstr "" "Akaram n useqdac ur yettwaf ara. Aseqdec n ukaram amiran am ukaram n useqdac." #: src/layer.c:63 msgid "Background" msgstr "Agilal" #: src/layer.c:122 src/mainwindow.c:5931 msgid "(Modified)" msgstr "(Yettwabeddel)" #: src/layer.c:123 src/mainwindow.c:5932 msgid "Untitled" msgstr "War azwel" #: src/layer.c:308 #, c-format msgid "Do you really want to delete layer %i (%s) ?" msgstr "D tidet tebÉ£iḠad tekkseḠtissi %i (%s) ?" #: src/layer.c:380 msgid "" "One or more of the layers contains changes that have not been saved. Do you " "really want to lose these changes?" msgstr "" "Yiwet neÉ£ ugar n tissiyin yesÉ›an ibeddilen ur ttwaskelsent ara. D tidet " "tebÉ£iḠad tesá¹›uḥeḠibeddilen-agi ?" #: src/layer.c:381 src/mainwindow.c:1028 msgid "Cancel Operation" msgstr "Sefsex tamhelt" #: src/layer.c:381 src/mainwindow.c:1028 msgid "Lose Changes" msgstr "Eǧǧ ibeddilen" #: src/layer.c:523 #, c-format msgid "%d layers failed to load" msgstr "%d n tissiyin ggumant ad ldint" #: src/layer.c:826 msgid "" "One or more of the image layers has not been saved. You must save each " "image individually before saving the layers text file in order to load this " "composite image in the future." msgstr "" #: src/layer.c:841 msgid "Do you really want to delete all of the layers?" msgstr "D tidet tebÉ£iḠad tekkseḠakk tisiyin ?" #: src/layer.c:970 msgid "You cannot add any more layers." msgstr "Ur tezmireḠara ad ternuḠugar n tissiyin." #: src/layer.c:1083 src/otherwindow.c:241 msgid "New Layer" msgstr "Tissi tamaynutt" #: src/layer.c:1085 msgid "Raise" msgstr "Sali" #: src/layer.c:1087 msgid "Lower" msgstr "Sider" #: src/layer.c:1089 msgid "Duplicate Layer" msgstr "Sisleg tissi" #: src/layer.c:1091 msgid "Centralise Layer" msgstr "" #: src/layer.c:1093 msgid "Delete Layer" msgstr "Kkes Tissi" #: src/layer.c:1095 msgid "Close Layers Window" msgstr "Mdel asfaylu n tissiyin" #: src/layer.c:1101 msgid "Layer Name" msgstr "Isem n tissi" #: src/layer.c:1104 src/toolbar.c:209 msgid "Position" msgstr "Adig" #: src/layer.c:1112 msgid "Transparent Colour" msgstr "Ini afrawan" #: src/layer.c:1117 msgid "Show all layers in main window" msgstr "BeqqeḠakk tissiyin deg usfaylu agejdan" #: src/mainwindow.c:67 src/otherwindow.c:844 src/otherwindow.c:2756 #: src/toolbar.c:342 msgid "Image" msgstr "Tugna" #: src/mainwindow.c:69 src/mainwindow.c:489 src/otherwindow.c:1613 #: src/otherwindow.c:2302 msgid "RGB" msgstr "RGB" #: src/mainwindow.c:69 src/otherwindow.c:1613 src/otherwindow.c:2302 msgid "sRGB" msgstr "sRGB" #: src/mainwindow.c:342 msgid "There were no unused colours to remove!" msgstr "Ulac initen ur nettwaseqdec ara ara tekkseḠ!" #: src/mainwindow.c:371 msgid "The palette does not contain 2 colours that have identical RGB values" msgstr "" #: src/mainwindow.c:374 #, c-format msgid "" "The palette contains %i colours that have identical RGB values. Do you " "really want to merge them into one index and realign the canvas?" msgstr "" #: src/mainwindow.c:492 msgid "indexed" msgstr "" #: src/mainwindow.c:498 #, c-format msgid "" "You are trying to save an %s image to an %s file which is not possible. I " "would suggest you save with a PNG extension." msgstr "" "Ala tettaÉ›raá¸eḠad teskelseḠtugna %s deg ufaylu %s, maca ulamk. Ad k-" "semtereÉ£ ad tt-teskelseḠs usiÉ£zef PNG." #: src/mainwindow.c:500 #, c-format msgid "" "You are trying to save an %s file with a palette of more than %d colours. " "Either use another format or reduce the palette to %d colours." msgstr "" "Ala tettaÉ›raá¸eḠad teskelseḠafaylu %s s tpaliá¸t yesÉ›an ugar n %d n yiniten. " "Seqdec amasal-nniá¸en neÉ£ sader tapaliá¸t É£er %d n yiniten." #: src/mainwindow.c:578 msgid "Unable to load clipboard" msgstr "Ulamek asali n tecfawit" #: src/mainwindow.c:604 msgid "Unable to save clipboard" msgstr "Ulamek asekles n tecfawit" #: src/mainwindow.c:775 msgid "Zoom in" msgstr "" #: src/mainwindow.c:777 msgid "Zoom out" msgstr "" #: src/mainwindow.c:779 #, c-format msgid "10% zoom" msgstr "" #: src/mainwindow.c:781 #, c-format msgid "25% zoom" msgstr "" #: src/mainwindow.c:783 #, c-format msgid "50% zoom" msgstr "" #: src/mainwindow.c:785 #, c-format msgid "100% zoom" msgstr "" #: src/mainwindow.c:787 #, c-format msgid "400% zoom" msgstr "" #: src/mainwindow.c:789 #, c-format msgid "600% zoom" msgstr "" #: src/mainwindow.c:791 #, c-format msgid "800% zoom" msgstr "" #: src/mainwindow.c:793 #, c-format msgid "1000% zoom" msgstr "" #: src/mainwindow.c:795 #, c-format msgid "1200% zoom" msgstr "" #: src/mainwindow.c:797 #, c-format msgid "1600% zoom" msgstr "" #: src/mainwindow.c:799 #, c-format msgid "2000% zoom" msgstr "" #: src/mainwindow.c:801 #, c-format msgid "4000% zoom" msgstr "" #: src/mainwindow.c:803 #, c-format msgid "8000% zoom" msgstr "" #: src/mainwindow.c:805 #, c-format msgid "10% opacity" msgstr "" #: src/mainwindow.c:807 #, c-format msgid "20% opacity" msgstr "" #: src/mainwindow.c:809 #, c-format msgid "30% opacity" msgstr "" #: src/mainwindow.c:811 #, c-format msgid "40% opacity" msgstr "" #: src/mainwindow.c:813 #, c-format msgid "50% opacity" msgstr "" #: src/mainwindow.c:815 #, c-format msgid "60% opacity" msgstr "" #: src/mainwindow.c:817 #, c-format msgid "70% opacity" msgstr "" #: src/mainwindow.c:819 #, c-format msgid "80% opacity" msgstr "" #: src/mainwindow.c:821 #, c-format msgid "90% opacity" msgstr "" #: src/mainwindow.c:823 #, c-format msgid "100% opacity" msgstr "" #: src/mainwindow.c:825 msgid "Increase opacity" msgstr "" #: src/mainwindow.c:827 msgid "Decrease opacity" msgstr "" #: src/mainwindow.c:829 msgid "Draw open arrow head" msgstr "" #: src/mainwindow.c:831 msgid "Draw closed arrow head" msgstr "" #: src/mainwindow.c:833 msgid "Previous colour A" msgstr "" #: src/mainwindow.c:835 msgid "Next colour A" msgstr "" #: src/mainwindow.c:837 msgid "Previous colour B" msgstr "" #: src/mainwindow.c:839 msgid "Next colour B" msgstr "" #: src/mainwindow.c:841 msgid "Previous pattern" msgstr "" #: src/mainwindow.c:843 msgid "Next pattern" msgstr "" #: src/mainwindow.c:845 msgid "Larger brush" msgstr "" #: src/mainwindow.c:847 msgid "Smaller brush" msgstr "" #: src/mainwindow.c:849 msgid "View window - Zoom in" msgstr "" #: src/mainwindow.c:851 msgid "View window - Zoom out" msgstr "" #: src/mainwindow.c:1027 msgid "" "This canvas/palette contains changes that have not been saved. Do you " "really want to lose these changes?" msgstr "" #: src/mainwindow.c:1094 msgid "Do you really want to quit?" msgstr "D tidet tebÉ£iḠad teffÉ£eḠ?" #: src/mainwindow.c:3754 msgid "Empty string or broken quoting" msgstr "" #: src/mainwindow.c:3755 msgid "Script must begin with a command" msgstr "" #: src/mainwindow.c:3756 msgid "Script nesting limit exceeded" msgstr "" #: src/mainwindow.c:3765 #, c-format msgid "'%s' does not match any item" msgstr "" #: src/mainwindow.c:3767 #, c-format msgid "'%s' matches a non-scriptable item" msgstr "" #: src/mainwindow.c:3769 #, c-format msgid "'%s' matches a disabled item" msgstr "" #: src/mainwindow.c:3788 #, c-format msgid "'%s' value does not fit item" msgstr "" #: src/mainwindow.c:3969 msgid "Script" msgstr "" #: src/mainwindow.c:3982 src/spawn.c:656 src/spawn.c:662 msgid "Action" msgstr "Tigawt" #: src/mainwindow.c:3991 src/spawn.c:666 msgid "Execute" msgstr "Selkem" #: src/mainwindow.c:4045 msgid "Unable to load script" msgstr "" #: src/mainwindow.c:5182 msgid "/_File" msgstr "/Afaylu" #: src/mainwindow.c:5184 msgid "//New" msgstr "//Amaynut" #: src/mainwindow.c:5186 msgid "//Open ..." msgstr "//Ldi ..." #: src/mainwindow.c:5188 src/mainwindow.c:5669 msgid "//Save" msgstr "//Sekles" #: src/mainwindow.c:5190 src/mainwindow.c:5549 src/mainwindow.c:5627 #: src/mainwindow.c:5671 msgid "//Save As ..." msgstr "//Sekles am ..." #: src/mainwindow.c:5192 msgid "//Export Undo Images ..." msgstr "" #: src/mainwindow.c:5194 msgid "//Export Undo Images (reversed) ..." msgstr "" #: src/mainwindow.c:5196 msgid "//Export ASCII Art ..." msgstr "//SifeḠs umasal n tẓuri ASCII ..." #: src/mainwindow.c:5198 msgid "//Export Animated GIF ..." msgstr "//SifeḠasmussu n GIF ..." #: src/mainwindow.c:5201 msgid "//Actions" msgstr "//Tigawin" #: src/mainwindow.c:5235 src/mainwindow.c:5488 msgid "///Configure" msgstr "///Swel" #: src/mainwindow.c:5290 msgid "//Quit" msgstr "//FfeÉ£" #: src/mainwindow.c:5293 msgid "/_Edit" msgstr "//Ẓreg" #: src/mainwindow.c:5295 msgid "//Undo" msgstr "//Sefsex" #: src/mainwindow.c:5297 msgid "//Redo" msgstr "//Err-d" #: src/mainwindow.c:5300 msgid "//Cut" msgstr "//Gzem" #: src/mainwindow.c:5302 msgid "//Copy" msgstr "//NÉ£el" #: src/mainwindow.c:5304 msgid "//Copy To Palette" msgstr "//NÉ£el É£er tpaliá¸t" #: src/mainwindow.c:5306 msgid "//Paste To Centre" msgstr "//Sená¹­eḠdi tlemmast" #: src/mainwindow.c:5308 msgid "//Paste To New Layer" msgstr "//Sená¹­eḠam tissi tamaynutt" #: src/mainwindow.c:5310 msgid "//Paste" msgstr "//Sená¹­eá¸" #: src/mainwindow.c:5312 msgid "//Paste Text" msgstr "//Sená¹­eḠaá¸ris" #: src/mainwindow.c:5318 msgid "//Paste Text (FreeType)" msgstr "//Sená¹­eḠaá¸ris (FreeType)" #: src/mainwindow.c:5321 msgid "//Paste Palette" msgstr "//Sená¹­eḠtapaliá¸t" #: src/mainwindow.c:5323 msgid "//Load Clipboard" msgstr "//Sali-d tacfawit" #: src/mainwindow.c:5350 msgid "//Save Clipboard" msgstr "//Sekles tacfawit" #: src/mainwindow.c:5377 msgid "//Import Clipboard from System" msgstr "//Kter tacfawit seg unagraw" #: src/mainwindow.c:5378 msgid "//Export Clipboard to System" msgstr "//SifeḠtacfawit s anagraw" #: src/mainwindow.c:5381 msgid "//Choose Pattern ..." msgstr "//Fren udlif ..." #: src/mainwindow.c:5383 msgid "//Choose Brush ..." msgstr "//Fren amfezzu ..." #: src/mainwindow.c:5385 msgid "//Choose Colour ..." msgstr "//Fren ini ..." #: src/mainwindow.c:5392 msgid "/_View" msgstr "//TamuÉ£li" #: src/mainwindow.c:5394 msgid "//Show Main Toolbar" msgstr "//BeqqeḠafeggag n yifedka agejdan" #: src/mainwindow.c:5396 msgid "//Show Tools Toolbar" msgstr "//BeqqeḠafeggag n yifecka" #: src/mainwindow.c:5399 msgid "//Show Settings Toolbar" msgstr "//BeqqeḠafeggag n yiÉ£ewwaren" #: src/mainwindow.c:5402 msgid "//Show Dock" msgstr "" #: src/mainwindow.c:5404 msgid "//Show Palette" msgstr "//BeqqeḠtapaliá¸t" #: src/mainwindow.c:5406 msgid "//Show Status Bar" msgstr "//BeqqeḠafeggag n waddad" #: src/mainwindow.c:5409 msgid "//Toggle Image View" msgstr "" #: src/mainwindow.c:5413 msgid "//Centralize Image" msgstr "//Selmes tugna" #: src/mainwindow.c:5414 msgid "//Show Zoom Grid" msgstr "" #: src/mainwindow.c:5415 msgid "//Snap To Tile Grid" msgstr "" #: src/mainwindow.c:5417 msgid "//Configure Grid ..." msgstr "//Swel aferrug ..." #: src/mainwindow.c:5418 msgid "//Tracing Image ..." msgstr "" #: src/mainwindow.c:5421 msgid "//View Window" msgstr "//Asfaylu n tmuÉ£li" #: src/mainwindow.c:5423 msgid "//Horizontal Split" msgstr "" #: src/mainwindow.c:5425 msgid "//Focus View Window" msgstr "//Fren asfaylu n tmuÉ£li" #: src/mainwindow.c:5427 msgid "//Pan Window" msgstr "" #: src/mainwindow.c:5430 msgid "//Layers Window" msgstr "//Asfaylu n tissiyin" #: src/mainwindow.c:5433 msgid "/_Image" msgstr "/Tugna" #: src/mainwindow.c:5436 msgid "//Convert To RGB" msgstr "//Selket É£er RVB" #: src/mainwindow.c:5438 msgid "//Convert To Indexed ..." msgstr "" #: src/mainwindow.c:5441 msgid "//Scale Canvas ..." msgstr "//Beddel taskala n teÉ£zut n usuneÉ£ ..." #: src/mainwindow.c:5443 msgid "//Resize Canvas ..." msgstr "//Tiddi n tugna ..." #: src/mainwindow.c:5445 msgid "//Crop" msgstr "//Æ”eẓ" #: src/mainwindow.c:5448 src/mainwindow.c:5517 msgid "//Flip Vertically" msgstr "Tuzzya taratakt" #: src/mainwindow.c:5449 src/mainwindow.c:5519 msgid "//Flip Horizontally" msgstr "Tuzttya taglawant" #: src/mainwindow.c:5452 src/mainwindow.c:5521 msgid "//Rotate Clockwise" msgstr "Tuzzya yugdan tamrilt" #: src/mainwindow.c:5453 src/mainwindow.c:5523 msgid "//Rotate Anti-Clockwise" msgstr "//Tuzzya mgal tamrilt" #: src/mainwindow.c:5454 msgid "//Free Rotate ..." msgstr "//Tuzzya ..." #: src/mainwindow.c:5455 msgid "//Skew ..." msgstr "//Seknu ..." #: src/mainwindow.c:5458 msgid "//Segment ..." msgstr "//IÉ£il..." #: src/mainwindow.c:5462 msgid "//Script ..." msgstr "" #: src/mainwindow.c:5464 msgid "//Scripts" msgstr "" #: src/mainwindow.c:5491 msgid "//Information ..." msgstr "//TalÉ£ut..." #: src/mainwindow.c:5494 msgid "//Preferences ..." msgstr "//Ismenyifen..." #: src/mainwindow.c:5497 msgid "/_Selection" msgstr "/Tafrayt" #: src/mainwindow.c:5499 msgid "//Select All" msgstr "//Fren akk" #: src/mainwindow.c:5501 msgid "//Select None (Esc)" msgstr "" #: src/mainwindow.c:5503 msgid "//Lasso Selection" msgstr "" #: src/mainwindow.c:5505 msgid "//Lasso Selection Cut" msgstr "" #: src/mainwindow.c:5508 msgid "//Outline Selection" msgstr "//SuneÉ£ azizdew n tefrayt" #: src/mainwindow.c:5510 msgid "//Fill Selection" msgstr "//AÄÄar tafrayt" #: src/mainwindow.c:5512 msgid "//Outline Ellipse" msgstr "//SuneÉ£ taglayt" #: src/mainwindow.c:5514 msgid "//Fill Ellipse" msgstr "" #: src/mainwindow.c:5526 msgid "//Horizontal Ramp" msgstr "" #: src/mainwindow.c:5528 msgid "//Vertical Ramp" msgstr "" #: src/mainwindow.c:5531 msgid "//Alpha Blend A,B" msgstr "" #: src/mainwindow.c:5533 msgid "//Move Alpha to Mask" msgstr "" #: src/mainwindow.c:5535 msgid "//Mask Colour A,B" msgstr "" #: src/mainwindow.c:5537 msgid "//Unmask Colour A,B" msgstr "" #: src/mainwindow.c:5539 msgid "//Mask All Colours" msgstr "//Ferr akk initen" #: src/mainwindow.c:5541 msgid "//Clear Mask" msgstr "//SfeḠtagelmust" #: src/mainwindow.c:5544 msgid "/_Palette" msgstr "/Ta_paliá¸t" #: src/mainwindow.c:5548 src/mainwindow.c:5626 msgid "//Load ..." msgstr "//Sali-d ..." #: src/mainwindow.c:5550 msgid "//Load Default" msgstr "//Sali-d lexá¹£as" #: src/mainwindow.c:5552 msgid "//Mask All" msgstr "//Ffer akk" #: src/mainwindow.c:5553 msgid "//Mask None" msgstr "//Ulac tagelmust" #: src/mainwindow.c:5555 msgid "//Swap A & B" msgstr "//Semmeskel A & B" #: src/mainwindow.c:5557 msgid "//Edit Colour A & B ..." msgstr "//Ẓreg ini A & B ..." #: src/mainwindow.c:5559 msgid "//Dither A" msgstr "" #: src/mainwindow.c:5561 msgid "//Palette Editor ..." msgstr "//Amaẓrag n tpaliá¸t ..." #: src/mainwindow.c:5563 msgid "//Set Palette Size ..." msgstr "//Sbadu tiddi n tpaliá¸t ..." #: src/mainwindow.c:5564 msgid "//Merge Duplicate Colours" msgstr "//Smezdi initen usligen" #: src/mainwindow.c:5566 msgid "//Remove Unused Colours" msgstr "//Kkes initen ur nettwaseqdec ara" #: src/mainwindow.c:5569 msgid "//Create Quantized ..." msgstr "" #: src/mainwindow.c:5572 msgid "//Sort Colours ..." msgstr "//Fren initen ..." #: src/mainwindow.c:5573 msgid "//Palette Shifter ..." msgstr "" #: src/mainwindow.c:5574 msgid "//Pick Gradient ..." msgstr "//Fren afesnaw..." #: src/mainwindow.c:5576 msgid "/Effe_cts" msgstr "/Ise_mda" #: src/mainwindow.c:5578 msgid "//Transform Colour ..." msgstr "//Beddel initen ..." #: src/mainwindow.c:5580 msgid "//Invert" msgstr "//Tti" #: src/mainwindow.c:5582 msgid "//Greyscale" msgstr "//Iswiren n umelliÉ£di" #: src/mainwindow.c:5584 msgid "//Greyscale (Gamma corrected)" msgstr "//Iswiren n umelliÉ£di (aseÉ£ti n gama)" #: src/mainwindow.c:5586 msgid "//Normalize" msgstr "" #: src/mainwindow.c:5587 src/mainwindow.c:5658 msgid "//Threshold ..." msgstr "//Amnar ..." #: src/mainwindow.c:5588 msgid "//Map ..." msgstr "" #: src/mainwindow.c:5590 msgid "//Isometric Transformation" msgstr "" #: src/mainwindow.c:5592 msgid "///Left Side Down" msgstr "" #: src/mainwindow.c:5593 msgid "///Right Side Down" msgstr "" #: src/mainwindow.c:5594 msgid "///Top Side Right" msgstr "" #: src/mainwindow.c:5595 msgid "///Bottom Side Right" msgstr "" #: src/mainwindow.c:5598 msgid "//Edge Detect ..." msgstr "//Tifin n yiran ..." #: src/mainwindow.c:5600 msgid "//Difference of Gaussians ..." msgstr "" #: src/mainwindow.c:5602 msgid "//Sharpen ..." msgstr "" #: src/mainwindow.c:5604 msgid "//Unsharp Mask ..." msgstr "" #: src/mainwindow.c:5606 msgid "//Soften ..." msgstr "//SilweÉ£ ..." #: src/mainwindow.c:5608 msgid "//Gaussian Blur ..." msgstr "//AluÉ£u n Gauss ..." #: src/mainwindow.c:5610 msgid "//Kuwahara-Nagao Blur ..." msgstr "//AluÉ£u n Kuwahara-Nagao ..." #: src/mainwindow.c:5612 msgid "//Emboss" msgstr "//Eg tiÉ›nurin" #: src/mainwindow.c:5614 msgid "//Dilate" msgstr "//Ḍleq" #: src/mainwindow.c:5616 msgid "//Erode" msgstr "" #: src/mainwindow.c:5619 msgid "//Solid Noise ..." msgstr "" #: src/mainwindow.c:5620 msgid "//Bacteria ..." msgstr "//Tibaktiriyin ..." #: src/mainwindow.c:5623 msgid "/Cha_nnels" msgstr "/Ibuda" #: src/mainwindow.c:5625 msgid "//New ..." msgstr "//Amaynut..." #: src/mainwindow.c:5628 msgid "//Delete ..." msgstr "//Kkes..." #: src/mainwindow.c:5632 msgid "//Edit Image" msgstr "//Ẓreg tugna" #: src/mainwindow.c:5635 msgid "//Edit Alpha" msgstr "//Ẓreg alfa" #: src/mainwindow.c:5638 msgid "//Edit Selection" msgstr "//Ẓreg tafrayt" #: src/mainwindow.c:5641 msgid "//Edit Mask" msgstr "//Ẓreg tagelmust" #: src/mainwindow.c:5645 msgid "//Hide Image" msgstr "//Ffer tugna" #: src/mainwindow.c:5648 msgid "//Disable Alpha" msgstr "//Sens alfa" #: src/mainwindow.c:5651 msgid "//Disable Selection" msgstr "//Sens tafrayt" #: src/mainwindow.c:5654 msgid "//Disable Mask" msgstr "//Sens tafrayt" #: src/mainwindow.c:5657 msgid "//Couple RGBA Operations" msgstr "" #: src/mainwindow.c:5659 msgid "//Unassociate Alpha" msgstr "" #: src/mainwindow.c:5663 msgid "//View Alpha as an Overlay" msgstr "" #: src/mainwindow.c:5664 msgid "//Configure Overlays ..." msgstr "" #: src/mainwindow.c:5666 msgid "/_Layers" msgstr "/Tissiyin" #: src/mainwindow.c:5668 msgid "//New Layer" msgstr "//Tissi tamaynutt" #: src/mainwindow.c:5672 msgid "//Save Composite Image ..." msgstr "//Sekles tugna tuddist ..." #: src/mainwindow.c:5673 msgid "//Composite to New Layer" msgstr "" #: src/mainwindow.c:5674 msgid "//Remove All Layers" msgstr "//Kkes akk tissiyin" #: src/mainwindow.c:5676 msgid "//Configure Animation ..." msgstr "//Swel asmussu..." #: src/mainwindow.c:5677 msgid "//Preview Animation ..." msgstr "//TamuÉ£li n usmusu ..." #: src/mainwindow.c:5678 msgid "//Set Key Frame ..." msgstr "//Sbadu tasarut n ukatar ..." #: src/mainwindow.c:5679 msgid "//Remove All Key Frames ..." msgstr "//Kkes akk tisura n yikataren ..." #: src/mainwindow.c:5681 msgid "/More..." msgstr "/Ugar..." #: src/mainwindow.c:5683 msgid "/_Help" msgstr "/Tallelt" #: src/mainwindow.c:5684 msgid "//Documentation" msgstr "//Tasemlit" #: src/mainwindow.c:5686 msgid "//About" msgstr "//Æ”ef" #: src/mainwindow.c:5689 msgid "//Keyboard Shortcuts ..." msgstr "" #: src/mainwindow.c:5690 msgid "//Rebind Shortcut Keycodes" msgstr "" #: src/memory.c:2800 msgid "Quantize Pass 1" msgstr "" #: src/memory.c:2854 msgid "Quantize Pass 2" msgstr "" #: src/memory.c:3073 src/memory.c:3458 msgid "Converting to Indexed Palette" msgstr "" #: src/memory.c:5135 src/otherwindow.c:540 msgid "Bacteria Effect" msgstr "Asemdu n tbaktiriyin" #: src/memory.c:5170 msgid "Rotating" msgstr "Tuzzya" #: src/memory.c:5511 msgid "Free Rotation" msgstr "Tuzzya tilellit" #: src/memory.c:6096 msgid "Scaling Image" msgstr "Beddel taskala n tugna" #: src/memory.c:7560 msgid "Counting Unique RGB Pixels" msgstr "" #: src/memory.c:7608 msgid "Applying Effect" msgstr "Asnes n usemdu" #: src/memory.c:8792 msgid "Kuwahara-Nagao Filter" msgstr "Tastayt Kuwahara-Nagao" #: src/memory.c:10456 src/otherwindow.c:2665 msgid "Skew" msgstr "Seknu" #: src/memory.c:10630 msgid "Segmentation Pass 1" msgstr "" #: src/memory.c:10757 msgid "Segmentation Pass 2" msgstr "" #: src/memory.c:11019 src/otherwindow.c:3156 msgid "Solid Noise" msgstr "" #: src/mygtk.c:134 src/mygtk.c:163 msgid "Please Wait ..." msgstr "Ttxil-k m arǧu ..." #: src/mygtk.c:141 msgid "STOP" msgstr "Ḥbes" #: src/mygtk.c:504 msgid "Disabled" msgstr "" #: src/mygtk.c:504 src/toolbar.c:301 msgid "Screen" msgstr "Agdil" #: src/mygtk.c:504 msgid "Window" msgstr "" #: src/mygtk.c:508 msgid "Input" msgstr "" #: src/mygtk.c:512 msgid "Device:" msgstr "" #: src/mygtk.c:514 msgid "Mode:" msgstr "" #: src/mygtk.c:519 msgid "Axes" msgstr "" #: src/mygtk.c:524 msgid "X:" msgstr "" #: src/mygtk.c:525 msgid "Y:" msgstr "" #: src/mygtk.c:526 msgid "Pressure:" msgstr "" #: src/mygtk.c:527 msgid "X tilt:" msgstr "" #: src/mygtk.c:528 msgid "Y tilt:" msgstr "" #: src/mygtk.c:529 msgid "Wheel:" msgstr "" #: src/mygtk.c:579 msgid "none" msgstr "" #: src/otherwindow.c:236 msgid "24 bit RGB" msgstr "RGB 24 ibiten" #: src/otherwindow.c:236 src/otherwindow.c:3179 msgid "Greyscale" msgstr "Iswiren n umelliÉ£di" #: src/otherwindow.c:237 msgid "Indexed Palette" msgstr "" #: src/otherwindow.c:237 msgid "From Clipboard" msgstr "Si tecfawit" #: src/otherwindow.c:237 msgid "Grab Screenshot" msgstr "" #: src/otherwindow.c:242 src/toolbar.c:542 msgid "New Image" msgstr "Tugna tamaynutt" #: src/otherwindow.c:246 src/otherwindow.c:3164 msgid "Colours" msgstr "Initen" #: src/otherwindow.c:409 msgid "Pattern Chooser" msgstr "Amefran n wudlifen" #: src/otherwindow.c:497 msgid "Set Palette Size" msgstr "Sbadu tiddi n tpaliá¸t" #: src/otherwindow.c:517 src/otherwindow.c:591 src/otherwindow.c:870 #: src/otherwindow.c:2538 src/otherwindow.c:2776 src/otherwindow.c:2939 #: src/prefs.c:338 src/prefs.c:538 msgid "Apply" msgstr "Snes" #: src/otherwindow.c:573 msgid "Luminance" msgstr "Tifawit" #: src/otherwindow.c:573 src/otherwindow.c:814 msgid "Brightness" msgstr "Tifawit" #: src/otherwindow.c:574 msgid "Distance to A" msgstr "" #: src/otherwindow.c:575 msgid "Projection to A->B" msgstr "" #: src/otherwindow.c:576 msgid "Frequency" msgstr "Asnagar" #: src/otherwindow.c:580 msgid "Sort Palette Colours" msgstr "Smizzwer initen n tpaliá¸t" #: src/otherwindow.c:582 msgid "Start Index" msgstr "Amatar n tazwara" #: src/otherwindow.c:583 msgid "End Index" msgstr "Amatar n taggara" #: src/otherwindow.c:589 msgid "Reverse Order" msgstr "Tti asmizzwer" #: src/otherwindow.c:805 msgid "Bitwise" msgstr "" #: src/otherwindow.c:805 msgid "Truncated" msgstr "" #: src/otherwindow.c:805 msgid "Rounded" msgstr "Imdewwer" #: src/otherwindow.c:809 src/toolbar.c:311 src/toolbar.c:558 msgid "Transform Colour" msgstr "Beddel initen" #: src/otherwindow.c:812 msgid "Gamma" msgstr "Gama" #: src/otherwindow.c:816 msgid "Contrast" msgstr "Amyeẓli" #: src/otherwindow.c:822 src/otherwindow.c:1674 msgid "Posterize" msgstr "" #: src/otherwindow.c:831 msgid "Show Detail" msgstr "BeqqeḠtalqayt" #: src/otherwindow.c:836 msgid "Posterize type" msgstr "" #: src/otherwindow.c:857 msgid "Auto-Preview" msgstr "TamuÉ£li tawurmant" #: src/otherwindow.c:869 msgid "Reset" msgstr "Ales awennez" #: src/otherwindow.c:931 msgid "New geometry is the same as now - nothing to do." msgstr "" #: src/otherwindow.c:980 msgid "The operating system cannot allocate the memory for this operation." msgstr "Anagraw n wammud ur yezmir ad iḥerri takatut i temhelt-agi." #: src/otherwindow.c:982 msgid "" "You have not allocated enough memory in the Preferences window for this " "operation." msgstr "Ur tḥeṛṛaḠara ddeqs n tkatut i temhelt-agi deg usfaylu n yismenyifen." #: src/otherwindow.c:993 src/otherwindow.c:2495 msgid "Mirror" msgstr "" #: src/otherwindow.c:993 src/otherwindow.c:994 msgid "Tile" msgstr "" #: src/otherwindow.c:993 msgid "Void" msgstr "Ilem" #: src/otherwindow.c:994 src/shifter.c:283 msgid "Clear" msgstr "Sfeá¸" #: src/otherwindow.c:994 msgid "Mirror tile" msgstr "" #: src/otherwindow.c:996 msgid "Nearest Neighbour" msgstr "Anarag iqerben aá¹­as" #: src/otherwindow.c:997 msgid "Bilinear / Area Mapping" msgstr "" #: src/otherwindow.c:998 msgid "Bicubic" msgstr "" #: src/otherwindow.c:999 msgid "Bicubic edged" msgstr "" #: src/otherwindow.c:1000 msgid "Bicubic better" msgstr "" #: src/otherwindow.c:1001 msgid "Bicubic sharper" msgstr "" #: src/otherwindow.c:1002 msgid "Blackman-Harris" msgstr "" #: src/otherwindow.c:1008 msgid "Scale Canvas" msgstr "Beddel taskala n teÉ£zut n usuneÉ£" #: src/otherwindow.c:1009 msgid "Resize Canvas" msgstr "Beddel tiddi n teÉ£zut n usuneÉ£" #: src/otherwindow.c:1012 msgid "Original " msgstr "Tazwara " #: src/otherwindow.c:1013 msgid "New" msgstr "Amaynut" #: src/otherwindow.c:1014 msgid "Width " msgstr "Tehri " #: src/otherwindow.c:1018 msgid "Height " msgstr "TeÉ£zi " #: src/otherwindow.c:1023 src/otherwindow.c:2514 src/otherwindow.c:2672 #: src/toolbar.c:212 msgid "Offset" msgstr "" #: src/otherwindow.c:1026 src/otherwindow.c:1615 src/viewer.c:1209 msgid "Centre" msgstr "" #: src/otherwindow.c:1033 src/otherwindow.c:1052 msgid "Fix Aspect Ratio" msgstr "Ḥrez assaÉ£ n tmeẓri" #: src/otherwindow.c:1039 src/otherwindow.c:2070 src/toolbar.c:312 msgid "Settings" msgstr "IÉ£ewwaren" #: src/otherwindow.c:1046 msgid "Sharper image reduction" msgstr "" #: src/otherwindow.c:1047 msgid "Boundary extension" msgstr "" #: src/otherwindow.c:1613 src/otherwindow.c:2302 msgid "HSV" msgstr "HSV" #: src/otherwindow.c:1614 msgid "Highlight" msgstr "" #: src/otherwindow.c:1615 msgid "Limit" msgstr "" #: src/otherwindow.c:1616 msgid "Sphere" msgstr "Takurt" #: src/otherwindow.c:1616 src/otherwindow.c:2670 msgid "Angle" msgstr "TiÉ£mert" #: src/otherwindow.c:1616 msgid "Cube" msgstr "Agasas" #: src/otherwindow.c:1617 msgid "Opaque" msgstr "Imá¸ulles" #: src/otherwindow.c:1617 msgid "Border" msgstr "Iri" #: src/otherwindow.c:1618 msgid "Transparent" msgstr "Afrawan" #: src/otherwindow.c:1618 msgid "Tile " msgstr "" #: src/otherwindow.c:1618 msgid "Segment" msgstr "IÉ£il" #: src/otherwindow.c:1656 msgid "Scale" msgstr "Taskala" #: src/otherwindow.c:1657 src/otherwindow.c:3059 msgid "From" msgstr "Seg" #: src/otherwindow.c:1659 src/otherwindow.c:3061 msgid "To" msgstr "" #: src/otherwindow.c:1699 msgid "Range" msgstr "Tagrumma" #: src/otherwindow.c:1702 msgid "Inverse" msgstr "Tti" #: src/otherwindow.c:1710 msgid "Smart grid" msgstr "" #: src/otherwindow.c:1712 msgid "Tile grid" msgstr "" #: src/otherwindow.c:1714 msgid "Minimum grid zoom" msgstr "" #: src/otherwindow.c:1717 msgid "Tile width" msgstr "" #: src/otherwindow.c:1720 msgid "Tile height" msgstr "" #: src/otherwindow.c:1744 msgid "Palette Editor" msgstr "Amaẓrag n tpaliá¸t" #: src/otherwindow.c:1763 msgid "Configure Overlays" msgstr "" #: src/otherwindow.c:1782 msgid "Colour Editor" msgstr "Amaẓrag n yiniten" #: src/otherwindow.c:1818 src/toolbar.c:430 msgid "Colour-Selective Mode" msgstr "" #: src/otherwindow.c:1843 msgid "Configure Grid" msgstr "Swel taferrugt" #: src/otherwindow.c:2045 msgid "Exact Conversion" msgstr "" #: src/otherwindow.c:2045 msgid "Use Current Palette" msgstr "Seqdec tapaliá¸t tamirant" #: src/otherwindow.c:2046 msgid "PNN Quantize (slow, better quality)" msgstr "" #: src/otherwindow.c:2047 msgid "Wu Quantize (fast)" msgstr "" #: src/otherwindow.c:2048 msgid "Max-Min Quantize (best for small palettes and dithering)" msgstr "" #: src/otherwindow.c:2049 src/otherwindow.c:2495 src/otherwindow.c:2756 #: src/png.c:2794 src/prefs.c:377 msgid "None" msgstr "Ulac" #: src/otherwindow.c:2049 msgid "Floyd-Steinberg" msgstr "" #: src/otherwindow.c:2049 msgid "Stucki" msgstr "" #: src/otherwindow.c:2052 msgid "Floyd-Steinberg (quick)" msgstr "" #: src/otherwindow.c:2052 msgid "Dithered (effect)" msgstr "" #: src/otherwindow.c:2053 msgid "Scattered (effect)" msgstr "" #: src/otherwindow.c:2054 msgid "Gamut" msgstr "" #: src/otherwindow.c:2054 msgid "Weakly" msgstr "" #: src/otherwindow.c:2054 msgid "Strongly" msgstr "" #: src/otherwindow.c:2055 msgid "Off" msgstr "Yensa" #: src/otherwindow.c:2055 msgid "Separate/Sum" msgstr "" #: src/otherwindow.c:2055 msgid "Separate/Split" msgstr "" #: src/otherwindow.c:2056 msgid "Length/Sum" msgstr "" #: src/otherwindow.c:2056 msgid "Length/Split" msgstr "" #: src/otherwindow.c:2057 msgid "Largest (Linf)" msgstr "Ahrawan maá¸i (Linf)" #: src/otherwindow.c:2057 msgid "Sum (L1)" msgstr "" #: src/otherwindow.c:2057 msgid "Euclidean (L2)" msgstr "" #: src/otherwindow.c:2061 msgid "Create Quantized" msgstr "" #: src/otherwindow.c:2062 msgid "Convert To Indexed" msgstr "" #: src/otherwindow.c:2065 msgid "Indexed Colours To Use" msgstr "" #: src/otherwindow.c:2078 msgid "Truncate palette" msgstr "" #: src/otherwindow.c:2079 msgid "Diameter based weighting" msgstr "" #: src/otherwindow.c:2084 msgid "Dither" msgstr "" #: src/otherwindow.c:2087 src/otherwindow.c:2584 src/otherwindow.c:2928 msgid "Colour space" msgstr "Tallunt n yiniten" #: src/otherwindow.c:2088 src/otherwindow.c:2929 msgid "Difference measure" msgstr "" #: src/otherwindow.c:2089 msgid "Reduce colour bleed" msgstr "" #: src/otherwindow.c:2090 msgid "Serpentine scan" msgstr "" #: src/otherwindow.c:2092 msgid "Error propagation, %" msgstr "" #: src/otherwindow.c:2093 msgid "Selective error propagation" msgstr "" #: src/otherwindow.c:2097 msgid "Full error precision" msgstr "" #: src/otherwindow.c:2302 msgid "Backward HSV" msgstr "" #: src/otherwindow.c:2303 src/otherwindow.c:2326 msgid "Constant" msgstr "Timezgit" #: src/otherwindow.c:2307 msgid "Edit Gradient" msgstr "Ẓreg afesnaw" #: src/otherwindow.c:2329 msgid "Points:" msgstr "Tinqiá¸in:" #: src/otherwindow.c:2493 msgid "Linear" msgstr "Imzirig" #: src/otherwindow.c:2493 src/otherwindow.c:2703 msgid "Bilinear" msgstr "" #: src/otherwindow.c:2493 msgid "Radial" msgstr "" #: src/otherwindow.c:2494 msgid "Square" msgstr "Amkuẓ" #: src/otherwindow.c:2494 msgid "Angular" msgstr "UÉ£mir" #: src/otherwindow.c:2494 msgid "Conical" msgstr "" #: src/otherwindow.c:2495 msgid "Level " msgstr "" #: src/otherwindow.c:2495 msgid "Repeat" msgstr "Ales" #: src/otherwindow.c:2496 msgid "A to B" msgstr "A É£er B" #: src/otherwindow.c:2496 msgid "A to B (RGB)" msgstr "A É£er B (RGB)" #: src/otherwindow.c:2497 msgid "A to B (sRGB)" msgstr "A É£er B (sRGB)" #: src/otherwindow.c:2497 msgid "A to B (HSV)" msgstr "A É£er B (TSV)" #: src/otherwindow.c:2497 msgid "A to B (backward HSV)" msgstr "" #: src/otherwindow.c:2498 msgid "A only" msgstr "" #: src/otherwindow.c:2498 src/otherwindow.c:2500 msgid "Custom" msgstr "Udmawan" #: src/otherwindow.c:2499 msgid "Current to 0" msgstr "" #: src/otherwindow.c:2499 msgid "Current only" msgstr "Amiran kan" #: src/otherwindow.c:2504 msgid "Configure Gradient" msgstr "Swel afesnaw" #: src/otherwindow.c:2507 src/png.c:1001 msgid "Channel" msgstr "Abadu" #: src/otherwindow.c:2512 msgid "Length" msgstr "TeÉ£zi" #: src/otherwindow.c:2513 msgid "Repeat length" msgstr "" #: src/otherwindow.c:2515 msgid "Gradient type" msgstr "Anaw n ufesnaw" #: src/otherwindow.c:2516 msgid "Extension type" msgstr "Anaw n ufesnaw" #: src/otherwindow.c:2517 msgid "Distance type" msgstr "" #: src/otherwindow.c:2518 msgid "Preview opacity" msgstr "Tiá¸ullest n tmuÉ£li" #: src/otherwindow.c:2527 src/otherwindow.c:2533 src/toolbar.c:309 msgid "Reverse" msgstr "Tti" #: src/otherwindow.c:2528 src/otherwindow.c:2534 msgid "Edit Custom" msgstr "Asiẓreg yugnen" #: src/otherwindow.c:2592 msgid "Pick Gradient" msgstr "Fren afesnaw" #: src/otherwindow.c:2668 msgid "Horizontal " msgstr "Aglawan " #: src/otherwindow.c:2674 msgid "At distance" msgstr "" #: src/otherwindow.c:2675 msgid "Vertical" msgstr "Ubdid" #: src/otherwindow.c:2756 msgid "Unchanged" msgstr "" #: src/otherwindow.c:2761 msgid "Tracing Image" msgstr "" #: src/otherwindow.c:2763 src/toolbar.c:315 msgid "Source" msgstr "AÉ£balu" #: src/otherwindow.c:2768 msgid "Origin" msgstr "" #: src/otherwindow.c:2771 msgid "Relative scale" msgstr "" #: src/otherwindow.c:2774 msgid "Display" msgstr "Beqqeá¸" #: src/otherwindow.c:2926 msgid "Segment Image" msgstr "" #: src/otherwindow.c:2931 src/toolbar.c:304 msgid "Threshold" msgstr "Amnar" #: src/otherwindow.c:2933 msgid "Level" msgstr "Aswir" #: src/otherwindow.c:2934 msgid "Minimum size" msgstr "Tiddi taddayt" #: src/otherwindow.c:3053 msgid "Max" msgstr "" #: src/otherwindow.c:3053 msgid "Min" msgstr "" #: src/otherwindow.c:3057 msgid "Threshold Image" msgstr "" #: src/otherwindow.c:3158 msgid "Seed" msgstr "" #: src/otherwindow.c:3160 msgid "X span" msgstr "" #: src/otherwindow.c:3161 msgid "Y span" msgstr "" #: src/otherwindow.c:3162 msgid "Octaves" msgstr "" #: src/png.c:620 #, c-format msgid "Saving %s image" msgstr "Asekles n tugna %s" #: src/png.c:620 #, c-format msgid "Loading %s image" msgstr "Asali n tugna %s" #: src/png.c:998 msgid "Layer" msgstr "Tissi" #: src/png.c:3577 msgid "Lossless" msgstr "" #: src/png.c:3577 msgid "Default" msgstr "" #: src/png.c:3577 msgid "Picture" msgstr "" #: src/png.c:3577 msgid "Photo" msgstr "" #: src/png.c:3578 msgid "Drawing" msgstr "" #: src/png.c:3578 msgid "Icon" msgstr "" #: src/png.c:8370 msgid "Applying colour profile" msgstr "Asnes n ulegdis n yini" #: src/png.c:8792 #, c-format msgid "%d out of %d frames could not be saved as %s - saved as PNG instead" msgstr "" #: src/png.c:8809 msgid "Explode frames" msgstr "" #: src/prefs.c:56 msgid "Default System Language" msgstr "Tutlayt n lexá¹£as n unagraw" #: src/prefs.c:57 msgid "Chinese (Simplified)" msgstr "Tacinwat (taḥerfit)" #: src/prefs.c:57 msgid "Chinese (Taiwanese)" msgstr "Tacinwat (Taá¹­aywanit)" #: src/prefs.c:57 msgid "Czech" msgstr "TaÄikit" #: src/prefs.c:58 msgid "Dutch" msgstr "Tahulandit" #: src/prefs.c:58 msgid "English (UK)" msgstr "Taglizit (Tagelda yedduklen)" #: src/prefs.c:58 msgid "French" msgstr "Tafransist" #: src/prefs.c:58 msgid "Galician" msgstr "Tagalikant" #: src/prefs.c:58 msgid "German" msgstr "Talmanit" #: src/prefs.c:59 msgid "Hungarian" msgstr "Tahungarit" #: src/prefs.c:59 msgid "Italian" msgstr "Taá¹­elyanit" #: src/prefs.c:59 msgid "Japanese" msgstr "Tajapunit" #: src/prefs.c:59 msgid "Kabyle" msgstr "" #: src/prefs.c:59 msgid "Polish" msgstr "Tapulunit" #: src/prefs.c:60 msgid "Portuguese" msgstr "Tapurtugit" #: src/prefs.c:60 msgid "Portuguese (Brazilian)" msgstr "Tapurtugalit (Brizil)" #: src/prefs.c:60 msgid "Russian" msgstr "Tarusit" #: src/prefs.c:60 msgid "Slovak" msgstr "Tasluvakit" #: src/prefs.c:61 msgid "Spanish" msgstr "Taspenyulit" #: src/prefs.c:61 msgid "Swedish" msgstr "Taswidit" #: src/prefs.c:61 msgid "Tagalog" msgstr "Taá¹­agalugt" #: src/prefs.c:61 msgid "Turkish" msgstr "Taá¹­urkit" #: src/prefs.c:81 msgid "Current Device" msgstr "Ibenk amiran" #: src/prefs.c:135 msgid "Pressure" msgstr "" #: src/prefs.c:149 msgid "Preferences" msgstr "Isemenyifen" #: src/prefs.c:163 msgid "Max threads (0 to autodetect)" msgstr "" #: src/prefs.c:164 msgid "Min kpixels per render thread" msgstr "" #: src/prefs.c:171 msgid "Max memory used for undo (MB)" msgstr "" #: src/prefs.c:172 msgid "Max undo levels" msgstr "" #: src/prefs.c:173 msgid "Communal layer undo space (%)" msgstr "" #: src/prefs.c:175 msgid "Bayer master pattern" msgstr "" #: src/prefs.c:178 msgid "Use gamma correction by default" msgstr "" #: src/prefs.c:179 msgid "Use gamma correction when painting" msgstr "" #: src/prefs.c:180 msgid "Separate patterns for A & B" msgstr "" #: src/prefs.c:183 msgid "Optimize alpha chequers" msgstr "" #: src/prefs.c:184 msgid "Disable view window transparencies" msgstr "" #: src/prefs.c:185 msgid "Enable overlays by layer" msgstr "" #: src/prefs.c:189 msgid "Language" msgstr "Tutlayt" #: src/prefs.c:191 msgid "" "Select preferred language translation\n" "\n" "You will need to restart mtPaint\n" "for this to take full effect" msgstr "" "Fren tutlayt n ugrudem\n" "\n" "Isefk ad talseḠasekker n mtPaint\n" "akken ad yeddu wayagi" #: src/prefs.c:198 msgid "Interface" msgstr "Agrudem" #: src/prefs.c:200 msgid "Greyscale backdrop" msgstr "Iswiren n umelliÉ£di" #: src/prefs.c:201 msgid "Selection nudge pixels" msgstr "" #: src/prefs.c:202 msgid "Max Pan Window Size" msgstr "" #: src/prefs.c:204 msgid "Display clipboard while pasting" msgstr "BeqqeḠtacfawit deg usená¹­eá¸" #: src/prefs.c:205 msgid "Mouse cursor = Tool" msgstr "Taḥnaccaá¸t n umumed = Afecku" #: src/prefs.c:206 msgid "Confirm Exit" msgstr "Sentem tuffÉ£a" #: src/prefs.c:207 msgid "Q key quits mtPaint" msgstr "Taqeffalt Q tessufuÉ£ si mtPaint" #: src/prefs.c:208 msgid "Arrow keys scroll canvas" msgstr "" #: src/prefs.c:209 msgid "Changing tool commits paste" msgstr "" #: src/prefs.c:210 msgid "Centre tool settings dialogs" msgstr "" #: src/prefs.c:211 msgid "New image sets zoom to 100%" msgstr "" #: src/prefs.c:212 msgid "Zoom on cursor position" msgstr "" #: src/prefs.c:214 msgid "Mouse Scroll Wheel = Zoom" msgstr "" #: src/prefs.c:215 msgid "Use menu icons" msgstr "Seqdec tignitin n wumuÉ£" #: src/prefs.c:220 msgid "Files" msgstr "Ifuyla" #: src/prefs.c:223 msgid "XBM X hotspot" msgstr "" #: src/prefs.c:224 msgid "XBM Y hotspot" msgstr "" #: src/prefs.c:228 msgid "Recently Used Files" msgstr "Ifuyla yettwasqedcen melmi kan" #: src/prefs.c:229 msgid "Progress bar silence limit" msgstr "" #: src/prefs.c:232 msgid "Read 16-bit TGAs as 5:6:5 BGR" msgstr "" #: src/prefs.c:233 msgid "Write TGAs in bottom-up row order" msgstr "" #: src/prefs.c:234 msgid "Undoable image loading" msgstr "" #: src/prefs.c:245 msgid "Compression (RGB)" msgstr "" #: src/prefs.c:246 msgid "Compression (indexed)" msgstr "" #: src/prefs.c:247 msgid "Compression (monochrome)" msgstr "" #: src/prefs.c:255 msgid "Enable predictor" msgstr "" #: src/prefs.c:262 msgid "Compression mode" msgstr "" #: src/prefs.c:271 msgid "Channel for Mask Plane" msgstr "" #: src/prefs.c:273 msgid "Ignore Transparent Colour" msgstr "" #: src/prefs.c:274 msgid "PackBits Compression" msgstr "" #: src/prefs.c:275 msgid "Write Indexed as Planar Bitmap (PBM)" msgstr "" #: src/prefs.c:280 msgid "Paths" msgstr "Iberdan" #: src/prefs.c:281 msgid "Clipboard Files" msgstr "Ifuyla n tecfawit" #: src/prefs.c:281 msgid "Select Clipboard File" msgstr "Fren afaylu n tecfawit" #: src/prefs.c:283 msgid "HTML Browser Program" msgstr "Iminig HTML" #: src/prefs.c:283 msgid "Select Browser Program" msgstr "Fren iminig" #: src/prefs.c:285 msgid "Location of Handbook index" msgstr "" #: src/prefs.c:285 msgid "Select Handbook Index File" msgstr "" #: src/prefs.c:287 msgid "Default Palette" msgstr "Tapaliá¸t n lexá¹£as" #: src/prefs.c:287 msgid "Select Default Palette" msgstr "Fren tapaliá¸t n lexá¹£as" #: src/prefs.c:289 msgid "Default Patterns" msgstr "Udlifen n lexá¹£as" #: src/prefs.c:289 msgid "Select Default Patterns File" msgstr "Fren afaylu n wudlifen n lexá¹£as" #: src/prefs.c:292 msgid "Default CSS" msgstr "" #: src/prefs.c:292 msgid "Select Default CSS File" msgstr "" #: src/prefs.c:295 msgid "Default Theme" msgstr "Asentel n lexá¹£as" #: src/prefs.c:295 msgid "Select Default Theme File" msgstr "Fren afaylu n usentel n lexá¹£as" #: src/prefs.c:300 msgid "Status Bar" msgstr "Afeggag n waddad" #: src/prefs.c:301 msgid "Canvas Geometry" msgstr "" #: src/prefs.c:302 msgid "Cursor X,Y" msgstr "Taḥnaccaá¸t X,Y" #: src/prefs.c:303 msgid "Pixel [I] {RGB}" msgstr "Apiksel [I] {RGB}" #: src/prefs.c:304 msgid "Selection Geometry" msgstr "Tisekta n tefrayt" #: src/prefs.c:305 msgid "Undo / Redo" msgstr "Sefsex / Err-d" #: src/prefs.c:308 msgid "Tablet" msgstr "Tafelwit" #: src/prefs.c:309 msgid "Device Settings" msgstr "IÉ£ewwaren n yibenk" #: src/prefs.c:313 msgid "Configure Device" msgstr "Swel ibenk" #: src/prefs.c:319 msgid "Tool Variable" msgstr "" #: src/prefs.c:322 src/toolbar.c:454 msgid "Flow" msgstr "" #: src/prefs.c:330 msgid "Test Area" msgstr "TaÉ£zut n usekyed" #: src/prefs.c:373 msgid "Factor" msgstr "Ameskar" #: src/prefs.c:459 msgid "This key is builtin" msgstr "" #: src/prefs.c:462 #, c-format msgid "" "This key is mapped to:\n" "\"%s\"" msgstr "" #: src/prefs.c:465 msgid "Remap" msgstr "" #: src/prefs.c:510 msgid "Keyboard Shortcuts" msgstr "" #: src/shifter.c:147 msgid "Frames" msgstr "Ikataren" #: src/shifter.c:258 msgid "Palette Shifter" msgstr "" #: src/shifter.c:263 msgid "Start" msgstr "Sekker" #: src/shifter.c:265 msgid "Finish" msgstr "Fak" #: src/shifter.c:284 msgid "Fix Palette" msgstr "Ḥrez tapaliá¸t" #: src/spawn.c:651 msgid "Configure File Actions" msgstr "Swel tigawin n ufaylu" #: src/spawn.c:657 src/spawn.c:663 msgid "Command" msgstr "Taladna" #: src/spawn.c:922 #, c-format msgid "Error %i reported when trying to run %s" msgstr "Tuccá¸a %i deg uselkem n tladna %s" #: src/spawn.c:979 msgid "" "I am unable to find the documentation. Either you need to download the " "mtPaint Handbook from the web site and install it, or you need to set the " "correct location in the Preferences window." msgstr "" #: src/spawn.c:1018 msgid "" "There was a problem running the HTML browser. You need to set the correct " "program name in the Preferences window." msgstr "" "Yeá¸ra-d wugur deg uelkem n yiminig HTML. Isefk ad tesbaduḠisem n wahil " "ameÉ£tu deg usfaylu n yiÉ£ewwaren." #: src/thread.c:361 msgid "Helper thread is not responding. Save your work and exit the program." msgstr "" #: src/toolbar.c:147 msgid "RGB Cube" msgstr "Agasas RVB" #: src/toolbar.c:148 msgid "By image channel" msgstr "S ubadu n tugna" #: src/toolbar.c:149 msgid "Gradient-driven" msgstr "" #: src/toolbar.c:157 msgid "Fill settings" msgstr "IÉ£ewwaren n taÄÄart" #: src/toolbar.c:170 msgid "Respect opacity mode" msgstr "Qader askar n tiá¸ullest" #: src/toolbar.c:176 msgid "Smudge settings" msgstr "" #: src/toolbar.c:215 msgid "Aligned" msgstr "" #: src/toolbar.c:222 msgid "Clone settings" msgstr "" #: src/toolbar.c:228 msgid "By selection channel" msgstr "" #: src/toolbar.c:234 msgid "Lasso settings" msgstr "" #: src/toolbar.c:252 msgid "Brush spacing" msgstr "" #: src/toolbar.c:299 src/toolbar.c:341 msgid "Normal" msgstr "Amagnu" #: src/toolbar.c:300 msgid "Colour" msgstr "Ini" #: src/toolbar.c:300 msgid "Saturate More" msgstr "Seá¹›wu ugar" #: src/toolbar.c:301 msgid "Multiply" msgstr "Ssugget" #: src/toolbar.c:301 msgid "Divide" msgstr "Bá¸u" #: src/toolbar.c:301 msgid "Dodge" msgstr "" #: src/toolbar.c:302 msgid "Burn" msgstr "" #: src/toolbar.c:302 msgid "Hard Light" msgstr "Tafat iǧehdden" #: src/toolbar.c:302 msgid "Soft Light" msgstr "" #: src/toolbar.c:302 msgid "Difference" msgstr "Amgarrad" #: src/toolbar.c:303 msgid "Darken" msgstr "" #: src/toolbar.c:303 msgid "Lighten" msgstr "Sfaw" #: src/toolbar.c:303 msgid "Grain Extract" msgstr "" #: src/toolbar.c:304 msgid "Grain Merge" msgstr "" #: src/toolbar.c:330 msgid "Blend mode" msgstr "Askar n usmezdi" #: src/toolbar.c:417 msgid "Continuous Mode" msgstr "Askar amaÉ£lal" #: src/toolbar.c:421 msgid "Opacity Mode" msgstr "Askar n tiá¸ullest" #: src/toolbar.c:424 msgid "Tint Mode" msgstr "Askar n tiÉ£mi" #: src/toolbar.c:427 msgid "Tint +-" msgstr "TiÉ£mi +-" #: src/toolbar.c:434 msgid "Blend Mode" msgstr "Askar n usmezdi" #: src/toolbar.c:438 msgid "Disable All Masks" msgstr "Sens akk tigelmusin" #: src/toolbar.c:441 msgid "Gradient Mode" msgstr "Askar n ufesnaw" #: src/toolbar.c:486 msgid "Settings Toolbar" msgstr "Afeggag n yiÉ£ewwaren" #: src/toolbar.c:546 msgid "Cut" msgstr "Gzem" #: src/toolbar.c:548 msgid "Copy" msgstr "TanÉ£elt" #: src/toolbar.c:550 msgid "Paste" msgstr "Sená¹­eá¸" #: src/toolbar.c:553 msgid "Undo" msgstr "Sefsex" #: src/toolbar.c:555 msgid "Redo" msgstr "Err-d" #: src/toolbar.c:559 src/viewer.c:328 msgid "Pan Window" msgstr "" #: src/toolbar.c:560 src/toolbar.c:640 msgid "More..." msgstr "Ugar..." #: src/toolbar.c:574 msgid "Paint" msgstr "Klu" #: src/toolbar.c:580 msgid "Shuffle" msgstr "" #: src/toolbar.c:583 msgid "Flood Fill" msgstr "" #: src/toolbar.c:587 msgid "Straight Line" msgstr "AjerriḠusrid" #: src/toolbar.c:590 msgid "Smudge" msgstr "" #: src/toolbar.c:594 msgid "Clone" msgstr "Sisleg" #: src/toolbar.c:597 msgid "Make Selection" msgstr "Eg tafrayt" #: src/toolbar.c:600 msgid "Polygon Selection" msgstr "Tafrayt s ugedis" #: src/toolbar.c:603 msgid "Place Gradient" msgstr "Afesnaw" #: src/toolbar.c:606 msgid "Lasso Selection" msgstr "" #: src/toolbar.c:614 msgid "Ellipse Outline" msgstr "Azizdew n teglayt" #: src/toolbar.c:617 msgid "Filled Ellipse" msgstr "Taglayt yeÄÄuren" #: src/toolbar.c:620 msgid "Outline Selection" msgstr "SuneÉ£ azizdew n tefrayt" #: src/toolbar.c:623 msgid "Fill Selection" msgstr "AÄÄar tafrayt" #: src/toolbar.c:627 msgid "Flip Selection Vertically" msgstr "Tuttya taratakt n tefrayt" #: src/toolbar.c:630 msgid "Flip Selection Horizontally" msgstr "Tuttya taglawant n tefrayt" #: src/toolbar.c:633 msgid "Rotate Selection Clockwise" msgstr "Tuzzya yugdan tamrilt n tefrayt" #: src/toolbar.c:636 msgid "Rotate Selection Anti-Clockwise" msgstr "Tuzzya mgal tamrilt n tefrayt" #: src/vcode.c:5201 msgid "Browse" msgstr "Snirem" #: src/vcode.c:7886 msgid "New key ..." msgstr "" #: src/vcode.c:9909 #, c-format msgid "'%s' does not match any widget" msgstr "" #: src/vcode.c:9910 #, c-format msgid "'%s' value does not fit '%s' widget" msgstr "" #: src/viewer.c:115 msgid "About" msgstr "Æ”ef" #: src/viewer.c:1179 msgid "No font selected" msgstr "" #: src/viewer.c:1209 msgid "Left" msgstr "" #: src/viewer.c:1209 msgid "Right" msgstr "" #~ msgid "Create GIF frames" #~ msgstr "Snulfu-d ikataren n GIF" #~ msgid "" #~ "You are trying to save an XPM file with more than 4096 colours. Either " #~ "use another format or posterize the image to 4 bits, or otherwise reduce " #~ "the number of colours." #~ msgstr "" #~ "Ala tettaÉ›raá¸eḠad teskelseḠafaylu XPM s wugar n 4096 n yiniten. Seqdec " #~ "amasal-nniá¸en neÉ£ err tugna É£er uskar n 4 n ibiten, neÉ£ sader amá¸an n " #~ "yiniten." #~ msgid "Store Values" #~ msgstr "Sekles azalen" mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/po/nl.po000066400000000000000000003065261471325446300215560ustar00rootroot00000000000000# Dutch translations for mtpaint package # Copyright (C) 2005 THE mtpaint'S COPYRIGHT HOLDER # This file is distributed under the same license as the mtpaint package. # Mark Tyler, 2005. # msgid "" msgstr "" "Project-Id-Version: mtpaint-3.20 dutch\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-01-04 21:31+0200\n" "PO-Revision-Date: 2008-112-31 23:24+0100\n" "Last-Translator: Hans Strijards hannesworst@hotmail.com>\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Language: Dutch\n" "X-Poedit-Country: Nederland\n" #: src/ani.c:647 msgid "Animation Preview" msgstr "Animatie-voorbeeldweergave" #: src/ani.c:650 src/shifter.c:275 msgid "Play" msgstr "Afspelen" #: src/ani.c:654 msgid "Fix" msgstr "Fixeren" #: src/ani.c:655 src/ani.c:1005 src/font.c:1624 src/font.c:1643 #: src/shifter.c:286 src/viewer.c:97 msgid "Close" msgstr "Sluiten" #: src/ani.c:709 src/ani.c:812 src/ani.c:1022 src/ani.c:1028 src/canvas.c:356 #: src/canvas.c:708 src/canvas.c:989 src/canvas.c:1353 src/canvas.c:1383 #: src/canvas.c:1470 src/canvas.c:1545 src/canvas.c:1988 src/canvas.c:1994 #: src/canvas.c:2077 src/canvas.c:2217 src/canvas.c:2240 src/font.c:1352 #: src/fpick.c:636 src/fpick.c:754 src/layer.c:524 src/layer.c:815 #: src/layer.c:970 src/mainwindow.c:341 src/mainwindow.c:370 #: src/mainwindow.c:534 src/mainwindow.c:578 src/mainwindow.c:604 #: src/mainwindow.c:3797 src/mainwindow.c:4045 src/otherwindow.c:931 #: src/otherwindow.c:980 src/otherwindow.c:982 src/prefs.c:459 src/spawn.c:924 #: src/spawn.c:978 src/spawn.c:1017 src/thread.c:360 src/vcode.c:9912 #: src/viewer.c:1161 src/viewer.c:1179 msgid "Error" msgstr "Fout" #: src/ani.c:709 msgid "Unable to create output directory" msgstr "Kan geen map voor uitvoer aanmaken" #: src/ani.c:759 msgid "Creating Animation Frames" msgstr "Kaders aanmaken voor animatie" #: src/ani.c:812 msgid "Unable to save image" msgstr "Niet in staat afbeelding te bewaren" #: src/ani.c:840 src/canvas.c:1171 src/fpick.c:731 src/layer.c:311 #: src/layer.c:379 src/layer.c:826 src/layer.c:840 src/mainwindow.c:375 #: src/mainwindow.c:1026 src/png.c:8794 src/prefs.c:464 msgid "Warning" msgstr "Waarschuwing" #: src/ani.c:840 msgid "" "Do you really want to clear all of the position and cycle data for all of " "the layers?" msgstr "" "Wilt u werkelijk bij alle lagen alle positie- en cyclusgegevens wissen?" #: src/ani.c:841 src/fpick.c:731 src/layer.c:311 src/layer.c:842 #: src/mainwindow.c:375 msgid "No" msgstr "Nee" #: src/ani.c:841 src/fpick.c:731 src/layer.c:311 src/layer.c:842 #: src/mainwindow.c:375 msgid "Yes" msgstr "Ja" #: src/ani.c:954 msgid "Set Key Frame" msgstr "Hoofdkader instellen" #: src/ani.c:961 msgid "Configure Animation" msgstr "Animatie instellen" #: src/ani.c:964 msgid "Output Files" msgstr "Uitvoerbestanden" #: src/ani.c:967 msgid "Start frame" msgstr "Kader opstarten" #: src/ani.c:969 msgid "End frame" msgstr "Kader afsluiten" #: src/ani.c:971 src/shifter.c:267 msgid "Delay" msgstr "Uitstellen" #: src/ani.c:973 msgid "Output path" msgstr "Uitvoerpad" #: src/ani.c:973 src/font.c:1637 src/spawn.c:664 msgid "Select Directory" msgstr "Map kiezen" #: src/ani.c:976 msgid "File prefix" msgstr "Voorvoegsel voor bestand" #: src/ani.c:978 src/canvas.c:2096 msgid "File Format" msgstr "Bestandsformaat" #: src/ani.c:982 msgid "Positions" msgstr "Posities" #: src/ani.c:997 msgid "Cycling" msgstr "Cycli" #: src/ani.c:1006 msgid "Save" msgstr "Bewaren" #: src/ani.c:1007 src/font.c:1577 src/otherwindow.c:868 src/otherwindow.c:1615 #: src/otherwindow.c:1728 src/otherwindow.c:2938 src/otherwindow.c:3071 #: src/otherwindow.c:3170 msgid "Preview" msgstr "Voorbeeldweergave" #: src/ani.c:1008 src/shifter.c:285 msgid "Create Frames" msgstr "Kaders aanmaken" #: src/ani.c:1022 msgid "You must have at least 2 layers to create an animation" msgstr "U moet tenminste twee lagen hebben voor een animatie" #: src/ani.c:1028 msgid "You must save your layers file before creating an animation" msgstr "U moet uw lagenbestand opslaan voordat u een animatie kunt maken" #: src/canvas.c:357 msgid "The image is too large to transform." msgstr "De afbeelding is te groot om om te zetten." #: src/canvas.c:393 src/canvas.c:430 src/otherwindow.c:1613 #: src/otherwindow.c:2524 src/otherwindow.c:2583 src/otherwindow.c:3179 msgid "Gradient" msgstr "Verloop" #: src/canvas.c:393 src/otherwindow.c:840 src/otherwindow.c:842 #: src/otherwindow.c:2074 src/otherwindow.c:3180 msgid "Palette" msgstr "Palet" #: src/canvas.c:393 src/info.c:265 src/otherwindow.c:847 src/otherwindow.c:2757 #: src/otherwindow.c:3180 src/png.c:781 src/png.c:995 msgid "Clipboard" msgstr "Klembord" #: src/canvas.c:394 src/cpick.c:831 src/toolbar.c:299 msgid "Value" msgstr "Waarde" #: src/canvas.c:394 src/cpick.c:811 src/otherwindow.c:575 src/otherwindow.c:859 #: src/otherwindow.c:3053 src/toolbar.c:318 msgid "Red" msgstr "Rood" #: src/canvas.c:394 src/cpick.c:815 src/otherwindow.c:575 src/otherwindow.c:860 #: src/otherwindow.c:3053 src/toolbar.c:319 msgid "Green" msgstr "Groen" #: src/canvas.c:394 src/cpick.c:819 src/otherwindow.c:575 src/otherwindow.c:861 #: src/otherwindow.c:3053 src/toolbar.c:320 msgid "Blue" msgstr "Blauw" #: src/canvas.c:399 msgid "From " msgstr "" #: src/canvas.c:403 msgid "To " msgstr "" #: src/canvas.c:410 msgid "Map" msgstr "" #: src/canvas.c:429 msgid "MT" msgstr "MT" #: src/canvas.c:429 msgid "Sobel" msgstr "Sobel" #: src/canvas.c:429 msgid "Prewitt" msgstr "Prewitt" #: src/canvas.c:429 msgid "Kirsch" msgstr "Kirsch" #: src/canvas.c:430 msgid "Roberts" msgstr "Roberts" #: src/canvas.c:430 msgid "Laplace" msgstr "Laplace" #: src/canvas.c:430 msgid "Morphological" msgstr "Morfologisch" #: src/canvas.c:442 msgid "Edge Detect" msgstr "Randen detecteren" #: src/canvas.c:464 msgid "Edge Sharpen" msgstr "Randen verscherpen" #: src/canvas.c:472 msgid "Edge Soften" msgstr "Randen verzachten" #: src/canvas.c:521 msgid "Different X/Y" msgstr "Verschillende X/Y" #: src/canvas.c:522 src/canvas.c:562 src/canvas.c:603 src/canvas.c:637 #: src/canvas.c:722 src/otherwindow.c:1037 src/otherwindow.c:2685 msgid "Gamma corrected" msgstr "Gamma gecorrigeerd" #: src/canvas.c:530 src/memory.c:8219 msgid "Gaussian Blur" msgstr "Guassiaans vervagen" #: src/canvas.c:558 msgid "Radius" msgstr "Straal" #: src/canvas.c:559 msgid "Amount" msgstr "Hoeveelheid" #: src/canvas.c:560 msgid "Threshold " msgstr "Drempel " #: src/canvas.c:570 src/memory.c:8360 msgid "Unsharp Mask" msgstr "Onscherptemasker" #: src/canvas.c:599 msgid "Outer radius" msgstr "Buitenste straal" #: src/canvas.c:600 msgid "Inner radius" msgstr "Binnenstraal" #: src/canvas.c:602 src/info.c:280 msgid "Normalize" msgstr "Normaliseren" #: src/canvas.c:611 src/memory.c:8512 msgid "Difference of Gaussians" msgstr "Gaussiaanse verschillen" #: src/canvas.c:636 msgid "Protect details" msgstr "Details beschermen" #: src/canvas.c:645 msgid "Kuwahara-Nagao Blur" msgstr "Kuwahara-Nagao vervagen" #: src/canvas.c:709 msgid "The image is too large for this rotation." msgstr "De afbeelding is te groot voor deze kanteling." #: src/canvas.c:723 msgid "Smooth" msgstr "Zacht" #: src/canvas.c:732 msgid "Free Rotate" msgstr "Vrij draaien" #: src/canvas.c:989 src/viewer.c:1161 msgid "Not enough memory to create clipboard" msgstr "Onvoldoende geheugen om klembord aan te maken" #: src/canvas.c:1172 msgid "" "You have not allocated enough memory in the Preferences window to undo this " "action." msgstr "" #: src/canvas.c:1353 msgid "Invalid palette file" msgstr "Ongeldig paletbestand" #: src/canvas.c:1383 msgid "Invalid channel file." msgstr "Ongeldig kanaalbestand." #: src/canvas.c:1401 msgid "Raw frames" msgstr "Ruwe frames" #: src/canvas.c:1401 msgid "Composited frames" msgstr "Samengestelde frames" #: src/canvas.c:1402 msgid "Composited frames with nonzero delay" msgstr "Samengestelde frames met niet-nul-vertraging" #: src/canvas.c:1406 msgid "Load Frames" msgstr "Frames laden" #: src/canvas.c:1409 msgid "Load into Layers" msgstr "In lagen laden" #: src/canvas.c:1415 msgid "Load First Frame" msgstr "Eerste frame laden" #: src/canvas.c:1416 msgid "Explode Frames" msgstr "Frames opblazen" #: src/canvas.c:1418 msgid "View Animation" msgstr "Animatie bekijken" #: src/canvas.c:1434 #, c-format msgid "This is an animated %s file." msgstr "Dit is een %s-bestand met animatie." #: src/canvas.c:1435 #, c-format msgid "This is a multipage %s file." msgstr "Dit is een %s-bestand met meerdere pagina's" #: src/canvas.c:1459 #, c-format msgid "File is too big, must be <= to width=%i height=%i" msgstr "Bestand is te groot, moet zijn <= breedte=%i hoogte=%i" #: src/canvas.c:1461 msgid "Unable to explode frames" msgstr "Niet in staat om frames op te blazen" #: src/canvas.c:1463 msgid "Unable to load file" msgstr "Kan bestand niet laden" #: src/canvas.c:1465 msgid "" "The file import library had to terminate due to a problem with the file " "(possibly corrupt image data or a truncated file). I have managed to load " "some data as the header seemed fine, but I would suggest you save this image " "to a new file to ensure this does not happen again." msgstr "" "De bibiotheek voor importbestanden werd afgesloten vanwege een probleem met " "het bestand (mogelijk corrupte beeldgegevens of een afgebroken bestand). Ik " "ben erin geslaagd bepaalde gegevens te laden, aangezien de header in orde " "is, maar ik stel voor dat u dit bestand in een nieuwe folder opslaat om " "herhaling te voorkomen" #: src/canvas.c:1467 msgid "The animation is too long to load all of it into layers." msgstr "De animatie is te lang om hem helemaal in lagen te laden." #: src/canvas.c:1469 msgid "Could not explode all the frames in the animation." msgstr "Kon niet alle frames in de animatie opblazen." #: src/canvas.c:1481 src/font.c:1556 src/fpick.c:937 src/otherwindow.c:2765 #: src/prefs.c:321 src/toolbar.c:451 msgid "Size" msgstr "Grootte" #: src/canvas.c:1484 src/otherwindow.c:244 msgid "Width" msgstr "Breedte" #: src/canvas.c:1485 src/otherwindow.c:245 msgid "Height" msgstr "Hoogte" #: src/canvas.c:1489 src/channels.c:253 src/channels.c:317 src/fpick.c:666 #: src/fpick.c:957 src/mainwindow.c:3990 src/otherwindow.c:255 #: src/otherwindow.c:517 src/otherwindow.c:591 src/otherwindow.c:867 #: src/otherwindow.c:1058 src/otherwindow.c:1727 src/otherwindow.c:2101 #: src/otherwindow.c:2336 src/otherwindow.c:2538 src/otherwindow.c:2691 #: src/otherwindow.c:2776 src/otherwindow.c:2937 src/otherwindow.c:3070 #: src/otherwindow.c:3169 src/prefs.c:338 src/prefs.c:464 src/prefs.c:538 #: src/spawn.c:666 src/viewer.c:1258 msgid "Cancel" msgstr "Annuleren" #: src/canvas.c:1490 src/channels.c:253 src/channels.c:317 src/fpick.c:956 #: src/info.c:297 src/mainwindow.c:3992 src/mygtk.c:233 src/mygtk.c:535 #: src/otherwindow.c:591 src/otherwindow.c:871 src/otherwindow.c:1058 #: src/otherwindow.c:1729 src/otherwindow.c:2101 src/otherwindow.c:2336 #: src/otherwindow.c:2538 src/otherwindow.c:2691 src/otherwindow.c:2776 #: src/otherwindow.c:3072 src/otherwindow.c:3171 src/prefs.c:338 #: src/prefs.c:538 src/spawn.c:666 msgid "OK" msgstr "OK" #: src/canvas.c:1504 #, c-format msgid "This is a scalable %s file." msgstr "" #: src/canvas.c:1545 msgid "Cannot open file" msgstr "Kan bestand niet openen" #: src/canvas.c:1546 msgid "Unsupported file format" msgstr "Niet-ondersteund bestandsformaat" #: src/canvas.c:1673 #, c-format msgid "File: %s already exists. Do you want to overwrite it?" msgstr "Bestand: %s bestaat al. Wilt u het overschrijven?" #: src/canvas.c:1674 msgid "File Found" msgstr "Bestand gevonden" #: src/canvas.c:1674 src/mainwindow.c:1095 msgid "NO" msgstr "NEE" #: src/canvas.c:1674 src/mainwindow.c:1095 msgid "YES" msgstr "JA" #: src/canvas.c:1988 msgid "Unable to export undo images" msgstr "Kan geen ongedaan-afbeeldingen exporteren" #: src/canvas.c:1994 msgid "Unable to export ASCII file" msgstr "Niet in staat om ASCII-bestand uit te voeren" #: src/canvas.c:2076 src/layer.c:814 src/mainwindow.c:529 #, c-format msgid "Unable to save file: %s" msgstr "Niet mogelijk om bestand op te slaan: %s" #: src/canvas.c:2101 src/prefs.c:222 msgid "Transparency index" msgstr "Transparantie-index" #: src/canvas.c:2103 msgid "TIFF Compression" msgstr "" #: src/canvas.c:2105 src/prefs.c:225 msgid "JPEG Save Quality (100=High)" msgstr "JPEG-opslagkwaliteit (100=Hoog)" #: src/canvas.c:2107 msgid "ZIP Compression (0=None)" msgstr "" #: src/canvas.c:2108 src/prefs.c:227 msgid "PNG Compression (0=None)" msgstr "PNG-compressie (0=geen)" #: src/canvas.c:2111 src/prefs.c:249 msgid "LZMA2 Compression (0=None)" msgstr "" #: src/canvas.c:2113 src/prefs.c:252 msgid "ZSTD Compression Level" msgstr "" #: src/canvas.c:2115 src/prefs.c:231 msgid "TGA RLE Compression" msgstr "TGA RLE-compressie" #: src/canvas.c:2117 msgid "LBM PackBits Compression" msgstr "" #: src/canvas.c:2118 src/prefs.c:226 msgid "JPEG2000 Compression (0=Lossless)" msgstr "JPEG2000-compressie (0=zonder verlies)" #: src/canvas.c:2120 msgid "WebP Compression" msgstr "" #: src/canvas.c:2122 msgid "WebP Save Quality (100=High)" msgstr "" #: src/canvas.c:2123 src/prefs.c:263 msgid "V8 Save Quality (100=High)" msgstr "" #: src/canvas.c:2125 src/prefs.c:264 msgid "V8L Compression (0=None)" msgstr "" #: src/canvas.c:2127 msgid "Hotspot at X =" msgstr "Centraal punt op X =" #: src/canvas.c:2129 msgid "Y =" msgstr "Y =" #: src/canvas.c:2133 msgid "Animation delay" msgstr "Animatievertraging" #: src/canvas.c:2136 src/otherwindow.c:253 msgid "Undoable" msgstr "Onuitvoerbaar" #: src/canvas.c:2138 src/prefs.c:236 msgid "Apply colour profile" msgstr "Kleurprofiel toepassen" #: src/canvas.c:2176 src/toolbar.c:543 msgid "Load Image File" msgstr "Afbeelding laden" #: src/canvas.c:2191 src/toolbar.c:544 msgid "Save Image File" msgstr "Afbeelding opslaan" #: src/canvas.c:2196 msgid "Load Palette File" msgstr "Palet laden" #: src/canvas.c:2202 msgid "Save Palette File" msgstr "Palet opslaan" #: src/canvas.c:2207 msgid "Export Undo Images" msgstr "Ongedaan-afbeeldingen exporteren" #: src/canvas.c:2212 msgid "Export Undo Images (reversed)" msgstr "Ongedaan-afbeeldingen exporteren (omgekeerd)" #: src/canvas.c:2217 msgid "You must have 16 or fewer palette colours to export ASCII art." msgstr "" "U kunt maximaal 16 paletkleuren hebben om ASCII-kunst uit te exporteren." #: src/canvas.c:2220 msgid "Export ASCII Art" msgstr "ASCII-kunst exporteren" #: src/canvas.c:2224 msgid "Save Layer Files" msgstr "Lagenbestand opslaan" #: src/canvas.c:2234 msgid "Choose frames directory" msgstr "Frames-map kiezen" #: src/canvas.c:2240 msgid "You must save at least one frame to create an animated GIF." msgstr "Voor een GIF-animatie moet u tenminste één frame opslaan." #: src/canvas.c:2243 msgid "Export GIF animation" msgstr "GIF-animatie uitvoeren" #: src/canvas.c:2247 msgid "Load Channel" msgstr "Kanaal laden" #: src/canvas.c:2255 msgid "Save Channel" msgstr "Kanaal opslaan" #: src/canvas.c:2260 msgid "Save Composite Image" msgstr "Samengestelde afbeelding opslaan" #: src/channels.c:243 msgid "Create Channel" msgstr "Kanaal aanmaken" #: src/channels.c:244 msgid "Channel Type" msgstr "Kanaaltype" #: src/channels.c:247 msgid "Initial Channel State" msgstr "Aanvankelijke staat van het kanaal" #: src/channels.c:251 msgid "Inverted" msgstr "Geïnverteerd" #: src/channels.c:265 msgid "Cleared" msgstr "Gewist" #: src/channels.c:266 msgid "Set" msgstr "Instellen" #: src/channels.c:267 msgid "Set colour A radius B" msgstr "Kleur A straal B instellen" #: src/channels.c:268 msgid "Set blend A to B" msgstr "A met B mengen" #: src/channels.c:269 msgid "Image Red" msgstr "Afbeelding rood" #: src/channels.c:270 msgid "Image Green" msgstr "Afbeelding groen" #: src/channels.c:271 msgid "Image Blue" msgstr "Afbeelding blauw" #: src/channels.c:273 src/channels.c:313 src/mainwindow.c:67 #: src/otherwindow.c:1679 msgid "Alpha" msgstr "Alfa" #: src/channels.c:274 src/channels.c:314 src/mainwindow.c:67 #: src/otherwindow.c:1683 msgid "Selection" msgstr "Selectie" #: src/channels.c:275 src/channels.c:315 src/mainwindow.c:67 #: src/otherwindow.c:1687 msgid "Mask" msgstr "Maskeren" #: src/channels.c:312 msgid "Delete Channels" msgstr "Kanalen wissen" #: src/channels.c:367 msgid "Threshold Channel" msgstr "Drempelkanaal" #: src/cpick.c:823 src/otherwindow.c:573 src/otherwindow.c:820 #: src/toolbar.c:299 msgid "Hue" msgstr "Tint" #: src/cpick.c:827 src/otherwindow.c:573 src/otherwindow.c:818 #: src/toolbar.c:299 msgid "Saturation" msgstr "Verzadiging" #: src/cpick.c:835 msgid "Hex" msgstr "Hex" #: src/cpick.c:840 src/layer.c:1109 src/otherwindow.c:2530 src/prefs.c:323 #: src/toolbar.c:457 msgid "Opacity" msgstr "Dekking" #: src/font.c:982 msgid "Creating Font Index" msgstr "Lettertype-index aanmaken" #: src/font.c:1353 msgid "You must select at least one directory to search for fonts." msgstr "U moet tenminste één map kiezen om te doorzoeken op lettertypes." #: src/font.c:1529 src/font.c:1624 src/toolbar.c:609 src/viewer.c:1213 #: src/viewer.c:1258 msgid "Paste Text" msgstr "Tekst plakken" #: src/font.c:1533 src/font.c:1572 src/png.c:3578 msgid "Text" msgstr "Tekst" #: src/font.c:1540 msgid "Font" msgstr "Lettertype" #: src/font.c:1548 msgid "Style" msgstr "Stijl" #: src/font.c:1566 msgid "Filename" msgstr "Bestandsnaam" #: src/font.c:1567 msgid "Face" msgstr "Gezicht" #: src/font.c:1587 src/viewer.c:1222 msgid "Antialias" msgstr "Anti-alias" #: src/font.c:1590 src/viewer.c:1224 msgid "Invert" msgstr "Inverteren" #: src/font.c:1593 src/viewer.c:1226 msgid "Background colour =" msgstr "Achtergrondkleur =" #: src/font.c:1601 src/viewer.c:1233 msgid "DPI =" msgstr "" #: src/font.c:1610 msgid "Oblique" msgstr "Schuin" #: src/font.c:1612 src/viewer.c:1244 msgid "Angle of rotation =" msgstr "Rotatiehoek =" #: src/font.c:1617 src/viewer.c:1248 msgid "Align" msgstr "" #: src/font.c:1620 src/viewer.c:1253 msgid "Spacing" msgstr "" #: src/font.c:1629 msgid "Font Directories" msgstr "Lettertypemappen" #: src/font.c:1634 src/spawn.c:664 msgid "Directory" msgstr "Map" #: src/font.c:1637 msgid "New Directory" msgstr "Nieuwe map" #: src/font.c:1644 src/prefs.c:532 msgid "Add" msgstr "Toevoegen" #: src/font.c:1645 src/prefs.c:533 msgid "Remove" msgstr "Verwijderen" #: src/font.c:1646 msgid "Create Index" msgstr "Index aanmaken" #: src/font.c:1660 src/viewer.c:1267 msgid "Enter Text Here" msgstr "Tekst hier invoegen" #: src/fpick.c:635 #, c-format msgid "Could not access directory %s" msgstr "Kreeg geen toegang tot map %s" #: src/fpick.c:668 src/fpick.c:698 msgid "Delete" msgstr "Wissen" #: src/fpick.c:669 src/fpick.c:698 msgid "Rename" msgstr "Hernoemen" #: src/fpick.c:672 src/otherwindow.c:255 src/otherwindow.c:1666 msgid "Create" msgstr "Aanmaken" #: src/fpick.c:699 msgid "Enter the new filename" msgstr "Voer de nieuwe bestandsnaam in" #: src/fpick.c:704 msgid "Create Directory" msgstr "Map aanmaken" #: src/fpick.c:705 msgid "Enter the name of the new directory" msgstr "Voer de naam van de nieuwe map in" #: src/fpick.c:729 #, c-format msgid "Do you really want to delete \"%s\" ?" msgstr "Wilt u echt \"%s\" wissen ?" #: src/fpick.c:735 msgid "Unable to delete" msgstr "Kan niet wissen" #: src/fpick.c:741 msgid "Unable to rename" msgstr "Kan niet hernoemen" #: src/fpick.c:750 msgid "Unable to create directory" msgstr "Kan map niet aanmaken" #: src/fpick.c:924 msgid "Up" msgstr "Omhoog" #: src/fpick.c:925 msgid "Home" msgstr "Persoonlijke map" #: src/fpick.c:926 msgid "Create New Directory" msgstr "Nieuwe map aanmaken" #: src/fpick.c:927 msgid "Show Hidden Files" msgstr "Verborgen bestanden tonen" #: src/fpick.c:929 msgid "Case Insensitive Sort" msgstr "Niet-hoofdlettergevoelige ordening" #: src/fpick.c:936 msgid "Name" msgstr "Naam" #: src/fpick.c:938 msgid "Type" msgstr "Type" #: src/fpick.c:939 msgid "Modified" msgstr "Aangepast" #: src/help.c:25 src/prefs.c:160 msgid "General" msgstr "Algemeen" #: src/help.c:26 msgid "Keyboard shortcuts" msgstr "Sneltoetsen" #: src/help.c:27 msgid "Mouse shortcuts" msgstr "Muis-sneltoetsen" #: src/help.c:28 msgid "Credits" msgstr "Met dank aan" #: src/help.c:32 msgid "mtPaint 3.51 - Copyright (C) 2004-2021 The Authors\n" msgstr "mtPaint 3.51 - Auteursrecht (C) 2004-2021 De auteurs\n" #: src/help.c:33 msgid "See 'Credits' section for a list of the authors.\n" msgstr "Voor alle auteurs, zie sectie 'Met dank aan'.\n" #: src/help.c:34 msgid "" "mtPaint 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.\n" msgstr "" "mtPaint is vrije software; u kunt het verder verspreiden en/of aanpassen " "onder de voorwaarden van de GNU General Public License zoals gepubliceerd " "door de Free Software Foundation; ofwel versie 3 van de licentie of (naar " "keuze) elke latere versie.\n" #: src/help.c:35 msgid "" "mtPaint 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.\n" msgstr "" "mtPaint wordt gedistribueerd in de hoop dat het nuttig zal zijn, maar ZONDER " "ENIGE GARANTIE; zonder zelfs de geïmpliceerde garantie van VERKOOPBAARHEID " "of GESCHIKTHEID VOOR EEN BEPAALD DOEL. Zie de GNU General Public License " "voor meer details.\n" #: src/help.c:36 msgid "" "mtPaint is a simple GTK+1/2/3 painting program designed for creating icons " "and pixel based artwork. It can edit indexed palette or 24 bit RGB images " "and offers basic painting and palette manipulation tools. It also has " "several other more powerful features such as channels, layers and animation. " "Due to its simplicity and lack of dependencies it runs well on GNU/Linux, " "Windows and older PC hardware.\n" msgstr "" "mtPaint is een eenvoudig GTK+1/2/3 tekenprogramma, ontworpen om pictogrammen " "en pixelgebaseerde kunst te maken. Men kan er een geïndexeerd kleurenpalet " "mee bewerken of 24 bits RGB afbeeldingen. Het biedt de mogelijkheid om " "eenvoudige kleurenafbeeldingen te ontwerpen. Het programma beschikt ook over " "krachtigere mogelijkheden, zoals het uitvoeren van kanalen, verschillende " "lagen en animaties. Vanwege de eenvoud, en omdat het geen afhankelijkheden " "bezit, werkt het programma goed onder GNU/Linux en Windows en op oudere " "computers.\n" #: src/help.c:37 msgid "" "There is full documentation of mtPaint's features contained in a handbook. " "If you don't already have this, you can download it from the mtPaint " "website.\n" msgstr "" "Er is een volledige documentatie over de functies van mtPaint beschikbaar " "als handleiding. U kunt deze ophalen vanaf de website van mtPaint.\n" #: src/help.c:38 msgid "" "If you like mtPaint and you want to keep up to date with new releases, or " "you want to give some feedback, then the mailing lists may be of interest to " "you:\n" msgstr "" "Wanner mtPaint u bevalt en wanneer u op de hoogte wilt blijven van nieuwe " "uitgaven, of wanneer u terugkoppeling wilt geven, dan kan het voor u " "interessant zijn in de verzendlijsten te worden opgenomen:\n" #: src/help.c:39 msgid "http://sourceforge.net/mail/?group_id=155874" msgstr "http://sourceforge.net/mail/?group_id=155874" #: src/help.c:42 msgid " Ctrl-N Create new image" msgstr " Ctrl-N Nieuwe afbeelding aanmaken" #: src/help.c:43 msgid " Ctrl-O Open Image" msgstr " Ctrl-O Afbeelding openen" #: src/help.c:44 msgid " Ctrl-S Save Image" msgstr " Ctrl-S Afbeelding opslaan" #: src/help.c:45 msgid " Ctrl-Shift-S Save layers file" msgstr " Ctrl-Shift-S Lagenbestand opslaan" #: src/help.c:46 msgid " Ctrl-Q Quit program\n" msgstr " Ctrl-Q Programma afsluiten\n" #: src/help.c:47 msgid " Ctrl-A Select whole image" msgstr " Ctrl-A Selecteer gehele afbeelding" #: src/help.c:48 msgid " Escape Select nothing, cancel paste box" msgstr " Escape Niets selecteren, plakken afzeggen" #: src/help.c:49 msgid " J Lasso selection\n" msgstr " J Lasso selectie\n" #: src/help.c:50 msgid " Ctrl-C Copy selection to clipboard" msgstr " Ctrl-C Kopieer selectie naar het klembord" #: src/help.c:51 msgid "" " Ctrl-X Copy selection to clipboard, and then paint current " "pattern to selection area" msgstr "" " Ctrl-X Kopieer selectie naar het klembord, en schilder dan het " "huidige patroon in het geselecteerde gebied" #: src/help.c:52 msgid " Ctrl-V Paste clipboard to centre of current view" msgstr "" " Ctrl-V Plak klembordinhoud in het midden van huidige weergave" #: src/help.c:53 msgid " Ctrl-K Paste clipboard to location it was copied from" msgstr "" " Ctrl-K Plak klembordinhoud terug op zijn oorspronkelijke plaats" #: src/help.c:54 msgid " Ctrl-Shift-V Paste clipboard to new layer" msgstr " Ctrl-Shift-V Plak klembordinhoud in nieuwe laag" #: src/help.c:55 msgid " Enter/Return Commit paste to canvas" msgstr " Enter/Return Plak op canvas" #: src/help.c:56 msgid " Shift+Enter/Return Commit paste and swap canvas into the clipboard\n" msgstr "" " Shift+Enter/Return Pas plakken toe en verplaats canvas naar klembord\n" #: src/help.c:57 msgid " Arrow keys Paint Mode - Move the mouse pointer" msgstr " Pijltjestoetsen Tekenmodus - verplaats de muisaanwijzer" #: src/help.c:58 msgid "" " Arrow keys Selection Mode - Nudge selection box or paste box by one " "pixel" msgstr "" " Pijltjestoetsen Selectiemodus - Klik op de selectiebalk of plak " "pixel voor pixel" #: src/help.c:59 msgid "" " Shift+Arrow keys Nudge mouse pointer, selection box or paste box by x " "pixels - x is defined by the Preferences window" msgstr "" " Shift+pijltjestoetsen Duw muisaanwijzer, of selectievak, of plak vak " "pixel voor pixel - x wordt vastgesteld vanuit het Voorkeurenvenster" #: src/help.c:60 msgid " Ctrl+Arrows Move layer or resize selection box" msgstr " Ctrl+pijltjestoetsen Verplaats de laag of pas het selectievak aan" #: src/help.c:61 msgid " Ctrl+Shift+Arrows Move layer or resize selection box by x pixels\n" msgstr "" " Ctrl+Shift+pijltjestoetsen Verplaats laag of verander de grootte van het " "selectievak met x pixels\n" #: src/help.c:62 msgid " Enter/Return Paint Mode - Simulate left click" msgstr " Enter/Return Tekenmodus - boots linkerklik na" #: src/help.c:63 msgid " Backspace Paint Mode - Simulate right click\n" msgstr " Backspace Tekenmodus - boots rechterklik na\n" #: src/help.c:64 msgid "" " [ or ] Change colour A to the next or previous palette item" msgstr "" " [ of ] Verander kleur A in het volgende of vorige paletonderdeel" #: src/help.c:65 msgid "" " Shift+[ or ] Change colour B to the next or previous palette item\n" msgstr "" " Shift+[ of ] Verander kleur B in het volgende of vorige " "paletonderdeel\n" #: src/help.c:66 msgid " Delete Crop image to selection" msgstr " Delete Afbeelding bijsnijden tot selectie" #: src/help.c:67 msgid "" " Insert Transform colours - i.e. Brightness, Contrast, " "Saturation, Posterize, Gamma" msgstr "" " Insert Kleuren transformeren - d.i. helderheid, contrast, " "verzadiging, posterisatie, gamma" #: src/help.c:68 msgid " Ctrl-G Greyscale the image" msgstr " Ctrl-G Afbeelding naar grijstinten omzetten" #: src/help.c:69 msgid " Shift-Ctrl-G Greyscale the image (Gamma corrected)" msgstr "" " Shift-Ctrl-G Afbeelding naar grijstinten omzetten (gamma-gecorrigeerd)" #: src/help.c:70 msgid " Ctrl+M Mirror the image" msgstr " Ctrl+M Afbeelding spiegelen" #: src/help.c:71 msgid " Shift-Ctrl-I Invert the image\n" msgstr " Shift-Ctrl-I Afbeelding inverteren\n" #: src/help.c:72 msgid "" " Ctrl-T Draw a rectangle around the selection area with the " "current fill" msgstr "" " Ctrl-Shift-T Vul het geselecteerde gebied met de gekozen vulling" #: src/help.c:73 msgid " Ctrl-Shift-T Fill in the selection area with the current fill" msgstr " Ctrl-Shift-T Vul de selectie met de gekozen vulling" #: src/help.c:74 msgid " Ctrl-L Draw an ellipse spanning the selection area" msgstr " Ctrl-L Teken een ellips in het geselecteerde gebied" #: src/help.c:75 msgid " Ctrl-Shift-L Draw a filled ellipse spanning the selection area\n" msgstr "" " Ctrl-Shift-L Teken een gevulde ellips in het geselecteerde gebied\n" #: src/help.c:76 msgid " Ctrl-E Edit the RGB values for colours A & B" msgstr " Ctrl-E Bewerk de RGB-waarden voor kleuren A & B" #: src/help.c:77 msgid " Ctrl-W Edit all palette colours\n" msgstr " Ctrl-W Bewerk alle paletkleuren\n" #: src/help.c:78 msgid " Ctrl-P Preferences" msgstr " Ctrl-P Voorkeuren" #: src/help.c:79 msgid " Ctrl-I Information\n" msgstr " Ctrl-I Informatie\n" #: src/help.c:80 msgid " Ctrl-Z Undo last action" msgstr " Ctrl-Z Maak laatste handeling ongedaan" #: src/help.c:81 msgid " Ctrl-R Redo an undone action\n" msgstr " Ctrl-R Voer een ongedaan gemaakte handeling opnieuw uit\n" #: src/help.c:82 msgid " Shift-T Text Tool (GTK+)" msgstr " Shift-T Tekstgereedschap (GTK+)" #: src/help.c:83 msgid " T Text Tool (FreeType)\n" msgstr " T Tekstgereedschap (FreeType)\n" #: src/help.c:84 msgid " V View Window" msgstr " V Kijkvenster" #: src/help.c:85 msgid " L Layers Window\n" msgstr " L Lagenvenster\n" #: src/help.c:86 msgid " Ctrl-H Toggle Hide Image mode" msgstr "" #: src/help.c:87 msgid " B Toggle Snap to Tile Grid mode\n" msgstr " B Schakel uitlijning op tegelraster om\n" #: src/help.c:88 msgid " X Swap Colours A & B" msgstr " X Wissel kleuren A & B om" #: src/help.c:89 msgid " E Choose Colour\n" msgstr " E Kies kleur\n" #: src/help.c:90 msgid "" " A Draw open arrow head when using the line tool (size set " "by flow setting)" msgstr "" " A Teken een open pijlpunt met het lijngereedschap (formaat " "wordt bepaald door stroominstelling)" #: src/help.c:91 msgid "" " S Draw closed arrow head when using the line tool (size " "set by flow setting)\n" msgstr "" " S Teken een dichte pijlpunt met het lijngereedschap " "(formaat wordt bepaald door stroominstelling)\n" #: src/help.c:92 msgid " D Line Tool" msgstr " D Lijngereedschap" #: src/help.c:93 msgid " F Flood Fill Tool\n" msgstr " F Emmer vulgereedschap\n" #: src/help.c:94 msgid " +,= Main edit window - Zoom in" msgstr " +,= Primair bewerkingsvenster - inzoomen" #: src/help.c:95 msgid " - Main edit window - Zoom out" msgstr " - Primair bewerkingsvenster - uitzoomen" #: src/help.c:96 msgid " Shift +,= View window - Zoom in" msgstr " Shift +,= Kijkvenster - inzoomen" #: src/help.c:97 msgid " Shift - View window - Zoom out\n" msgstr " Shift - Kijkvenster - uitzoomen\n" #: src/help.c:98 #, c-format msgid " 1 10% zoom" msgstr "" #: src/help.c:99 #, c-format msgid " 2 25% zoom" msgstr "" #: src/help.c:100 #, c-format msgid " 3 50% zoom" msgstr "" #: src/help.c:101 #, c-format msgid " 4 100% zoom" msgstr "" #: src/help.c:102 #, c-format msgid " 5 400% zoom" msgstr "" #: src/help.c:103 #, c-format msgid " 6 800% zoom" msgstr "" #: src/help.c:104 #, c-format msgid " 7 1200% zoom" msgstr "" #: src/help.c:105 #, c-format msgid " 8 1600% zoom" msgstr "" #: src/help.c:106 #, c-format msgid " 9 2000% zoom\n" msgstr "" #: src/help.c:107 msgid " Shift + 1 Edit image channel" msgstr " Shift + 1 Bewerk afbeeldingskanaal" #: src/help.c:108 msgid " Shift + 2 Edit alpha channel" msgstr " Shift + 2 Bewerk alfakanaal" #: src/help.c:109 msgid " Shift + 3 Edit selection channel" msgstr " Shift + 3 Bewerk selectiekanaal" #: src/help.c:110 msgid " Shift + 4 Edit mask channel\n" msgstr " Shift + 4 Bewerk maskeerkanaal\n" #: src/help.c:111 msgid " F1 Help" msgstr " F1 Hulp" #: src/help.c:112 msgid " F2 Choose Pattern" msgstr " F2 Patroon kiezen" #: src/help.c:113 msgid " F3 Choose Brush" msgstr " F3 Penseel kiezen" #: src/help.c:114 msgid " F4 Paint Tool" msgstr " F4 Schildergereedschap" #: src/help.c:115 msgid " F5 Toggle Main Toolbar" msgstr " F5 Primaire werkbalk omschakelen" #: src/help.c:116 msgid " F6 Toggle Tools Toolbar" msgstr " F6 Werkbalk 'gereedschap' omschakelen" #: src/help.c:117 msgid " F7 Toggle Settings Toolbar" msgstr " F7 Werkbalk 'Instellingen' omschakelen" #: src/help.c:118 msgid " F8 Toggle Palette" msgstr " F8 Palet omschakelen" #: src/help.c:119 msgid " F9 Selection Tool" msgstr " F9 Selectiegereedschap" #: src/help.c:120 msgid " F12 Toggle Dock Area\n" msgstr " F12 Dokgebied omschakelen\n" #: src/help.c:121 msgid " Ctrl + F1 - F12 Save current clipboard to file 1-12" msgstr " Ctrl + F1 - F12 Huidige klembordinhoud opslaan in bestand 1-12" #: src/help.c:122 msgid " Shift + F1 - F12 Load clipboard from file 1-12\n" msgstr " Shift + F1 - F12 klembord laden uit bestand 1-12\n" #: src/help.c:123 msgid "" " Ctrl + 1, 2, ... , 0 Set opacity to 10%, 20%, ... , 100% (main or keypad " "numbers)" msgstr "" " Ctrl + 1, 2, ... , 0 Dekking instellen op 10%, 20%, ... , 100% (algemene- " "of toetsenblokcijfers)" #: src/help.c:124 msgid " Ctrl + + or = Increase opacity by 1" msgstr " Ctrl + + of = Dekking vermeerderen met 1" #: src/help.c:125 msgid " Ctrl + - Decrease opacity by 1\n" msgstr " Ctrl + - Dekking verminderen met 1\n" #: src/help.c:126 msgid "" " Home Show or hide main window menu/toolbar/status bar/palette" msgstr "" " Home Toon of verberg primair venstermenu/werkbalk/statusbalk/" "palet" #: src/help.c:127 msgid " Page Up Scale Image" msgstr " Page Up Afbeelding schalen" #: src/help.c:128 msgid " Page Down Resize Image canvas" msgstr " Page Down Afbeelding canvas herschalen" #: src/help.c:129 msgid " End Pan Window" msgstr " End Overzichtsvenster" #: src/help.c:132 msgid " Left button Paint to canvas using the current tool" msgstr "" " Linkermuisknop Met het huidige gereedschap op het canvas schilderen" #: src/help.c:133 msgid "" " Middle button Selects the point which will be the centre of the " "image after the next zoom" msgstr "" " Middelste muisknop Kies een punt in de afbeelding als centrum om de " "volgende keer op in te zoomen" #: src/help.c:134 msgid "" " Right button Commit paste to canvas / Stop drawing current line / " "Cancel selection\n" msgstr "" " Rechtermuisknop Bevestig plakken naar het canvas / Stop met tekenen " "van huidige lijn / Annuleer selectie\n" #: src/help.c:135 msgid "" " Scroll Wheel In GTK+2/3 the user can have the scroll wheel zoom in " "or out via the Preferences window\n" msgstr "" " Muiswiel Gebruikers kunnen in GTK+2/3 via het " "Voorkeurenvenster het muiswiel instellen om in of uit te zoomen\n" #: src/help.c:136 msgid " Ctrl+Left button Choose colour A from under mouse pointer" msgstr " Ctrl+linkermuisknop Selecteer kleur A vanonder de muispijl" #: src/help.c:137 msgid " Ctrl+Left button Clone tool - Select source" msgstr "" #: src/help.c:138 msgid "" " Ctrl+Middle button Create colour A/B and pattern based on the RGB colour " "in A (RGB images only)" msgstr "" " Ctrl+Middelste muisknop Kleur A/B en patroon aanmaken vanuit de RGB-" "kleur in A (alleen RGB-afbeeldingen)" #: src/help.c:139 msgid " Ctrl+Right button Choose colour B from under mouse pointer" msgstr " Ctrl+Rechtermuisknop Selecteer kleur B vanonder muispijl" #: src/help.c:140 msgid "" " Ctrl+Right button Polygon tool - Delete last point / Delete nearest " "point" msgstr "" #: src/help.c:141 msgid " Ctrl+Scroll Wheel Scroll the main edit window left or right\n" msgstr "" " Ctrl+Muiswiel Het primaire bewerkingsvenster naar links of rechts " "verschuiven\n" #: src/help.c:142 msgid "" " Ctrl+Double click Set colour A or B to average colour under brush " "square or selection marquee (RGB only)\n" msgstr "" " Ctrl+Dubbelklik Stel kleur A of B in als algemene kleur van " "penseel, vierkant of gemarkeerde selectie (alleen RGB)\n" #: src/help.c:143 msgid "" " Shift+Right button Selects the point which will be the centre of the " "image after the next zoom\n" "\n" msgstr "" " Shift+Rechtermuisknop Kiest het punt als centrum van de afbeelding, na " "het volgende in- of uitzoomen\n" "\n" #: src/help.c:144 msgid "You can fixate the X/Y co-ordinates while moving the mouse:\n" msgstr "U kunt de X/Y coördinaten vastzetten terwijl u de muis beweegt:\n" #: src/help.c:145 msgid " Shift Constrain mouse movements to vertical line" msgstr " Shift Beperk muisbewegingen tot een vertikale lijn" #: src/help.c:146 msgid " Shift+Ctrl Constrain mouse movements to horizontal line" msgstr " Shift+Ctrl Beperk muisbewegingen tot een horizontale lijn" #: src/help.c:149 msgid "mtPaint is maintained by Dmitry Groshev.\n" msgstr "mtPaint wordt onderhouden door Dmitry Groshev.\n" #: src/help.c:150 msgid "wjaguar@users.sourceforge.net" msgstr "wjaguar@users.sourceforge.net" #: src/help.c:151 msgid "http://mtpaint.sourceforge.net/\n" msgstr "http://mtpaint.sourceforge.net/\n" #: src/help.c:152 msgid "" "The following people (in alphabetical order) have contributed directly to " "the project, and are therefore worthy of gracious thanks for their " "generosity and hard work:\n" "\n" msgstr "" "De volgende mensen (in alfabetische volgorde) hebben rechtstreeks aan dit " "project meegewerkt. We danken hen voor hun bijdrage en hun inspanningen:\n" "\n" #: src/help.c:153 msgid "Authors\n" msgstr "Auteurs\n" #: src/help.c:154 msgid "" "Dmitry Groshev - Contributing developer for version 2.30. Lead developer and " "maintainer from version 3.00 to the present." msgstr "" "Dmitry Groshev - Mede-ontwikkelaar voor versie 2.30. Hoofd ontwikkeling en " "onderhoud vanaf versie 3.00 tot op heden." #: src/help.c:155 msgid "" "Mark Tyler - Original author and maintainer up to version 3.00, occasional " "contributor thereafter." msgstr "" "Mark Tyler - Oorspronkelijke auteur en ontwikkelaar tot aan versie 3.00, " "sindsdien af en toe bijdrager." #: src/help.c:156 msgid "" "Xiaolin Wu - Wrote the Wu quantizing method - see wu.c for more " "information.\n" "\n" msgstr "" "Xiaolin Wu - Ontwierp de Wu-kwantiseer-methode - zie voor meer informatie wu." "c.\n" "\n" #: src/help.c:157 msgid "" "General Contributions (Feedback and Ideas for improvements unless otherwise " "stated)\n" msgstr "" "Algemene bijdragen (terugkoppeling en ideeën voor verbeteringen, tenzij " "anders vermeld)\n" #: src/help.c:158 msgid "Abdulla Al Muhairi - Website redesign April 2005" msgstr "Abdulla Al Muhari - herontwerp website April 2005" #: src/help.c:159 msgid "Alan Horkan" msgstr "Alan Horkan" #: src/help.c:160 msgid "Alexandre Prokoudine" msgstr "Alexandre Prokoudine" #: src/help.c:161 msgid "Antonio Andrea Bianco" msgstr "Antonio Andrea Bianco" #: src/help.c:162 msgid "Charlie Ledocq" msgstr "" #: src/help.c:163 msgid "Dennis Lee" msgstr "Dennis Lee" #: src/help.c:164 msgid "Donald White" msgstr "" #: src/help.c:165 msgid "Ed Jason" msgstr "Ed Jason" #: src/help.c:166 msgid "" "Eddie Kohler - Created Gifsicle which is needed for the creation and viewing " "of animated GIF files http://www.lcdf.org/gifsicle/" msgstr "" "Eddie Kohler - Ontwierp 'Gifsicle', benodigd voor het maken en bekijken van " "GIF-animaties http://www.lcdf.org/gifsicle/" #: src/help.c:167 msgid "" "Guadalinex Team (Junta de Andalucia) - man page, Launchpad/Rosetta " "registration" msgstr "" "Het Guadilinex Team (Junta de Andalucia) - man page, Launchpad/Rosetta-" "registratie" #: src/help.c:168 msgid "Lou Afonso" msgstr "Lou Alfonso" #: src/help.c:169 msgid "Magnus Hjorth" msgstr "Magnus Hjorth" #: src/help.c:170 msgid "Martin Zelaia" msgstr "Martin Zelaia" #: src/help.c:171 msgid "Pasi Kallinen" msgstr "" #: src/help.c:172 msgid "Pavel Ruzicka" msgstr "Pavel Ruzicka" #: src/help.c:173 msgid "Puppy Linux (Barry Kauler)" msgstr "Puppy Linux (Barry Kauler)" #: src/help.c:174 msgid "Victor Copovi" msgstr "" #: src/help.c:175 msgid "Vlastimil Krejcir" msgstr "Vlastimil Krejcir" #: src/help.c:176 msgid "" "William Kern\n" "\n" msgstr "" "William Kern\n" "\n" #: src/help.c:177 msgid "Translations\n" msgstr "Vertalingen\n" #: src/help.c:178 msgid "Brazilian Portuguese - Paulo Trevizan, Valter Nazianzeno" msgstr "Braziliaans-Portugees - Paulo Trevizan, Valter Nazianzeno" #: src/help.c:179 msgid "Czech - Pavel Ruzicka, Martin Petricek, Roman Hornik, Pavel Fric" msgstr "Tsjechisch - Pavel Ruzicka, Martin Petricek, Roman Hornik, Pavel Fric" #: src/help.c:180 msgid "Dutch - Hans Strijards, Pjotr" msgstr "Nederlands - Hans Strijards, Pjotr" #: src/help.c:181 msgid "" "French - Nicolas Velin, Pascal Billard, Sylvain Cresto, Johan Serre, " "Philippe Etienne, Victor Copovi" msgstr "" "Frans - Nicolas Velin, Pascal Billard, Sylvain Cresto, Johan Serre, Philippe " "Etienne, Victor Copovi" #: src/help.c:182 msgid "Galician - Miguel Anxo Bouzada" msgstr "Galicisch - Miguel Anxo Bouzada" #: src/help.c:183 msgid "German - Oliver Frommel, B. Clausius, Ulrich Ringel, Simon Brixel" msgstr "Duits - Oliver Frommel, B. Clausius, Ulrich Ringel, Simon Brixel" #: src/help.c:184 msgid "Hungarian - Ur Balazs" msgstr "Hongaars - Ur Balazs" #: src/help.c:185 msgid "Italian - Angelo Gemmi" msgstr "Italiaans - Angelo Gemmi" #: src/help.c:186 msgid "Japanese - Norihiro YONEDA" msgstr "Japans - Norihiro YONEDA" #: src/help.c:187 msgid "Kabyle - Yacine Bouklif" msgstr "" #: src/help.c:188 msgid "Polish - Bartosz Kaszubowski, LucaS" msgstr "Pools - Bartosz Kaszubowski, LucaS" #: src/help.c:189 msgid "Portuguese - Israel G. Lugo, Tiago Silva" msgstr "Portugees - Israel G. Lugo, Tiago Silva" #: src/help.c:190 msgid "Russian - Sergey Irupin, Dmitry Groshev" msgstr "Russisch - Sergey Irupin, Dmitry Groshev" #: src/help.c:191 msgid "Simplified Chinese - Cecc" msgstr "Vereenvoudigd Chinees - Cecc" #: src/help.c:192 msgid "Slovak - Jozef Riha" msgstr "Slowaaks - Jozef Riha" #: src/help.c:193 msgid "" "Spanish - Guadalinex Team (Junta de Andalucia), Antonio Sanchez Leon, Miguel " "Anxo Bouzada, Francisco Jose Rey, Adolfo Jayme" msgstr "" "Spaans - Guadalinex Team (Junta de Andalucia), Antonio Sanchez Leon, Miguel " "Anxo Bouzada, Francisco Jose Rey, Adolfo Jayme" #: src/help.c:194 msgid "Swedish - Daniel Nylander, Daniel Eriksson" msgstr "Zweeds - Daniel Nylander, Daniel Eriksson" #: src/help.c:195 msgid "Tagalog - Anjelo delCarmen" msgstr "" #: src/help.c:196 msgid "Taiwanese Chinese - Wei-Lun Chao" msgstr "Taiwanees-Chinees - Wei-Lun Chao" #: src/help.c:197 msgid "Turkish - Muhammet Kara, Tutku Dalmaz" msgstr "Turks - Muhammet Kara, Tutku Dalmaz" #: src/info.c:258 msgid "Information" msgstr "Informatie" #: src/info.c:260 msgid "Memory" msgstr "Geheugen" #: src/info.c:261 msgid "Total memory for main + undo images" msgstr "Totaal geheugen voor primaire en ongedaan-afbeeldingen" #: src/info.c:263 msgid "Undo / Redo / Max levels used" msgstr "Maak ongedaan / Doe opnieuw / Max gebruikte niveaus" #: src/info.c:265 msgid "Unused" msgstr "Ongebruikt" #: src/info.c:269 msgid "Unique RGB pixels" msgstr "Unieke RGB-pixels" #: src/info.c:272 src/layer.c:121 msgid "Layers" msgstr "Lagen" #: src/info.c:273 msgid "Total layer memory usage" msgstr "Totaal geheugengebruik voor lagen" #: src/info.c:277 msgid "Colour Histogram" msgstr "Kleurenhistogram" #: src/info.c:289 src/otherwindow.c:1614 msgid "Index" msgstr "Index" #: src/info.c:290 msgid "Canvas pixels" msgstr "Canvas pixels" #: src/info.c:328 #, c-format msgid "Clipboard = %i x %i" msgstr "Klembord = %i x %i" #: src/info.c:328 #, c-format msgid "Clipboard = %i x %i x RGB" msgstr "Klembord = %i x %i x RGB" #: src/info.c:377 msgid "Orphans" msgstr "Wezen" #: src/info.c:383 #, c-format msgid "Colour index totals - %i of %i used" msgstr "Kleuren-index totalen - %i van %i gebruikt" #: src/inifile.c:966 msgid "" "Could not find home directory. Using current directory as home directory." msgstr "" "Kon persoonlijke map niet vinden. Gebruikt nu huidige map als persoonlijke " "map." #: src/layer.c:63 msgid "Background" msgstr "Achtergrond" #: src/layer.c:122 src/mainwindow.c:5931 msgid "(Modified)" msgstr "(Aangepast)" #: src/layer.c:123 src/mainwindow.c:5932 msgid "Untitled" msgstr "Naamloos" #: src/layer.c:308 #, c-format msgid "Do you really want to delete layer %i (%s) ?" msgstr "Wilt u echt laag %i (%s) wissen?" #: src/layer.c:380 msgid "" "One or more of the layers contains changes that have not been saved. Do you " "really want to lose these changes?" msgstr "" "Een of meer lagen bevatten bewerkingen die niet zijn opgeslagen. Wilt u deze " "bewerkingen werkelijk kwijtraken?" #: src/layer.c:381 src/mainwindow.c:1028 msgid "Cancel Operation" msgstr "Bewerking annuleren" #: src/layer.c:381 src/mainwindow.c:1028 msgid "Lose Changes" msgstr "Afsluiten en bewerkingen verliezen" #: src/layer.c:523 #, c-format msgid "%d layers failed to load" msgstr "%d lagen konden niet geladen worden" #: src/layer.c:826 msgid "" "One or more of the image layers has not been saved. You must save each " "image individually before saving the layers text file in order to load this " "composite image in the future." msgstr "" "Een of meer afbeeldingslagen zijn niet bewaard. U moet elke afbeelding " "afzonderlijk opslaan voordat u het tekstbestand van de laag opslaat, om zo " "later deze samengestelde afbeelding te kunnen laden." #: src/layer.c:841 msgid "Do you really want to delete all of the layers?" msgstr "Wilt u werkelijk alle lagen wissen?" #: src/layer.c:970 msgid "You cannot add any more layers." msgstr "U kunt geen lagen meer toevoegen." #: src/layer.c:1083 src/otherwindow.c:241 msgid "New Layer" msgstr "Nieuwe laag" #: src/layer.c:1085 msgid "Raise" msgstr "Omhoog" #: src/layer.c:1087 msgid "Lower" msgstr "Omlaag" #: src/layer.c:1089 msgid "Duplicate Layer" msgstr "Laag verdubbelen" #: src/layer.c:1091 msgid "Centralise Layer" msgstr "Laag centraliseren" #: src/layer.c:1093 msgid "Delete Layer" msgstr "Laag wissen" #: src/layer.c:1095 msgid "Close Layers Window" msgstr "Lagenvenster sluiten" #: src/layer.c:1101 msgid "Layer Name" msgstr "Naam van de laag" #: src/layer.c:1104 src/toolbar.c:209 msgid "Position" msgstr "Positie" #: src/layer.c:1112 msgid "Transparent Colour" msgstr "Transparante kleur" #: src/layer.c:1117 msgid "Show all layers in main window" msgstr "Toon alle lagen in het hoofdvenster" #: src/mainwindow.c:67 src/otherwindow.c:844 src/otherwindow.c:2756 #: src/toolbar.c:342 msgid "Image" msgstr "Afbeelding" #: src/mainwindow.c:69 src/mainwindow.c:489 src/otherwindow.c:1613 #: src/otherwindow.c:2302 msgid "RGB" msgstr "RGB" #: src/mainwindow.c:69 src/otherwindow.c:1613 src/otherwindow.c:2302 msgid "sRGB" msgstr "" #: src/mainwindow.c:342 msgid "There were no unused colours to remove!" msgstr "Er waren geen ongebruikte kleuren om te verwijderen!" #: src/mainwindow.c:371 msgid "The palette does not contain 2 colours that have identical RGB values" msgstr "Het palet bevat geen twee kleuren met dezelfde RGB-waarden" #: src/mainwindow.c:374 #, c-format msgid "" "The palette contains %i colours that have identical RGB values. Do you " "really want to merge them into one index and realign the canvas?" msgstr "" "Het palet bevat %i kleuren met identieke RGB-waarden. Wilt u ze echt in één " "index samenbrengen en het canvas opnieuw uitlijnen?" #: src/mainwindow.c:492 msgid "indexed" msgstr "geïndexeerd" #: src/mainwindow.c:498 #, c-format msgid "" "You are trying to save an %s image to an %s file which is not possible. I " "would suggest you save with a PNG extension." msgstr "" "U probeert een %s afbeelding op te slaan als een %s bestand, hetgeen niet " "mogelijk is. U wordt aangeraden om het op te slaan met een PNG-extensie." #: src/mainwindow.c:500 #, c-format msgid "" "You are trying to save an %s file with a palette of more than %d colours. " "Either use another format or reduce the palette to %d colours." msgstr "" "U probeert een %s bestand op te slaan met een palet van meer dan %d kleuren. " "U moet of een ander bestandtype kiezen, of het palet terugbrengen tot %d " "kleuren." #: src/mainwindow.c:578 msgid "Unable to load clipboard" msgstr "Kan klembord niet laden" #: src/mainwindow.c:604 msgid "Unable to save clipboard" msgstr "Kan klembord niet opslaan" #: src/mainwindow.c:775 msgid "Zoom in" msgstr "" #: src/mainwindow.c:777 msgid "Zoom out" msgstr "" #: src/mainwindow.c:779 #, c-format msgid "10% zoom" msgstr "" #: src/mainwindow.c:781 #, c-format msgid "25% zoom" msgstr "" #: src/mainwindow.c:783 #, c-format msgid "50% zoom" msgstr "" #: src/mainwindow.c:785 #, c-format msgid "100% zoom" msgstr "" #: src/mainwindow.c:787 #, c-format msgid "400% zoom" msgstr "" #: src/mainwindow.c:789 #, c-format msgid "600% zoom" msgstr "" #: src/mainwindow.c:791 #, c-format msgid "800% zoom" msgstr "" #: src/mainwindow.c:793 #, c-format msgid "1000% zoom" msgstr "" #: src/mainwindow.c:795 #, c-format msgid "1200% zoom" msgstr "" #: src/mainwindow.c:797 #, c-format msgid "1600% zoom" msgstr "" #: src/mainwindow.c:799 #, c-format msgid "2000% zoom" msgstr "" #: src/mainwindow.c:801 #, c-format msgid "4000% zoom" msgstr "" #: src/mainwindow.c:803 #, c-format msgid "8000% zoom" msgstr "" #: src/mainwindow.c:805 #, c-format msgid "10% opacity" msgstr "" #: src/mainwindow.c:807 #, c-format msgid "20% opacity" msgstr "" #: src/mainwindow.c:809 #, c-format msgid "30% opacity" msgstr "" #: src/mainwindow.c:811 #, c-format msgid "40% opacity" msgstr "" #: src/mainwindow.c:813 #, c-format msgid "50% opacity" msgstr "" #: src/mainwindow.c:815 #, c-format msgid "60% opacity" msgstr "" #: src/mainwindow.c:817 #, c-format msgid "70% opacity" msgstr "" #: src/mainwindow.c:819 #, c-format msgid "80% opacity" msgstr "" #: src/mainwindow.c:821 #, c-format msgid "90% opacity" msgstr "" #: src/mainwindow.c:823 #, c-format msgid "100% opacity" msgstr "" #: src/mainwindow.c:825 msgid "Increase opacity" msgstr "" #: src/mainwindow.c:827 msgid "Decrease opacity" msgstr "" #: src/mainwindow.c:829 msgid "Draw open arrow head" msgstr "" #: src/mainwindow.c:831 msgid "Draw closed arrow head" msgstr "" #: src/mainwindow.c:833 msgid "Previous colour A" msgstr "" #: src/mainwindow.c:835 msgid "Next colour A" msgstr "" #: src/mainwindow.c:837 msgid "Previous colour B" msgstr "" #: src/mainwindow.c:839 msgid "Next colour B" msgstr "" #: src/mainwindow.c:841 msgid "Previous pattern" msgstr "" #: src/mainwindow.c:843 msgid "Next pattern" msgstr "" #: src/mainwindow.c:845 msgid "Larger brush" msgstr "" #: src/mainwindow.c:847 msgid "Smaller brush" msgstr "" #: src/mainwindow.c:849 msgid "View window - Zoom in" msgstr "" #: src/mainwindow.c:851 msgid "View window - Zoom out" msgstr "" #: src/mainwindow.c:1027 msgid "" "This canvas/palette contains changes that have not been saved. Do you " "really want to lose these changes?" msgstr "" "De afbeelding of het palet bevatten veranderingen die nog niet zijn " "opgeslagen. Wilt u werkelijk deze veranderingen wissen?" #: src/mainwindow.c:1094 msgid "Do you really want to quit?" msgstr "Weet u zeker dat u wilt afsluiten?" #: src/mainwindow.c:3754 msgid "Empty string or broken quoting" msgstr "" #: src/mainwindow.c:3755 msgid "Script must begin with a command" msgstr "" #: src/mainwindow.c:3756 msgid "Script nesting limit exceeded" msgstr "" #: src/mainwindow.c:3765 #, c-format msgid "'%s' does not match any item" msgstr "" #: src/mainwindow.c:3767 #, c-format msgid "'%s' matches a non-scriptable item" msgstr "" #: src/mainwindow.c:3769 #, c-format msgid "'%s' matches a disabled item" msgstr "" #: src/mainwindow.c:3788 #, c-format msgid "'%s' value does not fit item" msgstr "" #: src/mainwindow.c:3969 msgid "Script" msgstr "" #: src/mainwindow.c:3982 src/spawn.c:656 src/spawn.c:662 msgid "Action" msgstr "Actie" #: src/mainwindow.c:3991 src/spawn.c:666 msgid "Execute" msgstr "Uitvoeren" #: src/mainwindow.c:4045 msgid "Unable to load script" msgstr "" #: src/mainwindow.c:5182 msgid "/_File" msgstr "/_Bestand" #: src/mainwindow.c:5184 msgid "//New" msgstr "//Nieuw" #: src/mainwindow.c:5186 msgid "//Open ..." msgstr "//Openen ..." #: src/mainwindow.c:5188 src/mainwindow.c:5669 msgid "//Save" msgstr "//Opslaan" #: src/mainwindow.c:5190 src/mainwindow.c:5549 src/mainwindow.c:5627 #: src/mainwindow.c:5671 msgid "//Save As ..." msgstr "//Opslaan als ..." #: src/mainwindow.c:5192 msgid "//Export Undo Images ..." msgstr "//Ongedaan-afbeeldingen exporteren ..." #: src/mainwindow.c:5194 msgid "//Export Undo Images (reversed) ..." msgstr "//Ongedaan-afbeeldingen exporteren (omgekeerd) ..." #: src/mainwindow.c:5196 msgid "//Export ASCII Art ..." msgstr "//ASCII-kunst exporteren ..." #: src/mainwindow.c:5198 msgid "//Export Animated GIF ..." msgstr "//GIF-animatie exporteren ..." #: src/mainwindow.c:5201 msgid "//Actions" msgstr "//Acties" #: src/mainwindow.c:5235 src/mainwindow.c:5488 msgid "///Configure" msgstr "///Configureren" #: src/mainwindow.c:5290 msgid "//Quit" msgstr "//Afsluiten" #: src/mainwindow.c:5293 msgid "/_Edit" msgstr "/_Bewerken" #: src/mainwindow.c:5295 msgid "//Undo" msgstr "//Ongedaan maken" #: src/mainwindow.c:5297 msgid "//Redo" msgstr "//Opnieuw doen" #: src/mainwindow.c:5300 msgid "//Cut" msgstr "//Knippen" #: src/mainwindow.c:5302 msgid "//Copy" msgstr "//Kopiëren" #: src/mainwindow.c:5304 msgid "//Copy To Palette" msgstr "//Naar het palet kopiëren" #: src/mainwindow.c:5306 msgid "//Paste To Centre" msgstr "//Plak in het midden" #: src/mainwindow.c:5308 msgid "//Paste To New Layer" msgstr "//In nieuwe laag plakken" #: src/mainwindow.c:5310 msgid "//Paste" msgstr "//Plakken" #: src/mainwindow.c:5312 msgid "//Paste Text" msgstr "//Tekst plakken" #: src/mainwindow.c:5318 msgid "//Paste Text (FreeType)" msgstr "//Tekst plakken (FreeType)" #: src/mainwindow.c:5321 msgid "//Paste Palette" msgstr "//Palet plakken" #: src/mainwindow.c:5323 msgid "//Load Clipboard" msgstr "//Klembord laden" #: src/mainwindow.c:5350 msgid "//Save Clipboard" msgstr "//Klembord opslaan" #: src/mainwindow.c:5377 msgid "//Import Clipboard from System" msgstr "//Importeer klembord uit het systeem" #: src/mainwindow.c:5378 msgid "//Export Clipboard to System" msgstr "//Exporteer klembord naar het systeem" #: src/mainwindow.c:5381 msgid "//Choose Pattern ..." msgstr "//Patroon kiezen ..." #: src/mainwindow.c:5383 msgid "//Choose Brush ..." msgstr "//Penseel kiezen ..." #: src/mainwindow.c:5385 msgid "//Choose Colour ..." msgstr "//Kleur kiezen ..." #: src/mainwindow.c:5392 msgid "/_View" msgstr "/_Bekijken" #: src/mainwindow.c:5394 msgid "//Show Main Toolbar" msgstr "//Primaire taakbalk tonen" #: src/mainwindow.c:5396 msgid "//Show Tools Toolbar" msgstr "//Werkbalk 'gereedschap' tonen" #: src/mainwindow.c:5399 msgid "//Show Settings Toolbar" msgstr "//Werkbalk 'Instellingen' tonen" #: src/mainwindow.c:5402 msgid "//Show Dock" msgstr "//Dok tonen" #: src/mainwindow.c:5404 msgid "//Show Palette" msgstr "//Palet tonen" #: src/mainwindow.c:5406 msgid "//Show Status Bar" msgstr "//Statusbalk tonen" #: src/mainwindow.c:5409 msgid "//Toggle Image View" msgstr "//Afbeeldingbezichtiging omschakelen" #: src/mainwindow.c:5413 msgid "//Centralize Image" msgstr "//Afbeelding in het midden plaatsen" #: src/mainwindow.c:5414 msgid "//Show Zoom Grid" msgstr "//Zoomraster tonen" #: src/mainwindow.c:5415 msgid "//Snap To Tile Grid" msgstr "//Uitlijnen met tegelraster" #: src/mainwindow.c:5417 msgid "//Configure Grid ..." msgstr "//Raster instellen ..." #: src/mainwindow.c:5418 msgid "//Tracing Image ..." msgstr "//Afbeelding opsporen ..." #: src/mainwindow.c:5421 msgid "//View Window" msgstr "//Venster bekijken" #: src/mainwindow.c:5423 msgid "//Horizontal Split" msgstr "//Horizontaal splitsen" #: src/mainwindow.c:5425 msgid "//Focus View Window" msgstr "//Kijkvenster focusseren" #: src/mainwindow.c:5427 msgid "//Pan Window" msgstr "//Overzichtsvenster" #: src/mainwindow.c:5430 msgid "//Layers Window" msgstr "//Lagenvenster" #: src/mainwindow.c:5433 msgid "/_Image" msgstr "/_Afbeelding" #: src/mainwindow.c:5436 msgid "//Convert To RGB" msgstr "//Omzetten naar RGB" #: src/mainwindow.c:5438 msgid "//Convert To Indexed ..." msgstr "//Omzetten naar geïndexeerd ..." #: src/mainwindow.c:5441 msgid "//Scale Canvas ..." msgstr "//Canvas schalen ..." #: src/mainwindow.c:5443 msgid "//Resize Canvas ..." msgstr "//Canvasgrootte veranderen ..." #: src/mainwindow.c:5445 msgid "//Crop" msgstr "//Bijsnijden" #: src/mainwindow.c:5448 src/mainwindow.c:5517 msgid "//Flip Vertically" msgstr "//Verticaal draaien" #: src/mainwindow.c:5449 src/mainwindow.c:5519 msgid "//Flip Horizontally" msgstr "//Horizontaal draaien" #: src/mainwindow.c:5452 src/mainwindow.c:5521 msgid "//Rotate Clockwise" msgstr "//Met de klok mee draaien" #: src/mainwindow.c:5453 src/mainwindow.c:5523 msgid "//Rotate Anti-Clockwise" msgstr "//Tegen de klok in draaien" #: src/mainwindow.c:5454 msgid "//Free Rotate ..." msgstr "//Vrij draaien ..." #: src/mainwindow.c:5455 msgid "//Skew ..." msgstr "//Scheeftrekken ..." #: src/mainwindow.c:5458 msgid "//Segment ..." msgstr "//Segmenteren ..." #: src/mainwindow.c:5462 msgid "//Script ..." msgstr "" #: src/mainwindow.c:5464 msgid "//Scripts" msgstr "" #: src/mainwindow.c:5491 msgid "//Information ..." msgstr "//Informatie ..." #: src/mainwindow.c:5494 msgid "//Preferences ..." msgstr "//Voorkeuren ..." #: src/mainwindow.c:5497 msgid "/_Selection" msgstr "/_Selectie" #: src/mainwindow.c:5499 msgid "//Select All" msgstr "//Alles selecteren" #: src/mainwindow.c:5501 msgid "//Select None (Esc)" msgstr "//Niets selecteren (Esc)" #: src/mainwindow.c:5503 msgid "//Lasso Selection" msgstr "//Lasso-selectie" #: src/mainwindow.c:5505 msgid "//Lasso Selection Cut" msgstr "//Lasso-selectie knippen" #: src/mainwindow.c:5508 msgid "//Outline Selection" msgstr "//Selectie schetsen" #: src/mainwindow.c:5510 msgid "//Fill Selection" msgstr "//Selectie opvullen" #: src/mainwindow.c:5512 msgid "//Outline Ellipse" msgstr "//Ellips schetsen" #: src/mainwindow.c:5514 msgid "//Fill Ellipse" msgstr "//Ellips opvullen" #: src/mainwindow.c:5526 msgid "//Horizontal Ramp" msgstr "//Horizontale helling" #: src/mainwindow.c:5528 msgid "//Vertical Ramp" msgstr "//Verticale helling" #: src/mainwindow.c:5531 msgid "//Alpha Blend A,B" msgstr "//Alpha mengen A,B" #: src/mainwindow.c:5533 msgid "//Move Alpha to Mask" msgstr "//Alpha verplaatsen naar masker" #: src/mainwindow.c:5535 msgid "//Mask Colour A,B" msgstr "//Maskeer kleur A,B" #: src/mainwindow.c:5537 msgid "//Unmask Colour A,B" msgstr "//Ontmaskeer kleur A,B" #: src/mainwindow.c:5539 msgid "//Mask All Colours" msgstr "//Maskeer alle kleuren" #: src/mainwindow.c:5541 msgid "//Clear Mask" msgstr "//Verwijder masker" #: src/mainwindow.c:5544 msgid "/_Palette" msgstr "/_Palet" #: src/mainwindow.c:5548 src/mainwindow.c:5626 msgid "//Load ..." msgstr "//Laden ..." #: src/mainwindow.c:5550 msgid "//Load Default" msgstr "//Standaard laden" #: src/mainwindow.c:5552 msgid "//Mask All" msgstr "//Alles maskeren" #: src/mainwindow.c:5553 msgid "//Mask None" msgstr "//Niets maskeren" #: src/mainwindow.c:5555 msgid "//Swap A & B" msgstr "//A & B omwisselen" #: src/mainwindow.c:5557 msgid "//Edit Colour A & B ..." msgstr "//Kleuren A & B bewerken ..." #: src/mainwindow.c:5559 msgid "//Dither A" msgstr "//Kleur A rasteren" #: src/mainwindow.c:5561 msgid "//Palette Editor ..." msgstr "//Paletbewerker ..." #: src/mainwindow.c:5563 msgid "//Set Palette Size ..." msgstr "//Paletgrootte instellen ..." #: src/mainwindow.c:5564 msgid "//Merge Duplicate Colours" msgstr "//Dubbele kleuren samenvoegen" #: src/mainwindow.c:5566 msgid "//Remove Unused Colours" msgstr "//Verwijder ongebruikte kleuren" #: src/mainwindow.c:5569 msgid "//Create Quantized ..." msgstr "//Vast aantal aanmaken ..." #: src/mainwindow.c:5572 msgid "//Sort Colours ..." msgstr "//Kleuren ordenen ..." #: src/mainwindow.c:5573 msgid "//Palette Shifter ..." msgstr "//Paletwisselaar ..." #: src/mainwindow.c:5574 msgid "//Pick Gradient ..." msgstr "//Verloop assembleren ..." #: src/mainwindow.c:5576 msgid "/Effe_cts" msgstr "/Effe_cten" #: src/mainwindow.c:5578 msgid "//Transform Colour ..." msgstr "//Kleur omvormen ..." #: src/mainwindow.c:5580 msgid "//Invert" msgstr "//Invoegen" #: src/mainwindow.c:5582 msgid "//Greyscale" msgstr "//Grijstinten" #: src/mainwindow.c:5584 msgid "//Greyscale (Gamma corrected)" msgstr "//Grijstinten (gamma-gecorrigeerd)" #: src/mainwindow.c:5586 msgid "//Normalize" msgstr "" #: src/mainwindow.c:5587 src/mainwindow.c:5658 msgid "//Threshold ..." msgstr "//Drempel ..." #: src/mainwindow.c:5588 msgid "//Map ..." msgstr "" #: src/mainwindow.c:5590 msgid "//Isometric Transformation" msgstr "//Isometrische omvorming" #: src/mainwindow.c:5592 msgid "///Left Side Down" msgstr "///Linkerkant omlaag" #: src/mainwindow.c:5593 msgid "///Right Side Down" msgstr "///Rechterkant omlaag" #: src/mainwindow.c:5594 msgid "///Top Side Right" msgstr "///Bovenkant rechts" #: src/mainwindow.c:5595 msgid "///Bottom Side Right" msgstr "///Onderkant rechts" #: src/mainwindow.c:5598 msgid "//Edge Detect ..." msgstr "//Randen detecteren ..." #: src/mainwindow.c:5600 msgid "//Difference of Gaussians ..." msgstr "//Verschil van Gausiaans ..." #: src/mainwindow.c:5602 msgid "//Sharpen ..." msgstr "//Verscherpen ..." #: src/mainwindow.c:5604 msgid "//Unsharp Mask ..." msgstr "//Onscherp masker ..." #: src/mainwindow.c:5606 msgid "//Soften ..." msgstr "//Verzachten ..." #: src/mainwindow.c:5608 msgid "//Gaussian Blur ..." msgstr "//Gaussiaanse vervaging ..." #: src/mainwindow.c:5610 msgid "//Kuwahara-Nagao Blur ..." msgstr "//Kuwahara-Nagao vervaging ..." #: src/mainwindow.c:5612 msgid "//Emboss" msgstr "//Ciseleren" #: src/mainwindow.c:5614 msgid "//Dilate" msgstr "//Aandikken" #: src/mainwindow.c:5616 msgid "//Erode" msgstr "//Eroderen" #: src/mainwindow.c:5619 msgid "//Solid Noise ..." msgstr "" #: src/mainwindow.c:5620 msgid "//Bacteria ..." msgstr "//Korrelig ..." #: src/mainwindow.c:5623 msgid "/Cha_nnels" msgstr "/Ka_nalen" #: src/mainwindow.c:5625 msgid "//New ..." msgstr "//Nieuw ..." #: src/mainwindow.c:5628 msgid "//Delete ..." msgstr "//Wissen ..." #: src/mainwindow.c:5632 msgid "//Edit Image" msgstr "//Afbeelding bewerken" #: src/mainwindow.c:5635 msgid "//Edit Alpha" msgstr "//Alpha bewerken" #: src/mainwindow.c:5638 msgid "//Edit Selection" msgstr "//Selectie bewerken" #: src/mainwindow.c:5641 msgid "//Edit Mask" msgstr "//Masker bewerken" #: src/mainwindow.c:5645 msgid "//Hide Image" msgstr "//Afbeelding verbergen" #: src/mainwindow.c:5648 msgid "//Disable Alpha" msgstr "//Alpha uitschakelen" #: src/mainwindow.c:5651 msgid "//Disable Selection" msgstr "//Selectie uitschakelen" #: src/mainwindow.c:5654 msgid "//Disable Mask" msgstr "//Masker uitschakelen" #: src/mainwindow.c:5657 msgid "//Couple RGBA Operations" msgstr "//RGBA-bewerkingen koppelen" #: src/mainwindow.c:5659 msgid "//Unassociate Alpha" msgstr "//Alpha losmaken" #: src/mainwindow.c:5663 msgid "//View Alpha as an Overlay" msgstr "//Bekijk Alpha als een bovenlaag" #: src/mainwindow.c:5664 msgid "//Configure Overlays ..." msgstr "//Bovenlagen instellen ..." #: src/mainwindow.c:5666 msgid "/_Layers" msgstr "/_Lagen" #: src/mainwindow.c:5668 msgid "//New Layer" msgstr "//Nieuwe laag" #: src/mainwindow.c:5672 msgid "//Save Composite Image ..." msgstr "//Samengestelde afbeelding opslaan ..." #: src/mainwindow.c:5673 msgid "//Composite to New Layer" msgstr "//Samenstellen in een nieuwe laag" #: src/mainwindow.c:5674 msgid "//Remove All Layers" msgstr "//Alle lagen verwijderen" #: src/mainwindow.c:5676 msgid "//Configure Animation ..." msgstr "//Animatie instellen ..." #: src/mainwindow.c:5677 msgid "//Preview Animation ..." msgstr "//Animatie-voorbeeldweergave ..." #: src/mainwindow.c:5678 msgid "//Set Key Frame ..." msgstr "//Hoofdkader instellen ..." #: src/mainwindow.c:5679 msgid "//Remove All Key Frames ..." msgstr "//Alle hoofdkaders verwijderen ..." #: src/mainwindow.c:5681 msgid "/More..." msgstr "/Meer..." #: src/mainwindow.c:5683 msgid "/_Help" msgstr "/_Hulp" #: src/mainwindow.c:5684 msgid "//Documentation" msgstr "//Documentatie" #: src/mainwindow.c:5686 msgid "//About" msgstr "//Over" #: src/mainwindow.c:5689 msgid "//Keyboard Shortcuts ..." msgstr "" #: src/mainwindow.c:5690 msgid "//Rebind Shortcut Keycodes" msgstr "//Toetscodes sneltoetsen herbinden" #: src/memory.c:2800 msgid "Quantize Pass 1" msgstr "Quantize ronde 1" #: src/memory.c:2854 msgid "Quantize Pass 2" msgstr "Quantize ronde 2" #: src/memory.c:3073 src/memory.c:3458 msgid "Converting to Indexed Palette" msgstr "Bezig met omzetten naar een geïndexeerd palet" #: src/memory.c:5135 src/otherwindow.c:540 msgid "Bacteria Effect" msgstr "Korrel-effect" #: src/memory.c:5170 msgid "Rotating" msgstr "Aan het draaien" #: src/memory.c:5511 msgid "Free Rotation" msgstr "Vrije draaiing" #: src/memory.c:6096 msgid "Scaling Image" msgstr "Afbeelding aan het schalen" #: src/memory.c:7560 msgid "Counting Unique RGB Pixels" msgstr "Unieke RGB-pixels aan het tellen" #: src/memory.c:7608 msgid "Applying Effect" msgstr "Effect aan het toepassen" #: src/memory.c:8792 msgid "Kuwahara-Nagao Filter" msgstr "Kuwahara-Nagao-filter" #: src/memory.c:10456 src/otherwindow.c:2665 msgid "Skew" msgstr "Scheeftrekken" #: src/memory.c:10630 msgid "Segmentation Pass 1" msgstr "Segmentatieronde 1" #: src/memory.c:10757 msgid "Segmentation Pass 2" msgstr "Segmentatieronde 2" #: src/memory.c:11019 src/otherwindow.c:3156 msgid "Solid Noise" msgstr "" #: src/mygtk.c:134 src/mygtk.c:163 msgid "Please Wait ..." msgstr "Even wachten a.u.b...." #: src/mygtk.c:141 msgid "STOP" msgstr "STOP" #: src/mygtk.c:504 msgid "Disabled" msgstr "" #: src/mygtk.c:504 src/toolbar.c:301 msgid "Screen" msgstr "Scherm" #: src/mygtk.c:504 msgid "Window" msgstr "" #: src/mygtk.c:508 msgid "Input" msgstr "" #: src/mygtk.c:512 msgid "Device:" msgstr "" #: src/mygtk.c:514 msgid "Mode:" msgstr "" #: src/mygtk.c:519 msgid "Axes" msgstr "" #: src/mygtk.c:524 msgid "X:" msgstr "" #: src/mygtk.c:525 msgid "Y:" msgstr "" #: src/mygtk.c:526 msgid "Pressure:" msgstr "" #: src/mygtk.c:527 msgid "X tilt:" msgstr "" #: src/mygtk.c:528 msgid "Y tilt:" msgstr "" #: src/mygtk.c:529 msgid "Wheel:" msgstr "" #: src/mygtk.c:579 msgid "none" msgstr "" #: src/otherwindow.c:236 msgid "24 bit RGB" msgstr "24-bits RGB" #: src/otherwindow.c:236 src/otherwindow.c:3179 msgid "Greyscale" msgstr "Grijstinten" #: src/otherwindow.c:237 msgid "Indexed Palette" msgstr "Geïndexeerd palet" #: src/otherwindow.c:237 msgid "From Clipboard" msgstr "Vanuit het klembord" #: src/otherwindow.c:237 msgid "Grab Screenshot" msgstr "Schermafdruk pakken" #: src/otherwindow.c:242 src/toolbar.c:542 msgid "New Image" msgstr "Nieuwe afbeelding" #: src/otherwindow.c:246 src/otherwindow.c:3164 msgid "Colours" msgstr "Kleuren" #: src/otherwindow.c:409 msgid "Pattern Chooser" msgstr "Patroonkiezer" #: src/otherwindow.c:497 msgid "Set Palette Size" msgstr "Paletgrootte instellen" #: src/otherwindow.c:517 src/otherwindow.c:591 src/otherwindow.c:870 #: src/otherwindow.c:2538 src/otherwindow.c:2776 src/otherwindow.c:2939 #: src/prefs.c:338 src/prefs.c:538 msgid "Apply" msgstr "Toepassen" #: src/otherwindow.c:573 msgid "Luminance" msgstr "Luminantie" #: src/otherwindow.c:573 src/otherwindow.c:814 msgid "Brightness" msgstr "Helderheid" #: src/otherwindow.c:574 msgid "Distance to A" msgstr "Afstand tot A" #: src/otherwindow.c:575 msgid "Projection to A->B" msgstr "Projectie naar A->B" #: src/otherwindow.c:576 msgid "Frequency" msgstr "Frequentie" #: src/otherwindow.c:580 msgid "Sort Palette Colours" msgstr "Paletkleuren ordenen" #: src/otherwindow.c:582 msgid "Start Index" msgstr "Index starten" #: src/otherwindow.c:583 msgid "End Index" msgstr "Index beëindigen" #: src/otherwindow.c:589 msgid "Reverse Order" msgstr "Volgorde omkeren" #: src/otherwindow.c:805 msgid "Bitwise" msgstr "Bitgewijs" #: src/otherwindow.c:805 msgid "Truncated" msgstr "Afgekapt" #: src/otherwindow.c:805 msgid "Rounded" msgstr "Afgerond" #: src/otherwindow.c:809 src/toolbar.c:311 src/toolbar.c:558 msgid "Transform Colour" msgstr "Kleuren omvormen" #: src/otherwindow.c:812 msgid "Gamma" msgstr "Gamma" #: src/otherwindow.c:816 msgid "Contrast" msgstr "Contrast" #: src/otherwindow.c:822 src/otherwindow.c:1674 msgid "Posterize" msgstr "Posteriseren" #: src/otherwindow.c:831 msgid "Show Detail" msgstr "Detail tonen" #: src/otherwindow.c:836 msgid "Posterize type" msgstr "" #: src/otherwindow.c:857 msgid "Auto-Preview" msgstr "Auto-voorbeeldweergave" #: src/otherwindow.c:869 msgid "Reset" msgstr "Terugzetten" #: src/otherwindow.c:931 msgid "New geometry is the same as now - nothing to do." msgstr "De geometrie is hetzelfde gebleven - niets te doen." #: src/otherwindow.c:980 msgid "The operating system cannot allocate the memory for this operation." msgstr "Het besturingssysteem kan geen geheugen vrijmaken voor deze bewerking." #: src/otherwindow.c:982 msgid "" "You have not allocated enough memory in the Preferences window for this " "operation." msgstr "" "U hebt in het Voorkeurenvenster niet genoeg geheugen vrijgemaakt voor deze " "bewerking." #: src/otherwindow.c:993 src/otherwindow.c:2495 msgid "Mirror" msgstr "Spiegelen" #: src/otherwindow.c:993 src/otherwindow.c:994 msgid "Tile" msgstr "Tegelen" #: src/otherwindow.c:993 msgid "Void" msgstr "Leeg" #: src/otherwindow.c:994 src/shifter.c:283 msgid "Clear" msgstr "Wissen" #: src/otherwindow.c:994 msgid "Mirror tile" msgstr "Tegel spiegelen" #: src/otherwindow.c:996 msgid "Nearest Neighbour" msgstr "Naaste buur" #: src/otherwindow.c:997 msgid "Bilinear / Area Mapping" msgstr "Bilineair / Gebied in kaart brengen" #: src/otherwindow.c:998 msgid "Bicubic" msgstr "Bicubisch" #: src/otherwindow.c:999 msgid "Bicubic edged" msgstr "Bicubisch kantig" #: src/otherwindow.c:1000 msgid "Bicubic better" msgstr "Bicubisch beter" #: src/otherwindow.c:1001 msgid "Bicubic sharper" msgstr "Bicubisch scherper" #: src/otherwindow.c:1002 msgid "Blackman-Harris" msgstr "Blackman-Harris" #: src/otherwindow.c:1008 msgid "Scale Canvas" msgstr "Canvas schalen" #: src/otherwindow.c:1009 msgid "Resize Canvas" msgstr "Canvasgrootte veranderen" #: src/otherwindow.c:1012 msgid "Original " msgstr "Origineel " #: src/otherwindow.c:1013 msgid "New" msgstr "Nieuw" #: src/otherwindow.c:1014 msgid "Width " msgstr "Breedte " #: src/otherwindow.c:1018 msgid "Height " msgstr "Hoogte " #: src/otherwindow.c:1023 src/otherwindow.c:2514 src/otherwindow.c:2672 #: src/toolbar.c:212 msgid "Offset" msgstr "Vlakdruk" #: src/otherwindow.c:1026 src/otherwindow.c:1615 src/viewer.c:1209 msgid "Centre" msgstr "Centrum" #: src/otherwindow.c:1033 src/otherwindow.c:1052 msgid "Fix Aspect Ratio" msgstr "Verhouding herstellen" #: src/otherwindow.c:1039 src/otherwindow.c:2070 src/toolbar.c:312 msgid "Settings" msgstr "Instellingen" #: src/otherwindow.c:1046 msgid "Sharper image reduction" msgstr "Scherpere afbeeldingverkleining" #: src/otherwindow.c:1047 msgid "Boundary extension" msgstr "Grensuitbreiding" #: src/otherwindow.c:1613 src/otherwindow.c:2302 msgid "HSV" msgstr "HSV" #: src/otherwindow.c:1614 msgid "Highlight" msgstr "" #: src/otherwindow.c:1615 msgid "Limit" msgstr "Beperken" #: src/otherwindow.c:1616 msgid "Sphere" msgstr "Bol" #: src/otherwindow.c:1616 src/otherwindow.c:2670 msgid "Angle" msgstr "Hoek" #: src/otherwindow.c:1616 msgid "Cube" msgstr "Kubus" #: src/otherwindow.c:1617 msgid "Opaque" msgstr "Ondoorzichtig" #: src/otherwindow.c:1617 msgid "Border" msgstr "Grens" #: src/otherwindow.c:1618 msgid "Transparent" msgstr "Transparant" #: src/otherwindow.c:1618 msgid "Tile " msgstr "Tegel " #: src/otherwindow.c:1618 msgid "Segment" msgstr "" #: src/otherwindow.c:1656 msgid "Scale" msgstr "Verloop" #: src/otherwindow.c:1657 src/otherwindow.c:3059 msgid "From" msgstr "Van" #: src/otherwindow.c:1659 src/otherwindow.c:3061 msgid "To" msgstr "Naar" #: src/otherwindow.c:1699 msgid "Range" msgstr "Bereik" #: src/otherwindow.c:1702 msgid "Inverse" msgstr "Inverse" #: src/otherwindow.c:1710 msgid "Smart grid" msgstr "Slim raster" #: src/otherwindow.c:1712 msgid "Tile grid" msgstr "Tegelraster" #: src/otherwindow.c:1714 msgid "Minimum grid zoom" msgstr "Minimale rasterzoom" #: src/otherwindow.c:1717 msgid "Tile width" msgstr "Tegelbreedte" #: src/otherwindow.c:1720 msgid "Tile height" msgstr "Tegelhoogte" #: src/otherwindow.c:1744 msgid "Palette Editor" msgstr "Paletbewerker" #: src/otherwindow.c:1763 msgid "Configure Overlays" msgstr "Bovenlagen instellen" #: src/otherwindow.c:1782 msgid "Colour Editor" msgstr "Kleurenbewerker" #: src/otherwindow.c:1818 src/toolbar.c:430 msgid "Colour-Selective Mode" msgstr "Kleurselectieve modus" #: src/otherwindow.c:1843 msgid "Configure Grid" msgstr "Raster instellen" #: src/otherwindow.c:2045 msgid "Exact Conversion" msgstr "Exacte omzetting" #: src/otherwindow.c:2045 msgid "Use Current Palette" msgstr "Huidig palet gebruiken" #: src/otherwindow.c:2046 msgid "PNN Quantize (slow, better quality)" msgstr "PNN afronden (langzaam, hogere kwaliteit)" #: src/otherwindow.c:2047 msgid "Wu Quantize (fast)" msgstr "Wu afronden (snel)" #: src/otherwindow.c:2048 msgid "Max-Min Quantize (best for small palettes and dithering)" msgstr "Max-min afronden (het beste voor kleine paletten en stippelen)" #: src/otherwindow.c:2049 src/otherwindow.c:2495 src/otherwindow.c:2756 #: src/png.c:2794 src/prefs.c:377 msgid "None" msgstr "Geen" #: src/otherwindow.c:2049 msgid "Floyd-Steinberg" msgstr "Floyd-Steinberg" #: src/otherwindow.c:2049 msgid "Stucki" msgstr "Stucki" #: src/otherwindow.c:2052 msgid "Floyd-Steinberg (quick)" msgstr "Floyd-Steinberg (snel)" #: src/otherwindow.c:2052 msgid "Dithered (effect)" msgstr "Gestippeld (effect)" #: src/otherwindow.c:2053 msgid "Scattered (effect)" msgstr "Verspreid (effect)" #: src/otherwindow.c:2054 msgid "Gamut" msgstr "Scala" #: src/otherwindow.c:2054 msgid "Weakly" msgstr "Zwak" #: src/otherwindow.c:2054 msgid "Strongly" msgstr "Sterk" #: src/otherwindow.c:2055 msgid "Off" msgstr "Uit" #: src/otherwindow.c:2055 msgid "Separate/Sum" msgstr "Scheiden/Totaal" #: src/otherwindow.c:2055 msgid "Separate/Split" msgstr "Scheiden/Splitsen" #: src/otherwindow.c:2056 msgid "Length/Sum" msgstr "Lengte/Totaal" #: src/otherwindow.c:2056 msgid "Length/Split" msgstr "Lengte/Splitsen" #: src/otherwindow.c:2057 msgid "Largest (Linf)" msgstr "Grootste (Linf)" #: src/otherwindow.c:2057 msgid "Sum (L1)" msgstr "Totaal (L1)" #: src/otherwindow.c:2057 msgid "Euclidean (L2)" msgstr "Euclidiaans (L2)" #: src/otherwindow.c:2061 msgid "Create Quantized" msgstr "Afronding maken" #: src/otherwindow.c:2062 msgid "Convert To Indexed" msgstr "Omvormen tot geïndexeerd" #: src/otherwindow.c:2065 msgid "Indexed Colours To Use" msgstr "Geïndexeerde kleuren voor gebruik" #: src/otherwindow.c:2078 msgid "Truncate palette" msgstr "Palet afkappen" #: src/otherwindow.c:2079 msgid "Diameter based weighting" msgstr "Weging die op de diameter is gebaseerd" #: src/otherwindow.c:2084 msgid "Dither" msgstr "Dithering" #: src/otherwindow.c:2087 src/otherwindow.c:2584 src/otherwindow.c:2928 msgid "Colour space" msgstr "Kleurenruimte" #: src/otherwindow.c:2088 src/otherwindow.c:2929 msgid "Difference measure" msgstr "Verschilmeting" #: src/otherwindow.c:2089 msgid "Reduce colour bleed" msgstr "Verminder kleurvervloeiing" #: src/otherwindow.c:2090 msgid "Serpentine scan" msgstr "Serpentine scan" #: src/otherwindow.c:2092 msgid "Error propagation, %" msgstr "Uitvoerfout, %" #: src/otherwindow.c:2093 msgid "Selective error propagation" msgstr "Selectieve uitvoerfout" #: src/otherwindow.c:2097 msgid "Full error precision" msgstr "Fout geheel bepalen" #: src/otherwindow.c:2302 msgid "Backward HSV" msgstr "HSV terug" #: src/otherwindow.c:2303 src/otherwindow.c:2326 msgid "Constant" msgstr "Continu" #: src/otherwindow.c:2307 msgid "Edit Gradient" msgstr "Verloop bewerken" #: src/otherwindow.c:2329 msgid "Points:" msgstr "Punten:" #: src/otherwindow.c:2493 msgid "Linear" msgstr "Lineair" #: src/otherwindow.c:2493 src/otherwindow.c:2703 msgid "Bilinear" msgstr "Bilineair" #: src/otherwindow.c:2493 msgid "Radial" msgstr "Radiaal" #: src/otherwindow.c:2494 msgid "Square" msgstr "Vierkant" #: src/otherwindow.c:2494 msgid "Angular" msgstr "Hoekig" #: src/otherwindow.c:2494 msgid "Conical" msgstr "Conisch" #: src/otherwindow.c:2495 msgid "Level " msgstr "" #: src/otherwindow.c:2495 msgid "Repeat" msgstr "Herhalen" #: src/otherwindow.c:2496 msgid "A to B" msgstr "Van A naar B" #: src/otherwindow.c:2496 msgid "A to B (RGB)" msgstr "Van A naar B (RGB)" #: src/otherwindow.c:2497 msgid "A to B (sRGB)" msgstr "Van A naar B (sRGB)" #: src/otherwindow.c:2497 msgid "A to B (HSV)" msgstr "Van A naar B (HSV)" #: src/otherwindow.c:2497 msgid "A to B (backward HSV)" msgstr "Van A naar B (achterwaarts HSV)" #: src/otherwindow.c:2498 msgid "A only" msgstr "Alleen A" #: src/otherwindow.c:2498 src/otherwindow.c:2500 msgid "Custom" msgstr "Aangepast" #: src/otherwindow.c:2499 msgid "Current to 0" msgstr "Huidig naar 0" #: src/otherwindow.c:2499 msgid "Current only" msgstr "Alleen huidig" #: src/otherwindow.c:2504 msgid "Configure Gradient" msgstr "Verloop instellen" #: src/otherwindow.c:2507 src/png.c:1001 msgid "Channel" msgstr "Kanaal" #: src/otherwindow.c:2512 msgid "Length" msgstr "Lengte" #: src/otherwindow.c:2513 msgid "Repeat length" msgstr "Lengte herhalen" #: src/otherwindow.c:2515 msgid "Gradient type" msgstr "Soort verloop" #: src/otherwindow.c:2516 msgid "Extension type" msgstr "Soort verlenging" #: src/otherwindow.c:2517 msgid "Distance type" msgstr "" #: src/otherwindow.c:2518 msgid "Preview opacity" msgstr "Ondoorzichtigheid van voorbeeld" #: src/otherwindow.c:2527 src/otherwindow.c:2533 src/toolbar.c:309 msgid "Reverse" msgstr "Omkeren" #: src/otherwindow.c:2528 src/otherwindow.c:2534 msgid "Edit Custom" msgstr "Aangepast bewerken" #: src/otherwindow.c:2592 msgid "Pick Gradient" msgstr "Verloop assembleren" #: src/otherwindow.c:2668 msgid "Horizontal " msgstr "Horizontaal" #: src/otherwindow.c:2674 msgid "At distance" msgstr "Op afstand" #: src/otherwindow.c:2675 msgid "Vertical" msgstr "Verticaal" #: src/otherwindow.c:2756 msgid "Unchanged" msgstr "Onveranderd" #: src/otherwindow.c:2761 msgid "Tracing Image" msgstr "Afbeelding opsporen" #: src/otherwindow.c:2763 src/toolbar.c:315 msgid "Source" msgstr "Bron" #: src/otherwindow.c:2768 msgid "Origin" msgstr "Oorsprong" #: src/otherwindow.c:2771 msgid "Relative scale" msgstr "Relatieve schaal" #: src/otherwindow.c:2774 msgid "Display" msgstr "Laten zien" #: src/otherwindow.c:2926 msgid "Segment Image" msgstr "Afbeelding segmenteren" #: src/otherwindow.c:2931 src/toolbar.c:304 msgid "Threshold" msgstr "Drempelwaarde" #: src/otherwindow.c:2933 msgid "Level" msgstr "Niveau" #: src/otherwindow.c:2934 msgid "Minimum size" msgstr "Minimumgrootte" #: src/otherwindow.c:3053 msgid "Max" msgstr "" #: src/otherwindow.c:3053 msgid "Min" msgstr "" #: src/otherwindow.c:3057 msgid "Threshold Image" msgstr "" #: src/otherwindow.c:3158 msgid "Seed" msgstr "" #: src/otherwindow.c:3160 msgid "X span" msgstr "" #: src/otherwindow.c:3161 msgid "Y span" msgstr "" #: src/otherwindow.c:3162 msgid "Octaves" msgstr "" #: src/png.c:620 #, c-format msgid "Saving %s image" msgstr "Afbeelding %s aan het opslaan" #: src/png.c:620 #, c-format msgid "Loading %s image" msgstr "Afbeelding %s aan het laden" #: src/png.c:998 msgid "Layer" msgstr "Laag" #: src/png.c:3577 msgid "Lossless" msgstr "" #: src/png.c:3577 msgid "Default" msgstr "" #: src/png.c:3577 msgid "Picture" msgstr "" #: src/png.c:3577 msgid "Photo" msgstr "" #: src/png.c:3578 msgid "Drawing" msgstr "" #: src/png.c:3578 msgid "Icon" msgstr "" #: src/png.c:8370 msgid "Applying colour profile" msgstr "Kleurprofiel aan het toepassen" #: src/png.c:8792 #, c-format msgid "%d out of %d frames could not be saved as %s - saved as PNG instead" msgstr "" "%d van de %d frames konden niet worden opgeslagen als %s - in plaats daarvan " "als PNG opgeslagen" #: src/png.c:8809 msgid "Explode frames" msgstr "Frames opblazen" #: src/prefs.c:56 msgid "Default System Language" msgstr "Standaard-systeemtaal" #: src/prefs.c:57 msgid "Chinese (Simplified)" msgstr "Chinees (vereenvoudigd)" #: src/prefs.c:57 msgid "Chinese (Taiwanese)" msgstr "Chinees (Taiwanees)" #: src/prefs.c:57 msgid "Czech" msgstr "Tsjechisch" #: src/prefs.c:58 msgid "Dutch" msgstr "Nederlands" #: src/prefs.c:58 msgid "English (UK)" msgstr "Engels (Verenigd Koninkrijk)" #: src/prefs.c:58 msgid "French" msgstr "Frans" #: src/prefs.c:58 msgid "Galician" msgstr "Galicisch" #: src/prefs.c:58 msgid "German" msgstr "Duits" #: src/prefs.c:59 msgid "Hungarian" msgstr "Hongaars" #: src/prefs.c:59 msgid "Italian" msgstr "Italiaans" #: src/prefs.c:59 msgid "Japanese" msgstr "Japans" #: src/prefs.c:59 msgid "Kabyle" msgstr "" #: src/prefs.c:59 msgid "Polish" msgstr "Pools" #: src/prefs.c:60 msgid "Portuguese" msgstr "Portugees" #: src/prefs.c:60 msgid "Portuguese (Brazilian)" msgstr "Portugees (Braziliaans)" #: src/prefs.c:60 msgid "Russian" msgstr "Russisch" #: src/prefs.c:60 msgid "Slovak" msgstr "Slowaaks" #: src/prefs.c:61 msgid "Spanish" msgstr "Spaans" #: src/prefs.c:61 msgid "Swedish" msgstr "Zweeds" #: src/prefs.c:61 msgid "Tagalog" msgstr "Tagalog" #: src/prefs.c:61 msgid "Turkish" msgstr "Turks" #: src/prefs.c:81 msgid "Current Device" msgstr "Huidig apparaat" #: src/prefs.c:135 msgid "Pressure" msgstr "Druk" #: src/prefs.c:149 msgid "Preferences" msgstr "Voorkeuren" #: src/prefs.c:163 msgid "Max threads (0 to autodetect)" msgstr "Max aantal threads (0 voor automatische bepaling)" #: src/prefs.c:164 msgid "Min kpixels per render thread" msgstr "" #: src/prefs.c:171 msgid "Max memory used for undo (MB)" msgstr "Max geheugen gebruikt voor het ongedaan maken (MB)" #: src/prefs.c:172 msgid "Max undo levels" msgstr "Max aantal ongedaanmakingen" #: src/prefs.c:173 msgid "Communal layer undo space (%)" msgstr "Gemeenschappelijke laag ruimte voor ongedaan maken (%)" #: src/prefs.c:175 msgid "Bayer master pattern" msgstr "" #: src/prefs.c:178 msgid "Use gamma correction by default" msgstr "Gebruik standaard gammacorrectie" #: src/prefs.c:179 msgid "Use gamma correction when painting" msgstr "" #: src/prefs.c:180 msgid "Separate patterns for A & B" msgstr "" #: src/prefs.c:183 msgid "Optimize alpha chequers" msgstr "Alpha chequers optimaliseren" #: src/prefs.c:184 msgid "Disable view window transparencies" msgstr "Schakel transparanties uit voor kijkvenster" #: src/prefs.c:185 msgid "Enable overlays by layer" msgstr "" #: src/prefs.c:189 msgid "Language" msgstr "Taal" #: src/prefs.c:191 msgid "" "Select preferred language translation\n" "\n" "You will need to restart mtPaint\n" "for this to take full effect" msgstr "" "Kies voorkeurstaal\n" "\n" "U moet mtPaint herstarten om de\n" "veranderingen geheel door te voeren" #: src/prefs.c:198 msgid "Interface" msgstr "Interface" #: src/prefs.c:200 msgid "Greyscale backdrop" msgstr "Grijstinten achtergrond" #: src/prefs.c:201 msgid "Selection nudge pixels" msgstr "Selectie van aangebrachte pixels" #: src/prefs.c:202 msgid "Max Pan Window Size" msgstr "Max formaat overzicht-scherm" #: src/prefs.c:204 msgid "Display clipboard while pasting" msgstr "Toon klembord tijdens plakken" #: src/prefs.c:205 msgid "Mouse cursor = Tool" msgstr "Muispijl verplaatsen = gereedschap" #: src/prefs.c:206 msgid "Confirm Exit" msgstr "Afsluiten bevestigen" #: src/prefs.c:207 msgid "Q key quits mtPaint" msgstr "De Q-toets sluit mtPaint af" #: src/prefs.c:208 msgid "Arrow keys scroll canvas" msgstr "" #: src/prefs.c:209 msgid "Changing tool commits paste" msgstr "Veranderen van gereedschap voert plakactie uit" #: src/prefs.c:210 msgid "Centre tool settings dialogs" msgstr "Dialoogvensters voor gereedschapinstellingen centreren" #: src/prefs.c:211 msgid "New image sets zoom to 100%" msgstr "Nieuwe afbeelding stelt zoom in op 100%" #: src/prefs.c:212 msgid "Zoom on cursor position" msgstr "" #: src/prefs.c:214 msgid "Mouse Scroll Wheel = Zoom" msgstr "Muiswiel = zoomen" #: src/prefs.c:215 msgid "Use menu icons" msgstr "Gebruik menupictogrammen" #: src/prefs.c:220 msgid "Files" msgstr "Bestanden" #: src/prefs.c:223 msgid "XBM X hotspot" msgstr "XBM X hotspot" #: src/prefs.c:224 msgid "XBM Y hotspot" msgstr "XBM Y hotspot" #: src/prefs.c:228 msgid "Recently Used Files" msgstr "Recent gebruikte bestanden" #: src/prefs.c:229 msgid "Progress bar silence limit" msgstr "Stiltelimiet van voortgangsbalk" #: src/prefs.c:232 msgid "Read 16-bit TGAs as 5:6:5 BGR" msgstr "Lees 16-bit TGAs als 5:6:5 BGR" #: src/prefs.c:233 msgid "Write TGAs in bottom-up row order" msgstr "Schrijf TGA's in omgekeerde rijvolgorde" #: src/prefs.c:234 msgid "Undoable image loading" msgstr "Het laden van afbeelding die ongedaan gemaakt kan worden" #: src/prefs.c:245 msgid "Compression (RGB)" msgstr "" #: src/prefs.c:246 msgid "Compression (indexed)" msgstr "" #: src/prefs.c:247 msgid "Compression (monochrome)" msgstr "" #: src/prefs.c:255 msgid "Enable predictor" msgstr "" #: src/prefs.c:262 msgid "Compression mode" msgstr "" #: src/prefs.c:271 msgid "Channel for Mask Plane" msgstr "" #: src/prefs.c:273 msgid "Ignore Transparent Colour" msgstr "" #: src/prefs.c:274 msgid "PackBits Compression" msgstr "" #: src/prefs.c:275 msgid "Write Indexed as Planar Bitmap (PBM)" msgstr "" #: src/prefs.c:280 msgid "Paths" msgstr "Paden" #: src/prefs.c:281 msgid "Clipboard Files" msgstr "Klembordbestanden" #: src/prefs.c:281 msgid "Select Clipboard File" msgstr "Selecteer klembordbestand" #: src/prefs.c:283 msgid "HTML Browser Program" msgstr "HTML-browserprogramma" #: src/prefs.c:283 msgid "Select Browser Program" msgstr "Kies browserprogramma" #: src/prefs.c:285 msgid "Location of Handbook index" msgstr "Locatie van handboek-index" #: src/prefs.c:285 msgid "Select Handbook Index File" msgstr "Selecteer handboek-indexbestand" #: src/prefs.c:287 msgid "Default Palette" msgstr "Standaardpalet" #: src/prefs.c:287 msgid "Select Default Palette" msgstr "Selecteer standaardpalet" #: src/prefs.c:289 msgid "Default Patterns" msgstr "Standaardpatronen" #: src/prefs.c:289 msgid "Select Default Patterns File" msgstr "Kies bestand voor standaardpatronen" #: src/prefs.c:292 msgid "Default CSS" msgstr "" #: src/prefs.c:292 msgid "Select Default CSS File" msgstr "" #: src/prefs.c:295 msgid "Default Theme" msgstr "Standaardthema" #: src/prefs.c:295 msgid "Select Default Theme File" msgstr "Kies bestand voor standaardthema" #: src/prefs.c:300 msgid "Status Bar" msgstr "Statusbalk" #: src/prefs.c:301 msgid "Canvas Geometry" msgstr "Geometrie van het canvas" #: src/prefs.c:302 msgid "Cursor X,Y" msgstr "Cursor X,Y" #: src/prefs.c:303 msgid "Pixel [I] {RGB}" msgstr "Pixel [I] {RGB}" #: src/prefs.c:304 msgid "Selection Geometry" msgstr "Geometrie van selectie" #: src/prefs.c:305 msgid "Undo / Redo" msgstr "Ongedaan maken / Opnieuw uitvoeren" #: src/prefs.c:308 msgid "Tablet" msgstr "Tablet" #: src/prefs.c:309 msgid "Device Settings" msgstr "Apparaatinstellingen" #: src/prefs.c:313 msgid "Configure Device" msgstr "Apparaat instellen" #: src/prefs.c:319 msgid "Tool Variable" msgstr "Gereedschapsvariabele" #: src/prefs.c:322 src/toolbar.c:454 msgid "Flow" msgstr "Stroom" #: src/prefs.c:330 msgid "Test Area" msgstr "Proefgebied" #: src/prefs.c:373 msgid "Factor" msgstr "Factor" #: src/prefs.c:459 msgid "This key is builtin" msgstr "" #: src/prefs.c:462 #, c-format msgid "" "This key is mapped to:\n" "\"%s\"" msgstr "" #: src/prefs.c:465 msgid "Remap" msgstr "" #: src/prefs.c:510 msgid "Keyboard Shortcuts" msgstr "" #: src/shifter.c:147 msgid "Frames" msgstr "Kaders" #: src/shifter.c:258 msgid "Palette Shifter" msgstr "Paletwisselaar" #: src/shifter.c:263 msgid "Start" msgstr "Starten" #: src/shifter.c:265 msgid "Finish" msgstr "Beëindigen" #: src/shifter.c:284 msgid "Fix Palette" msgstr "Palet vastzetten" #: src/spawn.c:651 msgid "Configure File Actions" msgstr "Bestandacties instellen" #: src/spawn.c:657 src/spawn.c:663 msgid "Command" msgstr "Opdracht" #: src/spawn.c:922 #, c-format msgid "Error %i reported when trying to run %s" msgstr "Fout %i gemeld bij het uitvoeren van %s" #: src/spawn.c:979 msgid "" "I am unable to find the documentation. Either you need to download the " "mtPaint Handbook from the web site and install it, or you need to set the " "correct location in the Preferences window." msgstr "" "mtPaint kan geen documentatie vinden. Haal het mtPaint-handboek binnen van " "de website en installeer het, of stel in het Voorkeurenvenster de juiste " "locatie in." #: src/spawn.c:1018 msgid "" "There was a problem running the HTML browser. You need to set the correct " "program name in the Preferences window." msgstr "" "Er was een probleem met de HTML-browser. Voer in het Voorkeurenvenster de " "correcte naam voor het programma in." #: src/thread.c:361 msgid "Helper thread is not responding. Save your work and exit the program." msgstr "Hulp thread reageert niet. Sla uw werk op en sluit het programma af." #: src/toolbar.c:147 msgid "RGB Cube" msgstr "RGB-kubus" #: src/toolbar.c:148 msgid "By image channel" msgstr "Op afbeeldingkanaal" #: src/toolbar.c:149 msgid "Gradient-driven" msgstr "Verloop-gedreven" #: src/toolbar.c:157 msgid "Fill settings" msgstr "Vulinstellingen" #: src/toolbar.c:170 msgid "Respect opacity mode" msgstr "Dekkingmodus respecteren" #: src/toolbar.c:176 msgid "Smudge settings" msgstr "Vlekinstellingen" #: src/toolbar.c:215 msgid "Aligned" msgstr "" #: src/toolbar.c:222 msgid "Clone settings" msgstr "" #: src/toolbar.c:228 msgid "By selection channel" msgstr "" #: src/toolbar.c:234 msgid "Lasso settings" msgstr "" #: src/toolbar.c:252 msgid "Brush spacing" msgstr "Penseeltussenruimte" #: src/toolbar.c:299 src/toolbar.c:341 msgid "Normal" msgstr "Normaal" #: src/toolbar.c:300 msgid "Colour" msgstr "Kleur" #: src/toolbar.c:300 msgid "Saturate More" msgstr "Meer verzadigen" #: src/toolbar.c:301 msgid "Multiply" msgstr "Vermenigvuldigen" #: src/toolbar.c:301 msgid "Divide" msgstr "Delen" #: src/toolbar.c:301 msgid "Dodge" msgstr "Tegenhouden" #: src/toolbar.c:302 msgid "Burn" msgstr "Doordrukken" #: src/toolbar.c:302 msgid "Hard Light" msgstr "Hard licht" #: src/toolbar.c:302 msgid "Soft Light" msgstr "Zacht licht" #: src/toolbar.c:302 msgid "Difference" msgstr "Verschil" #: src/toolbar.c:303 msgid "Darken" msgstr "Donker maken" #: src/toolbar.c:303 msgid "Lighten" msgstr "Lichter maken" #: src/toolbar.c:303 msgid "Grain Extract" msgstr "Graanstructuur uittrekken" #: src/toolbar.c:304 msgid "Grain Merge" msgstr "Graanstructuur verdichten" #: src/toolbar.c:330 msgid "Blend mode" msgstr "Mengmodus" #: src/toolbar.c:417 msgid "Continuous Mode" msgstr "Continue modus" #: src/toolbar.c:421 msgid "Opacity Mode" msgstr "Dekkingmodus" #: src/toolbar.c:424 msgid "Tint Mode" msgstr "Tintmodus" #: src/toolbar.c:427 msgid "Tint +-" msgstr "Tint +-" #: src/toolbar.c:434 msgid "Blend Mode" msgstr "Mengmodus" #: src/toolbar.c:438 msgid "Disable All Masks" msgstr "Alle maskeringen uitschakelen" #: src/toolbar.c:441 msgid "Gradient Mode" msgstr "Verloopmodus" #: src/toolbar.c:486 msgid "Settings Toolbar" msgstr "Instellingenwerkbalk" #: src/toolbar.c:546 msgid "Cut" msgstr "Knippen" #: src/toolbar.c:548 msgid "Copy" msgstr "Kopiëren" #: src/toolbar.c:550 msgid "Paste" msgstr "Plakken" #: src/toolbar.c:553 msgid "Undo" msgstr "Ongedaan maken" #: src/toolbar.c:555 msgid "Redo" msgstr "Opnieuw doen" #: src/toolbar.c:559 src/viewer.c:328 msgid "Pan Window" msgstr "Overzicht-scherm" #: src/toolbar.c:560 src/toolbar.c:640 msgid "More..." msgstr "Meer..." #: src/toolbar.c:574 msgid "Paint" msgstr "Schilderen" #: src/toolbar.c:580 msgid "Shuffle" msgstr "Schuffelen" #: src/toolbar.c:583 msgid "Flood Fill" msgstr "Emmer vullen" #: src/toolbar.c:587 msgid "Straight Line" msgstr "Rechte lijn" #: src/toolbar.c:590 msgid "Smudge" msgstr "Vlek" #: src/toolbar.c:594 msgid "Clone" msgstr "Kloon" #: src/toolbar.c:597 msgid "Make Selection" msgstr "Selectie maken" #: src/toolbar.c:600 msgid "Polygon Selection" msgstr "Veelhoekselectie" #: src/toolbar.c:603 msgid "Place Gradient" msgstr "Verloop plaatsen" #: src/toolbar.c:606 msgid "Lasso Selection" msgstr "Lassoselectie" #: src/toolbar.c:614 msgid "Ellipse Outline" msgstr "Omtrek ellips" #: src/toolbar.c:617 msgid "Filled Ellipse" msgstr "Gevulde ellips" #: src/toolbar.c:620 msgid "Outline Selection" msgstr "Omtrekselectie" #: src/toolbar.c:623 msgid "Fill Selection" msgstr "Selectie vullen" #: src/toolbar.c:627 msgid "Flip Selection Vertically" msgstr "Selectie verticaal draaien" #: src/toolbar.c:630 msgid "Flip Selection Horizontally" msgstr "Selectie horizontaal draaien" #: src/toolbar.c:633 msgid "Rotate Selection Clockwise" msgstr "Selectie met de klok mee draaien" #: src/toolbar.c:636 msgid "Rotate Selection Anti-Clockwise" msgstr "Selectie tegen de klok in draaien" #: src/vcode.c:5201 msgid "Browse" msgstr "Bladeren" #: src/vcode.c:7886 msgid "New key ..." msgstr "" #: src/vcode.c:9909 #, c-format msgid "'%s' does not match any widget" msgstr "" #: src/vcode.c:9910 #, c-format msgid "'%s' value does not fit '%s' widget" msgstr "" #: src/viewer.c:115 msgid "About" msgstr "Over" #: src/viewer.c:1179 msgid "No font selected" msgstr "" #: src/viewer.c:1209 msgid "Left" msgstr "" #: src/viewer.c:1209 msgid "Right" msgstr "" #~ msgid "Create GIF frames" #~ msgstr "GIF-kader aanmaken" #~ msgid "Store Values" #~ msgstr "Waarden bewaren" #~ msgid "File: %s invalid - palette not updated" #~ msgstr "Bestand: %s niet valide - palet kan niet worden opgewaardeerd" #~ msgid "Import GIF animation - Choose frames directory" #~ msgstr "GIF-animatie invoegen - kies kaderbestand" #~ msgid "Distance to A+B" #~ msgstr "Afstand tot A+B" #~ msgid "Edit Frames" #~ msgstr "Kaders bewerken" #~ msgid " C Command Line Window" #~ msgstr " C Terminal" #~ msgid "The palette does not contain enough colours to do a merge" #~ msgstr "Het palet bevat niet genoeg kleuren om te mengen" #~ msgid "There are too many identical palette items to be reduced." #~ msgstr "Er zijn teveel dezelfde palet-items om te verminderen." #~ msgid "/View/Command Line Window" #~ msgstr "/Bekijken/Terminal" #~ msgid "Grid colour RGB" #~ msgstr "Raster-kleur RGB" #~ msgid "Zoom" #~ msgstr "Zoomen" #~ msgid "%i Files on Command Line" #~ msgstr "%i bestanden in de wachtrij" #~ msgid "Not enough memory to rotate image" #~ msgstr "Onvoldoende geheugen om afbeelding te draaien" #~ msgid "Not enough memory to rotate clipboard" #~ msgstr "Onvoldoende geheugen om klembord te draaien" #~ msgid "File is too big, must be <= to width=%i height=%i : %s" #~ msgstr "Bestand is te groot, moet <= dan breedte=%i hoogte=%i zijn : %s" #~ msgid "Could not open %s: %s" #~ msgstr "Kan %s: %s niet openen" #~ msgid "Error closing %s: %s" #~ msgstr "Fout bij afsluiten %s: %s" #~ msgid "Could not write to %s: %s" #~ msgstr "Kan niet schrijven naar %s: %s" #~ msgid "patterns_user.c could not be opened in current directory" #~ msgstr "patronen_gebruiker.c kan in het huidige bestand niet geopend worden" #~ msgid "Done" #~ msgstr "Klaar" #~ msgid "patterns_user.c created in current directory" #~ msgstr "patronen_gebruiker.c aangemaakt in het huidige bestand" #~ msgid "Current image is not 94x94x3 so I cannot create patterns_user.c" #~ msgstr "" #~ "Huidige afbeelding is niet 94x94x3, dus ik kan geen patronen_gebruiker.c " #~ "aanmaken" #~ msgid "" #~ "You are trying to save an RGB image to an XPM file which is not " #~ "possible. I would suggest you save with a PNG extension." #~ msgstr "" #~ "U probeert een RGB-afbeelding op te slaan, hetgeen niet mogelijk is. Sla " #~ "op met PNG-extensie." #~ msgid "" #~ "You are trying to save an RGB image to a GIF file which is not possible.I " #~ "would suggest you save with a PNG extension." #~ msgstr "" #~ "U probeert een RGB-afbeelding op te slaan als GIF-bestand, hetgeen niet " #~ "mogelijk is. Sla op met PNG-extensie." #~ msgid "" #~ "You are trying to save an XBM file with a palette of more than 2 " #~ "colours. Either use another format or reduce the palette to 2 colours." #~ msgstr "" #~ "U probeert een XBM-bestand te bewaren met een palet van meer dan 2 " #~ "kleuren. Gebruik een ander bestandsformaat of breng het palet terug tot " #~ "twee kleuren." #~ msgid "" #~ "You are trying to save an indexed canvas to a JPEG file which is not " #~ "possible. I would suggest you save with a PNG extension." #~ msgstr "" #~ "U probeert een geïndexeerde Ondergrond op te slaan in een JPEG-bestand, " #~ "hetgeen niet mogelijk is. Sla op met PNG-extensie." #~ msgid "/File/Actions/sep2" #~ msgstr "/Bestand/Acties/sep2" #~ msgid "/Edit/Create Patterns" #~ msgstr "/Bewerk/Patronen aanmaken" #~ msgid "/Palette/Create Quantized (DL1)" #~ msgstr "/Palet/Vast aantal aanmaken(DL1)" #~ msgid "/Palette/Create Quantized (DL3)" #~ msgstr "/Palet/Vast aantal aanmaken (DL3)" #~ msgid "/Palette/Create Quantized (Wu)" #~ msgstr "/Palet/Vast aantal aanmaken (Wu)" #~ msgid "/Frames" #~ msgstr "/Kaders" #~ msgid "/File/%i" #~ msgstr "/Bestand/%i" #~ msgid "/File/Actions/%i" #~ msgstr "/Bestand/Acties/%i" #~ msgid "DL1 Quantize (fastest)" #~ msgstr "DL1 Vast aantal aanmaken (snelst)" #~ msgid "DL3 Quantize (very slow, better quality)" #~ msgstr "DL3 vast aantal aanmaken (zeer traag, betere kwaliteit)" #~ msgid "Wu Quantize (best method for small palettes)" #~ msgstr "Wu Vast aantal aanmaken (de beste manier voor een kleine palet)" #~ msgid "Loading PNG image" #~ msgstr "PNG-afbeelding laden" #~ msgid "Loading clipboard image" #~ msgstr "Klembord-afbeelding laden" #~ msgid "Saving PNG image" #~ msgstr "PNG-afbeelding opslaan" #~ msgid "Saving Clipboard image" #~ msgstr "Klembord-afbeelding opslaan" #~ msgid "Saving Layer image" #~ msgstr "Afbeeldings-laag opslaan" #~ msgid "Saving Channel image" #~ msgstr "Afbeeldings-kanaal opslaan" #~ msgid "Loading GIF image" #~ msgstr "GIF-afbeelding laden" #~ msgid "Saving GIF image" #~ msgstr "GIF-afbeelding opslaan" #~ msgid "Loading JPEG image" #~ msgstr "JPEG-afbeelding laden" #~ msgid "Saving JPEG image" #~ msgstr "JPEG-afbeelding opslaan" #~ msgid "Loading TIFF image" #~ msgstr "TIFF-afbeelding laden" #~ msgid "Saving TIFF image" #~ msgstr "TIFF-afbeelding opslaan" #~ msgid "Loading BMP image" #~ msgstr "BMP-afbeelding laden" #~ msgid "Saving BMP image" #~ msgstr "BMP-afbeelding opslaan" #~ msgid "Loading XPM image" #~ msgstr "XPM-afbeelding laden" #~ msgid "Saving XPM image" #~ msgstr "XPM-afbeelding opslaan" #~ msgid "Loading XBM image" #~ msgstr "XBM-afbeelding laden" #~ msgid "Saving XBM image" #~ msgstr "XBM-afbeelding opslaan" #~ msgid "Loading LSS16 image" #~ msgstr "LSS16-afbeelding laden" #~ msgid "Saving LSS16 image" #~ msgstr "LSS16-afbeelding opslaan" #~ msgid "Saving UNDO images" #~ msgstr "Ongedaan gemaakte afbeeldingen opslaan" #~ msgid "Lanczos3" #~ msgstr "Lanczos3" mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/po/pl.po000066400000000000000000002627731471325446300215650ustar00rootroot00000000000000# Polish translation for mtpaint # Copyright (c) (c) 2006 Canonical Ltd, and Rosetta Contributors 2006 # This file is distributed under the same license as the mtpaint package. # FIRST AUTHOR , 2006. # msgid "" msgstr "" "Project-Id-Version: mtpaint\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-01-04 21:31+0200\n" "PO-Revision-Date: 2016-11-09 21:45+0000\n" "Last-Translator: marcin mikoÅ‚ajczak \n" "Language-Team: Polish \n" "Language: pl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Launchpad-Export-Date: 2020-04-05 23:36+0000\n" "X-Generator: Launchpad (build a296f04231dee355be5db73cc878b9e21689a253)\n" "First-Translator: Simek \n" #: src/ani.c:647 msgid "Animation Preview" msgstr "PodglÄ…d" #: src/ani.c:650 src/shifter.c:275 msgid "Play" msgstr "Odtwórz" #: src/ani.c:654 msgid "Fix" msgstr "Napraw" #: src/ani.c:655 src/ani.c:1005 src/font.c:1624 src/font.c:1643 #: src/shifter.c:286 src/viewer.c:97 msgid "Close" msgstr "Zamknij" #: src/ani.c:709 src/ani.c:812 src/ani.c:1022 src/ani.c:1028 src/canvas.c:356 #: src/canvas.c:708 src/canvas.c:989 src/canvas.c:1353 src/canvas.c:1383 #: src/canvas.c:1470 src/canvas.c:1545 src/canvas.c:1988 src/canvas.c:1994 #: src/canvas.c:2077 src/canvas.c:2217 src/canvas.c:2240 src/font.c:1352 #: src/fpick.c:636 src/fpick.c:754 src/layer.c:524 src/layer.c:815 #: src/layer.c:970 src/mainwindow.c:341 src/mainwindow.c:370 #: src/mainwindow.c:534 src/mainwindow.c:578 src/mainwindow.c:604 #: src/mainwindow.c:3797 src/mainwindow.c:4045 src/otherwindow.c:931 #: src/otherwindow.c:980 src/otherwindow.c:982 src/prefs.c:459 src/spawn.c:924 #: src/spawn.c:978 src/spawn.c:1017 src/thread.c:360 src/vcode.c:9912 #: src/viewer.c:1161 src/viewer.c:1179 msgid "Error" msgstr "Błąd" #: src/ani.c:709 msgid "Unable to create output directory" msgstr "Nie można utworzyć folderu" #: src/ani.c:759 msgid "Creating Animation Frames" msgstr "Utwórz ramki animacji" #: src/ani.c:812 msgid "Unable to save image" msgstr "Nie można zapisac obrazu" #: src/ani.c:840 src/canvas.c:1171 src/fpick.c:731 src/layer.c:311 #: src/layer.c:379 src/layer.c:826 src/layer.c:840 src/mainwindow.c:375 #: src/mainwindow.c:1026 src/png.c:8794 src/prefs.c:464 msgid "Warning" msgstr "Ostrzeżenie" #: src/ani.c:840 msgid "" "Do you really want to clear all of the position and cycle data for all of " "the layers?" msgstr "" "Czy na pewno chcesz wyczyÅ›cić wszystkie pozycje i dane dla każdej warstwy ?" #: src/ani.c:841 src/fpick.c:731 src/layer.c:311 src/layer.c:842 #: src/mainwindow.c:375 msgid "No" msgstr "Nie" #: src/ani.c:841 src/fpick.c:731 src/layer.c:311 src/layer.c:842 #: src/mainwindow.c:375 msgid "Yes" msgstr "Tak" #: src/ani.c:954 msgid "Set Key Frame" msgstr "Ustaw ramkÄ™ kluczowÄ…" #: src/ani.c:961 msgid "Configure Animation" msgstr "Konfiguruj animacjÄ™" #: src/ani.c:964 msgid "Output Files" msgstr "Pliki utworzone" #: src/ani.c:967 msgid "Start frame" msgstr "PoczÄ…tek ramki" #: src/ani.c:969 msgid "End frame" msgstr "Koniec ramki" #: src/ani.c:971 src/shifter.c:267 msgid "Delay" msgstr "Opóźnienie" #: src/ani.c:973 msgid "Output path" msgstr "Åšcieżka wyjÅ›ciowa" #: src/ani.c:973 src/font.c:1637 src/spawn.c:664 msgid "Select Directory" msgstr "" #: src/ani.c:976 msgid "File prefix" msgstr "Przedrostek pliku" #: src/ani.c:978 src/canvas.c:2096 msgid "File Format" msgstr "Format pliku" #: src/ani.c:982 msgid "Positions" msgstr "Pozycje" #: src/ani.c:997 msgid "Cycling" msgstr "Cycling" #: src/ani.c:1006 msgid "Save" msgstr "Zapisz" #: src/ani.c:1007 src/font.c:1577 src/otherwindow.c:868 src/otherwindow.c:1615 #: src/otherwindow.c:1728 src/otherwindow.c:2938 src/otherwindow.c:3071 #: src/otherwindow.c:3170 msgid "Preview" msgstr "PodglÄ…d" #: src/ani.c:1008 src/shifter.c:285 msgid "Create Frames" msgstr "Utwórz ramki" #: src/ani.c:1022 msgid "You must have at least 2 layers to create an animation" msgstr "Potrzebne sÄ… co najmniej 2 warstwy aby utworzyć animacjÄ™" #: src/ani.c:1028 msgid "You must save your layers file before creating an animation" msgstr "Należy zapisać plik przed utworzeniem animacji" #: src/canvas.c:357 msgid "The image is too large to transform." msgstr "Ten obrazek jest za duży, aby dokonać transformacji." #: src/canvas.c:393 src/canvas.c:430 src/otherwindow.c:1613 #: src/otherwindow.c:2524 src/otherwindow.c:2583 src/otherwindow.c:3179 msgid "Gradient" msgstr "Gradient" #: src/canvas.c:393 src/otherwindow.c:840 src/otherwindow.c:842 #: src/otherwindow.c:2074 src/otherwindow.c:3180 msgid "Palette" msgstr "Paleta" #: src/canvas.c:393 src/info.c:265 src/otherwindow.c:847 src/otherwindow.c:2757 #: src/otherwindow.c:3180 src/png.c:781 src/png.c:995 msgid "Clipboard" msgstr "Schowek" #: src/canvas.c:394 src/cpick.c:831 src/toolbar.c:299 msgid "Value" msgstr "Wartość" #: src/canvas.c:394 src/cpick.c:811 src/otherwindow.c:575 src/otherwindow.c:859 #: src/otherwindow.c:3053 src/toolbar.c:318 msgid "Red" msgstr "Czerwony" #: src/canvas.c:394 src/cpick.c:815 src/otherwindow.c:575 src/otherwindow.c:860 #: src/otherwindow.c:3053 src/toolbar.c:319 msgid "Green" msgstr "Zielony" #: src/canvas.c:394 src/cpick.c:819 src/otherwindow.c:575 src/otherwindow.c:861 #: src/otherwindow.c:3053 src/toolbar.c:320 msgid "Blue" msgstr "Niebieski" #: src/canvas.c:399 msgid "From " msgstr "" #: src/canvas.c:403 msgid "To " msgstr "" #: src/canvas.c:410 msgid "Map" msgstr "" #: src/canvas.c:429 msgid "MT" msgstr "" #: src/canvas.c:429 msgid "Sobel" msgstr "" #: src/canvas.c:429 msgid "Prewitt" msgstr "" #: src/canvas.c:429 msgid "Kirsch" msgstr "" #: src/canvas.c:430 msgid "Roberts" msgstr "" #: src/canvas.c:430 msgid "Laplace" msgstr "" #: src/canvas.c:430 msgid "Morphological" msgstr "" #: src/canvas.c:442 msgid "Edge Detect" msgstr "Wykrywanie krawÄ™dzi" #: src/canvas.c:464 msgid "Edge Sharpen" msgstr "Wyostrzanie krawÄ™dzi" #: src/canvas.c:472 msgid "Edge Soften" msgstr "WygÅ‚adzanie krawÄ™dzi" #: src/canvas.c:521 msgid "Different X/Y" msgstr "Różne X/Y" #: src/canvas.c:522 src/canvas.c:562 src/canvas.c:603 src/canvas.c:637 #: src/canvas.c:722 src/otherwindow.c:1037 src/otherwindow.c:2685 msgid "Gamma corrected" msgstr "Gamma poprawna" #: src/canvas.c:530 src/memory.c:8219 msgid "Gaussian Blur" msgstr "Rozmycie Gaussa" #: src/canvas.c:558 msgid "Radius" msgstr "PromieÅ„" #: src/canvas.c:559 msgid "Amount" msgstr "Ilość" #: src/canvas.c:560 msgid "Threshold " msgstr "Próg " #: src/canvas.c:570 src/memory.c:8360 msgid "Unsharp Mask" msgstr "Wzmocnienie" #: src/canvas.c:599 msgid "Outer radius" msgstr "" #: src/canvas.c:600 msgid "Inner radius" msgstr "WewnÄ™trzny promieÅ„" #: src/canvas.c:602 src/info.c:280 msgid "Normalize" msgstr "Normalizuj" #: src/canvas.c:611 src/memory.c:8512 msgid "Difference of Gaussians" msgstr "" #: src/canvas.c:636 msgid "Protect details" msgstr "Zachowaj detale" #: src/canvas.c:645 msgid "Kuwahara-Nagao Blur" msgstr "Rozmycie Kuwahara-Nagao" #: src/canvas.c:709 msgid "The image is too large for this rotation." msgstr "Obraz jest zbyt duży aby go obrócić" #: src/canvas.c:723 msgid "Smooth" msgstr "WygÅ‚adź" #: src/canvas.c:732 msgid "Free Rotate" msgstr "Dowolna rotacja" #: src/canvas.c:989 src/viewer.c:1161 msgid "Not enough memory to create clipboard" msgstr "Za maÅ‚o pamiÄ™ci, aby przenieść obraz do schowka" #: src/canvas.c:1172 msgid "" "You have not allocated enough memory in the Preferences window to undo this " "action." msgstr "" #: src/canvas.c:1353 msgid "Invalid palette file" msgstr "" #: src/canvas.c:1383 msgid "Invalid channel file." msgstr "NieprawidÅ‚owy plik kanaÅ‚u" #: src/canvas.c:1401 msgid "Raw frames" msgstr "" #: src/canvas.c:1401 msgid "Composited frames" msgstr "" #: src/canvas.c:1402 msgid "Composited frames with nonzero delay" msgstr "" #: src/canvas.c:1406 msgid "Load Frames" msgstr "" #: src/canvas.c:1409 msgid "Load into Layers" msgstr "" #: src/canvas.c:1415 msgid "Load First Frame" msgstr "" #: src/canvas.c:1416 msgid "Explode Frames" msgstr "" #: src/canvas.c:1418 msgid "View Animation" msgstr "WyÅ›wietl animacjÄ™" #: src/canvas.c:1434 #, c-format msgid "This is an animated %s file." msgstr "To jest animowany plik %s." #: src/canvas.c:1435 #, c-format msgid "This is a multipage %s file." msgstr "" #: src/canvas.c:1459 #, c-format msgid "File is too big, must be <= to width=%i height=%i" msgstr "" #: src/canvas.c:1461 msgid "Unable to explode frames" msgstr "" #: src/canvas.c:1463 msgid "Unable to load file" msgstr "Nie można otworzyć pliku" #: src/canvas.c:1465 msgid "" "The file import library had to terminate due to a problem with the file " "(possibly corrupt image data or a truncated file). I have managed to load " "some data as the header seemed fine, but I would suggest you save this image " "to a new file to ensure this does not happen again." msgstr "" "Importowana biblioteka powoduje problem z plikiem (uszkodzony obraz lub " "obciÄ™ty plik). Proponowane jest zapisanie tego obrazu do nowego pliku aby " "problem nie pojawiÅ‚ sie ponownie." #: src/canvas.c:1467 msgid "The animation is too long to load all of it into layers." msgstr "" #: src/canvas.c:1469 msgid "Could not explode all the frames in the animation." msgstr "" #: src/canvas.c:1481 src/font.c:1556 src/fpick.c:937 src/otherwindow.c:2765 #: src/prefs.c:321 src/toolbar.c:451 msgid "Size" msgstr "Rozmiar" #: src/canvas.c:1484 src/otherwindow.c:244 msgid "Width" msgstr "Szerokość" #: src/canvas.c:1485 src/otherwindow.c:245 msgid "Height" msgstr "Wysokość" #: src/canvas.c:1489 src/channels.c:253 src/channels.c:317 src/fpick.c:666 #: src/fpick.c:957 src/mainwindow.c:3990 src/otherwindow.c:255 #: src/otherwindow.c:517 src/otherwindow.c:591 src/otherwindow.c:867 #: src/otherwindow.c:1058 src/otherwindow.c:1727 src/otherwindow.c:2101 #: src/otherwindow.c:2336 src/otherwindow.c:2538 src/otherwindow.c:2691 #: src/otherwindow.c:2776 src/otherwindow.c:2937 src/otherwindow.c:3070 #: src/otherwindow.c:3169 src/prefs.c:338 src/prefs.c:464 src/prefs.c:538 #: src/spawn.c:666 src/viewer.c:1258 msgid "Cancel" msgstr "Anuluj" #: src/canvas.c:1490 src/channels.c:253 src/channels.c:317 src/fpick.c:956 #: src/info.c:297 src/mainwindow.c:3992 src/mygtk.c:233 src/mygtk.c:535 #: src/otherwindow.c:591 src/otherwindow.c:871 src/otherwindow.c:1058 #: src/otherwindow.c:1729 src/otherwindow.c:2101 src/otherwindow.c:2336 #: src/otherwindow.c:2538 src/otherwindow.c:2691 src/otherwindow.c:2776 #: src/otherwindow.c:3072 src/otherwindow.c:3171 src/prefs.c:338 #: src/prefs.c:538 src/spawn.c:666 msgid "OK" msgstr "OK" #: src/canvas.c:1504 #, c-format msgid "This is a scalable %s file." msgstr "" #: src/canvas.c:1545 msgid "Cannot open file" msgstr "Nie można otworzyć pliku" #: src/canvas.c:1546 msgid "Unsupported file format" msgstr "NieobsÅ‚ugiwany format pliku" #: src/canvas.c:1673 #, c-format msgid "File: %s already exists. Do you want to overwrite it?" msgstr "Plik: %s już istnieje. Czy chcesz go nadpisać?" #: src/canvas.c:1674 msgid "File Found" msgstr "Plik znaleziony" #: src/canvas.c:1674 src/mainwindow.c:1095 msgid "NO" msgstr "Nie" #: src/canvas.c:1674 src/mainwindow.c:1095 msgid "YES" msgstr "Tak" #: src/canvas.c:1988 msgid "Unable to export undo images" msgstr "Niemożliwy eksport cofniÄ™tych obrazów" #: src/canvas.c:1994 msgid "Unable to export ASCII file" msgstr "Nie mozna eksportować pliku ASCII" #: src/canvas.c:2076 src/layer.c:814 src/mainwindow.c:529 #, c-format msgid "Unable to save file: %s" msgstr "Nie można zapisać pliku: %s" #: src/canvas.c:2101 src/prefs.c:222 msgid "Transparency index" msgstr "Indeks niewidoczny" #: src/canvas.c:2103 msgid "TIFF Compression" msgstr "" #: src/canvas.c:2105 src/prefs.c:225 msgid "JPEG Save Quality (100=High)" msgstr "Jakość zapisu JPEG (100=Wysoka)" #: src/canvas.c:2107 msgid "ZIP Compression (0=None)" msgstr "" #: src/canvas.c:2108 src/prefs.c:227 msgid "PNG Compression (0=None)" msgstr "" #: src/canvas.c:2111 src/prefs.c:249 msgid "LZMA2 Compression (0=None)" msgstr "" #: src/canvas.c:2113 src/prefs.c:252 msgid "ZSTD Compression Level" msgstr "" #: src/canvas.c:2115 src/prefs.c:231 msgid "TGA RLE Compression" msgstr "" #: src/canvas.c:2117 msgid "LBM PackBits Compression" msgstr "" #: src/canvas.c:2118 src/prefs.c:226 msgid "JPEG2000 Compression (0=Lossless)" msgstr "" #: src/canvas.c:2120 msgid "WebP Compression" msgstr "" #: src/canvas.c:2122 msgid "WebP Save Quality (100=High)" msgstr "" #: src/canvas.c:2123 src/prefs.c:263 msgid "V8 Save Quality (100=High)" msgstr "" #: src/canvas.c:2125 src/prefs.c:264 msgid "V8L Compression (0=None)" msgstr "" #: src/canvas.c:2127 msgid "Hotspot at X =" msgstr "Hotspot w X=" #: src/canvas.c:2129 msgid "Y =" msgstr "Y=" #: src/canvas.c:2133 msgid "Animation delay" msgstr "Opóźnienie animacji" #: src/canvas.c:2136 src/otherwindow.c:253 msgid "Undoable" msgstr "" #: src/canvas.c:2138 src/prefs.c:236 msgid "Apply colour profile" msgstr "" #: src/canvas.c:2176 src/toolbar.c:543 msgid "Load Image File" msgstr "Otwórz Obrazek" #: src/canvas.c:2191 src/toolbar.c:544 msgid "Save Image File" msgstr "Zapisz Obrazek" #: src/canvas.c:2196 msgid "Load Palette File" msgstr "ZaÅ‚aduj PaletÄ™" #: src/canvas.c:2202 msgid "Save Palette File" msgstr "Zapisz PaletÄ™" #: src/canvas.c:2207 msgid "Export Undo Images" msgstr "Eksportuj cofniÄ™te obrazy" #: src/canvas.c:2212 msgid "Export Undo Images (reversed)" msgstr "Eksportuj cofniÄ™te obrazy (odwrócone)" #: src/canvas.c:2217 msgid "You must have 16 or fewer palette colours to export ASCII art." msgstr "Potrzeba co najwyżej 16 kolrów aby eksportować grafikÄ™ ASCII" #: src/canvas.c:2220 msgid "Export ASCII Art" msgstr "Eksportuj jako obrazek ASCII" #: src/canvas.c:2224 msgid "Save Layer Files" msgstr "Zapisz pliki warstw" #: src/canvas.c:2234 msgid "Choose frames directory" msgstr "Wybierz folder ramki" #: src/canvas.c:2240 msgid "You must save at least one frame to create an animated GIF." msgstr "Potrzeba zapisać co najmniej jednÄ… ramkÄ™ aby utworzyć GIF" #: src/canvas.c:2243 msgid "Export GIF animation" msgstr "Eksportuj animacjÄ™ GIF" #: src/canvas.c:2247 msgid "Load Channel" msgstr "Åaduj kanaÅ‚" #: src/canvas.c:2255 msgid "Save Channel" msgstr "Zapisz kanaÅ‚" #: src/canvas.c:2260 msgid "Save Composite Image" msgstr "Zapisz obrazek zÅ‚ożony" #: src/channels.c:243 msgid "Create Channel" msgstr "Utwórz kanaÅ‚" #: src/channels.c:244 msgid "Channel Type" msgstr "Typ kanaÅ‚u" #: src/channels.c:247 msgid "Initial Channel State" msgstr "Inicjuj stan kanaÅ‚u" #: src/channels.c:251 msgid "Inverted" msgstr "Odwrócone" #: src/channels.c:265 msgid "Cleared" msgstr "Wyczyszczony" #: src/channels.c:266 msgid "Set" msgstr "Ustaw" #: src/channels.c:267 msgid "Set colour A radius B" msgstr "Ustaw kolor A promieÅ„ B" #: src/channels.c:268 msgid "Set blend A to B" msgstr "Ustaw przejśćie z A do B" #: src/channels.c:269 msgid "Image Red" msgstr "Czerwony" #: src/channels.c:270 msgid "Image Green" msgstr "Zielony" #: src/channels.c:271 msgid "Image Blue" msgstr "Niebieski" #: src/channels.c:273 src/channels.c:313 src/mainwindow.c:67 #: src/otherwindow.c:1679 msgid "Alpha" msgstr "Alfa" #: src/channels.c:274 src/channels.c:314 src/mainwindow.c:67 #: src/otherwindow.c:1683 msgid "Selection" msgstr "Zaznaczenie" #: src/channels.c:275 src/channels.c:315 src/mainwindow.c:67 #: src/otherwindow.c:1687 msgid "Mask" msgstr "Maska" #: src/channels.c:312 msgid "Delete Channels" msgstr "UsuÅ„ kanaÅ‚y" #: src/channels.c:367 msgid "Threshold Channel" msgstr "KanaÅ‚ progu" #: src/cpick.c:823 src/otherwindow.c:573 src/otherwindow.c:820 #: src/toolbar.c:299 msgid "Hue" msgstr "OdcieÅ„" #: src/cpick.c:827 src/otherwindow.c:573 src/otherwindow.c:818 #: src/toolbar.c:299 msgid "Saturation" msgstr "Nasycenie" #: src/cpick.c:835 msgid "Hex" msgstr "" #: src/cpick.c:840 src/layer.c:1109 src/otherwindow.c:2530 src/prefs.c:323 #: src/toolbar.c:457 msgid "Opacity" msgstr "Przeźroczystość" #: src/font.c:982 msgid "Creating Font Index" msgstr "" #: src/font.c:1353 msgid "You must select at least one directory to search for fonts." msgstr "" #: src/font.c:1529 src/font.c:1624 src/toolbar.c:609 src/viewer.c:1213 #: src/viewer.c:1258 msgid "Paste Text" msgstr "Wklej tekst" #: src/font.c:1533 src/font.c:1572 src/png.c:3578 msgid "Text" msgstr "" #: src/font.c:1540 msgid "Font" msgstr "" #: src/font.c:1548 msgid "Style" msgstr "" #: src/font.c:1566 msgid "Filename" msgstr "" #: src/font.c:1567 msgid "Face" msgstr "" #: src/font.c:1587 src/viewer.c:1222 msgid "Antialias" msgstr "Antialias" #: src/font.c:1590 src/viewer.c:1224 msgid "Invert" msgstr "Negatyw" #: src/font.c:1593 src/viewer.c:1226 msgid "Background colour =" msgstr "Kolor tÅ‚a =" #: src/font.c:1601 src/viewer.c:1233 msgid "DPI =" msgstr "" #: src/font.c:1610 msgid "Oblique" msgstr "" #: src/font.c:1612 src/viewer.c:1244 msgid "Angle of rotation =" msgstr "KÄ…t obrotu=" #: src/font.c:1617 src/viewer.c:1248 msgid "Align" msgstr "" #: src/font.c:1620 src/viewer.c:1253 msgid "Spacing" msgstr "" #: src/font.c:1629 msgid "Font Directories" msgstr "" #: src/font.c:1634 src/spawn.c:664 msgid "Directory" msgstr "" #: src/font.c:1637 msgid "New Directory" msgstr "" #: src/font.c:1644 src/prefs.c:532 msgid "Add" msgstr "" #: src/font.c:1645 src/prefs.c:533 msgid "Remove" msgstr "" #: src/font.c:1646 msgid "Create Index" msgstr "" #: src/font.c:1660 src/viewer.c:1267 msgid "Enter Text Here" msgstr "Wpisz tutaj tekst" #: src/fpick.c:635 #, c-format msgid "Could not access directory %s" msgstr "" #: src/fpick.c:668 src/fpick.c:698 msgid "Delete" msgstr "" #: src/fpick.c:669 src/fpick.c:698 msgid "Rename" msgstr "" #: src/fpick.c:672 src/otherwindow.c:255 src/otherwindow.c:1666 msgid "Create" msgstr "Utwórz" #: src/fpick.c:699 msgid "Enter the new filename" msgstr "" #: src/fpick.c:704 msgid "Create Directory" msgstr "" #: src/fpick.c:705 msgid "Enter the name of the new directory" msgstr "" #: src/fpick.c:729 #, c-format msgid "Do you really want to delete \"%s\" ?" msgstr "" #: src/fpick.c:735 msgid "Unable to delete" msgstr "" #: src/fpick.c:741 msgid "Unable to rename" msgstr "" #: src/fpick.c:750 msgid "Unable to create directory" msgstr "" #: src/fpick.c:924 msgid "Up" msgstr "" #: src/fpick.c:925 msgid "Home" msgstr "" #: src/fpick.c:926 msgid "Create New Directory" msgstr "" #: src/fpick.c:927 msgid "Show Hidden Files" msgstr "" #: src/fpick.c:929 msgid "Case Insensitive Sort" msgstr "" #: src/fpick.c:936 msgid "Name" msgstr "" #: src/fpick.c:938 msgid "Type" msgstr "" #: src/fpick.c:939 msgid "Modified" msgstr "" #: src/help.c:25 src/prefs.c:160 msgid "General" msgstr "Ogólne" #: src/help.c:26 msgid "Keyboard shortcuts" msgstr "Skróty klawiszowe" #: src/help.c:27 msgid "Mouse shortcuts" msgstr "Skróty myszki" #: src/help.c:28 msgid "Credits" msgstr "Autorzy" #: src/help.c:32 msgid "mtPaint 3.51 - Copyright (C) 2004-2021 The Authors\n" msgstr "" #: src/help.c:33 msgid "See 'Credits' section for a list of the authors.\n" msgstr "" #: src/help.c:34 msgid "" "mtPaint 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.\n" msgstr "" #: src/help.c:35 msgid "" "mtPaint 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.\n" msgstr "" #: src/help.c:36 msgid "" "mtPaint is a simple GTK+1/2/3 painting program designed for creating icons " "and pixel based artwork. It can edit indexed palette or 24 bit RGB images " "and offers basic painting and palette manipulation tools. It also has " "several other more powerful features such as channels, layers and animation. " "Due to its simplicity and lack of dependencies it runs well on GNU/Linux, " "Windows and older PC hardware.\n" msgstr "" #: src/help.c:37 msgid "" "There is full documentation of mtPaint's features contained in a handbook. " "If you don't already have this, you can download it from the mtPaint " "website.\n" msgstr "" #: src/help.c:38 msgid "" "If you like mtPaint and you want to keep up to date with new releases, or " "you want to give some feedback, then the mailing lists may be of interest to " "you:\n" msgstr "" #: src/help.c:39 msgid "http://sourceforge.net/mail/?group_id=155874" msgstr "" #: src/help.c:42 msgid " Ctrl-N Create new image" msgstr " Ctrl-N Utwórz Nowy Obraz" #: src/help.c:43 msgid " Ctrl-O Open Image" msgstr " Ctrl-O Otwórz obraz" #: src/help.c:44 msgid " Ctrl-S Save Image" msgstr " Ctrl-S Zapisz obraz" #: src/help.c:45 msgid " Ctrl-Shift-S Save layers file" msgstr "" #: src/help.c:46 msgid " Ctrl-Q Quit program\n" msgstr " Ctrl-Q Zamknij program\n" #: src/help.c:47 msgid " Ctrl-A Select whole image" msgstr " Ctrl-A Zaznacz caÅ‚y obraz" #: src/help.c:48 msgid " Escape Select nothing, cancel paste box" msgstr " Escape Odznacz wszystko, anuluj wklejanie" #: src/help.c:49 msgid " J Lasso selection\n" msgstr "" #: src/help.c:50 msgid " Ctrl-C Copy selection to clipboard" msgstr " Ctrl-C Kopiuj zaznaczenie do schowka" #: src/help.c:51 msgid "" " Ctrl-X Copy selection to clipboard, and then paint current " "pattern to selection area" msgstr "" " Ctrl-X Kopiuj zaznaczenie do schowka, rysuj bieżący wzór na " "zaznaczonym obszarze" #: src/help.c:52 msgid " Ctrl-V Paste clipboard to centre of current view" msgstr " Ctrl-V Wklej zawartość schowka w Å›rodek aktualnego widoku" #: src/help.c:53 msgid " Ctrl-K Paste clipboard to location it was copied from" msgstr " Ctrl-K Wklej obrazek schowka tam, skÄ…d zostaÅ‚ skopiowany" #: src/help.c:54 msgid " Ctrl-Shift-V Paste clipboard to new layer" msgstr "" #: src/help.c:55 msgid " Enter/Return Commit paste to canvas" msgstr " Enter/Return Wklej na płótno" #: src/help.c:56 msgid " Shift+Enter/Return Commit paste and swap canvas into the clipboard\n" msgstr "" #: src/help.c:57 msgid " Arrow keys Paint Mode - Move the mouse pointer" msgstr " Arrow keys Tryb rysowania - Ruszaj myszkÄ…" #: src/help.c:58 msgid "" " Arrow keys Selection Mode - Nudge selection box or paste box by one " "pixel" msgstr "" " Arrow keys Tryb zaznaczania - Nudge selection box or paste box by " "one pixel" #: src/help.c:59 msgid "" " Shift+Arrow keys Nudge mouse pointer, selection box or paste box by x " "pixels - x is defined by the Preferences window" msgstr "" #: src/help.c:60 msgid " Ctrl+Arrows Move layer or resize selection box" msgstr " Ctrl+Arrows PrzenieÅ› warstwÄ™ lub zmieÅ„ rozm. zaznaczenia" #: src/help.c:61 msgid " Ctrl+Shift+Arrows Move layer or resize selection box by x pixels\n" msgstr "" #: src/help.c:62 msgid " Enter/Return Paint Mode - Simulate left click" msgstr "" #: src/help.c:63 msgid " Backspace Paint Mode - Simulate right click\n" msgstr "" #: src/help.c:64 msgid "" " [ or ] Change colour A to the next or previous palette item" msgstr " [ or ] Zmien kolor A na nastÄ™pny w palecie" #: src/help.c:65 msgid "" " Shift+[ or ] Change colour B to the next or previous palette item\n" msgstr " Shift+[ or ] Zmien kolor B na nastÄ™pny w palecie\n" #: src/help.c:66 msgid " Delete Crop image to selection" msgstr " Delete Obcinaj obraz do zaznaczenia" #: src/help.c:67 msgid "" " Insert Transform colours - i.e. Brightness, Contrast, " "Saturation, Posterize, Gamma" msgstr "" " Insert Przekształć kolory np:Jasność, kontrast, Nasycenie, Gamma" #: src/help.c:68 msgid " Ctrl-G Greyscale the image" msgstr " Ctrl-G Skala szaroÅ›ci" #: src/help.c:69 msgid " Shift-Ctrl-G Greyscale the image (Gamma corrected)" msgstr " Shift-Ctrl-G Skala szarość (Gamma corrected)" #: src/help.c:70 msgid " Ctrl+M Mirror the image" msgstr "" #: src/help.c:71 msgid " Shift-Ctrl-I Invert the image\n" msgstr "" #: src/help.c:72 msgid "" " Ctrl-T Draw a rectangle around the selection area with the " "current fill" msgstr "" " Ctrl-T Rysuj prostokÄ…t dookoÅ‚a zaznaczenia akutalnum wypeÅ‚nieniem" #: src/help.c:73 msgid " Ctrl-Shift-T Fill in the selection area with the current fill" msgstr " Ctrl-Shift-T WypeÅ‚nij zaznaczony obszar aktualnym wypeÅ‚nieniem" #: src/help.c:74 msgid " Ctrl-L Draw an ellipse spanning the selection area" msgstr " Ctrl-L Rysuj elipsÄ™ wewnÄ…trz zaznaczonego obsaru" #: src/help.c:75 msgid " Ctrl-Shift-L Draw a filled ellipse spanning the selection area\n" msgstr "" " Ctrl-Shift-L Rysuj wypeÅ‚nionÄ… elipsÄ™ wewnÄ…trz zaznaczonego obsaru\n" #: src/help.c:76 msgid " Ctrl-E Edit the RGB values for colours A & B" msgstr " Ctrl-E Edytuj wartoÅ›ci RGB dla kolorów A & B" #: src/help.c:77 msgid " Ctrl-W Edit all palette colours\n" msgstr " Ctrl-W Edytuj kolory\n" #: src/help.c:78 msgid " Ctrl-P Preferences" msgstr " Ctrl-P Ustawienia" #: src/help.c:79 msgid " Ctrl-I Information\n" msgstr " Ctrl-I Informacje\n" #: src/help.c:80 msgid " Ctrl-Z Undo last action" msgstr " Ctrl-Z Wycofaj ostatniÄ… akcjÄ™" #: src/help.c:81 msgid " Ctrl-R Redo an undone action\n" msgstr " Ctrl-R Ponów niewykonane akcje\n" #: src/help.c:82 msgid " Shift-T Text Tool (GTK+)" msgstr "" #: src/help.c:83 msgid " T Text Tool (FreeType)\n" msgstr "" #: src/help.c:84 msgid " V View Window" msgstr " V Okno pokazu" #: src/help.c:85 msgid " L Layers Window\n" msgstr " L Okno warstw\n" #: src/help.c:86 msgid " Ctrl-H Toggle Hide Image mode" msgstr "" #: src/help.c:87 msgid " B Toggle Snap to Tile Grid mode\n" msgstr "" #: src/help.c:88 msgid " X Swap Colours A & B" msgstr "" #: src/help.c:89 msgid " E Choose Colour\n" msgstr "" #: src/help.c:90 msgid "" " A Draw open arrow head when using the line tool (size set " "by flow setting)" msgstr "" #: src/help.c:91 msgid "" " S Draw closed arrow head when using the line tool (size " "set by flow setting)\n" msgstr "" #: src/help.c:92 msgid " D Line Tool" msgstr "" #: src/help.c:93 msgid " F Flood Fill Tool\n" msgstr "" #: src/help.c:94 msgid " +,= Main edit window - Zoom in" msgstr " +,= Main edit window - PowiÄ™ksz" #: src/help.c:95 msgid " - Main edit window - Zoom out" msgstr " - Main edit window - Zmniejsz" #: src/help.c:96 msgid " Shift +,= View window - Zoom in" msgstr " Shift +,= View window - PowiÄ™ksz" #: src/help.c:97 msgid " Shift - View window - Zoom out\n" msgstr " Shift - View window - Zmniejsz\n" #: src/help.c:98 #, c-format msgid " 1 10% zoom" msgstr "" #: src/help.c:99 #, c-format msgid " 2 25% zoom" msgstr "" #: src/help.c:100 #, c-format msgid " 3 50% zoom" msgstr "" #: src/help.c:101 #, c-format msgid " 4 100% zoom" msgstr "" #: src/help.c:102 #, c-format msgid " 5 400% zoom" msgstr "" #: src/help.c:103 #, c-format msgid " 6 800% zoom" msgstr "" #: src/help.c:104 #, c-format msgid " 7 1200% zoom" msgstr "" #: src/help.c:105 #, c-format msgid " 8 1600% zoom" msgstr "" #: src/help.c:106 #, c-format msgid " 9 2000% zoom\n" msgstr "" #: src/help.c:107 msgid " Shift + 1 Edit image channel" msgstr " Shift + 1 Edytuj kanaÅ‚ obrazka" #: src/help.c:108 msgid " Shift + 2 Edit alpha channel" msgstr " Shift + 2 Edytuj kanaÅ‚ alfa" #: src/help.c:109 msgid " Shift + 3 Edit selection channel" msgstr " Shift + 3 Edytuj kanaÅ‚ zaznaczenia" #: src/help.c:110 msgid " Shift + 4 Edit mask channel\n" msgstr " Shift + 4 Edytuj kanaÅ‚ maski\n" #: src/help.c:111 msgid " F1 Help" msgstr "" #: src/help.c:112 msgid " F2 Choose Pattern" msgstr " F2 Wybierz wzór" #: src/help.c:113 msgid " F3 Choose Brush" msgstr " F3 Wybierz pedziel" #: src/help.c:114 msgid " F4 Paint Tool" msgstr " F4 NarzÄ™dzie rysowania" #: src/help.c:115 msgid " F5 Toggle Main Toolbar" msgstr " F5 Przełącz główny pasek" #: src/help.c:116 msgid " F6 Toggle Tools Toolbar" msgstr " F6 Przełącz pasek narzÄ™dzi" #: src/help.c:117 msgid " F7 Toggle Settings Toolbar" msgstr " F7 Przełącz pasek ustawieÅ„" #: src/help.c:118 msgid " F8 Toggle Palette" msgstr " F8 Przełącz paletÄ™" #: src/help.c:119 msgid " F9 Selection Tool" msgstr " F9 NarzÄ™dzie zaznaczenia" #: src/help.c:120 msgid " F12 Toggle Dock Area\n" msgstr "" #: src/help.c:121 msgid " Ctrl + F1 - F12 Save current clipboard to file 1-12" msgstr " Ctrl + F1 - F12 Zapisz bieżący obrazek ze schowka do pliku 1-12" #: src/help.c:122 msgid " Shift + F1 - F12 Load clipboard from file 1-12\n" msgstr " Shift + F1 - F12 Åaduj obrazek do schowka z pliku 1-12\n" #: src/help.c:123 msgid "" " Ctrl + 1, 2, ... , 0 Set opacity to 10%, 20%, ... , 100% (main or keypad " "numbers)" msgstr "" " Ctrl + 1, 2, ... , 0 Ustaw nieprzeźroczystość na 10%, 20%, ... , 100% " "(główne lub numeryczne klawisze liczbowe)" #: src/help.c:124 msgid " Ctrl + + or = Increase opacity by 1" msgstr " Ctrl + + or = ZwiÄ™ksz nieprzeźroczystość o 1" #: src/help.c:125 msgid " Ctrl + - Decrease opacity by 1\n" msgstr " Ctrl + - Zmniejsz przźroczystość o 1\n" #: src/help.c:126 msgid "" " Home Show or hide main window menu/toolbar/status bar/palette" msgstr "" " Home Pokaż lub ukryj główne okon/paski narzÄ™dzi/pasek statusu/" "palette" #: src/help.c:127 msgid " Page Up Scale Image" msgstr " Page Up Skaluj obraz" #: src/help.c:128 msgid " Page Down Resize Image canvas" msgstr " Page Down ZmieÅ„ rozmiar obrazu na płótnie" #: src/help.c:129 msgid " End Pan Window" msgstr "" #: src/help.c:132 msgid " Left button Paint to canvas using the current tool" msgstr " Lewy przycisk myszki Rysuj u użyciem bieżącego narzÄ™dzia" #: src/help.c:133 msgid "" " Middle button Selects the point which will be the centre of the " "image after the next zoom" msgstr "" " Åšrodkowy przycisk myszki Wybierz punkt, który bÄ™dzie w Å›rodku " "obrazu po zmianie powiÄ™kszenia" #: src/help.c:134 msgid "" " Right button Commit paste to canvas / Stop drawing current line / " "Cancel selection\n" msgstr "" " Prawy przycisk myszki Wklej na płótno / ZakoÅ„cz rysowanie lini / " "Cancel selection\n" #: src/help.c:135 msgid "" " Scroll Wheel In GTK+2/3 the user can have the scroll wheel zoom in " "or out via the Preferences window\n" msgstr "" " Kółko myszki In GTK+2/3 the user can have the scroll wheel zoom in " "or out via the Preferences window\n" #: src/help.c:136 msgid " Ctrl+Left button Choose colour A from under mouse pointer" msgstr " Ctrl+ Lewy myszki Wybierz kolor A" #: src/help.c:137 msgid " Ctrl+Left button Clone tool - Select source" msgstr "" #: src/help.c:138 msgid "" " Ctrl+Middle button Create colour A/B and pattern based on the RGB colour " "in A (RGB images only)" msgstr "" #: src/help.c:139 msgid " Ctrl+Right button Choose colour B from under mouse pointer" msgstr " Ctrl+Prawy myszki Wybierz kolor B" #: src/help.c:140 msgid "" " Ctrl+Right button Polygon tool - Delete last point / Delete nearest " "point" msgstr "" #: src/help.c:141 msgid " Ctrl+Scroll Wheel Scroll the main edit window left or right\n" msgstr " Ctrl+Kółko myszki PrzewiÅ„ zawartość okna w prawo/lewo\n" #: src/help.c:142 msgid "" " Ctrl+Double click Set colour A or B to average colour under brush " "square or selection marquee (RGB only)\n" msgstr "" #: src/help.c:143 msgid "" " Shift+Right button Selects the point which will be the centre of the " "image after the next zoom\n" "\n" msgstr "" " Shift+Prawy myszki Wybierz punkt który bÄ™dzie w Å›rodku obrazu po " "kolejnym powiÄ™kszeniu\n" "\n" #: src/help.c:144 msgid "You can fixate the X/Y co-ordinates while moving the mouse:\n" msgstr "" #: src/help.c:145 msgid " Shift Constrain mouse movements to vertical line" msgstr " Shift Ogranicz ruch myszki do lini poziomych" #: src/help.c:146 msgid " Shift+Ctrl Constrain mouse movements to horizontal line" msgstr " Shift+Ctrl Ogranicz ruch myszki do lini pionowych" #: src/help.c:149 msgid "mtPaint is maintained by Dmitry Groshev.\n" msgstr "" #: src/help.c:150 msgid "wjaguar@users.sourceforge.net" msgstr "" #: src/help.c:151 msgid "http://mtpaint.sourceforge.net/\n" msgstr "" #: src/help.c:152 msgid "" "The following people (in alphabetical order) have contributed directly to " "the project, and are therefore worthy of gracious thanks for their " "generosity and hard work:\n" "\n" msgstr "" #: src/help.c:153 msgid "Authors\n" msgstr "" #: src/help.c:154 msgid "" "Dmitry Groshev - Contributing developer for version 2.30. Lead developer and " "maintainer from version 3.00 to the present." msgstr "" #: src/help.c:155 msgid "" "Mark Tyler - Original author and maintainer up to version 3.00, occasional " "contributor thereafter." msgstr "" #: src/help.c:156 msgid "" "Xiaolin Wu - Wrote the Wu quantizing method - see wu.c for more " "information.\n" "\n" msgstr "" #: src/help.c:157 msgid "" "General Contributions (Feedback and Ideas for improvements unless otherwise " "stated)\n" msgstr "" #: src/help.c:158 msgid "Abdulla Al Muhairi - Website redesign April 2005" msgstr "" #: src/help.c:159 msgid "Alan Horkan" msgstr "" #: src/help.c:160 msgid "Alexandre Prokoudine" msgstr "" #: src/help.c:161 msgid "Antonio Andrea Bianco" msgstr "" #: src/help.c:162 msgid "Charlie Ledocq" msgstr "" #: src/help.c:163 msgid "Dennis Lee" msgstr "" #: src/help.c:164 msgid "Donald White" msgstr "" #: src/help.c:165 msgid "Ed Jason" msgstr "" #: src/help.c:166 msgid "" "Eddie Kohler - Created Gifsicle which is needed for the creation and viewing " "of animated GIF files http://www.lcdf.org/gifsicle/" msgstr "" #: src/help.c:167 msgid "" "Guadalinex Team (Junta de Andalucia) - man page, Launchpad/Rosetta " "registration" msgstr "" #: src/help.c:168 msgid "Lou Afonso" msgstr "" #: src/help.c:169 msgid "Magnus Hjorth" msgstr "" #: src/help.c:170 msgid "Martin Zelaia" msgstr "" #: src/help.c:171 msgid "Pasi Kallinen" msgstr "" #: src/help.c:172 msgid "Pavel Ruzicka" msgstr "" #: src/help.c:173 msgid "Puppy Linux (Barry Kauler)" msgstr "" #: src/help.c:174 msgid "Victor Copovi" msgstr "" #: src/help.c:175 msgid "Vlastimil Krejcir" msgstr "" #: src/help.c:176 msgid "" "William Kern\n" "\n" msgstr "" #: src/help.c:177 msgid "Translations\n" msgstr "" #: src/help.c:178 msgid "Brazilian Portuguese - Paulo Trevizan, Valter Nazianzeno" msgstr "" #: src/help.c:179 msgid "Czech - Pavel Ruzicka, Martin Petricek, Roman Hornik, Pavel Fric" msgstr "" #: src/help.c:180 msgid "Dutch - Hans Strijards, Pjotr" msgstr "" #: src/help.c:181 msgid "" "French - Nicolas Velin, Pascal Billard, Sylvain Cresto, Johan Serre, " "Philippe Etienne, Victor Copovi" msgstr "" #: src/help.c:182 msgid "Galician - Miguel Anxo Bouzada" msgstr "" #: src/help.c:183 msgid "German - Oliver Frommel, B. Clausius, Ulrich Ringel, Simon Brixel" msgstr "" #: src/help.c:184 msgid "Hungarian - Ur Balazs" msgstr "" #: src/help.c:185 msgid "Italian - Angelo Gemmi" msgstr "" #: src/help.c:186 msgid "Japanese - Norihiro YONEDA" msgstr "" #: src/help.c:187 msgid "Kabyle - Yacine Bouklif" msgstr "" #: src/help.c:188 msgid "Polish - Bartosz Kaszubowski, LucaS" msgstr "" #: src/help.c:189 msgid "Portuguese - Israel G. Lugo, Tiago Silva" msgstr "" #: src/help.c:190 msgid "Russian - Sergey Irupin, Dmitry Groshev" msgstr "" #: src/help.c:191 msgid "Simplified Chinese - Cecc" msgstr "" #: src/help.c:192 msgid "Slovak - Jozef Riha" msgstr "" #: src/help.c:193 msgid "" "Spanish - Guadalinex Team (Junta de Andalucia), Antonio Sanchez Leon, Miguel " "Anxo Bouzada, Francisco Jose Rey, Adolfo Jayme" msgstr "" #: src/help.c:194 msgid "Swedish - Daniel Nylander, Daniel Eriksson" msgstr "" #: src/help.c:195 msgid "Tagalog - Anjelo delCarmen" msgstr "" #: src/help.c:196 msgid "Taiwanese Chinese - Wei-Lun Chao" msgstr "" #: src/help.c:197 msgid "Turkish - Muhammet Kara, Tutku Dalmaz" msgstr "" #: src/info.c:258 msgid "Information" msgstr "Informacja" #: src/info.c:260 msgid "Memory" msgstr "Pamięć" #: src/info.c:261 msgid "Total memory for main + undo images" msgstr "CaÅ‚kowita ilość pamiÄ™ci + pamięć dla cofniÄ™tych zmian" #: src/info.c:263 msgid "Undo / Redo / Max levels used" msgstr "Cofnij / Ponów / Maksymalna liczba wyczerpana" #: src/info.c:265 msgid "Unused" msgstr "Nieużywany" #: src/info.c:269 msgid "Unique RGB pixels" msgstr "Unikalne piksele RGB" #: src/info.c:272 src/layer.c:121 msgid "Layers" msgstr "Warstwy" #: src/info.c:273 msgid "Total layer memory usage" msgstr "CaÅ‚kowite zużycie pamiÄ™ci przez warstwy" #: src/info.c:277 msgid "Colour Histogram" msgstr "Histogram kolorów" #: src/info.c:289 src/otherwindow.c:1614 msgid "Index" msgstr "Indeks" #: src/info.c:290 msgid "Canvas pixels" msgstr "Punkty płótna" #: src/info.c:328 #, c-format msgid "Clipboard = %i x %i" msgstr "Schowek = %i x %i" #: src/info.c:328 #, c-format msgid "Clipboard = %i x %i x RGB" msgstr "Schowek = %i x %i x RGB" #: src/info.c:377 msgid "Orphans" msgstr "Sieroty" #: src/info.c:383 #, c-format msgid "Colour index totals - %i of %i used" msgstr "" #: src/inifile.c:966 msgid "" "Could not find home directory. Using current directory as home directory." msgstr "Nie można odnaleźć folderu domowego. Użyj folderu bieżącego." #: src/layer.c:63 msgid "Background" msgstr "TÅ‚o" #: src/layer.c:122 src/mainwindow.c:5931 msgid "(Modified)" msgstr "(Zmodyfikowano)" #: src/layer.c:123 src/mainwindow.c:5932 msgid "Untitled" msgstr "Bez nazwy" #: src/layer.c:308 #, c-format msgid "Do you really want to delete layer %i (%s) ?" msgstr "Czy na pewno chcesz usunąć warstwÄ™ %i (%s) ?" #: src/layer.c:380 msgid "" "One or more of the layers contains changes that have not been saved. Do you " "really want to lose these changes?" msgstr "" "Jedna lub wiÄ™cej warstw, która zostaÅ‚a zmieniona nie może zostać zapisanaCzy " "na pewno chcesz utracić zmiany?" #: src/layer.c:381 src/mainwindow.c:1028 msgid "Cancel Operation" msgstr "Anuluj operacjÄ™" #: src/layer.c:381 src/mainwindow.c:1028 msgid "Lose Changes" msgstr "Nie zapisuj zmian" #: src/layer.c:523 #, c-format msgid "%d layers failed to load" msgstr "%d warstwy niemożliwe do zaÅ‚adowania" #: src/layer.c:826 msgid "" "One or more of the image layers has not been saved. You must save each " "image individually before saving the layers text file in order to load this " "composite image in the future." msgstr "" "Jedna lub wiÄ™cej warstw nie zostaÅ‚a zapisana. Należy zapisać każdÄ… osobno." #: src/layer.c:841 msgid "Do you really want to delete all of the layers?" msgstr "Czy na pewno chcesz usunąć wszystkie warstwy?" #: src/layer.c:970 msgid "You cannot add any more layers." msgstr "Nie możesz dodać wiÄ™cej warstw." #: src/layer.c:1083 src/otherwindow.c:241 msgid "New Layer" msgstr "Nowa warstwa" #: src/layer.c:1085 msgid "Raise" msgstr "ZwiÄ™ksz" #: src/layer.c:1087 msgid "Lower" msgstr "Zmniejsz" #: src/layer.c:1089 msgid "Duplicate Layer" msgstr "Duplikuj warstwÄ™" #: src/layer.c:1091 msgid "Centralise Layer" msgstr "WyÅ›rodkuj warstwÄ™" #: src/layer.c:1093 msgid "Delete Layer" msgstr "UsuÅ„ warstwÄ™" #: src/layer.c:1095 msgid "Close Layers Window" msgstr "Zamknij okno warstw" #: src/layer.c:1101 msgid "Layer Name" msgstr "Nazwa warstwy" #: src/layer.c:1104 src/toolbar.c:209 msgid "Position" msgstr "Pozycja" #: src/layer.c:1112 msgid "Transparent Colour" msgstr "Kolor przezroczysty" #: src/layer.c:1117 msgid "Show all layers in main window" msgstr "Pokaż wszystkie warstwy w głównym oknie" #: src/mainwindow.c:67 src/otherwindow.c:844 src/otherwindow.c:2756 #: src/toolbar.c:342 msgid "Image" msgstr "Obrazek" #: src/mainwindow.c:69 src/mainwindow.c:489 src/otherwindow.c:1613 #: src/otherwindow.c:2302 msgid "RGB" msgstr "" #: src/mainwindow.c:69 src/otherwindow.c:1613 src/otherwindow.c:2302 msgid "sRGB" msgstr "" #: src/mainwindow.c:342 msgid "There were no unused colours to remove!" msgstr "Nie ma nieużywanych kolorów do usniÄ™cia!" #: src/mainwindow.c:371 msgid "The palette does not contain 2 colours that have identical RGB values" msgstr "Paleta nie zawiera dwóch kolorów o identycznych wartoÅ›ciach RGB" #: src/mainwindow.c:374 #, c-format msgid "" "The palette contains %i colours that have identical RGB values. Do you " "really want to merge them into one index and realign the canvas?" msgstr "" #: src/mainwindow.c:492 msgid "indexed" msgstr "" #: src/mainwindow.c:498 #, c-format msgid "" "You are trying to save an %s image to an %s file which is not possible. I " "would suggest you save with a PNG extension." msgstr "" #: src/mainwindow.c:500 #, c-format msgid "" "You are trying to save an %s file with a palette of more than %d colours. " "Either use another format or reduce the palette to %d colours." msgstr "" #: src/mainwindow.c:578 msgid "Unable to load clipboard" msgstr "Nie można zaÅ‚adować obrazu ze schowka" #: src/mainwindow.c:604 msgid "Unable to save clipboard" msgstr "Nie można zapisać obrazu do schowka" #: src/mainwindow.c:775 msgid "Zoom in" msgstr "" #: src/mainwindow.c:777 msgid "Zoom out" msgstr "" #: src/mainwindow.c:779 #, c-format msgid "10% zoom" msgstr "" #: src/mainwindow.c:781 #, c-format msgid "25% zoom" msgstr "" #: src/mainwindow.c:783 #, c-format msgid "50% zoom" msgstr "" #: src/mainwindow.c:785 #, c-format msgid "100% zoom" msgstr "" #: src/mainwindow.c:787 #, c-format msgid "400% zoom" msgstr "" #: src/mainwindow.c:789 #, c-format msgid "600% zoom" msgstr "" #: src/mainwindow.c:791 #, c-format msgid "800% zoom" msgstr "" #: src/mainwindow.c:793 #, c-format msgid "1000% zoom" msgstr "" #: src/mainwindow.c:795 #, c-format msgid "1200% zoom" msgstr "" #: src/mainwindow.c:797 #, c-format msgid "1600% zoom" msgstr "" #: src/mainwindow.c:799 #, c-format msgid "2000% zoom" msgstr "" #: src/mainwindow.c:801 #, c-format msgid "4000% zoom" msgstr "" #: src/mainwindow.c:803 #, c-format msgid "8000% zoom" msgstr "" #: src/mainwindow.c:805 #, c-format msgid "10% opacity" msgstr "" #: src/mainwindow.c:807 #, c-format msgid "20% opacity" msgstr "" #: src/mainwindow.c:809 #, c-format msgid "30% opacity" msgstr "" #: src/mainwindow.c:811 #, c-format msgid "40% opacity" msgstr "" #: src/mainwindow.c:813 #, c-format msgid "50% opacity" msgstr "" #: src/mainwindow.c:815 #, c-format msgid "60% opacity" msgstr "" #: src/mainwindow.c:817 #, c-format msgid "70% opacity" msgstr "" #: src/mainwindow.c:819 #, c-format msgid "80% opacity" msgstr "" #: src/mainwindow.c:821 #, c-format msgid "90% opacity" msgstr "" #: src/mainwindow.c:823 #, c-format msgid "100% opacity" msgstr "" #: src/mainwindow.c:825 msgid "Increase opacity" msgstr "" #: src/mainwindow.c:827 msgid "Decrease opacity" msgstr "" #: src/mainwindow.c:829 msgid "Draw open arrow head" msgstr "" #: src/mainwindow.c:831 msgid "Draw closed arrow head" msgstr "" #: src/mainwindow.c:833 msgid "Previous colour A" msgstr "" #: src/mainwindow.c:835 msgid "Next colour A" msgstr "" #: src/mainwindow.c:837 msgid "Previous colour B" msgstr "" #: src/mainwindow.c:839 msgid "Next colour B" msgstr "" #: src/mainwindow.c:841 msgid "Previous pattern" msgstr "" #: src/mainwindow.c:843 msgid "Next pattern" msgstr "" #: src/mainwindow.c:845 msgid "Larger brush" msgstr "" #: src/mainwindow.c:847 msgid "Smaller brush" msgstr "" #: src/mainwindow.c:849 msgid "View window - Zoom in" msgstr "" #: src/mainwindow.c:851 msgid "View window - Zoom out" msgstr "" #: src/mainwindow.c:1027 msgid "" "This canvas/palette contains changes that have not been saved. Do you " "really want to lose these changes?" msgstr "" "Obraz zostaÅ‚ zmieniony i nie zapisano zmian. Czy na pewno chcesz utracić " "zmiany?" #: src/mainwindow.c:1094 msgid "Do you really want to quit?" msgstr "Czy na pewno chcesz zamknąć program?" #: src/mainwindow.c:3754 msgid "Empty string or broken quoting" msgstr "" #: src/mainwindow.c:3755 msgid "Script must begin with a command" msgstr "" #: src/mainwindow.c:3756 msgid "Script nesting limit exceeded" msgstr "" #: src/mainwindow.c:3765 #, c-format msgid "'%s' does not match any item" msgstr "" #: src/mainwindow.c:3767 #, c-format msgid "'%s' matches a non-scriptable item" msgstr "" #: src/mainwindow.c:3769 #, c-format msgid "'%s' matches a disabled item" msgstr "" #: src/mainwindow.c:3788 #, c-format msgid "'%s' value does not fit item" msgstr "" #: src/mainwindow.c:3969 msgid "Script" msgstr "" #: src/mainwindow.c:3982 src/spawn.c:656 src/spawn.c:662 msgid "Action" msgstr "" #: src/mainwindow.c:3991 src/spawn.c:666 msgid "Execute" msgstr "" #: src/mainwindow.c:4045 msgid "Unable to load script" msgstr "" #: src/mainwindow.c:5182 msgid "/_File" msgstr "/_Plik" #: src/mainwindow.c:5184 msgid "//New" msgstr "//Nowy" #: src/mainwindow.c:5186 msgid "//Open ..." msgstr "//Otwórz ..." #: src/mainwindow.c:5188 src/mainwindow.c:5669 msgid "//Save" msgstr "//Zapisz" #: src/mainwindow.c:5190 src/mainwindow.c:5549 src/mainwindow.c:5627 #: src/mainwindow.c:5671 msgid "//Save As ..." msgstr "//Zapisz jako ..." #: src/mainwindow.c:5192 msgid "//Export Undo Images ..." msgstr "" #: src/mainwindow.c:5194 msgid "//Export Undo Images (reversed) ..." msgstr "" #: src/mainwindow.c:5196 msgid "//Export ASCII Art ..." msgstr "" #: src/mainwindow.c:5198 msgid "//Export Animated GIF ..." msgstr "" #: src/mainwindow.c:5201 msgid "//Actions" msgstr "" #: src/mainwindow.c:5235 src/mainwindow.c:5488 msgid "///Configure" msgstr "" #: src/mainwindow.c:5290 msgid "//Quit" msgstr "//Wyjdź" #: src/mainwindow.c:5293 msgid "/_Edit" msgstr "/_Edycja" #: src/mainwindow.c:5295 msgid "//Undo" msgstr "//Cofnij" #: src/mainwindow.c:5297 msgid "//Redo" msgstr "//Ponów" #: src/mainwindow.c:5300 msgid "//Cut" msgstr "//Wytnij" #: src/mainwindow.c:5302 msgid "//Copy" msgstr "//Kopiuj" #: src/mainwindow.c:5304 msgid "//Copy To Palette" msgstr "" #: src/mainwindow.c:5306 msgid "//Paste To Centre" msgstr "//Wklej na Å›rodku" #: src/mainwindow.c:5308 msgid "//Paste To New Layer" msgstr "//Wklej w nowej warstwie" #: src/mainwindow.c:5310 msgid "//Paste" msgstr "//Wklej" #: src/mainwindow.c:5312 msgid "//Paste Text" msgstr "//Wklej tekst" #: src/mainwindow.c:5318 msgid "//Paste Text (FreeType)" msgstr "" #: src/mainwindow.c:5321 msgid "//Paste Palette" msgstr "" #: src/mainwindow.c:5323 msgid "//Load Clipboard" msgstr "" #: src/mainwindow.c:5350 msgid "//Save Clipboard" msgstr "//Zapisz obraz" #: src/mainwindow.c:5377 msgid "//Import Clipboard from System" msgstr "" #: src/mainwindow.c:5378 msgid "//Export Clipboard to System" msgstr "" #: src/mainwindow.c:5381 msgid "//Choose Pattern ..." msgstr "//Wybierz wzór ..." #: src/mainwindow.c:5383 msgid "//Choose Brush ..." msgstr "//Wybierz pÄ™dzel ..." #: src/mainwindow.c:5385 msgid "//Choose Colour ..." msgstr "" #: src/mainwindow.c:5392 msgid "/_View" msgstr "/_Widok" #: src/mainwindow.c:5394 msgid "//Show Main Toolbar" msgstr "//Pokazuj główny pasek narzÄ™dzi" #: src/mainwindow.c:5396 msgid "//Show Tools Toolbar" msgstr "" #: src/mainwindow.c:5399 msgid "//Show Settings Toolbar" msgstr "" #: src/mainwindow.c:5402 msgid "//Show Dock" msgstr "" #: src/mainwindow.c:5404 msgid "//Show Palette" msgstr "" #: src/mainwindow.c:5406 msgid "//Show Status Bar" msgstr "" #: src/mainwindow.c:5409 msgid "//Toggle Image View" msgstr "" #: src/mainwindow.c:5413 msgid "//Centralize Image" msgstr "" #: src/mainwindow.c:5414 msgid "//Show Zoom Grid" msgstr "//Pokaż siatkÄ™" #: src/mainwindow.c:5415 msgid "//Snap To Tile Grid" msgstr "" #: src/mainwindow.c:5417 msgid "//Configure Grid ..." msgstr "" #: src/mainwindow.c:5418 msgid "//Tracing Image ..." msgstr "" #: src/mainwindow.c:5421 msgid "//View Window" msgstr "" #: src/mainwindow.c:5423 msgid "//Horizontal Split" msgstr "" #: src/mainwindow.c:5425 msgid "//Focus View Window" msgstr "" #: src/mainwindow.c:5427 msgid "//Pan Window" msgstr "" #: src/mainwindow.c:5430 msgid "//Layers Window" msgstr "//Okno warstw" #: src/mainwindow.c:5433 msgid "/_Image" msgstr "/_Obrazek" #: src/mainwindow.c:5436 msgid "//Convert To RGB" msgstr "//Przekształć do RGB" #: src/mainwindow.c:5438 msgid "//Convert To Indexed ..." msgstr "//Konwertuj do indeksowanych ..." #: src/mainwindow.c:5441 msgid "//Scale Canvas ..." msgstr "" #: src/mainwindow.c:5443 msgid "//Resize Canvas ..." msgstr "" #: src/mainwindow.c:5445 msgid "//Crop" msgstr "//Przytnij" #: src/mainwindow.c:5448 src/mainwindow.c:5517 msgid "//Flip Vertically" msgstr "//Obróć w pionie" #: src/mainwindow.c:5449 src/mainwindow.c:5519 msgid "//Flip Horizontally" msgstr "//Obróć w poziomie" #: src/mainwindow.c:5452 src/mainwindow.c:5521 msgid "//Rotate Clockwise" msgstr "//Obróć w prawo" #: src/mainwindow.c:5453 src/mainwindow.c:5523 msgid "//Rotate Anti-Clockwise" msgstr "//Obróć w lewo" #: src/mainwindow.c:5454 msgid "//Free Rotate ..." msgstr "//Dodolna rotacja ..." #: src/mainwindow.c:5455 msgid "//Skew ..." msgstr "" #: src/mainwindow.c:5458 msgid "//Segment ..." msgstr "" #: src/mainwindow.c:5462 msgid "//Script ..." msgstr "" #: src/mainwindow.c:5464 msgid "//Scripts" msgstr "" #: src/mainwindow.c:5491 msgid "//Information ..." msgstr "//Informacje ..." #: src/mainwindow.c:5494 msgid "//Preferences ..." msgstr "//Ustawienia ..." #: src/mainwindow.c:5497 msgid "/_Selection" msgstr "/_Zaznaczenie" #: src/mainwindow.c:5499 msgid "//Select All" msgstr "//Zaznacz wszystko" #: src/mainwindow.c:5501 msgid "//Select None (Esc)" msgstr "//Brak zaznaczenia" #: src/mainwindow.c:5503 msgid "//Lasso Selection" msgstr "//Zaznaczenie Lasso" #: src/mainwindow.c:5505 msgid "//Lasso Selection Cut" msgstr "//Wytnij Zaznaczenie Lasso" #: src/mainwindow.c:5508 msgid "//Outline Selection" msgstr "//Zaznaczenie krawÄ™dzi" #: src/mainwindow.c:5510 msgid "//Fill Selection" msgstr "" #: src/mainwindow.c:5512 msgid "//Outline Ellipse" msgstr "//Krawedzie elipsy" #: src/mainwindow.c:5514 msgid "//Fill Ellipse" msgstr "//WypeÅ‚nij elipsÄ™" #: src/mainwindow.c:5526 msgid "//Horizontal Ramp" msgstr "" #: src/mainwindow.c:5528 msgid "//Vertical Ramp" msgstr "" #: src/mainwindow.c:5531 msgid "//Alpha Blend A,B" msgstr "" #: src/mainwindow.c:5533 msgid "//Move Alpha to Mask" msgstr "//PrzesuÅ„ alfa do maski" #: src/mainwindow.c:5535 msgid "//Mask Colour A,B" msgstr "//Kolor maski A,B" #: src/mainwindow.c:5537 msgid "//Unmask Colour A,B" msgstr "//Odmaskuj kolor A,B" #: src/mainwindow.c:5539 msgid "//Mask All Colours" msgstr "//Maskuj wszystkie kolory" #: src/mainwindow.c:5541 msgid "//Clear Mask" msgstr "//Wyczyść maskÄ™" #: src/mainwindow.c:5544 msgid "/_Palette" msgstr "/P_aleta" #: src/mainwindow.c:5548 src/mainwindow.c:5626 msgid "//Load ..." msgstr "//Otwórz ..." #: src/mainwindow.c:5550 msgid "//Load Default" msgstr "//DomyÅ›lne ustawienia" #: src/mainwindow.c:5552 msgid "//Mask All" msgstr "//Maskuj wszystko" #: src/mainwindow.c:5553 msgid "//Mask None" msgstr "//Nie maskuj niczego" #: src/mainwindow.c:5555 msgid "//Swap A & B" msgstr "//ZamieÅ„ A & B" #: src/mainwindow.c:5557 msgid "//Edit Colour A & B ..." msgstr "//Edytuj kolor A & B ..." #: src/mainwindow.c:5559 msgid "//Dither A" msgstr "" #: src/mainwindow.c:5561 msgid "//Palette Editor ..." msgstr "//Edytor palety ..." #: src/mainwindow.c:5563 msgid "//Set Palette Size ..." msgstr "//Ustaw rozmiar palety ..." #: src/mainwindow.c:5564 msgid "//Merge Duplicate Colours" msgstr "//Scal duplikujÄ…ce siÄ™ kolory" #: src/mainwindow.c:5566 msgid "//Remove Unused Colours" msgstr "//UsuÅ„ nieużywane kolory" #: src/mainwindow.c:5569 msgid "//Create Quantized ..." msgstr "//Utwórz Kwantyzator ..." #: src/mainwindow.c:5572 msgid "//Sort Colours ..." msgstr "//Sortuj kolory ..." #: src/mainwindow.c:5573 msgid "//Palette Shifter ..." msgstr "//Edytor palety ..." #: src/mainwindow.c:5574 msgid "//Pick Gradient ..." msgstr "" #: src/mainwindow.c:5576 msgid "/Effe_cts" msgstr "/_Efekty" #: src/mainwindow.c:5578 msgid "//Transform Colour ..." msgstr "//Transformacja kolorów ..." #: src/mainwindow.c:5580 msgid "//Invert" msgstr "//Odwróć" #: src/mainwindow.c:5582 msgid "//Greyscale" msgstr "//Skala szaroÅ›ci" #: src/mainwindow.c:5584 msgid "//Greyscale (Gamma corrected)" msgstr "//Skala szaroÅ›ci (Gamma poprawne)" #: src/mainwindow.c:5586 msgid "//Normalize" msgstr "" #: src/mainwindow.c:5587 src/mainwindow.c:5658 msgid "//Threshold ..." msgstr "//Próg ..." #: src/mainwindow.c:5588 msgid "//Map ..." msgstr "" #: src/mainwindow.c:5590 msgid "//Isometric Transformation" msgstr "//Transformacja izometryczna" #: src/mainwindow.c:5592 msgid "///Left Side Down" msgstr "///W lewy dół" #: src/mainwindow.c:5593 msgid "///Right Side Down" msgstr "///W prawy dół" #: src/mainwindow.c:5594 msgid "///Top Side Right" msgstr "///W górny prawy" #: src/mainwindow.c:5595 msgid "///Bottom Side Right" msgstr "///W dolny prawy" #: src/mainwindow.c:5598 msgid "//Edge Detect ..." msgstr "//Wyszukiwanie krawÄ™dzi ..." #: src/mainwindow.c:5600 msgid "//Difference of Gaussians ..." msgstr "" #: src/mainwindow.c:5602 msgid "//Sharpen ..." msgstr "//Wyostrzanie ..." #: src/mainwindow.c:5604 msgid "//Unsharp Mask ..." msgstr "//Wzmocnienie ..." #: src/mainwindow.c:5606 msgid "//Soften ..." msgstr "//WygÅ‚adzanie ..." #: src/mainwindow.c:5608 msgid "//Gaussian Blur ..." msgstr "//Rozmycie Gaussa ..." #: src/mainwindow.c:5610 msgid "//Kuwahara-Nagao Blur ..." msgstr "" #: src/mainwindow.c:5612 msgid "//Emboss" msgstr "//WytÅ‚oczenie" #: src/mainwindow.c:5614 msgid "//Dilate" msgstr "" #: src/mainwindow.c:5616 msgid "//Erode" msgstr "" #: src/mainwindow.c:5619 msgid "//Solid Noise ..." msgstr "" #: src/mainwindow.c:5620 msgid "//Bacteria ..." msgstr "//Bakteria ..." #: src/mainwindow.c:5623 msgid "/Cha_nnels" msgstr "/Ka_naÅ‚y" #: src/mainwindow.c:5625 msgid "//New ..." msgstr "//Nowy ..." #: src/mainwindow.c:5628 msgid "//Delete ..." msgstr "//UsuÅ„ ..." #: src/mainwindow.c:5632 msgid "//Edit Image" msgstr "//Edytuj obraz" #: src/mainwindow.c:5635 msgid "//Edit Alpha" msgstr "//Edytuj alfe" #: src/mainwindow.c:5638 msgid "//Edit Selection" msgstr "//Edytuj zaznaczenie" #: src/mainwindow.c:5641 msgid "//Edit Mask" msgstr "//Edytuj maskÄ™" #: src/mainwindow.c:5645 msgid "//Hide Image" msgstr "//Ukryj obraz" #: src/mainwindow.c:5648 msgid "//Disable Alpha" msgstr "//Wyłącz alfÄ™" #: src/mainwindow.c:5651 msgid "//Disable Selection" msgstr "//Wyłącz zaznaczenie" #: src/mainwindow.c:5654 msgid "//Disable Mask" msgstr "//Wyłącz maskÄ™" #: src/mainwindow.c:5657 msgid "//Couple RGBA Operations" msgstr "//Operacje RGBA" #: src/mainwindow.c:5659 msgid "//Unassociate Alpha" msgstr "" #: src/mainwindow.c:5663 msgid "//View Alpha as an Overlay" msgstr "//Pokaż alfÄ™ jako powÅ‚okÄ™" #: src/mainwindow.c:5664 msgid "//Configure Overlays ..." msgstr "//Konfiguruj powÅ‚oki ..." #: src/mainwindow.c:5666 msgid "/_Layers" msgstr "/Wa_rstwy" #: src/mainwindow.c:5668 msgid "//New Layer" msgstr "" #: src/mainwindow.c:5672 msgid "//Save Composite Image ..." msgstr "//Zapisz obraz zÅ‚ożony ..." #: src/mainwindow.c:5673 msgid "//Composite to New Layer" msgstr "" #: src/mainwindow.c:5674 msgid "//Remove All Layers" msgstr "//UsuÅ„ wszystkie warstwy" #: src/mainwindow.c:5676 msgid "//Configure Animation ..." msgstr "//Konfiguruj animacjÄ™ ..." #: src/mainwindow.c:5677 msgid "//Preview Animation ..." msgstr "//PodglÄ…d animacji ..." #: src/mainwindow.c:5678 msgid "//Set Key Frame ..." msgstr "//Ustaw klucz ramki ..." #: src/mainwindow.c:5679 msgid "//Remove All Key Frames ..." msgstr "//UsuÅ„ wszystkie klucze ramki ..." #: src/mainwindow.c:5681 msgid "/More..." msgstr "" #: src/mainwindow.c:5683 msgid "/_Help" msgstr "/Po_moc" #: src/mainwindow.c:5684 msgid "//Documentation" msgstr "//Dokumentacja" #: src/mainwindow.c:5686 msgid "//About" msgstr "//Informacje o..." #: src/mainwindow.c:5689 msgid "//Keyboard Shortcuts ..." msgstr "" #: src/mainwindow.c:5690 msgid "//Rebind Shortcut Keycodes" msgstr "//ZmieÅ„ skróty klawiaturowe" #: src/memory.c:2800 msgid "Quantize Pass 1" msgstr "" #: src/memory.c:2854 msgid "Quantize Pass 2" msgstr "" #: src/memory.c:3073 src/memory.c:3458 msgid "Converting to Indexed Palette" msgstr "Konwertuj do palety indeksowanej" #: src/memory.c:5135 src/otherwindow.c:540 msgid "Bacteria Effect" msgstr "Efekt Bakterii" #: src/memory.c:5170 msgid "Rotating" msgstr "Obracanie" #: src/memory.c:5511 msgid "Free Rotation" msgstr "Dowolna rotacja" #: src/memory.c:6096 msgid "Scaling Image" msgstr "Skalowanie obrazka" #: src/memory.c:7560 msgid "Counting Unique RGB Pixels" msgstr "Obliczanie unikalnych pikseli RGB" #: src/memory.c:7608 msgid "Applying Effect" msgstr "Zastosuj efekt" #: src/memory.c:8792 msgid "Kuwahara-Nagao Filter" msgstr "" #: src/memory.c:10456 src/otherwindow.c:2665 msgid "Skew" msgstr "" #: src/memory.c:10630 msgid "Segmentation Pass 1" msgstr "" #: src/memory.c:10757 msgid "Segmentation Pass 2" msgstr "" #: src/memory.c:11019 src/otherwindow.c:3156 msgid "Solid Noise" msgstr "" #: src/mygtk.c:134 src/mygtk.c:163 msgid "Please Wait ..." msgstr "ProszÄ™ czekać ..." #: src/mygtk.c:141 msgid "STOP" msgstr "STOP" #: src/mygtk.c:504 msgid "Disabled" msgstr "" #: src/mygtk.c:504 src/toolbar.c:301 msgid "Screen" msgstr "Przesiewanie" #: src/mygtk.c:504 msgid "Window" msgstr "" #: src/mygtk.c:508 msgid "Input" msgstr "" #: src/mygtk.c:512 msgid "Device:" msgstr "" #: src/mygtk.c:514 msgid "Mode:" msgstr "" #: src/mygtk.c:519 msgid "Axes" msgstr "" #: src/mygtk.c:524 msgid "X:" msgstr "" #: src/mygtk.c:525 msgid "Y:" msgstr "" #: src/mygtk.c:526 msgid "Pressure:" msgstr "" #: src/mygtk.c:527 msgid "X tilt:" msgstr "" #: src/mygtk.c:528 msgid "Y tilt:" msgstr "" #: src/mygtk.c:529 msgid "Wheel:" msgstr "" #: src/mygtk.c:579 msgid "none" msgstr "" #: src/otherwindow.c:236 msgid "24 bit RGB" msgstr "24 bit RGB" #: src/otherwindow.c:236 src/otherwindow.c:3179 msgid "Greyscale" msgstr "Skala szaroÅ›ci" #: src/otherwindow.c:237 msgid "Indexed Palette" msgstr "Paleta indeksowana" #: src/otherwindow.c:237 msgid "From Clipboard" msgstr "" #: src/otherwindow.c:237 msgid "Grab Screenshot" msgstr "Zrzut ekranu" #: src/otherwindow.c:242 src/toolbar.c:542 msgid "New Image" msgstr "Nowy obrazek" #: src/otherwindow.c:246 src/otherwindow.c:3164 msgid "Colours" msgstr "Kolory" #: src/otherwindow.c:409 msgid "Pattern Chooser" msgstr "Wybór wzoru" #: src/otherwindow.c:497 msgid "Set Palette Size" msgstr "Ustaw rozmiar palety" #: src/otherwindow.c:517 src/otherwindow.c:591 src/otherwindow.c:870 #: src/otherwindow.c:2538 src/otherwindow.c:2776 src/otherwindow.c:2939 #: src/prefs.c:338 src/prefs.c:538 msgid "Apply" msgstr "Zastosuj" #: src/otherwindow.c:573 msgid "Luminance" msgstr "Jasność" #: src/otherwindow.c:573 src/otherwindow.c:814 msgid "Brightness" msgstr "RozjaÅ›nianie" #: src/otherwindow.c:574 msgid "Distance to A" msgstr "OdlegÅ‚ość do A" #: src/otherwindow.c:575 msgid "Projection to A->B" msgstr "WyÅ›wietlanie A->B" #: src/otherwindow.c:576 msgid "Frequency" msgstr "CzÄ™stotliwość" #: src/otherwindow.c:580 msgid "Sort Palette Colours" msgstr "Sortuj Kolory palety" #: src/otherwindow.c:582 msgid "Start Index" msgstr "Rozpocznij indeksowanie" #: src/otherwindow.c:583 msgid "End Index" msgstr "ZakoÅ„cz indeksowanie" #: src/otherwindow.c:589 msgid "Reverse Order" msgstr "Odwrócony porzÄ…dek" #: src/otherwindow.c:805 msgid "Bitwise" msgstr "" #: src/otherwindow.c:805 msgid "Truncated" msgstr "" #: src/otherwindow.c:805 msgid "Rounded" msgstr "" #: src/otherwindow.c:809 src/toolbar.c:311 src/toolbar.c:558 msgid "Transform Colour" msgstr "Transformacja kolorów" #: src/otherwindow.c:812 msgid "Gamma" msgstr "Gamma" #: src/otherwindow.c:816 msgid "Contrast" msgstr "Kontrast" #: src/otherwindow.c:822 src/otherwindow.c:1674 msgid "Posterize" msgstr "Redukcja liczby kolorów" #: src/otherwindow.c:831 msgid "Show Detail" msgstr "Pokaż szczegóły" #: src/otherwindow.c:836 msgid "Posterize type" msgstr "" #: src/otherwindow.c:857 msgid "Auto-Preview" msgstr "Auto podglÄ…d" #: src/otherwindow.c:869 msgid "Reset" msgstr "Resetuj" #: src/otherwindow.c:931 msgid "New geometry is the same as now - nothing to do." msgstr "Nowa geomteria jest taka sama - nic nie rób" #: src/otherwindow.c:980 msgid "The operating system cannot allocate the memory for this operation." msgstr "System operacyjny nie dysponuje wystarczajÄ…cÄ… iloÅ›ciÄ… pamiÄ™ci" #: src/otherwindow.c:982 msgid "" "You have not allocated enough memory in the Preferences window for this " "operation." msgstr "" "W oknie Ustawienia nie ma ustawionej wystarczajÄ…cej iloÅ›ci pamiÄ™ciaby " "wykonać tÄ™ operacjÄ™" #: src/otherwindow.c:993 src/otherwindow.c:2495 msgid "Mirror" msgstr "" #: src/otherwindow.c:993 src/otherwindow.c:994 msgid "Tile" msgstr "TytuÅ‚" #: src/otherwindow.c:993 msgid "Void" msgstr "" #: src/otherwindow.c:994 src/shifter.c:283 msgid "Clear" msgstr "Wyczyść" #: src/otherwindow.c:994 msgid "Mirror tile" msgstr "TytuÅ‚ mirror'a" #: src/otherwindow.c:996 msgid "Nearest Neighbour" msgstr "Najbliższy sÄ…siad" #: src/otherwindow.c:997 msgid "Bilinear / Area Mapping" msgstr "Bilinear / Area Mapping" #: src/otherwindow.c:998 msgid "Bicubic" msgstr "Bicubic" #: src/otherwindow.c:999 msgid "Bicubic edged" msgstr "Bicubic edged" #: src/otherwindow.c:1000 msgid "Bicubic better" msgstr "Bicubic lepszy" #: src/otherwindow.c:1001 msgid "Bicubic sharper" msgstr "Bicubic ostrzejszy" #: src/otherwindow.c:1002 msgid "Blackman-Harris" msgstr "Blackman-Harris" #: src/otherwindow.c:1008 msgid "Scale Canvas" msgstr "Skala płótna" #: src/otherwindow.c:1009 msgid "Resize Canvas" msgstr "ZmieÅ„ rozmiar płótna" #: src/otherwindow.c:1012 msgid "Original " msgstr "Oryginalny " #: src/otherwindow.c:1013 msgid "New" msgstr "Nowy" #: src/otherwindow.c:1014 msgid "Width " msgstr "Szerokość " #: src/otherwindow.c:1018 msgid "Height " msgstr "Wysokość " #: src/otherwindow.c:1023 src/otherwindow.c:2514 src/otherwindow.c:2672 #: src/toolbar.c:212 msgid "Offset" msgstr "PrzesuniÄ™cie" #: src/otherwindow.c:1026 src/otherwindow.c:1615 src/viewer.c:1209 msgid "Centre" msgstr "Åšrodek" #: src/otherwindow.c:1033 src/otherwindow.c:1052 msgid "Fix Aspect Ratio" msgstr "Napraw Aspect Ratio" #: src/otherwindow.c:1039 src/otherwindow.c:2070 src/toolbar.c:312 msgid "Settings" msgstr "Ustawienia" #: src/otherwindow.c:1046 msgid "Sharper image reduction" msgstr "" #: src/otherwindow.c:1047 msgid "Boundary extension" msgstr "" #: src/otherwindow.c:1613 src/otherwindow.c:2302 msgid "HSV" msgstr "" #: src/otherwindow.c:1614 msgid "Highlight" msgstr "" #: src/otherwindow.c:1615 msgid "Limit" msgstr "Limit" #: src/otherwindow.c:1616 msgid "Sphere" msgstr "Sfera" #: src/otherwindow.c:1616 src/otherwindow.c:2670 msgid "Angle" msgstr "KÄ…t" #: src/otherwindow.c:1616 msgid "Cube" msgstr "SzeÅ›cian" #: src/otherwindow.c:1617 msgid "Opaque" msgstr "" #: src/otherwindow.c:1617 msgid "Border" msgstr "" #: src/otherwindow.c:1618 msgid "Transparent" msgstr "" #: src/otherwindow.c:1618 msgid "Tile " msgstr "" #: src/otherwindow.c:1618 msgid "Segment" msgstr "" #: src/otherwindow.c:1656 msgid "Scale" msgstr "Skala" #: src/otherwindow.c:1657 src/otherwindow.c:3059 msgid "From" msgstr "Od" #: src/otherwindow.c:1659 src/otherwindow.c:3061 msgid "To" msgstr "Do" #: src/otherwindow.c:1699 msgid "Range" msgstr "Ranga" #: src/otherwindow.c:1702 msgid "Inverse" msgstr "Odwróć" #: src/otherwindow.c:1710 msgid "Smart grid" msgstr "" #: src/otherwindow.c:1712 msgid "Tile grid" msgstr "" #: src/otherwindow.c:1714 msgid "Minimum grid zoom" msgstr "Minimalne powiÄ™kszenie siatki" #: src/otherwindow.c:1717 msgid "Tile width" msgstr "" #: src/otherwindow.c:1720 msgid "Tile height" msgstr "" #: src/otherwindow.c:1744 msgid "Palette Editor" msgstr "Edytor palety" #: src/otherwindow.c:1763 msgid "Configure Overlays" msgstr "Konfiguruj NakÅ‚adki" #: src/otherwindow.c:1782 msgid "Colour Editor" msgstr "Edytor Kolorów" #: src/otherwindow.c:1818 src/toolbar.c:430 msgid "Colour-Selective Mode" msgstr "Tryb wyboru koloru" #: src/otherwindow.c:1843 msgid "Configure Grid" msgstr "" #: src/otherwindow.c:2045 msgid "Exact Conversion" msgstr "Konwersja dokÅ‚adna" #: src/otherwindow.c:2045 msgid "Use Current Palette" msgstr "Użyj aktualnej palety" #: src/otherwindow.c:2046 msgid "PNN Quantize (slow, better quality)" msgstr "" #: src/otherwindow.c:2047 msgid "Wu Quantize (fast)" msgstr "" #: src/otherwindow.c:2048 msgid "Max-Min Quantize (best for small palettes and dithering)" msgstr "" #: src/otherwindow.c:2049 src/otherwindow.c:2495 src/otherwindow.c:2756 #: src/png.c:2794 src/prefs.c:377 msgid "None" msgstr "Å»aden" #: src/otherwindow.c:2049 msgid "Floyd-Steinberg" msgstr "Floyd-Steinberg" #: src/otherwindow.c:2049 msgid "Stucki" msgstr "Stucki" #: src/otherwindow.c:2052 msgid "Floyd-Steinberg (quick)" msgstr "Floyd-Steinberg (szybki)" #: src/otherwindow.c:2052 msgid "Dithered (effect)" msgstr "Kolor Symulowany (efekt)" #: src/otherwindow.c:2053 msgid "Scattered (effect)" msgstr "Rozproszenie (efekt)" #: src/otherwindow.c:2054 msgid "Gamut" msgstr "Gamut" #: src/otherwindow.c:2054 msgid "Weakly" msgstr "SÅ‚abszy" #: src/otherwindow.c:2054 msgid "Strongly" msgstr "Mocniejszy" #: src/otherwindow.c:2055 msgid "Off" msgstr "WyÅ‚." #: src/otherwindow.c:2055 msgid "Separate/Sum" msgstr "Oddziel/ÅÄ…cz" #: src/otherwindow.c:2055 msgid "Separate/Split" msgstr "Dziel" #: src/otherwindow.c:2056 msgid "Length/Sum" msgstr "DÅ‚ugość/Suma" #: src/otherwindow.c:2056 msgid "Length/Split" msgstr "DÅ‚ugość/Dziel" #: src/otherwindow.c:2057 msgid "Largest (Linf)" msgstr "WiÄ™kszy (Linf)" #: src/otherwindow.c:2057 msgid "Sum (L1)" msgstr "Suma (L1)" #: src/otherwindow.c:2057 msgid "Euclidean (L2)" msgstr "Euklides (L2)" #: src/otherwindow.c:2061 msgid "Create Quantized" msgstr "Utwórz Kwantyzator" #: src/otherwindow.c:2062 msgid "Convert To Indexed" msgstr "Konwertuj do indeksowanych" #: src/otherwindow.c:2065 msgid "Indexed Colours To Use" msgstr "Indeksowane kolory do używania" #: src/otherwindow.c:2078 msgid "Truncate palette" msgstr "" #: src/otherwindow.c:2079 msgid "Diameter based weighting" msgstr "" #: src/otherwindow.c:2084 msgid "Dither" msgstr "Drżenie" #: src/otherwindow.c:2087 src/otherwindow.c:2584 src/otherwindow.c:2928 msgid "Colour space" msgstr "Kolor przestrzeni" #: src/otherwindow.c:2088 src/otherwindow.c:2929 msgid "Difference measure" msgstr "Różnice pomiarów" #: src/otherwindow.c:2089 msgid "Reduce colour bleed" msgstr "Redukuj kolor zabarwienia" #: src/otherwindow.c:2090 msgid "Serpentine scan" msgstr "Skanowanie wężowe" #: src/otherwindow.c:2092 msgid "Error propagation, %" msgstr "Błąd propagacji, %" #: src/otherwindow.c:2093 msgid "Selective error propagation" msgstr "Krytyczny błąd propagacji" #: src/otherwindow.c:2097 msgid "Full error precision" msgstr "" #: src/otherwindow.c:2302 msgid "Backward HSV" msgstr "Wsteczny HSV" #: src/otherwindow.c:2303 src/otherwindow.c:2326 msgid "Constant" msgstr "StaÅ‚e" #: src/otherwindow.c:2307 msgid "Edit Gradient" msgstr "Edytuj gradient" #: src/otherwindow.c:2329 msgid "Points:" msgstr "Punkty" #: src/otherwindow.c:2493 msgid "Linear" msgstr "Linear" #: src/otherwindow.c:2493 src/otherwindow.c:2703 msgid "Bilinear" msgstr "Bilinear" #: src/otherwindow.c:2493 msgid "Radial" msgstr "PromieÅ„" #: src/otherwindow.c:2494 msgid "Square" msgstr "Kwadrat" #: src/otherwindow.c:2494 msgid "Angular" msgstr "" #: src/otherwindow.c:2494 msgid "Conical" msgstr "" #: src/otherwindow.c:2495 msgid "Level " msgstr "" #: src/otherwindow.c:2495 msgid "Repeat" msgstr "Powtórz" #: src/otherwindow.c:2496 msgid "A to B" msgstr "A do B" #: src/otherwindow.c:2496 msgid "A to B (RGB)" msgstr "A do B (RGB)" #: src/otherwindow.c:2497 msgid "A to B (sRGB)" msgstr "" #: src/otherwindow.c:2497 msgid "A to B (HSV)" msgstr "A do B (HSV)" #: src/otherwindow.c:2497 msgid "A to B (backward HSV)" msgstr "A do B (wsteczny HSV)" #: src/otherwindow.c:2498 msgid "A only" msgstr "Tylko A" #: src/otherwindow.c:2498 src/otherwindow.c:2500 msgid "Custom" msgstr "WÅ‚asne" #: src/otherwindow.c:2499 msgid "Current to 0" msgstr "Aktualny do 0" #: src/otherwindow.c:2499 msgid "Current only" msgstr "Tylko aktualny" #: src/otherwindow.c:2504 msgid "Configure Gradient" msgstr "Konfiguruj gradient" #: src/otherwindow.c:2507 src/png.c:1001 msgid "Channel" msgstr "KanaÅ‚" #: src/otherwindow.c:2512 msgid "Length" msgstr "DÅ‚ugość" #: src/otherwindow.c:2513 msgid "Repeat length" msgstr "Powtórz dÅ‚ugość" #: src/otherwindow.c:2515 msgid "Gradient type" msgstr "Rodzaj gradientu" #: src/otherwindow.c:2516 msgid "Extension type" msgstr "Typ rozszerzeÅ„" #: src/otherwindow.c:2517 msgid "Distance type" msgstr "" #: src/otherwindow.c:2518 msgid "Preview opacity" msgstr "PodglÄ…d nieprzeźroczystoÅ›ci" #: src/otherwindow.c:2527 src/otherwindow.c:2533 src/toolbar.c:309 msgid "Reverse" msgstr "Odwróc" #: src/otherwindow.c:2528 src/otherwindow.c:2534 msgid "Edit Custom" msgstr "Edytuj niestandardowe" #: src/otherwindow.c:2592 msgid "Pick Gradient" msgstr "" #: src/otherwindow.c:2668 msgid "Horizontal " msgstr "" #: src/otherwindow.c:2674 msgid "At distance" msgstr "" #: src/otherwindow.c:2675 msgid "Vertical" msgstr "" #: src/otherwindow.c:2756 msgid "Unchanged" msgstr "" #: src/otherwindow.c:2761 msgid "Tracing Image" msgstr "" #: src/otherwindow.c:2763 src/toolbar.c:315 msgid "Source" msgstr "" #: src/otherwindow.c:2768 msgid "Origin" msgstr "" #: src/otherwindow.c:2771 msgid "Relative scale" msgstr "" #: src/otherwindow.c:2774 msgid "Display" msgstr "" #: src/otherwindow.c:2926 msgid "Segment Image" msgstr "" #: src/otherwindow.c:2931 src/toolbar.c:304 msgid "Threshold" msgstr "" #: src/otherwindow.c:2933 msgid "Level" msgstr "Poziom" #: src/otherwindow.c:2934 msgid "Minimum size" msgstr "" #: src/otherwindow.c:3053 msgid "Max" msgstr "" #: src/otherwindow.c:3053 msgid "Min" msgstr "" #: src/otherwindow.c:3057 msgid "Threshold Image" msgstr "" #: src/otherwindow.c:3158 msgid "Seed" msgstr "" #: src/otherwindow.c:3160 msgid "X span" msgstr "" #: src/otherwindow.c:3161 msgid "Y span" msgstr "" #: src/otherwindow.c:3162 msgid "Octaves" msgstr "" #: src/png.c:620 #, c-format msgid "Saving %s image" msgstr "" #: src/png.c:620 #, c-format msgid "Loading %s image" msgstr "" #: src/png.c:998 msgid "Layer" msgstr "Warstwa" #: src/png.c:3577 msgid "Lossless" msgstr "" #: src/png.c:3577 msgid "Default" msgstr "" #: src/png.c:3577 msgid "Picture" msgstr "" #: src/png.c:3577 msgid "Photo" msgstr "" #: src/png.c:3578 msgid "Drawing" msgstr "" #: src/png.c:3578 msgid "Icon" msgstr "" #: src/png.c:8370 msgid "Applying colour profile" msgstr "" #: src/png.c:8792 #, c-format msgid "%d out of %d frames could not be saved as %s - saved as PNG instead" msgstr "%d koniec %d ramki nie może zostać zapisany jako %s- zapisz jako PNG" #: src/png.c:8809 msgid "Explode frames" msgstr "" #: src/prefs.c:56 msgid "Default System Language" msgstr "DomyÅ›lny jÄ™zyk systemowy" #: src/prefs.c:57 msgid "Chinese (Simplified)" msgstr "" #: src/prefs.c:57 msgid "Chinese (Taiwanese)" msgstr "ChiÅ„ski (TajwaÅ„ski)" #: src/prefs.c:57 msgid "Czech" msgstr "Czeski" #: src/prefs.c:58 msgid "Dutch" msgstr "" #: src/prefs.c:58 msgid "English (UK)" msgstr "Angielski" #: src/prefs.c:58 msgid "French" msgstr "Francuski" #: src/prefs.c:58 msgid "Galician" msgstr "" #: src/prefs.c:58 msgid "German" msgstr "Niemiecki" #: src/prefs.c:59 msgid "Hungarian" msgstr "" #: src/prefs.c:59 msgid "Italian" msgstr "" #: src/prefs.c:59 msgid "Japanese" msgstr "" #: src/prefs.c:59 msgid "Kabyle" msgstr "" #: src/prefs.c:59 msgid "Polish" msgstr "Polski" #: src/prefs.c:60 msgid "Portuguese" msgstr "Portugalski" #: src/prefs.c:60 msgid "Portuguese (Brazilian)" msgstr "Portugalski (Brazylijski)" #: src/prefs.c:60 msgid "Russian" msgstr "" #: src/prefs.c:60 msgid "Slovak" msgstr "SÅ‚owacki" #: src/prefs.c:61 msgid "Spanish" msgstr "HiszpaÅ„ski" #: src/prefs.c:61 msgid "Swedish" msgstr "" #: src/prefs.c:61 msgid "Tagalog" msgstr "" #: src/prefs.c:61 msgid "Turkish" msgstr "Turecki" #: src/prefs.c:81 msgid "Current Device" msgstr "Bieżące urzÄ…dzenie" #: src/prefs.c:135 msgid "Pressure" msgstr "Nacisk" #: src/prefs.c:149 msgid "Preferences" msgstr "Ustawienia" #: src/prefs.c:163 msgid "Max threads (0 to autodetect)" msgstr "" #: src/prefs.c:164 msgid "Min kpixels per render thread" msgstr "" #: src/prefs.c:171 msgid "Max memory used for undo (MB)" msgstr "Maksymalny rozmiar pamiÄ™ci na operacjÄ™ -Cofanie (MB)" #: src/prefs.c:172 msgid "Max undo levels" msgstr "" #: src/prefs.c:173 msgid "Communal layer undo space (%)" msgstr "" #: src/prefs.c:175 msgid "Bayer master pattern" msgstr "" #: src/prefs.c:178 msgid "Use gamma correction by default" msgstr "Ustaw korekcjÄ™ gamma jako domyÅ›lne" #: src/prefs.c:179 msgid "Use gamma correction when painting" msgstr "" #: src/prefs.c:180 msgid "Separate patterns for A & B" msgstr "" #: src/prefs.c:183 msgid "Optimize alpha chequers" msgstr "Optymalizuj 'alpha chequers'" #: src/prefs.c:184 msgid "Disable view window transparencies" msgstr "Wyłącz przezroczystosc okna" #: src/prefs.c:185 msgid "Enable overlays by layer" msgstr "" #: src/prefs.c:189 msgid "Language" msgstr "JÄ™zyk" #: src/prefs.c:191 msgid "" "Select preferred language translation\n" "\n" "You will need to restart mtPaint\n" "for this to take full effect" msgstr "" "Wybierz odpowiedni jÄ™zyk\n" "\n" "BÄ™dziesz musiaÅ‚ zrestartować mtPaint,\n" "aby jÄ™zyk w peÅ‚ni siÄ™ zaÅ‚adowaÅ‚" #: src/prefs.c:198 msgid "Interface" msgstr "" #: src/prefs.c:200 msgid "Greyscale backdrop" msgstr "" #: src/prefs.c:201 msgid "Selection nudge pixels" msgstr "" #: src/prefs.c:202 msgid "Max Pan Window Size" msgstr "" #: src/prefs.c:204 msgid "Display clipboard while pasting" msgstr "WyÅ›wietl schowek podczas wklejania" #: src/prefs.c:205 msgid "Mouse cursor = Tool" msgstr "Kursor myszki = NarzÄ™dzia" #: src/prefs.c:206 msgid "Confirm Exit" msgstr "Potwierdz zamykanie" #: src/prefs.c:207 msgid "Q key quits mtPaint" msgstr "Q zamyka mtPaint" #: src/prefs.c:208 msgid "Arrow keys scroll canvas" msgstr "" #: src/prefs.c:209 msgid "Changing tool commits paste" msgstr "Zmiana narzÄ™dzia potwierdzania wklejania" #: src/prefs.c:210 msgid "Centre tool settings dialogs" msgstr "WyÅ›rodkowuj okna dialogowe" #: src/prefs.c:211 msgid "New image sets zoom to 100%" msgstr "Ustaw powiÄ™kszenie nowego obrazu na 100%" #: src/prefs.c:212 msgid "Zoom on cursor position" msgstr "" #: src/prefs.c:214 msgid "Mouse Scroll Wheel = Zoom" msgstr "Rolka myszki = PowiÄ™kszanie" #: src/prefs.c:215 msgid "Use menu icons" msgstr "" #: src/prefs.c:220 msgid "Files" msgstr "Pliki" #: src/prefs.c:223 msgid "XBM X hotspot" msgstr "" #: src/prefs.c:224 msgid "XBM Y hotspot" msgstr "" #: src/prefs.c:228 msgid "Recently Used Files" msgstr "Ostatnio otwierane pliki" #: src/prefs.c:229 msgid "Progress bar silence limit" msgstr "Pasek postÄ™pu" #: src/prefs.c:232 msgid "Read 16-bit TGAs as 5:6:5 BGR" msgstr "" #: src/prefs.c:233 msgid "Write TGAs in bottom-up row order" msgstr "" #: src/prefs.c:234 msgid "Undoable image loading" msgstr "" #: src/prefs.c:245 msgid "Compression (RGB)" msgstr "" #: src/prefs.c:246 msgid "Compression (indexed)" msgstr "" #: src/prefs.c:247 msgid "Compression (monochrome)" msgstr "" #: src/prefs.c:255 msgid "Enable predictor" msgstr "" #: src/prefs.c:262 msgid "Compression mode" msgstr "" #: src/prefs.c:271 msgid "Channel for Mask Plane" msgstr "" #: src/prefs.c:273 msgid "Ignore Transparent Colour" msgstr "" #: src/prefs.c:274 msgid "PackBits Compression" msgstr "" #: src/prefs.c:275 msgid "Write Indexed as Planar Bitmap (PBM)" msgstr "" #: src/prefs.c:280 msgid "Paths" msgstr "" #: src/prefs.c:281 msgid "Clipboard Files" msgstr "Pliki schowka" #: src/prefs.c:281 msgid "Select Clipboard File" msgstr "Wybierz plik schowka" #: src/prefs.c:283 msgid "HTML Browser Program" msgstr "PrzeglÄ…darka HTML" #: src/prefs.c:283 msgid "Select Browser Program" msgstr "Wybierz program przeglÄ…dajÄ…cy" #: src/prefs.c:285 msgid "Location of Handbook index" msgstr "Åšcieżka do indeksu pomocy" #: src/prefs.c:285 msgid "Select Handbook Index File" msgstr "Wybierz plik Handbook Index" #: src/prefs.c:287 msgid "Default Palette" msgstr "" #: src/prefs.c:287 msgid "Select Default Palette" msgstr "" #: src/prefs.c:289 msgid "Default Patterns" msgstr "" #: src/prefs.c:289 msgid "Select Default Patterns File" msgstr "" #: src/prefs.c:292 msgid "Default CSS" msgstr "" #: src/prefs.c:292 msgid "Select Default CSS File" msgstr "" #: src/prefs.c:295 msgid "Default Theme" msgstr "" #: src/prefs.c:295 msgid "Select Default Theme File" msgstr "" #: src/prefs.c:300 msgid "Status Bar" msgstr "Pasek stanu" #: src/prefs.c:301 msgid "Canvas Geometry" msgstr "Płótno geometrii" #: src/prefs.c:302 msgid "Cursor X,Y" msgstr "Kursor X,Y" #: src/prefs.c:303 msgid "Pixel [I] {RGB}" msgstr "Piksel [I] {RGB}" #: src/prefs.c:304 msgid "Selection Geometry" msgstr "Zaznaczenie geometrii" #: src/prefs.c:305 msgid "Undo / Redo" msgstr "Cofnij / Ponów" #: src/prefs.c:308 msgid "Tablet" msgstr "Tablet" #: src/prefs.c:309 msgid "Device Settings" msgstr "Ustawienia urzÄ…dzenia" #: src/prefs.c:313 msgid "Configure Device" msgstr "Konfiguruj urzÄ…dzenie" #: src/prefs.c:319 msgid "Tool Variable" msgstr "NarzÄ™dzia zmienne" #: src/prefs.c:322 src/toolbar.c:454 msgid "Flow" msgstr "PrzepÅ‚yw" #: src/prefs.c:330 msgid "Test Area" msgstr "Pole testowe" #: src/prefs.c:373 msgid "Factor" msgstr "Współczynnik" #: src/prefs.c:459 msgid "This key is builtin" msgstr "" #: src/prefs.c:462 #, c-format msgid "" "This key is mapped to:\n" "\"%s\"" msgstr "" #: src/prefs.c:465 msgid "Remap" msgstr "" #: src/prefs.c:510 msgid "Keyboard Shortcuts" msgstr "" #: src/shifter.c:147 msgid "Frames" msgstr "Ramki" #: src/shifter.c:258 msgid "Palette Shifter" msgstr "Edytor palety" #: src/shifter.c:263 msgid "Start" msgstr "Rozpocznij" #: src/shifter.c:265 msgid "Finish" msgstr "ZakoÅ„cz" #: src/shifter.c:284 msgid "Fix Palette" msgstr "Napraw paletÄ™" #: src/spawn.c:651 msgid "Configure File Actions" msgstr "" #: src/spawn.c:657 src/spawn.c:663 msgid "Command" msgstr "" #: src/spawn.c:922 #, c-format msgid "Error %i reported when trying to run %s" msgstr "Błąd %i podczas uruchamiania %s" #: src/spawn.c:979 msgid "" "I am unable to find the documentation. Either you need to download the " "mtPaint Handbook from the web site and install it, or you need to set the " "correct location in the Preferences window." msgstr "" "Nie można odnaleźć dokumentacji. JeÅ›li chcesz pobrać mtPaint Handbook z " "Internetu i zainstalować go, ustaw odpowiedniÄ… Å›cieżke w oknie Ustawienia" #: src/spawn.c:1018 msgid "" "There was a problem running the HTML browser. You need to set the correct " "program name in the Preferences window." msgstr "" "PojawiÅ‚ siÄ™ problem podczas uruchamiania przeglÄ…darki HTML.Podaj prawidÅ‚owy " "program do otwierania HTML w oknie Ustawienia" #: src/thread.c:361 msgid "Helper thread is not responding. Save your work and exit the program." msgstr "" #: src/toolbar.c:147 msgid "RGB Cube" msgstr "SzeÅ›cian RGB" #: src/toolbar.c:148 msgid "By image channel" msgstr "Przez kanaÅ‚ obrazu" #: src/toolbar.c:149 msgid "Gradient-driven" msgstr "Gradient- sterowanie" #: src/toolbar.c:157 msgid "Fill settings" msgstr "Ustawienia wypeÅ‚niania" #: src/toolbar.c:170 msgid "Respect opacity mode" msgstr "Tryb włączonej przezroczystoÅ›ci" #: src/toolbar.c:176 msgid "Smudge settings" msgstr "Ustawienia smużenia" #: src/toolbar.c:215 msgid "Aligned" msgstr "" #: src/toolbar.c:222 msgid "Clone settings" msgstr "" #: src/toolbar.c:228 msgid "By selection channel" msgstr "" #: src/toolbar.c:234 msgid "Lasso settings" msgstr "" #: src/toolbar.c:252 msgid "Brush spacing" msgstr "" #: src/toolbar.c:299 src/toolbar.c:341 msgid "Normal" msgstr "ZwykÅ‚y" #: src/toolbar.c:300 msgid "Colour" msgstr "Kolor" #: src/toolbar.c:300 msgid "Saturate More" msgstr "" #: src/toolbar.c:301 msgid "Multiply" msgstr "Mnożenie" #: src/toolbar.c:301 msgid "Divide" msgstr "Dzielenie" #: src/toolbar.c:301 msgid "Dodge" msgstr "RozjaÅ›nianie" #: src/toolbar.c:302 msgid "Burn" msgstr "Wypalanie" #: src/toolbar.c:302 msgid "Hard Light" msgstr "Twarde Å›wiatÅ‚o" #: src/toolbar.c:302 msgid "Soft Light" msgstr "MiÄ™kkie Å›wiatÅ‚o" #: src/toolbar.c:302 msgid "Difference" msgstr "Różnica" #: src/toolbar.c:303 msgid "Darken" msgstr "Ciemniejsze" #: src/toolbar.c:303 msgid "Lighten" msgstr "JaÅ›niejsze" #: src/toolbar.c:303 msgid "Grain Extract" msgstr "Wydobycie ziarna" #: src/toolbar.c:304 msgid "Grain Merge" msgstr "Połączenie ziarna" #: src/toolbar.c:330 msgid "Blend mode" msgstr "" #: src/toolbar.c:417 msgid "Continuous Mode" msgstr "Tryb kontynuacji" #: src/toolbar.c:421 msgid "Opacity Mode" msgstr "Tryb przezroczystosci" #: src/toolbar.c:424 msgid "Tint Mode" msgstr "Tryb zabarwnienia" #: src/toolbar.c:427 msgid "Tint +-" msgstr "Zabarwienie +-" #: src/toolbar.c:434 msgid "Blend Mode" msgstr "" #: src/toolbar.c:438 msgid "Disable All Masks" msgstr "Wyłącz wszystkie maski" #: src/toolbar.c:441 msgid "Gradient Mode" msgstr "Tryb gradient" #: src/toolbar.c:486 msgid "Settings Toolbar" msgstr "Pasek Ustawienia" #: src/toolbar.c:546 msgid "Cut" msgstr "Wytnij" #: src/toolbar.c:548 msgid "Copy" msgstr "Kopiuj" #: src/toolbar.c:550 msgid "Paste" msgstr "Wklej" #: src/toolbar.c:553 msgid "Undo" msgstr "Cofnij" #: src/toolbar.c:555 msgid "Redo" msgstr "Ponów" #: src/toolbar.c:559 src/viewer.c:328 msgid "Pan Window" msgstr "Rozszerz okno" #: src/toolbar.c:560 src/toolbar.c:640 msgid "More..." msgstr "" #: src/toolbar.c:574 msgid "Paint" msgstr "Rysuj" #: src/toolbar.c:580 msgid "Shuffle" msgstr "Tasuj" #: src/toolbar.c:583 msgid "Flood Fill" msgstr "WypeÅ‚nienie" #: src/toolbar.c:587 msgid "Straight Line" msgstr "Linia prosta" #: src/toolbar.c:590 msgid "Smudge" msgstr "Smużenie" #: src/toolbar.c:594 msgid "Clone" msgstr "Klonuj" #: src/toolbar.c:597 msgid "Make Selection" msgstr "Zrób zaznaczenie" #: src/toolbar.c:600 msgid "Polygon Selection" msgstr "Zaznaczenie - WielokÄ…t" #: src/toolbar.c:603 msgid "Place Gradient" msgstr "Umieść gradient" #: src/toolbar.c:606 msgid "Lasso Selection" msgstr "Zaznaczenie lasso" #: src/toolbar.c:614 msgid "Ellipse Outline" msgstr "Obwódka elipsy" #: src/toolbar.c:617 msgid "Filled Ellipse" msgstr "WypeÅ‚niona elipsa" #: src/toolbar.c:620 msgid "Outline Selection" msgstr "Zaznaczanie krawÄ™dzi" #: src/toolbar.c:623 msgid "Fill Selection" msgstr "WypeÅ‚nij zaznaczenie" #: src/toolbar.c:627 msgid "Flip Selection Vertically" msgstr "Odwróć zaznaczenie w pionie" #: src/toolbar.c:630 msgid "Flip Selection Horizontally" msgstr "Odwróć zaznaczenie w poziomie" #: src/toolbar.c:633 msgid "Rotate Selection Clockwise" msgstr "Obróć zaznaczenie w prawo" #: src/toolbar.c:636 msgid "Rotate Selection Anti-Clockwise" msgstr "Obróć zaznaczenie w lewo" #: src/vcode.c:5201 msgid "Browse" msgstr "PrzeglÄ…daj" #: src/vcode.c:7886 msgid "New key ..." msgstr "" #: src/vcode.c:9909 #, c-format msgid "'%s' does not match any widget" msgstr "" #: src/vcode.c:9910 #, c-format msgid "'%s' value does not fit '%s' widget" msgstr "" #: src/viewer.c:115 msgid "About" msgstr "O..." #: src/viewer.c:1179 msgid "No font selected" msgstr "" #: src/viewer.c:1209 msgid "Left" msgstr "" #: src/viewer.c:1209 msgid "Right" msgstr "" #~ msgid "Create GIF frames" #~ msgstr "Utwórz ramki GIF" #~ msgid "File: %s invalid - palette not updated" #~ msgstr "Plik: %s nieprawidÅ‚owy - paleta nieodÅ›wieżona" #~ msgid "Distance to A+B" #~ msgstr "OdlegÅ‚ość do A+B" #~ msgid "Edit Frames" #~ msgstr "Edytuj ramki" #~ msgid " C Command Line Window" #~ msgstr " C Okno linii komend" #~ msgid "The palette does not contain enough colours to do a merge" #~ msgstr "Paleta nie zawiera wystaraczajÄ…cej liczby kolorów do złączenia" #~ msgid "There are too many identical palette items to be reduced." #~ msgstr "Jest zbyt wiele identycznych skÅ‚adników palety " #~ msgid "/View/Command Line Window" #~ msgstr "/Widok/Command Line Window" #~ msgid "Grid colour RGB" #~ msgstr "Siatka kolorów RGB" #~ msgid "Zoom" #~ msgstr "PowiÄ™kszenie" #~ msgid "%i Files on Command Line" #~ msgstr "%i Pliki w lini komend" #~ msgid "Not enough memory to rotate image" #~ msgstr "Za maÅ‚o pamiÄ™ci, aby obrócić obrazek" #~ msgid "Not enough memory to rotate clipboard" #~ msgstr "Za maÅ‚o pamiÄ™ci, aby obrócić obrazek ze schowka" #~ msgid "File is too big, must be <= to width=%i height=%i : %s" #~ msgstr "" #~ "Plik jest zbyt duży, powinien mieć <= to Szerokość=%i Wysokość=%i : %s" #~ msgid "Could not open %s: %s" #~ msgstr "Nie można otworzyć pliku %s: %s" #~ msgid "Error closing %s: %s" #~ msgstr "BlÄ…d przy zamykaniu %s: %s" #~ msgid "Could not write to %s: %s" #~ msgstr "Nie można zapisać do %s: %s" #~ msgid "patterns_user.c could not be opened in current directory" #~ msgstr "wzór _user.c nie może zostać otwarty w bieżącym folderze" #~ msgid "Done" #~ msgstr "UkoÅ„czono" #~ msgid "patterns_user.c created in current directory" #~ msgstr "wzór _user.c utworzony w bieżącym folderze" #~ msgid "Current image is not 94x94x3 so I cannot create patterns_user.c" #~ msgstr "" #~ "Wymiary obrazka nie sÄ… równe (94x94)x3- nie można utworzyć wzoru _user.c" #~ msgid "" #~ "You are trying to save an RGB image to an XPM file which is not " #~ "possible. I would suggest you save with a PNG extension." #~ msgstr "" #~ "Próbujesz zapisać obraz RGB jako plik XPM, a to nie jest możliwe.Zaleca " #~ "siÄ™ zapisanie pliku jako PNG." #~ msgid "" #~ "You are trying to save an RGB image to a GIF file which is not possible. " #~ "I would suggest you save with a PNG extension." #~ msgstr "" #~ "Próbujesz zapisać obraz RGB jako GIF, a to nie jest możliwe.Zaleca siÄ™ " #~ "zapisanie pliku jako PNG." #~ msgid "" #~ "You are trying to save an XBM file with a palette of more than 2 " #~ "colours. Either use another format or reduce the palette to 2 colours." #~ msgstr "" #~ "Próbujesz zapisać obraz do pliku XBM z wiÄ™cej niż dwoma kolorami.Użyj " #~ "innego formatu albo zredukuj liczbÄ™ kolorów do dwóch" #~ msgid "" #~ "You are trying to save an indexed canvas to a JPEG file which is not " #~ "possible. I would suggest you save with a PNG extension." #~ msgstr "" #~ "Próbujesz zapisać obraz do formatu JPEG a to nie jest możliwe.Użyj " #~ "zamiast tego formatu PNG." #~ msgid "" #~ "You are trying to save an LSS16 file with a palette of more than 16 " #~ "colours. Either use another format or reduce the palette to 16 colours." #~ msgstr "" #~ "Próbujesz zapisać plik LSS16 z paletÄ… która zawiera wiÄ™cej niż 16 kolorów." #~ "Użyj innego formatu albo zredukuj liczbÄ™ kolorów do 16." #~ msgid "/Edit/Create Patterns" #~ msgstr "/Edycja/Stwórz wzór" #~ msgid "/Palette/Create Quantized (DL1)" #~ msgstr "/Paleta/Utwórz Kwantyzator(DL1)" #~ msgid "/Palette/Create Quantized (DL3)" #~ msgstr "/Paleta/Utwórz Kwnatyzator (DL3)" #~ msgid "/Palette/Create Quantized (Wu)" #~ msgstr "/Paleta/Utwórz Kwantyzator (Wu)" #~ msgid "/File/%i" #~ msgstr "/Plik/%i" #~ msgid "Lanczos3" #~ msgstr "Lanczos3" #~ msgid "DL1 Quantize (fastest)" #~ msgstr "DL1 Quantize (szybkie)" #~ msgid "DL3 Quantize (very slow, better quality)" #~ msgstr "DL3 Quantize (wolne, lepsza jakość)" #~ msgid "Wu Quantize (best method for small palettes)" #~ msgstr "Wu Quantize (lepsza metoda dla maÅ‚ych palet)" #~ msgid "Loading PNG image" #~ msgstr "Åadowanie obrazku PNG" #~ msgid "Loading clipboard image" #~ msgstr "Åaduj obraz schowka" #~ msgid "Saving PNG image" #~ msgstr "Zapisywanie obrazku PNG" #~ msgid "Saving Clipboard image" #~ msgstr "Zapisaywanie obrazu schowka" #~ msgid "Saving Layer image" #~ msgstr "Zapisywanie warstwy" #~ msgid "Saving Channel image" #~ msgstr "Zapisywanie kanaÅ‚u" #~ msgid "Loading GIF image" #~ msgstr "Otwieranie obrazku GIF" #~ msgid "Saving GIF image" #~ msgstr "Zapisywanie obrazku GIF" #~ msgid "Loading JPEG image" #~ msgstr "Otwieranie obrazku JPEG" #~ msgid "Saving JPEG image" #~ msgstr "Zapisywanie obrazku JPEG" #~ msgid "Loading TIFF image" #~ msgstr "Otwieranie obrazku TIFF" #~ msgid "Saving TIFF image" #~ msgstr "Zapisywanie obrazku TIFF" #~ msgid "Loading BMP image" #~ msgstr "Otwieranie obrazku BMP" #~ msgid "Saving BMP image" #~ msgstr "Zapisywanie obrazku BMP" #~ msgid "Loading XPM image" #~ msgstr "Otwieranie obrazku XPM" #~ msgid "Saving XPM image" #~ msgstr "Zapisywanie obrazku XPM" #~ msgid "Loading XBM image" #~ msgstr "Otwieranie obrazku XBM" #~ msgid "Saving XBM image" #~ msgstr "Zapisywanie obrazku XBM" #~ msgid "Loading LSS16 image" #~ msgstr "Otwieranie obrazku LSS16" #~ msgid "Saving LSS16 image" #~ msgstr "Zapisywanie obrazku LSS16" #~ msgid "Saving UNDO images" #~ msgstr "Zapisywanie CofniÄ™tych zmian" #~ msgid "JPEG Save Quality (100=High) " #~ msgstr "Jakość zapisu JPEG (100=Wysoka) " mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/po/pt.po000066400000000000000000002337711471325446300215710ustar00rootroot00000000000000# Portuguese translation for mtpaint # Copyright (c) (c) 2005 Canonical Ltd, and Rosetta Contributors 2005 # This file is distributed under the same license as the mtpaint package. # FIRST AUTHOR , 2005. # msgid "" msgstr "" "Project-Id-Version: mtpaint\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-01-04 21:31+0200\n" "PO-Revision-Date: 2008-06-19 18:04+0000\n" "Last-Translator: Tiago Silva \n" "Language-Team: Portuguese \n" "Language: pt\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Launchpad-Export-Date: 2009-01-18 12:36+0000\n" "X-Generator: Launchpad (build Unknown)\n" "X-Rosetta-Version: 0.1\n" #: src/ani.c:647 msgid "Animation Preview" msgstr "" #: src/ani.c:650 src/shifter.c:275 msgid "Play" msgstr "Reproduzir" #: src/ani.c:654 msgid "Fix" msgstr "Corrigir" #: src/ani.c:655 src/ani.c:1005 src/font.c:1624 src/font.c:1643 #: src/shifter.c:286 src/viewer.c:97 msgid "Close" msgstr "Fechar" #: src/ani.c:709 src/ani.c:812 src/ani.c:1022 src/ani.c:1028 src/canvas.c:356 #: src/canvas.c:708 src/canvas.c:989 src/canvas.c:1353 src/canvas.c:1383 #: src/canvas.c:1470 src/canvas.c:1545 src/canvas.c:1988 src/canvas.c:1994 #: src/canvas.c:2077 src/canvas.c:2217 src/canvas.c:2240 src/font.c:1352 #: src/fpick.c:636 src/fpick.c:754 src/layer.c:524 src/layer.c:815 #: src/layer.c:970 src/mainwindow.c:341 src/mainwindow.c:370 #: src/mainwindow.c:534 src/mainwindow.c:578 src/mainwindow.c:604 #: src/mainwindow.c:3797 src/mainwindow.c:4045 src/otherwindow.c:931 #: src/otherwindow.c:980 src/otherwindow.c:982 src/prefs.c:459 src/spawn.c:924 #: src/spawn.c:978 src/spawn.c:1017 src/thread.c:360 src/vcode.c:9912 #: src/viewer.c:1161 src/viewer.c:1179 msgid "Error" msgstr "Erro" #: src/ani.c:709 msgid "Unable to create output directory" msgstr "" #: src/ani.c:759 msgid "Creating Animation Frames" msgstr "" #: src/ani.c:812 msgid "Unable to save image" msgstr "Impossível gravar imagem" #: src/ani.c:840 src/canvas.c:1171 src/fpick.c:731 src/layer.c:311 #: src/layer.c:379 src/layer.c:826 src/layer.c:840 src/mainwindow.c:375 #: src/mainwindow.c:1026 src/png.c:8794 src/prefs.c:464 msgid "Warning" msgstr "Aviso" #: src/ani.c:840 msgid "" "Do you really want to clear all of the position and cycle data for all of " "the layers?" msgstr "" #: src/ani.c:841 src/fpick.c:731 src/layer.c:311 src/layer.c:842 #: src/mainwindow.c:375 msgid "No" msgstr "Não" #: src/ani.c:841 src/fpick.c:731 src/layer.c:311 src/layer.c:842 #: src/mainwindow.c:375 msgid "Yes" msgstr "Sim" #: src/ani.c:954 msgid "Set Key Frame" msgstr "" #: src/ani.c:961 msgid "Configure Animation" msgstr "Configurar Animação" #: src/ani.c:964 msgid "Output Files" msgstr "" #: src/ani.c:967 msgid "Start frame" msgstr "" #: src/ani.c:969 msgid "End frame" msgstr "" #: src/ani.c:971 src/shifter.c:267 msgid "Delay" msgstr "" #: src/ani.c:973 msgid "Output path" msgstr "" #: src/ani.c:973 src/font.c:1637 src/spawn.c:664 msgid "Select Directory" msgstr "" #: src/ani.c:976 msgid "File prefix" msgstr "" #: src/ani.c:978 src/canvas.c:2096 msgid "File Format" msgstr "Formato de Ficheiro" #: src/ani.c:982 msgid "Positions" msgstr "Posições" #: src/ani.c:997 msgid "Cycling" msgstr "" #: src/ani.c:1006 msgid "Save" msgstr "Guardar" #: src/ani.c:1007 src/font.c:1577 src/otherwindow.c:868 src/otherwindow.c:1615 #: src/otherwindow.c:1728 src/otherwindow.c:2938 src/otherwindow.c:3071 #: src/otherwindow.c:3170 msgid "Preview" msgstr "Previsualizar" #: src/ani.c:1008 src/shifter.c:285 msgid "Create Frames" msgstr "" #: src/ani.c:1022 msgid "You must have at least 2 layers to create an animation" msgstr "" #: src/ani.c:1028 msgid "You must save your layers file before creating an animation" msgstr "" #: src/canvas.c:357 msgid "The image is too large to transform." msgstr "A imagem é demasiado grande para transformar." #: src/canvas.c:393 src/canvas.c:430 src/otherwindow.c:1613 #: src/otherwindow.c:2524 src/otherwindow.c:2583 src/otherwindow.c:3179 msgid "Gradient" msgstr "" #: src/canvas.c:393 src/otherwindow.c:840 src/otherwindow.c:842 #: src/otherwindow.c:2074 src/otherwindow.c:3180 msgid "Palette" msgstr "Palete" #: src/canvas.c:393 src/info.c:265 src/otherwindow.c:847 src/otherwindow.c:2757 #: src/otherwindow.c:3180 src/png.c:781 src/png.c:995 msgid "Clipboard" msgstr "Ãrea de Transferência" #: src/canvas.c:394 src/cpick.c:831 src/toolbar.c:299 msgid "Value" msgstr "Valor" #: src/canvas.c:394 src/cpick.c:811 src/otherwindow.c:575 src/otherwindow.c:859 #: src/otherwindow.c:3053 src/toolbar.c:318 msgid "Red" msgstr "Vermelho" #: src/canvas.c:394 src/cpick.c:815 src/otherwindow.c:575 src/otherwindow.c:860 #: src/otherwindow.c:3053 src/toolbar.c:319 msgid "Green" msgstr "Verde" #: src/canvas.c:394 src/cpick.c:819 src/otherwindow.c:575 src/otherwindow.c:861 #: src/otherwindow.c:3053 src/toolbar.c:320 msgid "Blue" msgstr "Azul" #: src/canvas.c:399 msgid "From " msgstr "" #: src/canvas.c:403 msgid "To " msgstr "" #: src/canvas.c:410 msgid "Map" msgstr "" #: src/canvas.c:429 msgid "MT" msgstr "" #: src/canvas.c:429 msgid "Sobel" msgstr "" #: src/canvas.c:429 msgid "Prewitt" msgstr "" #: src/canvas.c:429 msgid "Kirsch" msgstr "" #: src/canvas.c:430 msgid "Roberts" msgstr "" #: src/canvas.c:430 msgid "Laplace" msgstr "" #: src/canvas.c:430 msgid "Morphological" msgstr "" #: src/canvas.c:442 msgid "Edge Detect" msgstr "" #: src/canvas.c:464 msgid "Edge Sharpen" msgstr "" #: src/canvas.c:472 msgid "Edge Soften" msgstr "" #: src/canvas.c:521 msgid "Different X/Y" msgstr "" #: src/canvas.c:522 src/canvas.c:562 src/canvas.c:603 src/canvas.c:637 #: src/canvas.c:722 src/otherwindow.c:1037 src/otherwindow.c:2685 msgid "Gamma corrected" msgstr "" #: src/canvas.c:530 src/memory.c:8219 msgid "Gaussian Blur" msgstr "" #: src/canvas.c:558 msgid "Radius" msgstr "" #: src/canvas.c:559 msgid "Amount" msgstr "" #: src/canvas.c:560 msgid "Threshold " msgstr "" #: src/canvas.c:570 src/memory.c:8360 msgid "Unsharp Mask" msgstr "" #: src/canvas.c:599 msgid "Outer radius" msgstr "" #: src/canvas.c:600 msgid "Inner radius" msgstr "" #: src/canvas.c:602 src/info.c:280 msgid "Normalize" msgstr "Normalizar" #: src/canvas.c:611 src/memory.c:8512 msgid "Difference of Gaussians" msgstr "" #: src/canvas.c:636 msgid "Protect details" msgstr "" #: src/canvas.c:645 msgid "Kuwahara-Nagao Blur" msgstr "" #: src/canvas.c:709 msgid "The image is too large for this rotation." msgstr "A imagem é demasiado grande para esta rotação." #: src/canvas.c:723 msgid "Smooth" msgstr "" #: src/canvas.c:732 msgid "Free Rotate" msgstr "" #: src/canvas.c:989 src/viewer.c:1161 msgid "Not enough memory to create clipboard" msgstr "Memória insuficiente para criar a área de transferência" #: src/canvas.c:1172 msgid "" "You have not allocated enough memory in the Preferences window to undo this " "action." msgstr "" #: src/canvas.c:1353 msgid "Invalid palette file" msgstr "" #: src/canvas.c:1383 msgid "Invalid channel file." msgstr "" #: src/canvas.c:1401 msgid "Raw frames" msgstr "" #: src/canvas.c:1401 msgid "Composited frames" msgstr "" #: src/canvas.c:1402 msgid "Composited frames with nonzero delay" msgstr "" #: src/canvas.c:1406 msgid "Load Frames" msgstr "" #: src/canvas.c:1409 msgid "Load into Layers" msgstr "" #: src/canvas.c:1415 msgid "Load First Frame" msgstr "" #: src/canvas.c:1416 msgid "Explode Frames" msgstr "" #: src/canvas.c:1418 msgid "View Animation" msgstr "" #: src/canvas.c:1434 #, c-format msgid "This is an animated %s file." msgstr "" #: src/canvas.c:1435 #, c-format msgid "This is a multipage %s file." msgstr "" #: src/canvas.c:1459 #, c-format msgid "File is too big, must be <= to width=%i height=%i" msgstr "" #: src/canvas.c:1461 msgid "Unable to explode frames" msgstr "" #: src/canvas.c:1463 msgid "Unable to load file" msgstr "Não se consegue carregar o ficheiro" #: src/canvas.c:1465 msgid "" "The file import library had to terminate due to a problem with the file " "(possibly corrupt image data or a truncated file). I have managed to load " "some data as the header seemed fine, but I would suggest you save this image " "to a new file to ensure this does not happen again." msgstr "" "A libraría de importação teve de terminar devido a um problema com o " "ficheiro (dados de imagem possivelmente corruptos ou ficheiro truncado). Eu " "consegui carregar alguns dados uma vez que o cabeçalho aparentava estar bem, " "mas sugeria que grave esta imagem para um novo ficheiro para garantir que " "isto não volte a acontecer." #: src/canvas.c:1467 msgid "The animation is too long to load all of it into layers." msgstr "" #: src/canvas.c:1469 msgid "Could not explode all the frames in the animation." msgstr "" #: src/canvas.c:1481 src/font.c:1556 src/fpick.c:937 src/otherwindow.c:2765 #: src/prefs.c:321 src/toolbar.c:451 msgid "Size" msgstr "Tamanho" #: src/canvas.c:1484 src/otherwindow.c:244 msgid "Width" msgstr "Largura" #: src/canvas.c:1485 src/otherwindow.c:245 msgid "Height" msgstr "Altura" #: src/canvas.c:1489 src/channels.c:253 src/channels.c:317 src/fpick.c:666 #: src/fpick.c:957 src/mainwindow.c:3990 src/otherwindow.c:255 #: src/otherwindow.c:517 src/otherwindow.c:591 src/otherwindow.c:867 #: src/otherwindow.c:1058 src/otherwindow.c:1727 src/otherwindow.c:2101 #: src/otherwindow.c:2336 src/otherwindow.c:2538 src/otherwindow.c:2691 #: src/otherwindow.c:2776 src/otherwindow.c:2937 src/otherwindow.c:3070 #: src/otherwindow.c:3169 src/prefs.c:338 src/prefs.c:464 src/prefs.c:538 #: src/spawn.c:666 src/viewer.c:1258 msgid "Cancel" msgstr "Cancelar" #: src/canvas.c:1490 src/channels.c:253 src/channels.c:317 src/fpick.c:956 #: src/info.c:297 src/mainwindow.c:3992 src/mygtk.c:233 src/mygtk.c:535 #: src/otherwindow.c:591 src/otherwindow.c:871 src/otherwindow.c:1058 #: src/otherwindow.c:1729 src/otherwindow.c:2101 src/otherwindow.c:2336 #: src/otherwindow.c:2538 src/otherwindow.c:2691 src/otherwindow.c:2776 #: src/otherwindow.c:3072 src/otherwindow.c:3171 src/prefs.c:338 #: src/prefs.c:538 src/spawn.c:666 msgid "OK" msgstr "OK" #: src/canvas.c:1504 #, c-format msgid "This is a scalable %s file." msgstr "" #: src/canvas.c:1545 msgid "Cannot open file" msgstr "" #: src/canvas.c:1546 msgid "Unsupported file format" msgstr "" #: src/canvas.c:1673 #, c-format msgid "File: %s already exists. Do you want to overwrite it?" msgstr "O ficheiro %s já existe. Deseja sobreescrevê-lo?" #: src/canvas.c:1674 msgid "File Found" msgstr "Ficheiro Encontrado" #: src/canvas.c:1674 src/mainwindow.c:1095 msgid "NO" msgstr "NÃO" #: src/canvas.c:1674 src/mainwindow.c:1095 msgid "YES" msgstr "SIM" #: src/canvas.c:1988 msgid "Unable to export undo images" msgstr "" #: src/canvas.c:1994 msgid "Unable to export ASCII file" msgstr "Não se consegue exportar o ficheiro ASCII" #: src/canvas.c:2076 src/layer.c:814 src/mainwindow.c:529 #, c-format msgid "Unable to save file: %s" msgstr "Não se consegue gravar o ficheiro: %s" #: src/canvas.c:2101 src/prefs.c:222 msgid "Transparency index" msgstr "" #: src/canvas.c:2103 msgid "TIFF Compression" msgstr "" #: src/canvas.c:2105 src/prefs.c:225 msgid "JPEG Save Quality (100=High)" msgstr "Qualidade de Gravação JPEG (100=Alta)" #: src/canvas.c:2107 msgid "ZIP Compression (0=None)" msgstr "" #: src/canvas.c:2108 src/prefs.c:227 msgid "PNG Compression (0=None)" msgstr "" #: src/canvas.c:2111 src/prefs.c:249 msgid "LZMA2 Compression (0=None)" msgstr "" #: src/canvas.c:2113 src/prefs.c:252 msgid "ZSTD Compression Level" msgstr "" #: src/canvas.c:2115 src/prefs.c:231 msgid "TGA RLE Compression" msgstr "" #: src/canvas.c:2117 msgid "LBM PackBits Compression" msgstr "" #: src/canvas.c:2118 src/prefs.c:226 msgid "JPEG2000 Compression (0=Lossless)" msgstr "" #: src/canvas.c:2120 msgid "WebP Compression" msgstr "" #: src/canvas.c:2122 msgid "WebP Save Quality (100=High)" msgstr "" #: src/canvas.c:2123 src/prefs.c:263 msgid "V8 Save Quality (100=High)" msgstr "" #: src/canvas.c:2125 src/prefs.c:264 msgid "V8L Compression (0=None)" msgstr "" #: src/canvas.c:2127 msgid "Hotspot at X =" msgstr "" #: src/canvas.c:2129 msgid "Y =" msgstr "" #: src/canvas.c:2133 msgid "Animation delay" msgstr "" #: src/canvas.c:2136 src/otherwindow.c:253 msgid "Undoable" msgstr "" #: src/canvas.c:2138 src/prefs.c:236 msgid "Apply colour profile" msgstr "" #: src/canvas.c:2176 src/toolbar.c:543 msgid "Load Image File" msgstr "Carregar Ficheiro de Imagem" #: src/canvas.c:2191 src/toolbar.c:544 msgid "Save Image File" msgstr "Gravar Ficheiro de Imagem" #: src/canvas.c:2196 msgid "Load Palette File" msgstr "Carregar Ficheiro de Paleta" #: src/canvas.c:2202 msgid "Save Palette File" msgstr "Gravar Ficheiro de Paleta" #: src/canvas.c:2207 msgid "Export Undo Images" msgstr "" #: src/canvas.c:2212 msgid "Export Undo Images (reversed)" msgstr "" #: src/canvas.c:2217 msgid "You must have 16 or fewer palette colours to export ASCII art." msgstr "Deve ter 16 cores de paleta ou menos para exportar arte ASCII." #: src/canvas.c:2220 msgid "Export ASCII Art" msgstr "Exportar Arte ASCII" #: src/canvas.c:2224 msgid "Save Layer Files" msgstr "Gravar Ficheiros de Camadas" #: src/canvas.c:2234 msgid "Choose frames directory" msgstr "" #: src/canvas.c:2240 msgid "You must save at least one frame to create an animated GIF." msgstr "" #: src/canvas.c:2243 msgid "Export GIF animation" msgstr "" #: src/canvas.c:2247 msgid "Load Channel" msgstr "Carregar Canal" #: src/canvas.c:2255 msgid "Save Channel" msgstr "Guardar Canal" #: src/canvas.c:2260 msgid "Save Composite Image" msgstr "" #: src/channels.c:243 msgid "Create Channel" msgstr "Criar Canal" #: src/channels.c:244 msgid "Channel Type" msgstr "Tipo de Canal" #: src/channels.c:247 msgid "Initial Channel State" msgstr "" #: src/channels.c:251 msgid "Inverted" msgstr "" #: src/channels.c:265 msgid "Cleared" msgstr "" #: src/channels.c:266 msgid "Set" msgstr "" #: src/channels.c:267 msgid "Set colour A radius B" msgstr "" #: src/channels.c:268 msgid "Set blend A to B" msgstr "" #: src/channels.c:269 msgid "Image Red" msgstr "" #: src/channels.c:270 msgid "Image Green" msgstr "" #: src/channels.c:271 msgid "Image Blue" msgstr "" #: src/channels.c:273 src/channels.c:313 src/mainwindow.c:67 #: src/otherwindow.c:1679 msgid "Alpha" msgstr "Alfa" #: src/channels.c:274 src/channels.c:314 src/mainwindow.c:67 #: src/otherwindow.c:1683 msgid "Selection" msgstr "Selecção" #: src/channels.c:275 src/channels.c:315 src/mainwindow.c:67 #: src/otherwindow.c:1687 msgid "Mask" msgstr "" #: src/channels.c:312 msgid "Delete Channels" msgstr "Eliminar Canais" #: src/channels.c:367 msgid "Threshold Channel" msgstr "" #: src/cpick.c:823 src/otherwindow.c:573 src/otherwindow.c:820 #: src/toolbar.c:299 msgid "Hue" msgstr "Tonalidade" #: src/cpick.c:827 src/otherwindow.c:573 src/otherwindow.c:818 #: src/toolbar.c:299 msgid "Saturation" msgstr "Saturação" #: src/cpick.c:835 msgid "Hex" msgstr "" #: src/cpick.c:840 src/layer.c:1109 src/otherwindow.c:2530 src/prefs.c:323 #: src/toolbar.c:457 msgid "Opacity" msgstr "Opacidade" #: src/font.c:982 msgid "Creating Font Index" msgstr "" #: src/font.c:1353 msgid "You must select at least one directory to search for fonts." msgstr "" #: src/font.c:1529 src/font.c:1624 src/toolbar.c:609 src/viewer.c:1213 #: src/viewer.c:1258 msgid "Paste Text" msgstr "Colar Texto" #: src/font.c:1533 src/font.c:1572 src/png.c:3578 msgid "Text" msgstr "" #: src/font.c:1540 msgid "Font" msgstr "" #: src/font.c:1548 msgid "Style" msgstr "" #: src/font.c:1566 msgid "Filename" msgstr "" #: src/font.c:1567 msgid "Face" msgstr "" #: src/font.c:1587 src/viewer.c:1222 msgid "Antialias" msgstr "Antialias" #: src/font.c:1590 src/viewer.c:1224 msgid "Invert" msgstr "Inverter" #: src/font.c:1593 src/viewer.c:1226 msgid "Background colour =" msgstr "Cor de fundo =" #: src/font.c:1601 src/viewer.c:1233 msgid "DPI =" msgstr "" #: src/font.c:1610 msgid "Oblique" msgstr "" #: src/font.c:1612 src/viewer.c:1244 msgid "Angle of rotation =" msgstr "Ângulo de rotação =" #: src/font.c:1617 src/viewer.c:1248 msgid "Align" msgstr "" #: src/font.c:1620 src/viewer.c:1253 msgid "Spacing" msgstr "" #: src/font.c:1629 msgid "Font Directories" msgstr "" #: src/font.c:1634 src/spawn.c:664 msgid "Directory" msgstr "" #: src/font.c:1637 msgid "New Directory" msgstr "" #: src/font.c:1644 src/prefs.c:532 msgid "Add" msgstr "" #: src/font.c:1645 src/prefs.c:533 msgid "Remove" msgstr "" #: src/font.c:1646 msgid "Create Index" msgstr "" #: src/font.c:1660 src/viewer.c:1267 msgid "Enter Text Here" msgstr "Introduzir Texto Aqui" #: src/fpick.c:635 #, c-format msgid "Could not access directory %s" msgstr "" #: src/fpick.c:668 src/fpick.c:698 msgid "Delete" msgstr "" #: src/fpick.c:669 src/fpick.c:698 msgid "Rename" msgstr "" #: src/fpick.c:672 src/otherwindow.c:255 src/otherwindow.c:1666 msgid "Create" msgstr "Criar" #: src/fpick.c:699 msgid "Enter the new filename" msgstr "" #: src/fpick.c:704 msgid "Create Directory" msgstr "" #: src/fpick.c:705 msgid "Enter the name of the new directory" msgstr "" #: src/fpick.c:729 #, c-format msgid "Do you really want to delete \"%s\" ?" msgstr "" #: src/fpick.c:735 msgid "Unable to delete" msgstr "" #: src/fpick.c:741 msgid "Unable to rename" msgstr "" #: src/fpick.c:750 msgid "Unable to create directory" msgstr "" #: src/fpick.c:924 msgid "Up" msgstr "" #: src/fpick.c:925 msgid "Home" msgstr "" #: src/fpick.c:926 msgid "Create New Directory" msgstr "" #: src/fpick.c:927 msgid "Show Hidden Files" msgstr "" #: src/fpick.c:929 msgid "Case Insensitive Sort" msgstr "" #: src/fpick.c:936 msgid "Name" msgstr "" #: src/fpick.c:938 msgid "Type" msgstr "" #: src/fpick.c:939 msgid "Modified" msgstr "" #: src/help.c:25 src/prefs.c:160 msgid "General" msgstr "Geral" #: src/help.c:26 msgid "Keyboard shortcuts" msgstr "Atalhos de teclado" #: src/help.c:27 msgid "Mouse shortcuts" msgstr "Atalhos de mouse" #: src/help.c:28 msgid "Credits" msgstr "Créditos" #: src/help.c:32 msgid "mtPaint 3.51 - Copyright (C) 2004-2021 The Authors\n" msgstr "" #: src/help.c:33 msgid "See 'Credits' section for a list of the authors.\n" msgstr "" #: src/help.c:34 msgid "" "mtPaint 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.\n" msgstr "" #: src/help.c:35 msgid "" "mtPaint 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.\n" msgstr "" #: src/help.c:36 msgid "" "mtPaint is a simple GTK+1/2/3 painting program designed for creating icons " "and pixel based artwork. It can edit indexed palette or 24 bit RGB images " "and offers basic painting and palette manipulation tools. It also has " "several other more powerful features such as channels, layers and animation. " "Due to its simplicity and lack of dependencies it runs well on GNU/Linux, " "Windows and older PC hardware.\n" msgstr "" #: src/help.c:37 msgid "" "There is full documentation of mtPaint's features contained in a handbook. " "If you don't already have this, you can download it from the mtPaint " "website.\n" msgstr "" #: src/help.c:38 msgid "" "If you like mtPaint and you want to keep up to date with new releases, or " "you want to give some feedback, then the mailing lists may be of interest to " "you:\n" msgstr "" #: src/help.c:39 msgid "http://sourceforge.net/mail/?group_id=155874" msgstr "" #: src/help.c:42 msgid " Ctrl-N Create new image" msgstr "" #: src/help.c:43 msgid " Ctrl-O Open Image" msgstr "" #: src/help.c:44 msgid " Ctrl-S Save Image" msgstr "" #: src/help.c:45 msgid " Ctrl-Shift-S Save layers file" msgstr "" #: src/help.c:46 msgid " Ctrl-Q Quit program\n" msgstr "" #: src/help.c:47 msgid " Ctrl-A Select whole image" msgstr "" #: src/help.c:48 msgid " Escape Select nothing, cancel paste box" msgstr "" #: src/help.c:49 msgid " J Lasso selection\n" msgstr "" #: src/help.c:50 msgid " Ctrl-C Copy selection to clipboard" msgstr "" #: src/help.c:51 msgid "" " Ctrl-X Copy selection to clipboard, and then paint current " "pattern to selection area" msgstr "" #: src/help.c:52 msgid " Ctrl-V Paste clipboard to centre of current view" msgstr "" #: src/help.c:53 msgid " Ctrl-K Paste clipboard to location it was copied from" msgstr "" #: src/help.c:54 msgid " Ctrl-Shift-V Paste clipboard to new layer" msgstr "" #: src/help.c:55 msgid " Enter/Return Commit paste to canvas" msgstr "" #: src/help.c:56 msgid " Shift+Enter/Return Commit paste and swap canvas into the clipboard\n" msgstr "" #: src/help.c:57 msgid " Arrow keys Paint Mode - Move the mouse pointer" msgstr "" #: src/help.c:58 msgid "" " Arrow keys Selection Mode - Nudge selection box or paste box by one " "pixel" msgstr "" #: src/help.c:59 msgid "" " Shift+Arrow keys Nudge mouse pointer, selection box or paste box by x " "pixels - x is defined by the Preferences window" msgstr "" #: src/help.c:60 msgid " Ctrl+Arrows Move layer or resize selection box" msgstr "" #: src/help.c:61 msgid " Ctrl+Shift+Arrows Move layer or resize selection box by x pixels\n" msgstr "" #: src/help.c:62 msgid " Enter/Return Paint Mode - Simulate left click" msgstr "" #: src/help.c:63 msgid " Backspace Paint Mode - Simulate right click\n" msgstr "" #: src/help.c:64 msgid "" " [ or ] Change colour A to the next or previous palette item" msgstr "" #: src/help.c:65 msgid "" " Shift+[ or ] Change colour B to the next or previous palette item\n" msgstr "" #: src/help.c:66 msgid " Delete Crop image to selection" msgstr "" #: src/help.c:67 msgid "" " Insert Transform colours - i.e. Brightness, Contrast, " "Saturation, Posterize, Gamma" msgstr "" #: src/help.c:68 msgid " Ctrl-G Greyscale the image" msgstr "" #: src/help.c:69 msgid " Shift-Ctrl-G Greyscale the image (Gamma corrected)" msgstr "" #: src/help.c:70 msgid " Ctrl+M Mirror the image" msgstr "" #: src/help.c:71 msgid " Shift-Ctrl-I Invert the image\n" msgstr "" #: src/help.c:72 msgid "" " Ctrl-T Draw a rectangle around the selection area with the " "current fill" msgstr "" #: src/help.c:73 msgid " Ctrl-Shift-T Fill in the selection area with the current fill" msgstr "" #: src/help.c:74 msgid " Ctrl-L Draw an ellipse spanning the selection area" msgstr "" #: src/help.c:75 msgid " Ctrl-Shift-L Draw a filled ellipse spanning the selection area\n" msgstr "" #: src/help.c:76 msgid " Ctrl-E Edit the RGB values for colours A & B" msgstr "" #: src/help.c:77 msgid " Ctrl-W Edit all palette colours\n" msgstr "" #: src/help.c:78 msgid " Ctrl-P Preferences" msgstr "" #: src/help.c:79 msgid " Ctrl-I Information\n" msgstr "" #: src/help.c:80 msgid " Ctrl-Z Undo last action" msgstr "" #: src/help.c:81 msgid " Ctrl-R Redo an undone action\n" msgstr "" #: src/help.c:82 msgid " Shift-T Text Tool (GTK+)" msgstr "" #: src/help.c:83 msgid " T Text Tool (FreeType)\n" msgstr "" #: src/help.c:84 msgid " V View Window" msgstr "" #: src/help.c:85 msgid " L Layers Window\n" msgstr "" #: src/help.c:86 msgid " Ctrl-H Toggle Hide Image mode" msgstr "" #: src/help.c:87 msgid " B Toggle Snap to Tile Grid mode\n" msgstr "" #: src/help.c:88 msgid " X Swap Colours A & B" msgstr "" #: src/help.c:89 msgid " E Choose Colour\n" msgstr "" #: src/help.c:90 msgid "" " A Draw open arrow head when using the line tool (size set " "by flow setting)" msgstr "" #: src/help.c:91 msgid "" " S Draw closed arrow head when using the line tool (size " "set by flow setting)\n" msgstr "" #: src/help.c:92 msgid " D Line Tool" msgstr "" #: src/help.c:93 msgid " F Flood Fill Tool\n" msgstr "" #: src/help.c:94 msgid " +,= Main edit window - Zoom in" msgstr "" #: src/help.c:95 msgid " - Main edit window - Zoom out" msgstr "" #: src/help.c:96 msgid " Shift +,= View window - Zoom in" msgstr "" #: src/help.c:97 msgid " Shift - View window - Zoom out\n" msgstr "" #: src/help.c:98 #, c-format msgid " 1 10% zoom" msgstr "" #: src/help.c:99 #, c-format msgid " 2 25% zoom" msgstr "" #: src/help.c:100 #, c-format msgid " 3 50% zoom" msgstr "" #: src/help.c:101 #, c-format msgid " 4 100% zoom" msgstr "" #: src/help.c:102 #, c-format msgid " 5 400% zoom" msgstr "" #: src/help.c:103 #, c-format msgid " 6 800% zoom" msgstr "" #: src/help.c:104 #, c-format msgid " 7 1200% zoom" msgstr "" #: src/help.c:105 #, c-format msgid " 8 1600% zoom" msgstr "" #: src/help.c:106 #, c-format msgid " 9 2000% zoom\n" msgstr "" #: src/help.c:107 msgid " Shift + 1 Edit image channel" msgstr "" #: src/help.c:108 msgid " Shift + 2 Edit alpha channel" msgstr "" #: src/help.c:109 msgid " Shift + 3 Edit selection channel" msgstr "" #: src/help.c:110 msgid " Shift + 4 Edit mask channel\n" msgstr "" #: src/help.c:111 msgid " F1 Help" msgstr "" #: src/help.c:112 msgid " F2 Choose Pattern" msgstr "" #: src/help.c:113 msgid " F3 Choose Brush" msgstr "" #: src/help.c:114 msgid " F4 Paint Tool" msgstr "" #: src/help.c:115 msgid " F5 Toggle Main Toolbar" msgstr "" #: src/help.c:116 msgid " F6 Toggle Tools Toolbar" msgstr "" #: src/help.c:117 msgid " F7 Toggle Settings Toolbar" msgstr "" #: src/help.c:118 msgid " F8 Toggle Palette" msgstr "" #: src/help.c:119 msgid " F9 Selection Tool" msgstr "" #: src/help.c:120 msgid " F12 Toggle Dock Area\n" msgstr "" #: src/help.c:121 msgid " Ctrl + F1 - F12 Save current clipboard to file 1-12" msgstr "" #: src/help.c:122 msgid " Shift + F1 - F12 Load clipboard from file 1-12\n" msgstr "" #: src/help.c:123 msgid "" " Ctrl + 1, 2, ... , 0 Set opacity to 10%, 20%, ... , 100% (main or keypad " "numbers)" msgstr "" #: src/help.c:124 msgid " Ctrl + + or = Increase opacity by 1" msgstr "" #: src/help.c:125 msgid " Ctrl + - Decrease opacity by 1\n" msgstr "" #: src/help.c:126 msgid "" " Home Show or hide main window menu/toolbar/status bar/palette" msgstr "" #: src/help.c:127 msgid " Page Up Scale Image" msgstr "" #: src/help.c:128 msgid " Page Down Resize Image canvas" msgstr "" #: src/help.c:129 msgid " End Pan Window" msgstr "" #: src/help.c:132 msgid " Left button Paint to canvas using the current tool" msgstr "" #: src/help.c:133 msgid "" " Middle button Selects the point which will be the centre of the " "image after the next zoom" msgstr "" #: src/help.c:134 msgid "" " Right button Commit paste to canvas / Stop drawing current line / " "Cancel selection\n" msgstr "" #: src/help.c:135 msgid "" " Scroll Wheel In GTK+2/3 the user can have the scroll wheel zoom in " "or out via the Preferences window\n" msgstr "" #: src/help.c:136 msgid " Ctrl+Left button Choose colour A from under mouse pointer" msgstr "" #: src/help.c:137 msgid " Ctrl+Left button Clone tool - Select source" msgstr "" #: src/help.c:138 msgid "" " Ctrl+Middle button Create colour A/B and pattern based on the RGB colour " "in A (RGB images only)" msgstr "" #: src/help.c:139 msgid " Ctrl+Right button Choose colour B from under mouse pointer" msgstr "" #: src/help.c:140 msgid "" " Ctrl+Right button Polygon tool - Delete last point / Delete nearest " "point" msgstr "" #: src/help.c:141 msgid " Ctrl+Scroll Wheel Scroll the main edit window left or right\n" msgstr "" #: src/help.c:142 msgid "" " Ctrl+Double click Set colour A or B to average colour under brush " "square or selection marquee (RGB only)\n" msgstr "" #: src/help.c:143 msgid "" " Shift+Right button Selects the point which will be the centre of the " "image after the next zoom\n" "\n" msgstr "" #: src/help.c:144 msgid "You can fixate the X/Y co-ordinates while moving the mouse:\n" msgstr "" #: src/help.c:145 msgid " Shift Constrain mouse movements to vertical line" msgstr "" #: src/help.c:146 msgid " Shift+Ctrl Constrain mouse movements to horizontal line" msgstr "" #: src/help.c:149 msgid "mtPaint is maintained by Dmitry Groshev.\n" msgstr "" #: src/help.c:150 msgid "wjaguar@users.sourceforge.net" msgstr "" #: src/help.c:151 msgid "http://mtpaint.sourceforge.net/\n" msgstr "" #: src/help.c:152 msgid "" "The following people (in alphabetical order) have contributed directly to " "the project, and are therefore worthy of gracious thanks for their " "generosity and hard work:\n" "\n" msgstr "" #: src/help.c:153 msgid "Authors\n" msgstr "" #: src/help.c:154 msgid "" "Dmitry Groshev - Contributing developer for version 2.30. Lead developer and " "maintainer from version 3.00 to the present." msgstr "" #: src/help.c:155 msgid "" "Mark Tyler - Original author and maintainer up to version 3.00, occasional " "contributor thereafter." msgstr "" #: src/help.c:156 msgid "" "Xiaolin Wu - Wrote the Wu quantizing method - see wu.c for more " "information.\n" "\n" msgstr "" #: src/help.c:157 msgid "" "General Contributions (Feedback and Ideas for improvements unless otherwise " "stated)\n" msgstr "" #: src/help.c:158 msgid "Abdulla Al Muhairi - Website redesign April 2005" msgstr "" #: src/help.c:159 msgid "Alan Horkan" msgstr "" #: src/help.c:160 msgid "Alexandre Prokoudine" msgstr "" #: src/help.c:161 msgid "Antonio Andrea Bianco" msgstr "" #: src/help.c:162 msgid "Charlie Ledocq" msgstr "" #: src/help.c:163 msgid "Dennis Lee" msgstr "" #: src/help.c:164 msgid "Donald White" msgstr "" #: src/help.c:165 msgid "Ed Jason" msgstr "" #: src/help.c:166 msgid "" "Eddie Kohler - Created Gifsicle which is needed for the creation and viewing " "of animated GIF files http://www.lcdf.org/gifsicle/" msgstr "" #: src/help.c:167 msgid "" "Guadalinex Team (Junta de Andalucia) - man page, Launchpad/Rosetta " "registration" msgstr "" #: src/help.c:168 msgid "Lou Afonso" msgstr "" #: src/help.c:169 msgid "Magnus Hjorth" msgstr "" #: src/help.c:170 msgid "Martin Zelaia" msgstr "" #: src/help.c:171 msgid "Pasi Kallinen" msgstr "" #: src/help.c:172 msgid "Pavel Ruzicka" msgstr "" #: src/help.c:173 msgid "Puppy Linux (Barry Kauler)" msgstr "" #: src/help.c:174 msgid "Victor Copovi" msgstr "" #: src/help.c:175 msgid "Vlastimil Krejcir" msgstr "" #: src/help.c:176 msgid "" "William Kern\n" "\n" msgstr "" #: src/help.c:177 msgid "Translations\n" msgstr "" #: src/help.c:178 msgid "Brazilian Portuguese - Paulo Trevizan, Valter Nazianzeno" msgstr "" #: src/help.c:179 msgid "Czech - Pavel Ruzicka, Martin Petricek, Roman Hornik, Pavel Fric" msgstr "" #: src/help.c:180 msgid "Dutch - Hans Strijards, Pjotr" msgstr "" #: src/help.c:181 msgid "" "French - Nicolas Velin, Pascal Billard, Sylvain Cresto, Johan Serre, " "Philippe Etienne, Victor Copovi" msgstr "" #: src/help.c:182 msgid "Galician - Miguel Anxo Bouzada" msgstr "" #: src/help.c:183 msgid "German - Oliver Frommel, B. Clausius, Ulrich Ringel, Simon Brixel" msgstr "" #: src/help.c:184 msgid "Hungarian - Ur Balazs" msgstr "" #: src/help.c:185 msgid "Italian - Angelo Gemmi" msgstr "" #: src/help.c:186 msgid "Japanese - Norihiro YONEDA" msgstr "" #: src/help.c:187 msgid "Kabyle - Yacine Bouklif" msgstr "" #: src/help.c:188 msgid "Polish - Bartosz Kaszubowski, LucaS" msgstr "" #: src/help.c:189 msgid "Portuguese - Israel G. Lugo, Tiago Silva" msgstr "" #: src/help.c:190 msgid "Russian - Sergey Irupin, Dmitry Groshev" msgstr "" #: src/help.c:191 msgid "Simplified Chinese - Cecc" msgstr "" #: src/help.c:192 msgid "Slovak - Jozef Riha" msgstr "" #: src/help.c:193 msgid "" "Spanish - Guadalinex Team (Junta de Andalucia), Antonio Sanchez Leon, Miguel " "Anxo Bouzada, Francisco Jose Rey, Adolfo Jayme" msgstr "" #: src/help.c:194 msgid "Swedish - Daniel Nylander, Daniel Eriksson" msgstr "" #: src/help.c:195 msgid "Tagalog - Anjelo delCarmen" msgstr "" #: src/help.c:196 msgid "Taiwanese Chinese - Wei-Lun Chao" msgstr "" #: src/help.c:197 msgid "Turkish - Muhammet Kara, Tutku Dalmaz" msgstr "" #: src/info.c:258 msgid "Information" msgstr "Informação" #: src/info.c:260 msgid "Memory" msgstr "Memória" #: src/info.c:261 msgid "Total memory for main + undo images" msgstr "Memória total para imagens principal e de desfazer" #: src/info.c:263 msgid "Undo / Redo / Max levels used" msgstr "" #: src/info.c:265 msgid "Unused" msgstr "Não Utilizado" #: src/info.c:269 msgid "Unique RGB pixels" msgstr "Píxeis RGB únicos" #: src/info.c:272 src/layer.c:121 msgid "Layers" msgstr "Camadas" #: src/info.c:273 msgid "Total layer memory usage" msgstr "" #: src/info.c:277 msgid "Colour Histogram" msgstr "" #: src/info.c:289 src/otherwindow.c:1614 msgid "Index" msgstr "" #: src/info.c:290 msgid "Canvas pixels" msgstr "" #: src/info.c:328 #, c-format msgid "Clipboard = %i x %i" msgstr "" #: src/info.c:328 #, c-format msgid "Clipboard = %i x %i x RGB" msgstr "" #: src/info.c:377 msgid "Orphans" msgstr "Órfãos" #: src/info.c:383 #, c-format msgid "Colour index totals - %i of %i used" msgstr "" #: src/inifile.c:966 msgid "" "Could not find home directory. Using current directory as home directory." msgstr "" "Não se conseguiu encontrar a directoria \"home\". A usar a directoria actual " "como directoria \"home\"." #: src/layer.c:63 msgid "Background" msgstr "Fundo" #: src/layer.c:122 src/mainwindow.c:5931 msgid "(Modified)" msgstr "(Modificado)" #: src/layer.c:123 src/mainwindow.c:5932 msgid "Untitled" msgstr "Sem título" #: src/layer.c:308 #, c-format msgid "Do you really want to delete layer %i (%s) ?" msgstr "Deseja mesmo apagar a camada %i (%s) ?" #: src/layer.c:380 msgid "" "One or more of the layers contains changes that have not been saved. Do you " "really want to lose these changes?" msgstr "" "Uma ou mais das camadas contêm alterações que ainda não foram gravadas. " "Deseja mesmo perder essas alterações?" #: src/layer.c:381 src/mainwindow.c:1028 msgid "Cancel Operation" msgstr "Cancelar Operação" #: src/layer.c:381 src/mainwindow.c:1028 msgid "Lose Changes" msgstr "Perder Alterações" #: src/layer.c:523 #, c-format msgid "%d layers failed to load" msgstr "" #: src/layer.c:826 msgid "" "One or more of the image layers has not been saved. You must save each " "image individually before saving the layers text file in order to load this " "composite image in the future." msgstr "" #: src/layer.c:841 msgid "Do you really want to delete all of the layers?" msgstr "Deseja mesmo apagar todas as camadas?" #: src/layer.c:970 msgid "You cannot add any more layers." msgstr "Não pode acrescentar mais camadas." #: src/layer.c:1083 src/otherwindow.c:241 msgid "New Layer" msgstr "Nova Camada" #: src/layer.c:1085 msgid "Raise" msgstr "Aumentar" #: src/layer.c:1087 msgid "Lower" msgstr "Diminuir" #: src/layer.c:1089 msgid "Duplicate Layer" msgstr "Duplicar Camada" #: src/layer.c:1091 msgid "Centralise Layer" msgstr "Centrar Camada" #: src/layer.c:1093 msgid "Delete Layer" msgstr "Apagar Camada" #: src/layer.c:1095 msgid "Close Layers Window" msgstr "Fechar Janela de Camadas" #: src/layer.c:1101 msgid "Layer Name" msgstr "Nome da Camada" #: src/layer.c:1104 src/toolbar.c:209 msgid "Position" msgstr "Posição" #: src/layer.c:1112 msgid "Transparent Colour" msgstr "Cor Transparente" #: src/layer.c:1117 msgid "Show all layers in main window" msgstr "Mostrar todas as camadas na janela principal" #: src/mainwindow.c:67 src/otherwindow.c:844 src/otherwindow.c:2756 #: src/toolbar.c:342 msgid "Image" msgstr "Imagem" #: src/mainwindow.c:69 src/mainwindow.c:489 src/otherwindow.c:1613 #: src/otherwindow.c:2302 msgid "RGB" msgstr "" #: src/mainwindow.c:69 src/otherwindow.c:1613 src/otherwindow.c:2302 msgid "sRGB" msgstr "" #: src/mainwindow.c:342 msgid "There were no unused colours to remove!" msgstr "Não havia cores não usadas para remover!" #: src/mainwindow.c:371 msgid "The palette does not contain 2 colours that have identical RGB values" msgstr "A paleta não contém 2 cores que tenham valores RGB idênticos" #: src/mainwindow.c:374 #, c-format msgid "" "The palette contains %i colours that have identical RGB values. Do you " "really want to merge them into one index and realign the canvas?" msgstr "" #: src/mainwindow.c:492 msgid "indexed" msgstr "" #: src/mainwindow.c:498 #, c-format msgid "" "You are trying to save an %s image to an %s file which is not possible. I " "would suggest you save with a PNG extension." msgstr "" #: src/mainwindow.c:500 #, c-format msgid "" "You are trying to save an %s file with a palette of more than %d colours. " "Either use another format or reduce the palette to %d colours." msgstr "" #: src/mainwindow.c:578 msgid "Unable to load clipboard" msgstr "" #: src/mainwindow.c:604 msgid "Unable to save clipboard" msgstr "" #: src/mainwindow.c:775 msgid "Zoom in" msgstr "" #: src/mainwindow.c:777 msgid "Zoom out" msgstr "" #: src/mainwindow.c:779 #, c-format msgid "10% zoom" msgstr "" #: src/mainwindow.c:781 #, c-format msgid "25% zoom" msgstr "" #: src/mainwindow.c:783 #, c-format msgid "50% zoom" msgstr "" #: src/mainwindow.c:785 #, c-format msgid "100% zoom" msgstr "" #: src/mainwindow.c:787 #, c-format msgid "400% zoom" msgstr "" #: src/mainwindow.c:789 #, c-format msgid "600% zoom" msgstr "" #: src/mainwindow.c:791 #, c-format msgid "800% zoom" msgstr "" #: src/mainwindow.c:793 #, c-format msgid "1000% zoom" msgstr "" #: src/mainwindow.c:795 #, c-format msgid "1200% zoom" msgstr "" #: src/mainwindow.c:797 #, c-format msgid "1600% zoom" msgstr "" #: src/mainwindow.c:799 #, c-format msgid "2000% zoom" msgstr "" #: src/mainwindow.c:801 #, c-format msgid "4000% zoom" msgstr "" #: src/mainwindow.c:803 #, c-format msgid "8000% zoom" msgstr "" #: src/mainwindow.c:805 #, c-format msgid "10% opacity" msgstr "" #: src/mainwindow.c:807 #, c-format msgid "20% opacity" msgstr "" #: src/mainwindow.c:809 #, c-format msgid "30% opacity" msgstr "" #: src/mainwindow.c:811 #, c-format msgid "40% opacity" msgstr "" #: src/mainwindow.c:813 #, c-format msgid "50% opacity" msgstr "" #: src/mainwindow.c:815 #, c-format msgid "60% opacity" msgstr "" #: src/mainwindow.c:817 #, c-format msgid "70% opacity" msgstr "" #: src/mainwindow.c:819 #, c-format msgid "80% opacity" msgstr "" #: src/mainwindow.c:821 #, c-format msgid "90% opacity" msgstr "" #: src/mainwindow.c:823 #, c-format msgid "100% opacity" msgstr "" #: src/mainwindow.c:825 msgid "Increase opacity" msgstr "" #: src/mainwindow.c:827 msgid "Decrease opacity" msgstr "" #: src/mainwindow.c:829 msgid "Draw open arrow head" msgstr "" #: src/mainwindow.c:831 msgid "Draw closed arrow head" msgstr "" #: src/mainwindow.c:833 msgid "Previous colour A" msgstr "" #: src/mainwindow.c:835 msgid "Next colour A" msgstr "" #: src/mainwindow.c:837 msgid "Previous colour B" msgstr "" #: src/mainwindow.c:839 msgid "Next colour B" msgstr "" #: src/mainwindow.c:841 msgid "Previous pattern" msgstr "" #: src/mainwindow.c:843 msgid "Next pattern" msgstr "" #: src/mainwindow.c:845 msgid "Larger brush" msgstr "" #: src/mainwindow.c:847 msgid "Smaller brush" msgstr "" #: src/mainwindow.c:849 msgid "View window - Zoom in" msgstr "" #: src/mainwindow.c:851 msgid "View window - Zoom out" msgstr "" #: src/mainwindow.c:1027 msgid "" "This canvas/palette contains changes that have not been saved. Do you " "really want to lose these changes?" msgstr "" #: src/mainwindow.c:1094 msgid "Do you really want to quit?" msgstr "Deseja mesmo sair?" #: src/mainwindow.c:3754 msgid "Empty string or broken quoting" msgstr "" #: src/mainwindow.c:3755 msgid "Script must begin with a command" msgstr "" #: src/mainwindow.c:3756 msgid "Script nesting limit exceeded" msgstr "" #: src/mainwindow.c:3765 #, c-format msgid "'%s' does not match any item" msgstr "" #: src/mainwindow.c:3767 #, c-format msgid "'%s' matches a non-scriptable item" msgstr "" #: src/mainwindow.c:3769 #, c-format msgid "'%s' matches a disabled item" msgstr "" #: src/mainwindow.c:3788 #, c-format msgid "'%s' value does not fit item" msgstr "" #: src/mainwindow.c:3969 msgid "Script" msgstr "" #: src/mainwindow.c:3982 src/spawn.c:656 src/spawn.c:662 msgid "Action" msgstr "" #: src/mainwindow.c:3991 src/spawn.c:666 msgid "Execute" msgstr "" #: src/mainwindow.c:4045 msgid "Unable to load script" msgstr "" #: src/mainwindow.c:5182 msgid "/_File" msgstr "/_Ficheiro" #: src/mainwindow.c:5184 msgid "//New" msgstr "//Novo" #: src/mainwindow.c:5186 msgid "//Open ..." msgstr "//Abrir ..." #: src/mainwindow.c:5188 src/mainwindow.c:5669 msgid "//Save" msgstr "//Gravar" #: src/mainwindow.c:5190 src/mainwindow.c:5549 src/mainwindow.c:5627 #: src/mainwindow.c:5671 msgid "//Save As ..." msgstr "//Gravar Como ..." #: src/mainwindow.c:5192 msgid "//Export Undo Images ..." msgstr "" #: src/mainwindow.c:5194 msgid "//Export Undo Images (reversed) ..." msgstr "" #: src/mainwindow.c:5196 msgid "//Export ASCII Art ..." msgstr "//Exportar Arte ASCII ..." #: src/mainwindow.c:5198 msgid "//Export Animated GIF ..." msgstr "" #: src/mainwindow.c:5201 msgid "//Actions" msgstr "" #: src/mainwindow.c:5235 src/mainwindow.c:5488 msgid "///Configure" msgstr "" #: src/mainwindow.c:5290 msgid "//Quit" msgstr "//Sair" #: src/mainwindow.c:5293 msgid "/_Edit" msgstr "/_Editar" #: src/mainwindow.c:5295 msgid "//Undo" msgstr "" #: src/mainwindow.c:5297 msgid "//Redo" msgstr "" #: src/mainwindow.c:5300 msgid "//Cut" msgstr "" #: src/mainwindow.c:5302 msgid "//Copy" msgstr "" #: src/mainwindow.c:5304 msgid "//Copy To Palette" msgstr "" #: src/mainwindow.c:5306 msgid "//Paste To Centre" msgstr "" #: src/mainwindow.c:5308 msgid "//Paste To New Layer" msgstr "//Colar Em Nova Camada" #: src/mainwindow.c:5310 msgid "//Paste" msgstr "//Colar" #: src/mainwindow.c:5312 msgid "//Paste Text" msgstr "//Colar Texto" #: src/mainwindow.c:5318 msgid "//Paste Text (FreeType)" msgstr "" #: src/mainwindow.c:5321 msgid "//Paste Palette" msgstr "" #: src/mainwindow.c:5323 msgid "//Load Clipboard" msgstr "" #: src/mainwindow.c:5350 msgid "//Save Clipboard" msgstr "" #: src/mainwindow.c:5377 msgid "//Import Clipboard from System" msgstr "" #: src/mainwindow.c:5378 msgid "//Export Clipboard to System" msgstr "" #: src/mainwindow.c:5381 msgid "//Choose Pattern ..." msgstr "" #: src/mainwindow.c:5383 msgid "//Choose Brush ..." msgstr "" #: src/mainwindow.c:5385 msgid "//Choose Colour ..." msgstr "" #: src/mainwindow.c:5392 msgid "/_View" msgstr "" #: src/mainwindow.c:5394 msgid "//Show Main Toolbar" msgstr "" #: src/mainwindow.c:5396 msgid "//Show Tools Toolbar" msgstr "" #: src/mainwindow.c:5399 msgid "//Show Settings Toolbar" msgstr "" #: src/mainwindow.c:5402 msgid "//Show Dock" msgstr "" #: src/mainwindow.c:5404 msgid "//Show Palette" msgstr "" #: src/mainwindow.c:5406 msgid "//Show Status Bar" msgstr "" #: src/mainwindow.c:5409 msgid "//Toggle Image View" msgstr "" #: src/mainwindow.c:5413 msgid "//Centralize Image" msgstr "" #: src/mainwindow.c:5414 msgid "//Show Zoom Grid" msgstr "" #: src/mainwindow.c:5415 msgid "//Snap To Tile Grid" msgstr "" #: src/mainwindow.c:5417 msgid "//Configure Grid ..." msgstr "" #: src/mainwindow.c:5418 msgid "//Tracing Image ..." msgstr "" #: src/mainwindow.c:5421 msgid "//View Window" msgstr "" #: src/mainwindow.c:5423 msgid "//Horizontal Split" msgstr "" #: src/mainwindow.c:5425 msgid "//Focus View Window" msgstr "" #: src/mainwindow.c:5427 msgid "//Pan Window" msgstr "" #: src/mainwindow.c:5430 msgid "//Layers Window" msgstr "" #: src/mainwindow.c:5433 msgid "/_Image" msgstr "" #: src/mainwindow.c:5436 msgid "//Convert To RGB" msgstr "" #: src/mainwindow.c:5438 msgid "//Convert To Indexed ..." msgstr "" #: src/mainwindow.c:5441 msgid "//Scale Canvas ..." msgstr "" #: src/mainwindow.c:5443 msgid "//Resize Canvas ..." msgstr "" #: src/mainwindow.c:5445 msgid "//Crop" msgstr "" #: src/mainwindow.c:5448 src/mainwindow.c:5517 msgid "//Flip Vertically" msgstr "" #: src/mainwindow.c:5449 src/mainwindow.c:5519 msgid "//Flip Horizontally" msgstr "" #: src/mainwindow.c:5452 src/mainwindow.c:5521 msgid "//Rotate Clockwise" msgstr "" #: src/mainwindow.c:5453 src/mainwindow.c:5523 msgid "//Rotate Anti-Clockwise" msgstr "" #: src/mainwindow.c:5454 msgid "//Free Rotate ..." msgstr "" #: src/mainwindow.c:5455 msgid "//Skew ..." msgstr "" #: src/mainwindow.c:5458 msgid "//Segment ..." msgstr "" #: src/mainwindow.c:5462 msgid "//Script ..." msgstr "" #: src/mainwindow.c:5464 msgid "//Scripts" msgstr "" #: src/mainwindow.c:5491 msgid "//Information ..." msgstr "" #: src/mainwindow.c:5494 msgid "//Preferences ..." msgstr "" #: src/mainwindow.c:5497 msgid "/_Selection" msgstr "" #: src/mainwindow.c:5499 msgid "//Select All" msgstr "" #: src/mainwindow.c:5501 msgid "//Select None (Esc)" msgstr "" #: src/mainwindow.c:5503 msgid "//Lasso Selection" msgstr "" #: src/mainwindow.c:5505 msgid "//Lasso Selection Cut" msgstr "" #: src/mainwindow.c:5508 msgid "//Outline Selection" msgstr "" #: src/mainwindow.c:5510 msgid "//Fill Selection" msgstr "" #: src/mainwindow.c:5512 msgid "//Outline Ellipse" msgstr "" #: src/mainwindow.c:5514 msgid "//Fill Ellipse" msgstr "" #: src/mainwindow.c:5526 msgid "//Horizontal Ramp" msgstr "" #: src/mainwindow.c:5528 msgid "//Vertical Ramp" msgstr "" #: src/mainwindow.c:5531 msgid "//Alpha Blend A,B" msgstr "" #: src/mainwindow.c:5533 msgid "//Move Alpha to Mask" msgstr "" #: src/mainwindow.c:5535 msgid "//Mask Colour A,B" msgstr "" #: src/mainwindow.c:5537 msgid "//Unmask Colour A,B" msgstr "" #: src/mainwindow.c:5539 msgid "//Mask All Colours" msgstr "" #: src/mainwindow.c:5541 msgid "//Clear Mask" msgstr "" #: src/mainwindow.c:5544 msgid "/_Palette" msgstr "" #: src/mainwindow.c:5548 src/mainwindow.c:5626 msgid "//Load ..." msgstr "" #: src/mainwindow.c:5550 msgid "//Load Default" msgstr "" #: src/mainwindow.c:5552 msgid "//Mask All" msgstr "" #: src/mainwindow.c:5553 msgid "//Mask None" msgstr "" #: src/mainwindow.c:5555 msgid "//Swap A & B" msgstr "" #: src/mainwindow.c:5557 msgid "//Edit Colour A & B ..." msgstr "" #: src/mainwindow.c:5559 msgid "//Dither A" msgstr "" #: src/mainwindow.c:5561 msgid "//Palette Editor ..." msgstr "" #: src/mainwindow.c:5563 msgid "//Set Palette Size ..." msgstr "" #: src/mainwindow.c:5564 msgid "//Merge Duplicate Colours" msgstr "" #: src/mainwindow.c:5566 msgid "//Remove Unused Colours" msgstr "" #: src/mainwindow.c:5569 msgid "//Create Quantized ..." msgstr "" #: src/mainwindow.c:5572 msgid "//Sort Colours ..." msgstr "" #: src/mainwindow.c:5573 msgid "//Palette Shifter ..." msgstr "" #: src/mainwindow.c:5574 msgid "//Pick Gradient ..." msgstr "" #: src/mainwindow.c:5576 msgid "/Effe_cts" msgstr "" #: src/mainwindow.c:5578 msgid "//Transform Colour ..." msgstr "" #: src/mainwindow.c:5580 msgid "//Invert" msgstr "" #: src/mainwindow.c:5582 msgid "//Greyscale" msgstr "" #: src/mainwindow.c:5584 msgid "//Greyscale (Gamma corrected)" msgstr "" #: src/mainwindow.c:5586 msgid "//Normalize" msgstr "" #: src/mainwindow.c:5587 src/mainwindow.c:5658 msgid "//Threshold ..." msgstr "" #: src/mainwindow.c:5588 msgid "//Map ..." msgstr "" #: src/mainwindow.c:5590 msgid "//Isometric Transformation" msgstr "" #: src/mainwindow.c:5592 msgid "///Left Side Down" msgstr "" #: src/mainwindow.c:5593 msgid "///Right Side Down" msgstr "" #: src/mainwindow.c:5594 msgid "///Top Side Right" msgstr "" #: src/mainwindow.c:5595 msgid "///Bottom Side Right" msgstr "" #: src/mainwindow.c:5598 msgid "//Edge Detect ..." msgstr "" #: src/mainwindow.c:5600 msgid "//Difference of Gaussians ..." msgstr "" #: src/mainwindow.c:5602 msgid "//Sharpen ..." msgstr "" #: src/mainwindow.c:5604 msgid "//Unsharp Mask ..." msgstr "" #: src/mainwindow.c:5606 msgid "//Soften ..." msgstr "" #: src/mainwindow.c:5608 msgid "//Gaussian Blur ..." msgstr "" #: src/mainwindow.c:5610 msgid "//Kuwahara-Nagao Blur ..." msgstr "" #: src/mainwindow.c:5612 msgid "//Emboss" msgstr "" #: src/mainwindow.c:5614 msgid "//Dilate" msgstr "" #: src/mainwindow.c:5616 msgid "//Erode" msgstr "" #: src/mainwindow.c:5619 msgid "//Solid Noise ..." msgstr "" #: src/mainwindow.c:5620 msgid "//Bacteria ..." msgstr "" #: src/mainwindow.c:5623 msgid "/Cha_nnels" msgstr "" #: src/mainwindow.c:5625 msgid "//New ..." msgstr "" #: src/mainwindow.c:5628 msgid "//Delete ..." msgstr "" #: src/mainwindow.c:5632 msgid "//Edit Image" msgstr "" #: src/mainwindow.c:5635 msgid "//Edit Alpha" msgstr "" #: src/mainwindow.c:5638 msgid "//Edit Selection" msgstr "" #: src/mainwindow.c:5641 msgid "//Edit Mask" msgstr "" #: src/mainwindow.c:5645 msgid "//Hide Image" msgstr "" #: src/mainwindow.c:5648 msgid "//Disable Alpha" msgstr "" #: src/mainwindow.c:5651 msgid "//Disable Selection" msgstr "" #: src/mainwindow.c:5654 msgid "//Disable Mask" msgstr "" #: src/mainwindow.c:5657 msgid "//Couple RGBA Operations" msgstr "" #: src/mainwindow.c:5659 msgid "//Unassociate Alpha" msgstr "" #: src/mainwindow.c:5663 msgid "//View Alpha as an Overlay" msgstr "" #: src/mainwindow.c:5664 msgid "//Configure Overlays ..." msgstr "" #: src/mainwindow.c:5666 msgid "/_Layers" msgstr "" #: src/mainwindow.c:5668 msgid "//New Layer" msgstr "" #: src/mainwindow.c:5672 msgid "//Save Composite Image ..." msgstr "" #: src/mainwindow.c:5673 msgid "//Composite to New Layer" msgstr "" #: src/mainwindow.c:5674 msgid "//Remove All Layers" msgstr "" #: src/mainwindow.c:5676 msgid "//Configure Animation ..." msgstr "" #: src/mainwindow.c:5677 msgid "//Preview Animation ..." msgstr "" #: src/mainwindow.c:5678 msgid "//Set Key Frame ..." msgstr "" #: src/mainwindow.c:5679 msgid "//Remove All Key Frames ..." msgstr "" #: src/mainwindow.c:5681 msgid "/More..." msgstr "" #: src/mainwindow.c:5683 msgid "/_Help" msgstr "/_Ajuda" #: src/mainwindow.c:5684 msgid "//Documentation" msgstr "" #: src/mainwindow.c:5686 msgid "//About" msgstr "" #: src/mainwindow.c:5689 msgid "//Keyboard Shortcuts ..." msgstr "" #: src/mainwindow.c:5690 msgid "//Rebind Shortcut Keycodes" msgstr "" #: src/memory.c:2800 msgid "Quantize Pass 1" msgstr "" #: src/memory.c:2854 msgid "Quantize Pass 2" msgstr "" #: src/memory.c:3073 src/memory.c:3458 msgid "Converting to Indexed Palette" msgstr "A converter para Paleta Indexada" #: src/memory.c:5135 src/otherwindow.c:540 msgid "Bacteria Effect" msgstr "" #: src/memory.c:5170 msgid "Rotating" msgstr "" #: src/memory.c:5511 msgid "Free Rotation" msgstr "" #: src/memory.c:6096 msgid "Scaling Image" msgstr "" #: src/memory.c:7560 msgid "Counting Unique RGB Pixels" msgstr "" #: src/memory.c:7608 msgid "Applying Effect" msgstr "A Aplicar Efeito" #: src/memory.c:8792 msgid "Kuwahara-Nagao Filter" msgstr "" #: src/memory.c:10456 src/otherwindow.c:2665 msgid "Skew" msgstr "" #: src/memory.c:10630 msgid "Segmentation Pass 1" msgstr "" #: src/memory.c:10757 msgid "Segmentation Pass 2" msgstr "" #: src/memory.c:11019 src/otherwindow.c:3156 msgid "Solid Noise" msgstr "" #: src/mygtk.c:134 src/mygtk.c:163 msgid "Please Wait ..." msgstr "Por Favor Espere ..." #: src/mygtk.c:141 msgid "STOP" msgstr "STOP" #: src/mygtk.c:504 msgid "Disabled" msgstr "" #: src/mygtk.c:504 src/toolbar.c:301 msgid "Screen" msgstr "Ecrã" #: src/mygtk.c:504 msgid "Window" msgstr "" #: src/mygtk.c:508 msgid "Input" msgstr "" #: src/mygtk.c:512 msgid "Device:" msgstr "" #: src/mygtk.c:514 msgid "Mode:" msgstr "" #: src/mygtk.c:519 msgid "Axes" msgstr "" #: src/mygtk.c:524 msgid "X:" msgstr "" #: src/mygtk.c:525 msgid "Y:" msgstr "" #: src/mygtk.c:526 msgid "Pressure:" msgstr "" #: src/mygtk.c:527 msgid "X tilt:" msgstr "" #: src/mygtk.c:528 msgid "Y tilt:" msgstr "" #: src/mygtk.c:529 msgid "Wheel:" msgstr "" #: src/mygtk.c:579 msgid "none" msgstr "" #: src/otherwindow.c:236 msgid "24 bit RGB" msgstr "" #: src/otherwindow.c:236 src/otherwindow.c:3179 msgid "Greyscale" msgstr "Escala de Cinzentos" #: src/otherwindow.c:237 msgid "Indexed Palette" msgstr "Paleta Indexada" #: src/otherwindow.c:237 msgid "From Clipboard" msgstr "" #: src/otherwindow.c:237 msgid "Grab Screenshot" msgstr "" #: src/otherwindow.c:242 src/toolbar.c:542 msgid "New Image" msgstr "Nova Imagem" #: src/otherwindow.c:246 src/otherwindow.c:3164 msgid "Colours" msgstr "Cores" #: src/otherwindow.c:409 msgid "Pattern Chooser" msgstr "Selector de Padrões" #: src/otherwindow.c:497 msgid "Set Palette Size" msgstr "Ajustar Tamanho da Paleta" #: src/otherwindow.c:517 src/otherwindow.c:591 src/otherwindow.c:870 #: src/otherwindow.c:2538 src/otherwindow.c:2776 src/otherwindow.c:2939 #: src/prefs.c:338 src/prefs.c:538 msgid "Apply" msgstr "Aplicar" #: src/otherwindow.c:573 msgid "Luminance" msgstr "Luminância" #: src/otherwindow.c:573 src/otherwindow.c:814 msgid "Brightness" msgstr "Luminosidade" #: src/otherwindow.c:574 msgid "Distance to A" msgstr "" #: src/otherwindow.c:575 msgid "Projection to A->B" msgstr "" #: src/otherwindow.c:576 msgid "Frequency" msgstr "Frequência" #: src/otherwindow.c:580 msgid "Sort Palette Colours" msgstr "Ordenar Cores da Paleta" #: src/otherwindow.c:582 msgid "Start Index" msgstr "Ãndice Inicial" #: src/otherwindow.c:583 msgid "End Index" msgstr "Ãndice Final" #: src/otherwindow.c:589 msgid "Reverse Order" msgstr "Ordem Inversa" #: src/otherwindow.c:805 msgid "Bitwise" msgstr "" #: src/otherwindow.c:805 msgid "Truncated" msgstr "" #: src/otherwindow.c:805 msgid "Rounded" msgstr "" #: src/otherwindow.c:809 src/toolbar.c:311 src/toolbar.c:558 msgid "Transform Colour" msgstr "Transformar Cor" #: src/otherwindow.c:812 msgid "Gamma" msgstr "" #: src/otherwindow.c:816 msgid "Contrast" msgstr "Contraste" #: src/otherwindow.c:822 src/otherwindow.c:1674 msgid "Posterize" msgstr "" #: src/otherwindow.c:831 msgid "Show Detail" msgstr "" #: src/otherwindow.c:836 msgid "Posterize type" msgstr "" #: src/otherwindow.c:857 msgid "Auto-Preview" msgstr "Auto-Previsualização" #: src/otherwindow.c:869 msgid "Reset" msgstr "" #: src/otherwindow.c:931 msgid "New geometry is the same as now - nothing to do." msgstr "" #: src/otherwindow.c:980 msgid "The operating system cannot allocate the memory for this operation." msgstr "" #: src/otherwindow.c:982 msgid "" "You have not allocated enough memory in the Preferences window for this " "operation." msgstr "" #: src/otherwindow.c:993 src/otherwindow.c:2495 msgid "Mirror" msgstr "" #: src/otherwindow.c:993 src/otherwindow.c:994 msgid "Tile" msgstr "" #: src/otherwindow.c:993 msgid "Void" msgstr "" #: src/otherwindow.c:994 src/shifter.c:283 msgid "Clear" msgstr "" #: src/otherwindow.c:994 msgid "Mirror tile" msgstr "" #: src/otherwindow.c:996 msgid "Nearest Neighbour" msgstr "" #: src/otherwindow.c:997 msgid "Bilinear / Area Mapping" msgstr "" #: src/otherwindow.c:998 msgid "Bicubic" msgstr "" #: src/otherwindow.c:999 msgid "Bicubic edged" msgstr "" #: src/otherwindow.c:1000 msgid "Bicubic better" msgstr "" #: src/otherwindow.c:1001 msgid "Bicubic sharper" msgstr "" #: src/otherwindow.c:1002 msgid "Blackman-Harris" msgstr "" #: src/otherwindow.c:1008 msgid "Scale Canvas" msgstr "" #: src/otherwindow.c:1009 msgid "Resize Canvas" msgstr "Redimensionar Tela" #: src/otherwindow.c:1012 msgid "Original " msgstr "Original " #: src/otherwindow.c:1013 msgid "New" msgstr "Novo" #: src/otherwindow.c:1014 msgid "Width " msgstr "Largura " #: src/otherwindow.c:1018 msgid "Height " msgstr "Altura " #: src/otherwindow.c:1023 src/otherwindow.c:2514 src/otherwindow.c:2672 #: src/toolbar.c:212 msgid "Offset" msgstr "Deslocamento" #: src/otherwindow.c:1026 src/otherwindow.c:1615 src/viewer.c:1209 msgid "Centre" msgstr "Centro" #: src/otherwindow.c:1033 src/otherwindow.c:1052 msgid "Fix Aspect Ratio" msgstr "" #: src/otherwindow.c:1039 src/otherwindow.c:2070 src/toolbar.c:312 msgid "Settings" msgstr "" #: src/otherwindow.c:1046 msgid "Sharper image reduction" msgstr "" #: src/otherwindow.c:1047 msgid "Boundary extension" msgstr "" #: src/otherwindow.c:1613 src/otherwindow.c:2302 msgid "HSV" msgstr "" #: src/otherwindow.c:1614 msgid "Highlight" msgstr "" #: src/otherwindow.c:1615 msgid "Limit" msgstr "" #: src/otherwindow.c:1616 msgid "Sphere" msgstr "" #: src/otherwindow.c:1616 src/otherwindow.c:2670 msgid "Angle" msgstr "" #: src/otherwindow.c:1616 msgid "Cube" msgstr "" #: src/otherwindow.c:1617 msgid "Opaque" msgstr "" #: src/otherwindow.c:1617 msgid "Border" msgstr "" #: src/otherwindow.c:1618 msgid "Transparent" msgstr "" #: src/otherwindow.c:1618 msgid "Tile " msgstr "" #: src/otherwindow.c:1618 msgid "Segment" msgstr "" #: src/otherwindow.c:1656 msgid "Scale" msgstr "" #: src/otherwindow.c:1657 src/otherwindow.c:3059 msgid "From" msgstr "" #: src/otherwindow.c:1659 src/otherwindow.c:3061 msgid "To" msgstr "" #: src/otherwindow.c:1699 msgid "Range" msgstr "" #: src/otherwindow.c:1702 msgid "Inverse" msgstr "" #: src/otherwindow.c:1710 msgid "Smart grid" msgstr "" #: src/otherwindow.c:1712 msgid "Tile grid" msgstr "" #: src/otherwindow.c:1714 msgid "Minimum grid zoom" msgstr "" #: src/otherwindow.c:1717 msgid "Tile width" msgstr "" #: src/otherwindow.c:1720 msgid "Tile height" msgstr "" #: src/otherwindow.c:1744 msgid "Palette Editor" msgstr "" #: src/otherwindow.c:1763 msgid "Configure Overlays" msgstr "" #: src/otherwindow.c:1782 msgid "Colour Editor" msgstr "" #: src/otherwindow.c:1818 src/toolbar.c:430 msgid "Colour-Selective Mode" msgstr "" #: src/otherwindow.c:1843 msgid "Configure Grid" msgstr "" #: src/otherwindow.c:2045 msgid "Exact Conversion" msgstr "Conversão Exacta" #: src/otherwindow.c:2045 msgid "Use Current Palette" msgstr "" #: src/otherwindow.c:2046 msgid "PNN Quantize (slow, better quality)" msgstr "" #: src/otherwindow.c:2047 msgid "Wu Quantize (fast)" msgstr "" #: src/otherwindow.c:2048 msgid "Max-Min Quantize (best for small palettes and dithering)" msgstr "" #: src/otherwindow.c:2049 src/otherwindow.c:2495 src/otherwindow.c:2756 #: src/png.c:2794 src/prefs.c:377 msgid "None" msgstr "" #: src/otherwindow.c:2049 msgid "Floyd-Steinberg" msgstr "Floyd-Steinberg" #: src/otherwindow.c:2049 msgid "Stucki" msgstr "" #: src/otherwindow.c:2052 msgid "Floyd-Steinberg (quick)" msgstr "" #: src/otherwindow.c:2052 msgid "Dithered (effect)" msgstr "" #: src/otherwindow.c:2053 msgid "Scattered (effect)" msgstr "" #: src/otherwindow.c:2054 msgid "Gamut" msgstr "" #: src/otherwindow.c:2054 msgid "Weakly" msgstr "" #: src/otherwindow.c:2054 msgid "Strongly" msgstr "" #: src/otherwindow.c:2055 msgid "Off" msgstr "" #: src/otherwindow.c:2055 msgid "Separate/Sum" msgstr "" #: src/otherwindow.c:2055 msgid "Separate/Split" msgstr "" #: src/otherwindow.c:2056 msgid "Length/Sum" msgstr "" #: src/otherwindow.c:2056 msgid "Length/Split" msgstr "" #: src/otherwindow.c:2057 msgid "Largest (Linf)" msgstr "" #: src/otherwindow.c:2057 msgid "Sum (L1)" msgstr "" #: src/otherwindow.c:2057 msgid "Euclidean (L2)" msgstr "" #: src/otherwindow.c:2061 msgid "Create Quantized" msgstr "" #: src/otherwindow.c:2062 msgid "Convert To Indexed" msgstr "Converter Para Indexado" #: src/otherwindow.c:2065 msgid "Indexed Colours To Use" msgstr "Cores Indexadas A Usar" #: src/otherwindow.c:2078 msgid "Truncate palette" msgstr "" #: src/otherwindow.c:2079 msgid "Diameter based weighting" msgstr "" #: src/otherwindow.c:2084 msgid "Dither" msgstr "" #: src/otherwindow.c:2087 src/otherwindow.c:2584 src/otherwindow.c:2928 msgid "Colour space" msgstr "" #: src/otherwindow.c:2088 src/otherwindow.c:2929 msgid "Difference measure" msgstr "" #: src/otherwindow.c:2089 msgid "Reduce colour bleed" msgstr "" #: src/otherwindow.c:2090 msgid "Serpentine scan" msgstr "" #: src/otherwindow.c:2092 msgid "Error propagation, %" msgstr "" #: src/otherwindow.c:2093 msgid "Selective error propagation" msgstr "" #: src/otherwindow.c:2097 msgid "Full error precision" msgstr "" #: src/otherwindow.c:2302 msgid "Backward HSV" msgstr "" #: src/otherwindow.c:2303 src/otherwindow.c:2326 msgid "Constant" msgstr "" #: src/otherwindow.c:2307 msgid "Edit Gradient" msgstr "" #: src/otherwindow.c:2329 msgid "Points:" msgstr "" #: src/otherwindow.c:2493 msgid "Linear" msgstr "" #: src/otherwindow.c:2493 src/otherwindow.c:2703 msgid "Bilinear" msgstr "" #: src/otherwindow.c:2493 msgid "Radial" msgstr "" #: src/otherwindow.c:2494 msgid "Square" msgstr "" #: src/otherwindow.c:2494 msgid "Angular" msgstr "" #: src/otherwindow.c:2494 msgid "Conical" msgstr "" #: src/otherwindow.c:2495 msgid "Level " msgstr "" #: src/otherwindow.c:2495 msgid "Repeat" msgstr "" #: src/otherwindow.c:2496 msgid "A to B" msgstr "" #: src/otherwindow.c:2496 msgid "A to B (RGB)" msgstr "" #: src/otherwindow.c:2497 msgid "A to B (sRGB)" msgstr "" #: src/otherwindow.c:2497 msgid "A to B (HSV)" msgstr "" #: src/otherwindow.c:2497 msgid "A to B (backward HSV)" msgstr "" #: src/otherwindow.c:2498 msgid "A only" msgstr "" #: src/otherwindow.c:2498 src/otherwindow.c:2500 msgid "Custom" msgstr "" #: src/otherwindow.c:2499 msgid "Current to 0" msgstr "" #: src/otherwindow.c:2499 msgid "Current only" msgstr "" #: src/otherwindow.c:2504 msgid "Configure Gradient" msgstr "" #: src/otherwindow.c:2507 src/png.c:1001 msgid "Channel" msgstr "" #: src/otherwindow.c:2512 msgid "Length" msgstr "" #: src/otherwindow.c:2513 msgid "Repeat length" msgstr "" #: src/otherwindow.c:2515 msgid "Gradient type" msgstr "" #: src/otherwindow.c:2516 msgid "Extension type" msgstr "" #: src/otherwindow.c:2517 msgid "Distance type" msgstr "" #: src/otherwindow.c:2518 msgid "Preview opacity" msgstr "" #: src/otherwindow.c:2527 src/otherwindow.c:2533 src/toolbar.c:309 msgid "Reverse" msgstr "" #: src/otherwindow.c:2528 src/otherwindow.c:2534 msgid "Edit Custom" msgstr "" #: src/otherwindow.c:2592 msgid "Pick Gradient" msgstr "" #: src/otherwindow.c:2668 msgid "Horizontal " msgstr "" #: src/otherwindow.c:2674 msgid "At distance" msgstr "" #: src/otherwindow.c:2675 msgid "Vertical" msgstr "" #: src/otherwindow.c:2756 msgid "Unchanged" msgstr "" #: src/otherwindow.c:2761 msgid "Tracing Image" msgstr "" #: src/otherwindow.c:2763 src/toolbar.c:315 msgid "Source" msgstr "" #: src/otherwindow.c:2768 msgid "Origin" msgstr "" #: src/otherwindow.c:2771 msgid "Relative scale" msgstr "" #: src/otherwindow.c:2774 msgid "Display" msgstr "" #: src/otherwindow.c:2926 msgid "Segment Image" msgstr "" #: src/otherwindow.c:2931 src/toolbar.c:304 msgid "Threshold" msgstr "" #: src/otherwindow.c:2933 msgid "Level" msgstr "" #: src/otherwindow.c:2934 msgid "Minimum size" msgstr "" #: src/otherwindow.c:3053 msgid "Max" msgstr "" #: src/otherwindow.c:3053 msgid "Min" msgstr "" #: src/otherwindow.c:3057 msgid "Threshold Image" msgstr "" #: src/otherwindow.c:3158 msgid "Seed" msgstr "" #: src/otherwindow.c:3160 msgid "X span" msgstr "" #: src/otherwindow.c:3161 msgid "Y span" msgstr "" #: src/otherwindow.c:3162 msgid "Octaves" msgstr "" #: src/png.c:620 #, c-format msgid "Saving %s image" msgstr "" #: src/png.c:620 #, c-format msgid "Loading %s image" msgstr "" #: src/png.c:998 msgid "Layer" msgstr "Camada" #: src/png.c:3577 msgid "Lossless" msgstr "" #: src/png.c:3577 msgid "Default" msgstr "" #: src/png.c:3577 msgid "Picture" msgstr "" #: src/png.c:3577 msgid "Photo" msgstr "" #: src/png.c:3578 msgid "Drawing" msgstr "" #: src/png.c:3578 msgid "Icon" msgstr "" #: src/png.c:8370 msgid "Applying colour profile" msgstr "" #: src/png.c:8792 #, c-format msgid "%d out of %d frames could not be saved as %s - saved as PNG instead" msgstr "" #: src/png.c:8809 msgid "Explode frames" msgstr "" #: src/prefs.c:56 msgid "Default System Language" msgstr "Linguagem por Omissão do Sistema" #: src/prefs.c:57 msgid "Chinese (Simplified)" msgstr "" #: src/prefs.c:57 msgid "Chinese (Taiwanese)" msgstr "" #: src/prefs.c:57 msgid "Czech" msgstr "Checo" #: src/prefs.c:58 msgid "Dutch" msgstr "" #: src/prefs.c:58 msgid "English (UK)" msgstr "Inglês (UK)" #: src/prefs.c:58 msgid "French" msgstr "Francês" #: src/prefs.c:58 msgid "Galician" msgstr "" #: src/prefs.c:58 msgid "German" msgstr "" #: src/prefs.c:59 msgid "Hungarian" msgstr "" #: src/prefs.c:59 msgid "Italian" msgstr "" #: src/prefs.c:59 msgid "Japanese" msgstr "" #: src/prefs.c:59 msgid "Kabyle" msgstr "" #: src/prefs.c:59 msgid "Polish" msgstr "" #: src/prefs.c:60 msgid "Portuguese" msgstr "Português" #: src/prefs.c:60 msgid "Portuguese (Brazilian)" msgstr "Português (Brasileiro)" #: src/prefs.c:60 msgid "Russian" msgstr "" #: src/prefs.c:60 msgid "Slovak" msgstr "" #: src/prefs.c:61 msgid "Spanish" msgstr "Espanhol" #: src/prefs.c:61 msgid "Swedish" msgstr "" #: src/prefs.c:61 msgid "Tagalog" msgstr "" #: src/prefs.c:61 msgid "Turkish" msgstr "" #: src/prefs.c:81 msgid "Current Device" msgstr "" #: src/prefs.c:135 msgid "Pressure" msgstr "" #: src/prefs.c:149 msgid "Preferences" msgstr "Preferências" #: src/prefs.c:163 msgid "Max threads (0 to autodetect)" msgstr "" #: src/prefs.c:164 msgid "Min kpixels per render thread" msgstr "" #: src/prefs.c:171 msgid "Max memory used for undo (MB)" msgstr "" #: src/prefs.c:172 msgid "Max undo levels" msgstr "" #: src/prefs.c:173 msgid "Communal layer undo space (%)" msgstr "" #: src/prefs.c:175 msgid "Bayer master pattern" msgstr "" #: src/prefs.c:178 msgid "Use gamma correction by default" msgstr "" #: src/prefs.c:179 msgid "Use gamma correction when painting" msgstr "" #: src/prefs.c:180 msgid "Separate patterns for A & B" msgstr "" #: src/prefs.c:183 msgid "Optimize alpha chequers" msgstr "" #: src/prefs.c:184 msgid "Disable view window transparencies" msgstr "" #: src/prefs.c:185 msgid "Enable overlays by layer" msgstr "" #: src/prefs.c:189 msgid "Language" msgstr "Língua" #: src/prefs.c:191 msgid "" "Select preferred language translation\n" "\n" "You will need to restart mtPaint\n" "for this to take full effect" msgstr "" "Seleccionar língua de tradução preferida\n" "\n" "Terá de reiniciar o mtPaint\n" "para que tome efeito" #: src/prefs.c:198 msgid "Interface" msgstr "" #: src/prefs.c:200 msgid "Greyscale backdrop" msgstr "" #: src/prefs.c:201 msgid "Selection nudge pixels" msgstr "" #: src/prefs.c:202 msgid "Max Pan Window Size" msgstr "" #: src/prefs.c:204 msgid "Display clipboard while pasting" msgstr "" #: src/prefs.c:205 msgid "Mouse cursor = Tool" msgstr "" #: src/prefs.c:206 msgid "Confirm Exit" msgstr "Comfirmar Saída" #: src/prefs.c:207 msgid "Q key quits mtPaint" msgstr "" #: src/prefs.c:208 msgid "Arrow keys scroll canvas" msgstr "" #: src/prefs.c:209 msgid "Changing tool commits paste" msgstr "" #: src/prefs.c:210 msgid "Centre tool settings dialogs" msgstr "" #: src/prefs.c:211 msgid "New image sets zoom to 100%" msgstr "" #: src/prefs.c:212 msgid "Zoom on cursor position" msgstr "" #: src/prefs.c:214 msgid "Mouse Scroll Wheel = Zoom" msgstr "" #: src/prefs.c:215 msgid "Use menu icons" msgstr "" #: src/prefs.c:220 msgid "Files" msgstr "Ficheiros" #: src/prefs.c:223 msgid "XBM X hotspot" msgstr "" #: src/prefs.c:224 msgid "XBM Y hotspot" msgstr "" #: src/prefs.c:228 msgid "Recently Used Files" msgstr "Ficheiros Usados Recentemente" #: src/prefs.c:229 msgid "Progress bar silence limit" msgstr "" #: src/prefs.c:232 msgid "Read 16-bit TGAs as 5:6:5 BGR" msgstr "" #: src/prefs.c:233 msgid "Write TGAs in bottom-up row order" msgstr "" #: src/prefs.c:234 msgid "Undoable image loading" msgstr "" #: src/prefs.c:245 msgid "Compression (RGB)" msgstr "" #: src/prefs.c:246 msgid "Compression (indexed)" msgstr "" #: src/prefs.c:247 msgid "Compression (monochrome)" msgstr "" #: src/prefs.c:255 msgid "Enable predictor" msgstr "" #: src/prefs.c:262 msgid "Compression mode" msgstr "" #: src/prefs.c:271 msgid "Channel for Mask Plane" msgstr "" #: src/prefs.c:273 msgid "Ignore Transparent Colour" msgstr "" #: src/prefs.c:274 msgid "PackBits Compression" msgstr "" #: src/prefs.c:275 msgid "Write Indexed as Planar Bitmap (PBM)" msgstr "" #: src/prefs.c:280 msgid "Paths" msgstr "" #: src/prefs.c:281 msgid "Clipboard Files" msgstr "" #: src/prefs.c:281 msgid "Select Clipboard File" msgstr "Seleccionar Ficheiro de Clipboard" #: src/prefs.c:283 msgid "HTML Browser Program" msgstr "" #: src/prefs.c:283 msgid "Select Browser Program" msgstr "" #: src/prefs.c:285 msgid "Location of Handbook index" msgstr "" #: src/prefs.c:285 msgid "Select Handbook Index File" msgstr "" #: src/prefs.c:287 msgid "Default Palette" msgstr "" #: src/prefs.c:287 msgid "Select Default Palette" msgstr "" #: src/prefs.c:289 msgid "Default Patterns" msgstr "" #: src/prefs.c:289 msgid "Select Default Patterns File" msgstr "" #: src/prefs.c:292 msgid "Default CSS" msgstr "" #: src/prefs.c:292 msgid "Select Default CSS File" msgstr "" #: src/prefs.c:295 msgid "Default Theme" msgstr "" #: src/prefs.c:295 msgid "Select Default Theme File" msgstr "" #: src/prefs.c:300 msgid "Status Bar" msgstr "Barra de Estado" #: src/prefs.c:301 msgid "Canvas Geometry" msgstr "" #: src/prefs.c:302 msgid "Cursor X,Y" msgstr "" #: src/prefs.c:303 msgid "Pixel [I] {RGB}" msgstr "" #: src/prefs.c:304 msgid "Selection Geometry" msgstr "" #: src/prefs.c:305 msgid "Undo / Redo" msgstr "Desfazer / Refazer" #: src/prefs.c:308 msgid "Tablet" msgstr "" #: src/prefs.c:309 msgid "Device Settings" msgstr "" #: src/prefs.c:313 msgid "Configure Device" msgstr "" #: src/prefs.c:319 msgid "Tool Variable" msgstr "" #: src/prefs.c:322 src/toolbar.c:454 msgid "Flow" msgstr "" #: src/prefs.c:330 msgid "Test Area" msgstr "Ãrea de Teste" #: src/prefs.c:373 msgid "Factor" msgstr "Factor" #: src/prefs.c:459 msgid "This key is builtin" msgstr "" #: src/prefs.c:462 #, c-format msgid "" "This key is mapped to:\n" "\"%s\"" msgstr "" #: src/prefs.c:465 msgid "Remap" msgstr "" #: src/prefs.c:510 msgid "Keyboard Shortcuts" msgstr "" #: src/shifter.c:147 msgid "Frames" msgstr "" #: src/shifter.c:258 msgid "Palette Shifter" msgstr "" #: src/shifter.c:263 msgid "Start" msgstr "Começar" #: src/shifter.c:265 msgid "Finish" msgstr "Finalizar" #: src/shifter.c:284 msgid "Fix Palette" msgstr "" #: src/spawn.c:651 msgid "Configure File Actions" msgstr "" #: src/spawn.c:657 src/spawn.c:663 msgid "Command" msgstr "" #: src/spawn.c:922 #, c-format msgid "Error %i reported when trying to run %s" msgstr "" #: src/spawn.c:979 msgid "" "I am unable to find the documentation. Either you need to download the " "mtPaint Handbook from the web site and install it, or you need to set the " "correct location in the Preferences window." msgstr "" #: src/spawn.c:1018 msgid "" "There was a problem running the HTML browser. You need to set the correct " "program name in the Preferences window." msgstr "" #: src/thread.c:361 msgid "Helper thread is not responding. Save your work and exit the program." msgstr "" #: src/toolbar.c:147 msgid "RGB Cube" msgstr "" #: src/toolbar.c:148 msgid "By image channel" msgstr "" #: src/toolbar.c:149 msgid "Gradient-driven" msgstr "" #: src/toolbar.c:157 msgid "Fill settings" msgstr "" #: src/toolbar.c:170 msgid "Respect opacity mode" msgstr "" #: src/toolbar.c:176 msgid "Smudge settings" msgstr "" #: src/toolbar.c:215 msgid "Aligned" msgstr "" #: src/toolbar.c:222 msgid "Clone settings" msgstr "" #: src/toolbar.c:228 msgid "By selection channel" msgstr "" #: src/toolbar.c:234 msgid "Lasso settings" msgstr "" #: src/toolbar.c:252 msgid "Brush spacing" msgstr "" #: src/toolbar.c:299 src/toolbar.c:341 msgid "Normal" msgstr "" #: src/toolbar.c:300 msgid "Colour" msgstr "Cor" #: src/toolbar.c:300 msgid "Saturate More" msgstr "" #: src/toolbar.c:301 msgid "Multiply" msgstr "Multiplicar" #: src/toolbar.c:301 msgid "Divide" msgstr "Dividir" #: src/toolbar.c:301 msgid "Dodge" msgstr "Sub-Exposição" #: src/toolbar.c:302 msgid "Burn" msgstr "Super-Exposição" #: src/toolbar.c:302 msgid "Hard Light" msgstr "Luz Sólida" #: src/toolbar.c:302 msgid "Soft Light" msgstr "Luz Suave" #: src/toolbar.c:302 msgid "Difference" msgstr "Diferença" #: src/toolbar.c:303 msgid "Darken" msgstr "Escurecer" #: src/toolbar.c:303 msgid "Lighten" msgstr "Clarear" #: src/toolbar.c:303 msgid "Grain Extract" msgstr "Extractor Grão" #: src/toolbar.c:304 msgid "Grain Merge" msgstr "Misturar Grão" #: src/toolbar.c:330 msgid "Blend mode" msgstr "" #: src/toolbar.c:417 msgid "Continuous Mode" msgstr "" #: src/toolbar.c:421 msgid "Opacity Mode" msgstr "" #: src/toolbar.c:424 msgid "Tint Mode" msgstr "" #: src/toolbar.c:427 msgid "Tint +-" msgstr "" #: src/toolbar.c:434 msgid "Blend Mode" msgstr "" #: src/toolbar.c:438 msgid "Disable All Masks" msgstr "" #: src/toolbar.c:441 msgid "Gradient Mode" msgstr "" #: src/toolbar.c:486 msgid "Settings Toolbar" msgstr "" #: src/toolbar.c:546 msgid "Cut" msgstr "Cortar" #: src/toolbar.c:548 msgid "Copy" msgstr "Copiar" #: src/toolbar.c:550 msgid "Paste" msgstr "Colar" #: src/toolbar.c:553 msgid "Undo" msgstr "Desfazer" #: src/toolbar.c:555 msgid "Redo" msgstr "Refazer" #: src/toolbar.c:559 src/viewer.c:328 msgid "Pan Window" msgstr "" #: src/toolbar.c:560 src/toolbar.c:640 msgid "More..." msgstr "" #: src/toolbar.c:574 msgid "Paint" msgstr "Pintar" #: src/toolbar.c:580 msgid "Shuffle" msgstr "Baralhar" #: src/toolbar.c:583 msgid "Flood Fill" msgstr "Preencher" #: src/toolbar.c:587 msgid "Straight Line" msgstr "Linha Recta" #: src/toolbar.c:590 msgid "Smudge" msgstr "Esborratar" #: src/toolbar.c:594 msgid "Clone" msgstr "Clonar" #: src/toolbar.c:597 msgid "Make Selection" msgstr "Seleccionar" #: src/toolbar.c:600 msgid "Polygon Selection" msgstr "Selecção de Polígono" #: src/toolbar.c:603 msgid "Place Gradient" msgstr "" #: src/toolbar.c:606 msgid "Lasso Selection" msgstr "" #: src/toolbar.c:614 msgid "Ellipse Outline" msgstr "" #: src/toolbar.c:617 msgid "Filled Ellipse" msgstr "" #: src/toolbar.c:620 msgid "Outline Selection" msgstr "Selecção de Contorno" #: src/toolbar.c:623 msgid "Fill Selection" msgstr "Preencher Selecção" #: src/toolbar.c:627 msgid "Flip Selection Vertically" msgstr "" #: src/toolbar.c:630 msgid "Flip Selection Horizontally" msgstr "" #: src/toolbar.c:633 msgid "Rotate Selection Clockwise" msgstr "" #: src/toolbar.c:636 msgid "Rotate Selection Anti-Clockwise" msgstr "" #: src/vcode.c:5201 msgid "Browse" msgstr "" #: src/vcode.c:7886 msgid "New key ..." msgstr "" #: src/vcode.c:9909 #, c-format msgid "'%s' does not match any widget" msgstr "" #: src/vcode.c:9910 #, c-format msgid "'%s' value does not fit '%s' widget" msgstr "" #: src/viewer.c:115 msgid "About" msgstr "" #: src/viewer.c:1179 msgid "No font selected" msgstr "" #: src/viewer.c:1209 msgid "Left" msgstr "" #: src/viewer.c:1209 msgid "Right" msgstr "" #~ msgid "File: %s invalid - palette not updated" #~ msgstr "Ficheiro %s inválido - paleta não actualizada" #~ msgid "%i Files on Command Line" #~ msgstr "%i Ficheiros na Linha de Comandos" #~ msgid "Not enough memory to rotate image" #~ msgstr "Memória insuficiente para rotar a imagem." #~ msgid "Not enough memory to rotate clipboard" #~ msgstr "Memória insuficiente para rotar a área de transferência" #~ msgid "File is too big, must be <= to width=%i height=%i : %s" #~ msgstr "" #~ "O ficheiro é demasiado grande, deve ser <= a largura=%i altura=%i : %s" #~ msgid "Could not open %s: %s" #~ msgstr "Não se conseguiu abrir %s: %s" #~ msgid "Error closing %s: %s" #~ msgstr "Erro ao fechar %s: %s" #~ msgid "Could not write to %s: %s" #~ msgstr "Não se conseguiu escrever em %s: %s" #~ msgid "patterns_user.c created in current directory" #~ msgstr "patters_user.c criado na directoria actual" #~ msgid "Current image is not 94x94x3 so I cannot create patterns_user.c" #~ msgstr "" #~ "A imagem actual não é 94x94x3 portanto não posso criar patterns_user.c" #~ msgid "" #~ "You are trying to save an RGB image to an XPM file which is not " #~ "possible. I would suggest you save with a PNG extension." #~ msgstr "" #~ "Está a tentar gravar uma imagem RGB num ficheiro XPM, o qual não é " #~ "possível. Sugiro que grave com uma extensão PNG." #~ msgid "" #~ "You are trying to save an RGB image to a GIF file which is not possible. " #~ "I would suggest you save with a PNG extension." #~ msgstr "" #~ "Está a tentar gravar uma imagem RGB num ficheiro GIF, o qual não é " #~ "possível. Sugiro que grave com uma extensão PNG." #~ msgid "" #~ "You are trying to save an XBM file with a palette of more than 2 " #~ "colours. Either use another format or reduce the palette to 2 colours." #~ msgstr "" #~ "Está a tentar gravar um ficheiro XBM com uma paleta de mais de 2 cores. " #~ "Use outro formato ou reduza a paleta a 2 cores." #~ msgid "" #~ "You are trying to save an indexed canvas to a JPEG file which is not " #~ "possible. I would suggest you save with a PNG extension." #~ msgstr "" #~ "Está a tentar gravar uma tela indexada num ficheiro JPEG, o qual não é " #~ "possível. Sugiro que grave com uma extensão PNG." #~ msgid "" #~ "You are trying to save an LSS16 file with a palette of more than 16 " #~ "colours. Either use another format or reduce the palette to 16 colours." #~ msgstr "" #~ "Está a tentar gravar um ficheiro LSS16 com uma paleta de mais de 16 " #~ "cores. Use outro formato ou reduza a paleta a 16 cores." #~ msgid "/Edit/Create Patterns" #~ msgstr "/Editar/Create Patterns" #~ msgid "/File/%i" #~ msgstr "/Ficheiro/%i" #~ msgid "Loading PNG image" #~ msgstr "A Carregar Imagem PNG" #~ msgid "Saving PNG image" #~ msgstr "A Gravar Imagem PNG" #~ msgid "Loading GIF image" #~ msgstr "A Carregar Imagem GIF" #~ msgid "Saving GIF image" #~ msgstr "A Gravar Imagem GIF" #~ msgid "Loading JPEG image" #~ msgstr "A Carregar Imagem JPEG" #~ msgid "Saving JPEG image" #~ msgstr "A guardar imagem JPEG" #~ msgid "Loading TIFF image" #~ msgstr "A carregar imagem TIFF" #~ msgid "Saving TIFF image" #~ msgstr "A guardar imagem TIFF" #~ msgid "Loading BMP image" #~ msgstr "A carregar imagem BMP" #~ msgid "Saving BMP image" #~ msgstr "A guardar imagem BMP" #~ msgid "Loading XPM image" #~ msgstr "A carregar imagem XPM" #~ msgid "Saving XPM image" #~ msgstr "A guardar imagem XPM" #~ msgid "Loading XBM image" #~ msgstr "A Carregar Imagem XPM" #~ msgid "Saving XBM image" #~ msgstr "A Gravar Imagem XBM" #~ msgid "Loading LSS16 image" #~ msgstr "A Carregar Imagem LSS16" #~ msgid "Saving LSS16 image" #~ msgstr "A Gravar Imagem LSS16" mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/po/pt_BR.po000066400000000000000000002526521471325446300221530ustar00rootroot00000000000000# Portuguese (Brazil) translation for mtpaint # Copyright (c) (c) 2005 Canonical Ltd, and Rosetta Contributors 2005 # This file is distributed under the same license as the mtpaint package. # FIRST AUTHOR , 2005. # msgid "" msgstr "" "Project-Id-Version: mtpaint\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-01-04 21:31+0200\n" "PO-Revision-Date: 2011-09-09 18:26+0000\n" "Last-Translator: Valter Nazianzeno \n" "Language-Team: Portuguese (Brazil) \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Launchpad-Export-Date: 2011-09-22 21:02+0000\n" "X-Generator: Launchpad (build 13996)\n" "X-Rosetta-Version: 0.1\n" #: src/ani.c:647 msgid "Animation Preview" msgstr "Pré-visualização da animação" #: src/ani.c:650 src/shifter.c:275 msgid "Play" msgstr "Reproduzir" #: src/ani.c:654 msgid "Fix" msgstr "" #: src/ani.c:655 src/ani.c:1005 src/font.c:1624 src/font.c:1643 #: src/shifter.c:286 src/viewer.c:97 msgid "Close" msgstr "Fechar" #: src/ani.c:709 src/ani.c:812 src/ani.c:1022 src/ani.c:1028 src/canvas.c:356 #: src/canvas.c:708 src/canvas.c:989 src/canvas.c:1353 src/canvas.c:1383 #: src/canvas.c:1470 src/canvas.c:1545 src/canvas.c:1988 src/canvas.c:1994 #: src/canvas.c:2077 src/canvas.c:2217 src/canvas.c:2240 src/font.c:1352 #: src/fpick.c:636 src/fpick.c:754 src/layer.c:524 src/layer.c:815 #: src/layer.c:970 src/mainwindow.c:341 src/mainwindow.c:370 #: src/mainwindow.c:534 src/mainwindow.c:578 src/mainwindow.c:604 #: src/mainwindow.c:3797 src/mainwindow.c:4045 src/otherwindow.c:931 #: src/otherwindow.c:980 src/otherwindow.c:982 src/prefs.c:459 src/spawn.c:924 #: src/spawn.c:978 src/spawn.c:1017 src/thread.c:360 src/vcode.c:9912 #: src/viewer.c:1161 src/viewer.c:1179 msgid "Error" msgstr "Erro" #: src/ani.c:709 msgid "Unable to create output directory" msgstr "Não foi possível criar o diretório de saída" #: src/ani.c:759 msgid "Creating Animation Frames" msgstr "Criando Quadros de Animação" #: src/ani.c:812 msgid "Unable to save image" msgstr "Não foi possível salvar a imagem" #: src/ani.c:840 src/canvas.c:1171 src/fpick.c:731 src/layer.c:311 #: src/layer.c:379 src/layer.c:826 src/layer.c:840 src/mainwindow.c:375 #: src/mainwindow.c:1026 src/png.c:8794 src/prefs.c:464 msgid "Warning" msgstr "Aviso" #: src/ani.c:840 msgid "" "Do you really want to clear all of the position and cycle data for all of " "the layers?" msgstr "" "Você quer mesmo limpar todos os dados das posições e de ciclo de todas as " "camadas?" #: src/ani.c:841 src/fpick.c:731 src/layer.c:311 src/layer.c:842 #: src/mainwindow.c:375 msgid "No" msgstr "Não" #: src/ani.c:841 src/fpick.c:731 src/layer.c:311 src/layer.c:842 #: src/mainwindow.c:375 msgid "Yes" msgstr "Sim" #: src/ani.c:954 msgid "Set Key Frame" msgstr "" #: src/ani.c:961 msgid "Configure Animation" msgstr "Configurar Animação" #: src/ani.c:964 msgid "Output Files" msgstr "Arquivos de Saída" #: src/ani.c:967 msgid "Start frame" msgstr "Quadro inicial" #: src/ani.c:969 msgid "End frame" msgstr "Quadro final" #: src/ani.c:971 src/shifter.c:267 msgid "Delay" msgstr "Atraso" #: src/ani.c:973 msgid "Output path" msgstr "Diretório de saída" #: src/ani.c:973 src/font.c:1637 src/spawn.c:664 msgid "Select Directory" msgstr "Selecionar Diretório" #: src/ani.c:976 msgid "File prefix" msgstr "Prefixo do arquivo" #: src/ani.c:978 src/canvas.c:2096 msgid "File Format" msgstr "Formato do Arquivo" #: src/ani.c:982 msgid "Positions" msgstr "Posições" #: src/ani.c:997 msgid "Cycling" msgstr "Circulação" #: src/ani.c:1006 msgid "Save" msgstr "Salvar" #: src/ani.c:1007 src/font.c:1577 src/otherwindow.c:868 src/otherwindow.c:1615 #: src/otherwindow.c:1728 src/otherwindow.c:2938 src/otherwindow.c:3071 #: src/otherwindow.c:3170 msgid "Preview" msgstr "Pré-visualizar" #: src/ani.c:1008 src/shifter.c:285 msgid "Create Frames" msgstr "Criar quadros" #: src/ani.c:1022 msgid "You must have at least 2 layers to create an animation" msgstr "Você deve ter pelo menos duas camadas para criar uma animação" #: src/ani.c:1028 msgid "You must save your layers file before creating an animation" msgstr "Você deve salvar as camadas antes de criar uma animação" #: src/canvas.c:357 msgid "The image is too large to transform." msgstr "A imagem é muito grande para ser transformada." #: src/canvas.c:393 src/canvas.c:430 src/otherwindow.c:1613 #: src/otherwindow.c:2524 src/otherwindow.c:2583 src/otherwindow.c:3179 msgid "Gradient" msgstr "Gradiente" #: src/canvas.c:393 src/otherwindow.c:840 src/otherwindow.c:842 #: src/otherwindow.c:2074 src/otherwindow.c:3180 msgid "Palette" msgstr "Paleta" #: src/canvas.c:393 src/info.c:265 src/otherwindow.c:847 src/otherwindow.c:2757 #: src/otherwindow.c:3180 src/png.c:781 src/png.c:995 msgid "Clipboard" msgstr "Ãrea de Transferência" #: src/canvas.c:394 src/cpick.c:831 src/toolbar.c:299 msgid "Value" msgstr "Valor" #: src/canvas.c:394 src/cpick.c:811 src/otherwindow.c:575 src/otherwindow.c:859 #: src/otherwindow.c:3053 src/toolbar.c:318 msgid "Red" msgstr "Vermelho" #: src/canvas.c:394 src/cpick.c:815 src/otherwindow.c:575 src/otherwindow.c:860 #: src/otherwindow.c:3053 src/toolbar.c:319 msgid "Green" msgstr "Verde" #: src/canvas.c:394 src/cpick.c:819 src/otherwindow.c:575 src/otherwindow.c:861 #: src/otherwindow.c:3053 src/toolbar.c:320 msgid "Blue" msgstr "Azul" #: src/canvas.c:399 msgid "From " msgstr "" #: src/canvas.c:403 msgid "To " msgstr "" #: src/canvas.c:410 msgid "Map" msgstr "" #: src/canvas.c:429 msgid "MT" msgstr "" #: src/canvas.c:429 msgid "Sobel" msgstr "" #: src/canvas.c:429 msgid "Prewitt" msgstr "" #: src/canvas.c:429 msgid "Kirsch" msgstr "" #: src/canvas.c:430 msgid "Roberts" msgstr "" #: src/canvas.c:430 msgid "Laplace" msgstr "" #: src/canvas.c:430 msgid "Morphological" msgstr "Morfológico" #: src/canvas.c:442 msgid "Edge Detect" msgstr "Detecção de borda" #: src/canvas.c:464 msgid "Edge Sharpen" msgstr "Aguçar Borda" #: src/canvas.c:472 msgid "Edge Soften" msgstr "Suavizar Borda" #: src/canvas.c:521 msgid "Different X/Y" msgstr "Diferentes X/Y" #: src/canvas.c:522 src/canvas.c:562 src/canvas.c:603 src/canvas.c:637 #: src/canvas.c:722 src/otherwindow.c:1037 src/otherwindow.c:2685 msgid "Gamma corrected" msgstr "" #: src/canvas.c:530 src/memory.c:8219 msgid "Gaussian Blur" msgstr "Desfocagem gaussiana" #: src/canvas.c:558 msgid "Radius" msgstr "Raio" #: src/canvas.c:559 msgid "Amount" msgstr "Quantidade " #: src/canvas.c:560 msgid "Threshold " msgstr "Limite" #: src/canvas.c:570 src/memory.c:8360 msgid "Unsharp Mask" msgstr "Máscara de desaguçar" #: src/canvas.c:599 msgid "Outer radius" msgstr "Raio externo" #: src/canvas.c:600 msgid "Inner radius" msgstr "Raio interno" #: src/canvas.c:602 src/info.c:280 msgid "Normalize" msgstr "Normalizar" #: src/canvas.c:611 src/memory.c:8512 msgid "Difference of Gaussians" msgstr "Diferença de Gaussianas" #: src/canvas.c:636 msgid "Protect details" msgstr "" #: src/canvas.c:645 msgid "Kuwahara-Nagao Blur" msgstr "Desfocagem Kuwahara-Nagao" #: src/canvas.c:709 msgid "The image is too large for this rotation." msgstr "A imagem é muito grande para essa rotação." #: src/canvas.c:723 msgid "Smooth" msgstr "Suavizar" #: src/canvas.c:732 msgid "Free Rotate" msgstr "Rotação Livre" #: src/canvas.c:989 src/viewer.c:1161 msgid "Not enough memory to create clipboard" msgstr "Memória insuficiente para criar a área de transferência" #: src/canvas.c:1172 msgid "" "You have not allocated enough memory in the Preferences window to undo this " "action." msgstr "" #: src/canvas.c:1353 msgid "Invalid palette file" msgstr "" #: src/canvas.c:1383 msgid "Invalid channel file." msgstr "Arquivo de Canal Inválido" #: src/canvas.c:1401 msgid "Raw frames" msgstr "" #: src/canvas.c:1401 msgid "Composited frames" msgstr "" #: src/canvas.c:1402 msgid "Composited frames with nonzero delay" msgstr "" #: src/canvas.c:1406 msgid "Load Frames" msgstr "" #: src/canvas.c:1409 msgid "Load into Layers" msgstr "" #: src/canvas.c:1415 msgid "Load First Frame" msgstr "" #: src/canvas.c:1416 msgid "Explode Frames" msgstr "" #: src/canvas.c:1418 msgid "View Animation" msgstr "" #: src/canvas.c:1434 #, c-format msgid "This is an animated %s file." msgstr "" #: src/canvas.c:1435 #, c-format msgid "This is a multipage %s file." msgstr "" #: src/canvas.c:1459 #, c-format msgid "File is too big, must be <= to width=%i height=%i" msgstr "O arquivo é muito grande, deve ser <= a largura=%i altura=%i" #: src/canvas.c:1461 msgid "Unable to explode frames" msgstr "" #: src/canvas.c:1463 msgid "Unable to load file" msgstr "Não é possivel carregar o arquivo" #: src/canvas.c:1465 msgid "" "The file import library had to terminate due to a problem with the file " "(possibly corrupt image data or a truncated file). I have managed to load " "some data as the header seemed fine, but I would suggest you save this image " "to a new file to ensure this does not happen again." msgstr "" #: src/canvas.c:1467 msgid "The animation is too long to load all of it into layers." msgstr "" #: src/canvas.c:1469 msgid "Could not explode all the frames in the animation." msgstr "" #: src/canvas.c:1481 src/font.c:1556 src/fpick.c:937 src/otherwindow.c:2765 #: src/prefs.c:321 src/toolbar.c:451 msgid "Size" msgstr "Tamanho" #: src/canvas.c:1484 src/otherwindow.c:244 msgid "Width" msgstr "Largura" #: src/canvas.c:1485 src/otherwindow.c:245 msgid "Height" msgstr "Altura" #: src/canvas.c:1489 src/channels.c:253 src/channels.c:317 src/fpick.c:666 #: src/fpick.c:957 src/mainwindow.c:3990 src/otherwindow.c:255 #: src/otherwindow.c:517 src/otherwindow.c:591 src/otherwindow.c:867 #: src/otherwindow.c:1058 src/otherwindow.c:1727 src/otherwindow.c:2101 #: src/otherwindow.c:2336 src/otherwindow.c:2538 src/otherwindow.c:2691 #: src/otherwindow.c:2776 src/otherwindow.c:2937 src/otherwindow.c:3070 #: src/otherwindow.c:3169 src/prefs.c:338 src/prefs.c:464 src/prefs.c:538 #: src/spawn.c:666 src/viewer.c:1258 msgid "Cancel" msgstr "Cancelar" #: src/canvas.c:1490 src/channels.c:253 src/channels.c:317 src/fpick.c:956 #: src/info.c:297 src/mainwindow.c:3992 src/mygtk.c:233 src/mygtk.c:535 #: src/otherwindow.c:591 src/otherwindow.c:871 src/otherwindow.c:1058 #: src/otherwindow.c:1729 src/otherwindow.c:2101 src/otherwindow.c:2336 #: src/otherwindow.c:2538 src/otherwindow.c:2691 src/otherwindow.c:2776 #: src/otherwindow.c:3072 src/otherwindow.c:3171 src/prefs.c:338 #: src/prefs.c:538 src/spawn.c:666 msgid "OK" msgstr "OK" #: src/canvas.c:1504 #, c-format msgid "This is a scalable %s file." msgstr "" #: src/canvas.c:1545 msgid "Cannot open file" msgstr "Não foi possível abrir o arquivo" #: src/canvas.c:1546 msgid "Unsupported file format" msgstr "Formato do arquivo não suportado" #: src/canvas.c:1673 #, c-format msgid "File: %s already exists. Do you want to overwrite it?" msgstr "Arquivo: %s já existe. Deseja sobrescrever o arquivo?" #: src/canvas.c:1674 msgid "File Found" msgstr "Arquivo encontrado" #: src/canvas.c:1674 src/mainwindow.c:1095 msgid "NO" msgstr "Não" #: src/canvas.c:1674 src/mainwindow.c:1095 msgid "YES" msgstr "Sim" #: src/canvas.c:1988 msgid "Unable to export undo images" msgstr "Impossível de exportar imagems desfeitas" #: src/canvas.c:1994 msgid "Unable to export ASCII file" msgstr "Não é possível exportar o arquivo ASCII" #: src/canvas.c:2076 src/layer.c:814 src/mainwindow.c:529 #, c-format msgid "Unable to save file: %s" msgstr "Não é possível salvar o arquivo: %s" #: src/canvas.c:2101 src/prefs.c:222 msgid "Transparency index" msgstr "Ãndice de Transparência" #: src/canvas.c:2103 msgid "TIFF Compression" msgstr "" #: src/canvas.c:2105 src/prefs.c:225 msgid "JPEG Save Quality (100=High)" msgstr "Qualidade JPEG (100=Alta)" #: src/canvas.c:2107 msgid "ZIP Compression (0=None)" msgstr "" #: src/canvas.c:2108 src/prefs.c:227 msgid "PNG Compression (0=None)" msgstr "Compressão PNG (0=Nada)" #: src/canvas.c:2111 src/prefs.c:249 msgid "LZMA2 Compression (0=None)" msgstr "" #: src/canvas.c:2113 src/prefs.c:252 msgid "ZSTD Compression Level" msgstr "" #: src/canvas.c:2115 src/prefs.c:231 msgid "TGA RLE Compression" msgstr "Compressão TGA RLE" #: src/canvas.c:2117 msgid "LBM PackBits Compression" msgstr "" #: src/canvas.c:2118 src/prefs.c:226 msgid "JPEG2000 Compression (0=Lossless)" msgstr "Compressão JPEG2000 (0=Sem Perdas)" #: src/canvas.c:2120 msgid "WebP Compression" msgstr "" #: src/canvas.c:2122 msgid "WebP Save Quality (100=High)" msgstr "" #: src/canvas.c:2123 src/prefs.c:263 msgid "V8 Save Quality (100=High)" msgstr "" #: src/canvas.c:2125 src/prefs.c:264 msgid "V8L Compression (0=None)" msgstr "" #: src/canvas.c:2127 msgid "Hotspot at X =" msgstr "Ponto em X =" #: src/canvas.c:2129 msgid "Y =" msgstr "Y =" #: src/canvas.c:2133 msgid "Animation delay" msgstr "Intervalo de animação" #: src/canvas.c:2136 src/otherwindow.c:253 msgid "Undoable" msgstr "Reversível" #: src/canvas.c:2138 src/prefs.c:236 msgid "Apply colour profile" msgstr "" #: src/canvas.c:2176 src/toolbar.c:543 msgid "Load Image File" msgstr "Abrir Arquivo de Imagem" #: src/canvas.c:2191 src/toolbar.c:544 msgid "Save Image File" msgstr "Salvar Arquivo de Imagem" #: src/canvas.c:2196 msgid "Load Palette File" msgstr "Carregar Paleta" #: src/canvas.c:2202 msgid "Save Palette File" msgstr "Salvar Paleta" #: src/canvas.c:2207 msgid "Export Undo Images" msgstr "Exportar Imagem Desfeitas" #: src/canvas.c:2212 msgid "Export Undo Images (reversed)" msgstr "Exportar Imagens de Desfazer (invertidas)" #: src/canvas.c:2217 msgid "You must have 16 or fewer palette colours to export ASCII art." msgstr "" "Você precisa ter 16 ou menos cores na paleta para exportar uma arte ASCII." #: src/canvas.c:2220 msgid "Export ASCII Art" msgstr "Exportar Arte ASCII" #: src/canvas.c:2224 msgid "Save Layer Files" msgstr "Salvar Arquivos de Camada" #: src/canvas.c:2234 msgid "Choose frames directory" msgstr "" #: src/canvas.c:2240 msgid "You must save at least one frame to create an animated GIF." msgstr "Você deve ter ao menos um quadro para criar um GIF animado." #: src/canvas.c:2243 msgid "Export GIF animation" msgstr "Exportar animação GIF" #: src/canvas.c:2247 msgid "Load Channel" msgstr "Carregar Canal" #: src/canvas.c:2255 msgid "Save Channel" msgstr "Salvar Canal" #: src/canvas.c:2260 msgid "Save Composite Image" msgstr "Salvar imagem composta" #: src/channels.c:243 msgid "Create Channel" msgstr "Criar Canal" #: src/channels.c:244 msgid "Channel Type" msgstr "Tipo de Canal" #: src/channels.c:247 msgid "Initial Channel State" msgstr "Estado inicial de canal" #: src/channels.c:251 msgid "Inverted" msgstr "Invertido" #: src/channels.c:265 msgid "Cleared" msgstr "" #: src/channels.c:266 msgid "Set" msgstr "" #: src/channels.c:267 msgid "Set colour A radius B" msgstr "" #: src/channels.c:268 msgid "Set blend A to B" msgstr "Mesclar A em B" #: src/channels.c:269 msgid "Image Red" msgstr "Imagem Vermelha" #: src/channels.c:270 msgid "Image Green" msgstr "Imagem Verde" #: src/channels.c:271 msgid "Image Blue" msgstr "Imagem Azul" #: src/channels.c:273 src/channels.c:313 src/mainwindow.c:67 #: src/otherwindow.c:1679 msgid "Alpha" msgstr "Alfa" #: src/channels.c:274 src/channels.c:314 src/mainwindow.c:67 #: src/otherwindow.c:1683 msgid "Selection" msgstr "Seleção" #: src/channels.c:275 src/channels.c:315 src/mainwindow.c:67 #: src/otherwindow.c:1687 msgid "Mask" msgstr "Máscara" #: src/channels.c:312 msgid "Delete Channels" msgstr "Excluir Canais" #: src/channels.c:367 msgid "Threshold Channel" msgstr "Limite do Canal" #: src/cpick.c:823 src/otherwindow.c:573 src/otherwindow.c:820 #: src/toolbar.c:299 msgid "Hue" msgstr "Matiz" #: src/cpick.c:827 src/otherwindow.c:573 src/otherwindow.c:818 #: src/toolbar.c:299 msgid "Saturation" msgstr "Saturação" #: src/cpick.c:835 msgid "Hex" msgstr "" #: src/cpick.c:840 src/layer.c:1109 src/otherwindow.c:2530 src/prefs.c:323 #: src/toolbar.c:457 msgid "Opacity" msgstr "Opacidade" #: src/font.c:982 msgid "Creating Font Index" msgstr "Criando Ãndice de Fontes" #: src/font.c:1353 msgid "You must select at least one directory to search for fonts." msgstr "Você deve selecionar ao menos um diretório para procurar fontes." #: src/font.c:1529 src/font.c:1624 src/toolbar.c:609 src/viewer.c:1213 #: src/viewer.c:1258 msgid "Paste Text" msgstr "Colar Texto" #: src/font.c:1533 src/font.c:1572 src/png.c:3578 msgid "Text" msgstr "Texto" #: src/font.c:1540 msgid "Font" msgstr "Fonte" #: src/font.c:1548 msgid "Style" msgstr "Estilo" #: src/font.c:1566 msgid "Filename" msgstr "Nome do arquivo" #: src/font.c:1567 msgid "Face" msgstr "Cara" #: src/font.c:1587 src/viewer.c:1222 msgid "Antialias" msgstr "" #: src/font.c:1590 src/viewer.c:1224 msgid "Invert" msgstr "Inverter" #: src/font.c:1593 src/viewer.c:1226 msgid "Background colour =" msgstr "Cor do Segundo Plano =" #: src/font.c:1601 src/viewer.c:1233 msgid "DPI =" msgstr "" #: src/font.c:1610 msgid "Oblique" msgstr "Oblíquo" #: src/font.c:1612 src/viewer.c:1244 msgid "Angle of rotation =" msgstr "Angulo de Rotação =" #: src/font.c:1617 src/viewer.c:1248 msgid "Align" msgstr "" #: src/font.c:1620 src/viewer.c:1253 msgid "Spacing" msgstr "" #: src/font.c:1629 msgid "Font Directories" msgstr "Diretório de Fontes" #: src/font.c:1634 src/spawn.c:664 msgid "Directory" msgstr "Diretório" #: src/font.c:1637 msgid "New Directory" msgstr "Novo Diretório" #: src/font.c:1644 src/prefs.c:532 msgid "Add" msgstr "Adicionar" #: src/font.c:1645 src/prefs.c:533 msgid "Remove" msgstr "Remover" #: src/font.c:1646 msgid "Create Index" msgstr "Criar índice" #: src/font.c:1660 src/viewer.c:1267 msgid "Enter Text Here" msgstr "Escreva Seu Texto Aqui" #: src/fpick.c:635 #, c-format msgid "Could not access directory %s" msgstr "" #: src/fpick.c:668 src/fpick.c:698 msgid "Delete" msgstr "Deletar" #: src/fpick.c:669 src/fpick.c:698 msgid "Rename" msgstr "Renomear" #: src/fpick.c:672 src/otherwindow.c:255 src/otherwindow.c:1666 msgid "Create" msgstr "Criar" #: src/fpick.c:699 msgid "Enter the new filename" msgstr "Digite o novo nome do arquivo" #: src/fpick.c:704 msgid "Create Directory" msgstr "Criar Diretório" #: src/fpick.c:705 msgid "Enter the name of the new directory" msgstr "Digite o nome do novo diretório" #: src/fpick.c:729 #, c-format msgid "Do you really want to delete \"%s\" ?" msgstr "Você tem certeza que deseja apagar \"%s\" ?" #: src/fpick.c:735 msgid "Unable to delete" msgstr "Não foi possível excluir" #: src/fpick.c:741 msgid "Unable to rename" msgstr "Não foi possível renomear" #: src/fpick.c:750 msgid "Unable to create directory" msgstr "Não foi possível criar o diretório" #: src/fpick.c:924 msgid "Up" msgstr "Subir" #: src/fpick.c:925 msgid "Home" msgstr "Inicio" #: src/fpick.c:926 msgid "Create New Directory" msgstr "Criar Diretório Novo" #: src/fpick.c:927 msgid "Show Hidden Files" msgstr "Mostrar Arquivos Ocultos" #: src/fpick.c:929 msgid "Case Insensitive Sort" msgstr "Ordenar por nome (ignorar min/maiúsculas)" #: src/fpick.c:936 msgid "Name" msgstr "Nome" #: src/fpick.c:938 msgid "Type" msgstr "Tipo" #: src/fpick.c:939 msgid "Modified" msgstr "Modificado" #: src/help.c:25 src/prefs.c:160 msgid "General" msgstr "Geral" #: src/help.c:26 msgid "Keyboard shortcuts" msgstr "Atalhos do teclado" #: src/help.c:27 msgid "Mouse shortcuts" msgstr "Atalhos do mouse" #: src/help.c:28 msgid "Credits" msgstr "Créditos" #: src/help.c:32 msgid "mtPaint 3.51 - Copyright (C) 2004-2021 The Authors\n" msgstr "mtPaint 3.51 - Copyright (C) 2004-2021 Os Autores\n" #: src/help.c:33 msgid "See 'Credits' section for a list of the authors.\n" msgstr "Para ver a lista de autores veja a sessão de \"Créditos\".\n" #: src/help.c:34 msgid "" "mtPaint 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.\n" msgstr "" "mtPaint é um software livre: você pode redistribuí-lo e/ou modificá-lo sob " "os termos da Licença Pública Geral GNU conforme publicada pela Free Software " "Foundation, tanto a versão 3 da Licença, ou (na sua opção) qualquer versão " "posterior.\n" #: src/help.c:35 msgid "" "mtPaint 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.\n" msgstr "" "mtPaint é distribuído na esperança que será útil, mas SEM QUALQUER GARANTIA, " "sem mesmo a garantia implícita de COMERCIABILIDADE ou ADEQUAÇÃO A UM " "DETERMINADO PROPÓSITO. Veja a Licença Pública Geral GNU para mais detalhes.\n" #: src/help.c:36 msgid "" "mtPaint is a simple GTK+1/2/3 painting program designed for creating icons " "and pixel based artwork. It can edit indexed palette or 24 bit RGB images " "and offers basic painting and palette manipulation tools. It also has " "several other more powerful features such as channels, layers and animation. " "Due to its simplicity and lack of dependencies it runs well on GNU/Linux, " "Windows and older PC hardware.\n" msgstr "" "mtPaint é um simples programa de pintura em GTK+1/2/3 projetado para a " "criação ícones e pixel art. Ele pode editar paletas indexadas ou imagem RGB " "de 24 bit ele também oferece ferramentas básicas de manipulação e pintura. " "Ele também tem várias outras caracteristicas poderosas como Canais, Camadas " "e Animação. Devido a sua simplicidade e sua falta de dependências ele " "funciona bem no GNU/Linux, Windows e em PCs com hardware antigo.\n" #: src/help.c:37 msgid "" "There is full documentation of mtPaint's features contained in a handbook. " "If you don't already have this, you can download it from the mtPaint " "website.\n" msgstr "" "Existe a documentação completa dos recursos do mtPaint contida em um manual. " "Se você não tiver ele, você pode baixá-lo no site do mtPaint.\n" #: src/help.c:38 msgid "" "If you like mtPaint and you want to keep up to date with new releases, or " "you want to give some feedback, then the mailing lists may be of interest to " "you:\n" msgstr "" "Se você gosta do mtPaint e deseja manter-se atualizado sobre novas versões, " "ou se quiser dar algum feedback, então a lista de discussão pode ser de seu " "interesse:\n" #: src/help.c:39 msgid "http://sourceforge.net/mail/?group_id=155874" msgstr "" #: src/help.c:42 msgid " Ctrl-N Create new image" msgstr " Ctrl-N Criar nova imagem" #: src/help.c:43 msgid " Ctrl-O Open Image" msgstr " Ctrl-O Abrir Imagem" #: src/help.c:44 msgid " Ctrl-S Save Image" msgstr " Ctrl-S Salvar Imagem" #: src/help.c:45 msgid " Ctrl-Shift-S Save layers file" msgstr "" #: src/help.c:46 msgid " Ctrl-Q Quit program\n" msgstr " Ctrl-Q Sair do programa\n" #: src/help.c:47 msgid " Ctrl-A Select whole image" msgstr " Ctrl-A Selecionar toda imagem" #: src/help.c:48 msgid " Escape Select nothing, cancel paste box" msgstr "" #: src/help.c:49 msgid " J Lasso selection\n" msgstr "" #: src/help.c:50 msgid " Ctrl-C Copy selection to clipboard" msgstr " Ctrl-C Copiar área selecionada" #: src/help.c:51 msgid "" " Ctrl-X Copy selection to clipboard, and then paint current " "pattern to selection area" msgstr "" #: src/help.c:52 msgid " Ctrl-V Paste clipboard to centre of current view" msgstr "" #: src/help.c:53 msgid " Ctrl-K Paste clipboard to location it was copied from" msgstr "" #: src/help.c:54 msgid " Ctrl-Shift-V Paste clipboard to new layer" msgstr "" #: src/help.c:55 msgid " Enter/Return Commit paste to canvas" msgstr "" #: src/help.c:56 msgid " Shift+Enter/Return Commit paste and swap canvas into the clipboard\n" msgstr "" #: src/help.c:57 msgid " Arrow keys Paint Mode - Move the mouse pointer" msgstr "" #: src/help.c:58 msgid "" " Arrow keys Selection Mode - Nudge selection box or paste box by one " "pixel" msgstr "" #: src/help.c:59 msgid "" " Shift+Arrow keys Nudge mouse pointer, selection box or paste box by x " "pixels - x is defined by the Preferences window" msgstr "" #: src/help.c:60 msgid " Ctrl+Arrows Move layer or resize selection box" msgstr "" #: src/help.c:61 msgid " Ctrl+Shift+Arrows Move layer or resize selection box by x pixels\n" msgstr "" #: src/help.c:62 msgid " Enter/Return Paint Mode - Simulate left click" msgstr "" #: src/help.c:63 msgid " Backspace Paint Mode - Simulate right click\n" msgstr "" #: src/help.c:64 msgid "" " [ or ] Change colour A to the next or previous palette item" msgstr "" #: src/help.c:65 msgid "" " Shift+[ or ] Change colour B to the next or previous palette item\n" msgstr "" #: src/help.c:66 msgid " Delete Crop image to selection" msgstr "" #: src/help.c:67 msgid "" " Insert Transform colours - i.e. Brightness, Contrast, " "Saturation, Posterize, Gamma" msgstr "" #: src/help.c:68 msgid " Ctrl-G Greyscale the image" msgstr "" #: src/help.c:69 msgid " Shift-Ctrl-G Greyscale the image (Gamma corrected)" msgstr "" #: src/help.c:70 msgid " Ctrl+M Mirror the image" msgstr "" #: src/help.c:71 msgid " Shift-Ctrl-I Invert the image\n" msgstr "" #: src/help.c:72 msgid "" " Ctrl-T Draw a rectangle around the selection area with the " "current fill" msgstr "" #: src/help.c:73 msgid " Ctrl-Shift-T Fill in the selection area with the current fill" msgstr "" #: src/help.c:74 msgid " Ctrl-L Draw an ellipse spanning the selection area" msgstr "" #: src/help.c:75 msgid " Ctrl-Shift-L Draw a filled ellipse spanning the selection area\n" msgstr "" #: src/help.c:76 msgid " Ctrl-E Edit the RGB values for colours A & B" msgstr "" #: src/help.c:77 msgid " Ctrl-W Edit all palette colours\n" msgstr "" #: src/help.c:78 msgid " Ctrl-P Preferences" msgstr "" #: src/help.c:79 msgid " Ctrl-I Information\n" msgstr "" #: src/help.c:80 msgid " Ctrl-Z Undo last action" msgstr "" #: src/help.c:81 msgid " Ctrl-R Redo an undone action\n" msgstr "" #: src/help.c:82 msgid " Shift-T Text Tool (GTK+)" msgstr "" #: src/help.c:83 msgid " T Text Tool (FreeType)\n" msgstr "" #: src/help.c:84 msgid " V View Window" msgstr "" #: src/help.c:85 msgid " L Layers Window\n" msgstr "" #: src/help.c:86 msgid " Ctrl-H Toggle Hide Image mode" msgstr "" #: src/help.c:87 msgid " B Toggle Snap to Tile Grid mode\n" msgstr "" #: src/help.c:88 msgid " X Swap Colours A & B" msgstr "" #: src/help.c:89 msgid " E Choose Colour\n" msgstr "" #: src/help.c:90 msgid "" " A Draw open arrow head when using the line tool (size set " "by flow setting)" msgstr "" #: src/help.c:91 msgid "" " S Draw closed arrow head when using the line tool (size " "set by flow setting)\n" msgstr "" #: src/help.c:92 msgid " D Line Tool" msgstr "" #: src/help.c:93 msgid " F Flood Fill Tool\n" msgstr "" #: src/help.c:94 msgid " +,= Main edit window - Zoom in" msgstr "" #: src/help.c:95 msgid " - Main edit window - Zoom out" msgstr "" #: src/help.c:96 msgid " Shift +,= View window - Zoom in" msgstr "" #: src/help.c:97 msgid " Shift - View window - Zoom out\n" msgstr "" #: src/help.c:98 #, c-format msgid " 1 10% zoom" msgstr "" #: src/help.c:99 #, c-format msgid " 2 25% zoom" msgstr "" #: src/help.c:100 #, c-format msgid " 3 50% zoom" msgstr "" #: src/help.c:101 #, c-format msgid " 4 100% zoom" msgstr "" #: src/help.c:102 #, c-format msgid " 5 400% zoom" msgstr "" #: src/help.c:103 #, c-format msgid " 6 800% zoom" msgstr "" #: src/help.c:104 #, c-format msgid " 7 1200% zoom" msgstr "" #: src/help.c:105 #, c-format msgid " 8 1600% zoom" msgstr "" #: src/help.c:106 #, c-format msgid " 9 2000% zoom\n" msgstr "" #: src/help.c:107 msgid " Shift + 1 Edit image channel" msgstr "" #: src/help.c:108 msgid " Shift + 2 Edit alpha channel" msgstr "" #: src/help.c:109 msgid " Shift + 3 Edit selection channel" msgstr "" #: src/help.c:110 msgid " Shift + 4 Edit mask channel\n" msgstr "" #: src/help.c:111 msgid " F1 Help" msgstr " F1 Ajuda" #: src/help.c:112 msgid " F2 Choose Pattern" msgstr "" #: src/help.c:113 msgid " F3 Choose Brush" msgstr "" #: src/help.c:114 msgid " F4 Paint Tool" msgstr "" #: src/help.c:115 msgid " F5 Toggle Main Toolbar" msgstr "" #: src/help.c:116 msgid " F6 Toggle Tools Toolbar" msgstr "" #: src/help.c:117 msgid " F7 Toggle Settings Toolbar" msgstr "" #: src/help.c:118 msgid " F8 Toggle Palette" msgstr "" #: src/help.c:119 msgid " F9 Selection Tool" msgstr "" #: src/help.c:120 msgid " F12 Toggle Dock Area\n" msgstr "" #: src/help.c:121 msgid " Ctrl + F1 - F12 Save current clipboard to file 1-12" msgstr "" #: src/help.c:122 msgid " Shift + F1 - F12 Load clipboard from file 1-12\n" msgstr "" #: src/help.c:123 msgid "" " Ctrl + 1, 2, ... , 0 Set opacity to 10%, 20%, ... , 100% (main or keypad " "numbers)" msgstr "" #: src/help.c:124 msgid " Ctrl + + or = Increase opacity by 1" msgstr "" #: src/help.c:125 msgid " Ctrl + - Decrease opacity by 1\n" msgstr "" #: src/help.c:126 msgid "" " Home Show or hide main window menu/toolbar/status bar/palette" msgstr "" #: src/help.c:127 msgid " Page Up Scale Image" msgstr "" #: src/help.c:128 msgid " Page Down Resize Image canvas" msgstr "" #: src/help.c:129 msgid " End Pan Window" msgstr "" #: src/help.c:132 msgid " Left button Paint to canvas using the current tool" msgstr "" #: src/help.c:133 msgid "" " Middle button Selects the point which will be the centre of the " "image after the next zoom" msgstr "" #: src/help.c:134 msgid "" " Right button Commit paste to canvas / Stop drawing current line / " "Cancel selection\n" msgstr "" #: src/help.c:135 msgid "" " Scroll Wheel In GTK+2/3 the user can have the scroll wheel zoom in " "or out via the Preferences window\n" msgstr "" #: src/help.c:136 msgid " Ctrl+Left button Choose colour A from under mouse pointer" msgstr "" #: src/help.c:137 msgid " Ctrl+Left button Clone tool - Select source" msgstr "" #: src/help.c:138 msgid "" " Ctrl+Middle button Create colour A/B and pattern based on the RGB colour " "in A (RGB images only)" msgstr "" #: src/help.c:139 msgid " Ctrl+Right button Choose colour B from under mouse pointer" msgstr "" #: src/help.c:140 msgid "" " Ctrl+Right button Polygon tool - Delete last point / Delete nearest " "point" msgstr "" #: src/help.c:141 msgid " Ctrl+Scroll Wheel Scroll the main edit window left or right\n" msgstr "" #: src/help.c:142 msgid "" " Ctrl+Double click Set colour A or B to average colour under brush " "square or selection marquee (RGB only)\n" msgstr "" #: src/help.c:143 msgid "" " Shift+Right button Selects the point which will be the centre of the " "image after the next zoom\n" "\n" msgstr "" #: src/help.c:144 msgid "You can fixate the X/Y co-ordinates while moving the mouse:\n" msgstr "" #: src/help.c:145 msgid " Shift Constrain mouse movements to vertical line" msgstr "" #: src/help.c:146 msgid " Shift+Ctrl Constrain mouse movements to horizontal line" msgstr "" #: src/help.c:149 msgid "mtPaint is maintained by Dmitry Groshev.\n" msgstr "mtPaint é mantido por Dmitry Groshev.\n" #: src/help.c:150 msgid "wjaguar@users.sourceforge.net" msgstr "" #: src/help.c:151 msgid "http://mtpaint.sourceforge.net/\n" msgstr "" #: src/help.c:152 msgid "" "The following people (in alphabetical order) have contributed directly to " "the project, and are therefore worthy of gracious thanks for their " "generosity and hard work:\n" "\n" msgstr "" #: src/help.c:153 msgid "Authors\n" msgstr "" #: src/help.c:154 msgid "" "Dmitry Groshev - Contributing developer for version 2.30. Lead developer and " "maintainer from version 3.00 to the present." msgstr "" #: src/help.c:155 msgid "" "Mark Tyler - Original author and maintainer up to version 3.00, occasional " "contributor thereafter." msgstr "" #: src/help.c:156 msgid "" "Xiaolin Wu - Wrote the Wu quantizing method - see wu.c for more " "information.\n" "\n" msgstr "" #: src/help.c:157 msgid "" "General Contributions (Feedback and Ideas for improvements unless otherwise " "stated)\n" msgstr "" #: src/help.c:158 msgid "Abdulla Al Muhairi - Website redesign April 2005" msgstr "" #: src/help.c:159 msgid "Alan Horkan" msgstr "" #: src/help.c:160 msgid "Alexandre Prokoudine" msgstr "" #: src/help.c:161 msgid "Antonio Andrea Bianco" msgstr "" #: src/help.c:162 msgid "Charlie Ledocq" msgstr "" #: src/help.c:163 msgid "Dennis Lee" msgstr "" #: src/help.c:164 msgid "Donald White" msgstr "" #: src/help.c:165 msgid "Ed Jason" msgstr "" #: src/help.c:166 msgid "" "Eddie Kohler - Created Gifsicle which is needed for the creation and viewing " "of animated GIF files http://www.lcdf.org/gifsicle/" msgstr "" #: src/help.c:167 msgid "" "Guadalinex Team (Junta de Andalucia) - man page, Launchpad/Rosetta " "registration" msgstr "" #: src/help.c:168 msgid "Lou Afonso" msgstr "" #: src/help.c:169 msgid "Magnus Hjorth" msgstr "" #: src/help.c:170 msgid "Martin Zelaia" msgstr "" #: src/help.c:171 msgid "Pasi Kallinen" msgstr "" #: src/help.c:172 msgid "Pavel Ruzicka" msgstr "" #: src/help.c:173 msgid "Puppy Linux (Barry Kauler)" msgstr "" #: src/help.c:174 msgid "Victor Copovi" msgstr "" #: src/help.c:175 msgid "Vlastimil Krejcir" msgstr "" #: src/help.c:176 msgid "" "William Kern\n" "\n" msgstr "" #: src/help.c:177 msgid "Translations\n" msgstr "" #: src/help.c:178 msgid "Brazilian Portuguese - Paulo Trevizan, Valter Nazianzeno" msgstr "" #: src/help.c:179 msgid "Czech - Pavel Ruzicka, Martin Petricek, Roman Hornik, Pavel Fric" msgstr "" #: src/help.c:180 msgid "Dutch - Hans Strijards, Pjotr" msgstr "" #: src/help.c:181 msgid "" "French - Nicolas Velin, Pascal Billard, Sylvain Cresto, Johan Serre, " "Philippe Etienne, Victor Copovi" msgstr "" #: src/help.c:182 msgid "Galician - Miguel Anxo Bouzada" msgstr "" #: src/help.c:183 msgid "German - Oliver Frommel, B. Clausius, Ulrich Ringel, Simon Brixel" msgstr "" #: src/help.c:184 msgid "Hungarian - Ur Balazs" msgstr "" #: src/help.c:185 msgid "Italian - Angelo Gemmi" msgstr "" #: src/help.c:186 msgid "Japanese - Norihiro YONEDA" msgstr "" #: src/help.c:187 msgid "Kabyle - Yacine Bouklif" msgstr "" #: src/help.c:188 msgid "Polish - Bartosz Kaszubowski, LucaS" msgstr "" #: src/help.c:189 msgid "Portuguese - Israel G. Lugo, Tiago Silva" msgstr "" #: src/help.c:190 msgid "Russian - Sergey Irupin, Dmitry Groshev" msgstr "" #: src/help.c:191 msgid "Simplified Chinese - Cecc" msgstr "" #: src/help.c:192 msgid "Slovak - Jozef Riha" msgstr "" #: src/help.c:193 msgid "" "Spanish - Guadalinex Team (Junta de Andalucia), Antonio Sanchez Leon, Miguel " "Anxo Bouzada, Francisco Jose Rey, Adolfo Jayme" msgstr "" #: src/help.c:194 msgid "Swedish - Daniel Nylander, Daniel Eriksson" msgstr "" #: src/help.c:195 msgid "Tagalog - Anjelo delCarmen" msgstr "" #: src/help.c:196 msgid "Taiwanese Chinese - Wei-Lun Chao" msgstr "" #: src/help.c:197 msgid "Turkish - Muhammet Kara, Tutku Dalmaz" msgstr "" #: src/info.c:258 msgid "Information" msgstr "Informação" #: src/info.c:260 msgid "Memory" msgstr "Memória" #: src/info.c:261 msgid "Total memory for main + undo images" msgstr "Memória total para imagem principal e desfazer" #: src/info.c:263 msgid "Undo / Redo / Max levels used" msgstr "Desfazer / Refazer / Nível máximo usado" #: src/info.c:265 msgid "Unused" msgstr "Não Usado" #: src/info.c:269 msgid "Unique RGB pixels" msgstr "Pixels RGB Únicos" #: src/info.c:272 src/layer.c:121 msgid "Layers" msgstr "Camadas" #: src/info.c:273 msgid "Total layer memory usage" msgstr "Total de memória usada pelas camadas" #: src/info.c:277 msgid "Colour Histogram" msgstr "Histograma de Cores" #: src/info.c:289 src/otherwindow.c:1614 msgid "Index" msgstr "Ãndice" #: src/info.c:290 msgid "Canvas pixels" msgstr "" #: src/info.c:328 #, c-format msgid "Clipboard = %i x %i" msgstr "Ãrea de Transferência = %i x %i" #: src/info.c:328 #, c-format msgid "Clipboard = %i x %i x RGB" msgstr "Ãrea de Transferência = %i x %i x RGB" #: src/info.c:377 msgid "Orphans" msgstr "Órfãos" #: src/info.c:383 #, c-format msgid "Colour index totals - %i of %i used" msgstr "Ãndice de Cores - %i de %i usados" #: src/inifile.c:966 msgid "" "Could not find home directory. Using current directory as home directory." msgstr "" "Não foi possível achar o diretório principal. Usando o diretório atual como " "diretório principal." #: src/layer.c:63 msgid "Background" msgstr "Plano de fundo" #: src/layer.c:122 src/mainwindow.c:5931 msgid "(Modified)" msgstr "(Modificado)" #: src/layer.c:123 src/mainwindow.c:5932 msgid "Untitled" msgstr "Sem Título" #: src/layer.c:308 #, c-format msgid "Do you really want to delete layer %i (%s) ?" msgstr "Você realmente deseja deletar a camada %i (%s) ?" #: src/layer.c:380 msgid "" "One or more of the layers contains changes that have not been saved. Do you " "really want to lose these changes?" msgstr "" "Uma ou mais camadas contem mudanças que não foram salvas. Você realmente " "quer perder essas mudanças?" #: src/layer.c:381 src/mainwindow.c:1028 msgid "Cancel Operation" msgstr "Cancelar Operação" #: src/layer.c:381 src/mainwindow.c:1028 msgid "Lose Changes" msgstr "Perder Mudanças" #: src/layer.c:523 #, c-format msgid "%d layers failed to load" msgstr "" #: src/layer.c:826 msgid "" "One or more of the image layers has not been saved. You must save each " "image individually before saving the layers text file in order to load this " "composite image in the future." msgstr "" #: src/layer.c:841 msgid "Do you really want to delete all of the layers?" msgstr "Você realmente deseja deletar todas as camadas?" #: src/layer.c:970 msgid "You cannot add any more layers." msgstr "Você não pode adicionar mais camadas." #: src/layer.c:1083 src/otherwindow.c:241 msgid "New Layer" msgstr "Nova Camada" #: src/layer.c:1085 msgid "Raise" msgstr "Aumentar" #: src/layer.c:1087 msgid "Lower" msgstr "Diminuir" #: src/layer.c:1089 msgid "Duplicate Layer" msgstr "Duplicar Camada" #: src/layer.c:1091 msgid "Centralise Layer" msgstr "Centralizar Camada" #: src/layer.c:1093 msgid "Delete Layer" msgstr "Deletar Camada" #: src/layer.c:1095 msgid "Close Layers Window" msgstr "Fechar Janela de Camadas" #: src/layer.c:1101 msgid "Layer Name" msgstr "Nome da Camada" #: src/layer.c:1104 src/toolbar.c:209 msgid "Position" msgstr "Posição" #: src/layer.c:1112 msgid "Transparent Colour" msgstr "Cor Transparente" #: src/layer.c:1117 msgid "Show all layers in main window" msgstr "Mostrar todas as camadas na janela principal" #: src/mainwindow.c:67 src/otherwindow.c:844 src/otherwindow.c:2756 #: src/toolbar.c:342 msgid "Image" msgstr "Imagem" #: src/mainwindow.c:69 src/mainwindow.c:489 src/otherwindow.c:1613 #: src/otherwindow.c:2302 msgid "RGB" msgstr "" #: src/mainwindow.c:69 src/otherwindow.c:1613 src/otherwindow.c:2302 msgid "sRGB" msgstr "" #: src/mainwindow.c:342 msgid "There were no unused colours to remove!" msgstr "Existe coress não usadas para remover!" #: src/mainwindow.c:371 msgid "The palette does not contain 2 colours that have identical RGB values" msgstr "A paleta não contém 2 cores com valores RGB identicos" #: src/mainwindow.c:374 #, c-format msgid "" "The palette contains %i colours that have identical RGB values. Do you " "really want to merge them into one index and realign the canvas?" msgstr "" #: src/mainwindow.c:492 msgid "indexed" msgstr "" #: src/mainwindow.c:498 #, c-format msgid "" "You are trying to save an %s image to an %s file which is not possible. I " "would suggest you save with a PNG extension." msgstr "" #: src/mainwindow.c:500 #, c-format msgid "" "You are trying to save an %s file with a palette of more than %d colours. " "Either use another format or reduce the palette to %d colours." msgstr "" #: src/mainwindow.c:578 msgid "Unable to load clipboard" msgstr "Não é possível carregar a área de tranferência" #: src/mainwindow.c:604 msgid "Unable to save clipboard" msgstr "Não é possível salvar a área de transferência" #: src/mainwindow.c:775 msgid "Zoom in" msgstr "" #: src/mainwindow.c:777 msgid "Zoom out" msgstr "" #: src/mainwindow.c:779 #, c-format msgid "10% zoom" msgstr "" #: src/mainwindow.c:781 #, c-format msgid "25% zoom" msgstr "" #: src/mainwindow.c:783 #, c-format msgid "50% zoom" msgstr "" #: src/mainwindow.c:785 #, c-format msgid "100% zoom" msgstr "" #: src/mainwindow.c:787 #, c-format msgid "400% zoom" msgstr "" #: src/mainwindow.c:789 #, c-format msgid "600% zoom" msgstr "" #: src/mainwindow.c:791 #, c-format msgid "800% zoom" msgstr "" #: src/mainwindow.c:793 #, c-format msgid "1000% zoom" msgstr "" #: src/mainwindow.c:795 #, c-format msgid "1200% zoom" msgstr "" #: src/mainwindow.c:797 #, c-format msgid "1600% zoom" msgstr "" #: src/mainwindow.c:799 #, c-format msgid "2000% zoom" msgstr "" #: src/mainwindow.c:801 #, c-format msgid "4000% zoom" msgstr "" #: src/mainwindow.c:803 #, c-format msgid "8000% zoom" msgstr "" #: src/mainwindow.c:805 #, c-format msgid "10% opacity" msgstr "" #: src/mainwindow.c:807 #, c-format msgid "20% opacity" msgstr "" #: src/mainwindow.c:809 #, c-format msgid "30% opacity" msgstr "" #: src/mainwindow.c:811 #, c-format msgid "40% opacity" msgstr "" #: src/mainwindow.c:813 #, c-format msgid "50% opacity" msgstr "" #: src/mainwindow.c:815 #, c-format msgid "60% opacity" msgstr "" #: src/mainwindow.c:817 #, c-format msgid "70% opacity" msgstr "" #: src/mainwindow.c:819 #, c-format msgid "80% opacity" msgstr "" #: src/mainwindow.c:821 #, c-format msgid "90% opacity" msgstr "" #: src/mainwindow.c:823 #, c-format msgid "100% opacity" msgstr "" #: src/mainwindow.c:825 msgid "Increase opacity" msgstr "" #: src/mainwindow.c:827 msgid "Decrease opacity" msgstr "" #: src/mainwindow.c:829 msgid "Draw open arrow head" msgstr "" #: src/mainwindow.c:831 msgid "Draw closed arrow head" msgstr "" #: src/mainwindow.c:833 msgid "Previous colour A" msgstr "" #: src/mainwindow.c:835 msgid "Next colour A" msgstr "" #: src/mainwindow.c:837 msgid "Previous colour B" msgstr "" #: src/mainwindow.c:839 msgid "Next colour B" msgstr "" #: src/mainwindow.c:841 msgid "Previous pattern" msgstr "" #: src/mainwindow.c:843 msgid "Next pattern" msgstr "" #: src/mainwindow.c:845 msgid "Larger brush" msgstr "" #: src/mainwindow.c:847 msgid "Smaller brush" msgstr "" #: src/mainwindow.c:849 msgid "View window - Zoom in" msgstr "" #: src/mainwindow.c:851 msgid "View window - Zoom out" msgstr "" #: src/mainwindow.c:1027 msgid "" "This canvas/palette contains changes that have not been saved. Do you " "really want to lose these changes?" msgstr "" "Essa tela/paleta contém mudanças que não foram salvas. Você realmente deseja " "perder essas mudanças?" #: src/mainwindow.c:1094 msgid "Do you really want to quit?" msgstr "Você realmente quer sair?" #: src/mainwindow.c:3754 msgid "Empty string or broken quoting" msgstr "" #: src/mainwindow.c:3755 msgid "Script must begin with a command" msgstr "" #: src/mainwindow.c:3756 msgid "Script nesting limit exceeded" msgstr "" #: src/mainwindow.c:3765 #, c-format msgid "'%s' does not match any item" msgstr "" #: src/mainwindow.c:3767 #, c-format msgid "'%s' matches a non-scriptable item" msgstr "" #: src/mainwindow.c:3769 #, c-format msgid "'%s' matches a disabled item" msgstr "" #: src/mainwindow.c:3788 #, c-format msgid "'%s' value does not fit item" msgstr "" #: src/mainwindow.c:3969 msgid "Script" msgstr "" #: src/mainwindow.c:3982 src/spawn.c:656 src/spawn.c:662 msgid "Action" msgstr "" #: src/mainwindow.c:3991 src/spawn.c:666 msgid "Execute" msgstr "" #: src/mainwindow.c:4045 msgid "Unable to load script" msgstr "" #: src/mainwindow.c:5182 msgid "/_File" msgstr "/_Arquivo" #: src/mainwindow.c:5184 msgid "//New" msgstr "//Novo" #: src/mainwindow.c:5186 msgid "//Open ..." msgstr "//Abrir ..." #: src/mainwindow.c:5188 src/mainwindow.c:5669 msgid "//Save" msgstr "//Salvar" #: src/mainwindow.c:5190 src/mainwindow.c:5549 src/mainwindow.c:5627 #: src/mainwindow.c:5671 msgid "//Save As ..." msgstr "//Salvar Como ..." #: src/mainwindow.c:5192 msgid "//Export Undo Images ..." msgstr "//Exportar Imagem Desfeitas ..." #: src/mainwindow.c:5194 msgid "//Export Undo Images (reversed) ..." msgstr "//Exportar Imagem Desfeitas (reverter) ..." #: src/mainwindow.c:5196 msgid "//Export ASCII Art ..." msgstr "//Exportar Arte ASCII ..." #: src/mainwindow.c:5198 msgid "//Export Animated GIF ..." msgstr "//Exportar GIF Animado ..." #: src/mainwindow.c:5201 msgid "//Actions" msgstr "//Ações" #: src/mainwindow.c:5235 src/mainwindow.c:5488 msgid "///Configure" msgstr "///Configurar" #: src/mainwindow.c:5290 msgid "//Quit" msgstr "//Sair" #: src/mainwindow.c:5293 msgid "/_Edit" msgstr "/_Editar" #: src/mainwindow.c:5295 msgid "//Undo" msgstr "//Desfazer" #: src/mainwindow.c:5297 msgid "//Redo" msgstr "//Refazer" #: src/mainwindow.c:5300 msgid "//Cut" msgstr "//Cortar" #: src/mainwindow.c:5302 msgid "//Copy" msgstr "//Copiar" #: src/mainwindow.c:5304 msgid "//Copy To Palette" msgstr "" #: src/mainwindow.c:5306 msgid "//Paste To Centre" msgstr "//Copiar Para o Centro" #: src/mainwindow.c:5308 msgid "//Paste To New Layer" msgstr "//Colar Como Nova Camada" #: src/mainwindow.c:5310 msgid "//Paste" msgstr "//Colar" #: src/mainwindow.c:5312 msgid "//Paste Text" msgstr "//Colar Texto" #: src/mainwindow.c:5318 msgid "//Paste Text (FreeType)" msgstr "//Colar Texto (FreeType)" #: src/mainwindow.c:5321 msgid "//Paste Palette" msgstr "//Colar Paleta" #: src/mainwindow.c:5323 msgid "//Load Clipboard" msgstr "//Carregar Ãrea de Transferência" #: src/mainwindow.c:5350 msgid "//Save Clipboard" msgstr "//Salvar Ãrea de Transferência" #: src/mainwindow.c:5377 msgid "//Import Clipboard from System" msgstr "//Importar Ãrea de Transferência do Sistema" #: src/mainwindow.c:5378 msgid "//Export Clipboard to System" msgstr "//Exportar Ãrea de Transferência para o Sistema" #: src/mainwindow.c:5381 msgid "//Choose Pattern ..." msgstr "//Escolher Modelo ..." #: src/mainwindow.c:5383 msgid "//Choose Brush ..." msgstr "//Escolher Pincel ..." #: src/mainwindow.c:5385 msgid "//Choose Colour ..." msgstr "" #: src/mainwindow.c:5392 msgid "/_View" msgstr "/_Ver" #: src/mainwindow.c:5394 msgid "//Show Main Toolbar" msgstr "//Mostrar Barra Principal" #: src/mainwindow.c:5396 msgid "//Show Tools Toolbar" msgstr "//Mostrar Barra de Ferramentas" #: src/mainwindow.c:5399 msgid "//Show Settings Toolbar" msgstr "//Mostrar Barra de Preferências" #: src/mainwindow.c:5402 msgid "//Show Dock" msgstr "" #: src/mainwindow.c:5404 msgid "//Show Palette" msgstr "//Mostrar Paleta" #: src/mainwindow.c:5406 msgid "//Show Status Bar" msgstr "//Mostrar Barra de Status" #: src/mainwindow.c:5409 msgid "//Toggle Image View" msgstr "//Visualizar Imagem em Tela Cheia" #: src/mainwindow.c:5413 msgid "//Centralize Image" msgstr "//Centralizar Imagem" #: src/mainwindow.c:5414 msgid "//Show Zoom Grid" msgstr "" #: src/mainwindow.c:5415 msgid "//Snap To Tile Grid" msgstr "" #: src/mainwindow.c:5417 msgid "//Configure Grid ..." msgstr "//Configurar Grade ..." #: src/mainwindow.c:5418 msgid "//Tracing Image ..." msgstr "//Imagem de Rastreamento ..." #: src/mainwindow.c:5421 msgid "//View Window" msgstr "//Ver Janela" #: src/mainwindow.c:5423 msgid "//Horizontal Split" msgstr "//Dividir na Horizontal" #: src/mainwindow.c:5425 msgid "//Focus View Window" msgstr "//Ver Janela em Foco" #: src/mainwindow.c:5427 msgid "//Pan Window" msgstr "//Visão Reduzida" #: src/mainwindow.c:5430 msgid "//Layers Window" msgstr "//Janela de Camadas" #: src/mainwindow.c:5433 msgid "/_Image" msgstr "/_Imagem" #: src/mainwindow.c:5436 msgid "//Convert To RGB" msgstr "//Converter para RGB" #: src/mainwindow.c:5438 msgid "//Convert To Indexed ..." msgstr "//Converter para Indexada ..." #: src/mainwindow.c:5441 msgid "//Scale Canvas ..." msgstr "" #: src/mainwindow.c:5443 msgid "//Resize Canvas ..." msgstr "//Redimensionar Imagem ..." #: src/mainwindow.c:5445 msgid "//Crop" msgstr "//Aparar" #: src/mainwindow.c:5448 src/mainwindow.c:5517 msgid "//Flip Vertically" msgstr "//Girar Verticalmente" #: src/mainwindow.c:5449 src/mainwindow.c:5519 msgid "//Flip Horizontally" msgstr "//Girar Horizontalmente" #: src/mainwindow.c:5452 src/mainwindow.c:5521 msgid "//Rotate Clockwise" msgstr "//Rotacionar Sentido Horário" #: src/mainwindow.c:5453 src/mainwindow.c:5523 msgid "//Rotate Anti-Clockwise" msgstr "//Rotacionar Sentido Anti-Horário" #: src/mainwindow.c:5454 msgid "//Free Rotate ..." msgstr "//Rotação Livre ..." #: src/mainwindow.c:5455 msgid "//Skew ..." msgstr "//Inclinar ..." #: src/mainwindow.c:5458 msgid "//Segment ..." msgstr "" #: src/mainwindow.c:5462 msgid "//Script ..." msgstr "" #: src/mainwindow.c:5464 msgid "//Scripts" msgstr "" #: src/mainwindow.c:5491 msgid "//Information ..." msgstr "//Informação ..." #: src/mainwindow.c:5494 msgid "//Preferences ..." msgstr "//Preferências ..." #: src/mainwindow.c:5497 msgid "/_Selection" msgstr "/_Seleção" #: src/mainwindow.c:5499 msgid "//Select All" msgstr "//Selecionar Todos" #: src/mainwindow.c:5501 msgid "//Select None (Esc)" msgstr "//Cancelar Seleção (Esc)" #: src/mainwindow.c:5503 msgid "//Lasso Selection" msgstr "//Seleção de Laço" #: src/mainwindow.c:5505 msgid "//Lasso Selection Cut" msgstr "" #: src/mainwindow.c:5508 msgid "//Outline Selection" msgstr "//Seleção de Contorno" #: src/mainwindow.c:5510 msgid "//Fill Selection" msgstr "//Preencher Seleção" #: src/mainwindow.c:5512 msgid "//Outline Ellipse" msgstr "" #: src/mainwindow.c:5514 msgid "//Fill Ellipse" msgstr "//Preencher Elipse" #: src/mainwindow.c:5526 msgid "//Horizontal Ramp" msgstr "" #: src/mainwindow.c:5528 msgid "//Vertical Ramp" msgstr "" #: src/mainwindow.c:5531 msgid "//Alpha Blend A,B" msgstr "" #: src/mainwindow.c:5533 msgid "//Move Alpha to Mask" msgstr "" #: src/mainwindow.c:5535 msgid "//Mask Colour A,B" msgstr "//Mascarar Cores A,B" #: src/mainwindow.c:5537 msgid "//Unmask Colour A,B" msgstr "//Desmascarar Cores A,B" #: src/mainwindow.c:5539 msgid "//Mask All Colours" msgstr "//Mascarar Todas as Cores" #: src/mainwindow.c:5541 msgid "//Clear Mask" msgstr "//Limpar Máscara" #: src/mainwindow.c:5544 msgid "/_Palette" msgstr "/_Paleta" #: src/mainwindow.c:5548 src/mainwindow.c:5626 msgid "//Load ..." msgstr "//Carregar ..." #: src/mainwindow.c:5550 msgid "//Load Default" msgstr "//Carregar Padrão" #: src/mainwindow.c:5552 msgid "//Mask All" msgstr "//Mascarar Todos" #: src/mainwindow.c:5553 msgid "//Mask None" msgstr "//Mascarar None" #: src/mainwindow.c:5555 msgid "//Swap A & B" msgstr "//Trocar A & B" #: src/mainwindow.c:5557 msgid "//Edit Colour A & B ..." msgstr "//Editar Cor A & B ..." #: src/mainwindow.c:5559 msgid "//Dither A" msgstr "" #: src/mainwindow.c:5561 msgid "//Palette Editor ..." msgstr "" #: src/mainwindow.c:5563 msgid "//Set Palette Size ..." msgstr "//Setar Tamaho da Paleta ..." #: src/mainwindow.c:5564 msgid "//Merge Duplicate Colours" msgstr "//Unir Cores Duplicadas" #: src/mainwindow.c:5566 msgid "//Remove Unused Colours" msgstr "//Remover Cores Não Usadas" #: src/mainwindow.c:5569 msgid "//Create Quantized ..." msgstr "" #: src/mainwindow.c:5572 msgid "//Sort Colours ..." msgstr "//Ordenar Cores ..." #: src/mainwindow.c:5573 msgid "//Palette Shifter ..." msgstr "" #: src/mainwindow.c:5574 msgid "//Pick Gradient ..." msgstr "" #: src/mainwindow.c:5576 msgid "/Effe_cts" msgstr "/Efei_tos" #: src/mainwindow.c:5578 msgid "//Transform Colour ..." msgstr "//Transformar Cor ..." #: src/mainwindow.c:5580 msgid "//Invert" msgstr "//Inverter" #: src/mainwindow.c:5582 msgid "//Greyscale" msgstr "//Escala de Cinza" #: src/mainwindow.c:5584 msgid "//Greyscale (Gamma corrected)" msgstr "" #: src/mainwindow.c:5586 msgid "//Normalize" msgstr "" #: src/mainwindow.c:5587 src/mainwindow.c:5658 msgid "//Threshold ..." msgstr "" #: src/mainwindow.c:5588 msgid "//Map ..." msgstr "" #: src/mainwindow.c:5590 msgid "//Isometric Transformation" msgstr "//Transformação Isométrica" #: src/mainwindow.c:5592 msgid "///Left Side Down" msgstr "" #: src/mainwindow.c:5593 msgid "///Right Side Down" msgstr "" #: src/mainwindow.c:5594 msgid "///Top Side Right" msgstr "" #: src/mainwindow.c:5595 msgid "///Bottom Side Right" msgstr "" #: src/mainwindow.c:5598 msgid "//Edge Detect ..." msgstr "//Detectar Margem ..." #: src/mainwindow.c:5600 msgid "//Difference of Gaussians ..." msgstr "//Diferença de Gaussianas ..." #: src/mainwindow.c:5602 msgid "//Sharpen ..." msgstr "//Aguçar ..." #: src/mainwindow.c:5604 msgid "//Unsharp Mask ..." msgstr "//Máscara de desaguçar ..." #: src/mainwindow.c:5606 msgid "//Soften ..." msgstr "//Suavizar ..." #: src/mainwindow.c:5608 msgid "//Gaussian Blur ..." msgstr "//Desfocagem gaussiana ..." #: src/mainwindow.c:5610 msgid "//Kuwahara-Nagao Blur ..." msgstr "//Desfocagem Kuwahara-Nagao ..." #: src/mainwindow.c:5612 msgid "//Emboss" msgstr "//Salientar" #: src/mainwindow.c:5614 msgid "//Dilate" msgstr "" #: src/mainwindow.c:5616 msgid "//Erode" msgstr "" #: src/mainwindow.c:5619 msgid "//Solid Noise ..." msgstr "" #: src/mainwindow.c:5620 msgid "//Bacteria ..." msgstr "//Bactéria ..." #: src/mainwindow.c:5623 msgid "/Cha_nnels" msgstr "/Can_ais" #: src/mainwindow.c:5625 msgid "//New ..." msgstr "//Novo ..." #: src/mainwindow.c:5628 msgid "//Delete ..." msgstr "//Deletar ..." #: src/mainwindow.c:5632 msgid "//Edit Image" msgstr "//Editar Imagem" #: src/mainwindow.c:5635 msgid "//Edit Alpha" msgstr "//Editar Alpha" #: src/mainwindow.c:5638 msgid "//Edit Selection" msgstr "//Editar Seleção" #: src/mainwindow.c:5641 msgid "//Edit Mask" msgstr "//Editar Máscara" #: src/mainwindow.c:5645 msgid "//Hide Image" msgstr "//Esconder Imagem" #: src/mainwindow.c:5648 msgid "//Disable Alpha" msgstr "//Desabilitar Alpha" #: src/mainwindow.c:5651 msgid "//Disable Selection" msgstr "//Desabilitar Seleção" #: src/mainwindow.c:5654 msgid "//Disable Mask" msgstr "//Desabilitar Máscara" #: src/mainwindow.c:5657 msgid "//Couple RGBA Operations" msgstr "" #: src/mainwindow.c:5659 msgid "//Unassociate Alpha" msgstr "" #: src/mainwindow.c:5663 msgid "//View Alpha as an Overlay" msgstr "" #: src/mainwindow.c:5664 msgid "//Configure Overlays ..." msgstr "" #: src/mainwindow.c:5666 msgid "/_Layers" msgstr "/_Camadas" #: src/mainwindow.c:5668 msgid "//New Layer" msgstr "//Nova Camada" #: src/mainwindow.c:5672 msgid "//Save Composite Image ..." msgstr "" #: src/mainwindow.c:5673 msgid "//Composite to New Layer" msgstr "" #: src/mainwindow.c:5674 msgid "//Remove All Layers" msgstr "//Remover Todas as Camadas" #: src/mainwindow.c:5676 msgid "//Configure Animation ..." msgstr "//Configurar Animação ..." #: src/mainwindow.c:5677 msgid "//Preview Animation ..." msgstr "//Pré-visualizar Animação ..." #: src/mainwindow.c:5678 msgid "//Set Key Frame ..." msgstr "" #: src/mainwindow.c:5679 msgid "//Remove All Key Frames ..." msgstr "" #: src/mainwindow.c:5681 msgid "/More..." msgstr "/Mais..." #: src/mainwindow.c:5683 msgid "/_Help" msgstr "/_Ajuda" #: src/mainwindow.c:5684 msgid "//Documentation" msgstr "//Documentação" #: src/mainwindow.c:5686 msgid "//About" msgstr "//Sobre" #: src/mainwindow.c:5689 msgid "//Keyboard Shortcuts ..." msgstr "" #: src/mainwindow.c:5690 msgid "//Rebind Shortcut Keycodes" msgstr "" #: src/memory.c:2800 msgid "Quantize Pass 1" msgstr "" #: src/memory.c:2854 msgid "Quantize Pass 2" msgstr "" #: src/memory.c:3073 src/memory.c:3458 msgid "Converting to Indexed Palette" msgstr "Converter para Paleta Indexada" #: src/memory.c:5135 src/otherwindow.c:540 msgid "Bacteria Effect" msgstr "Efeito Bactéria" #: src/memory.c:5170 msgid "Rotating" msgstr "Rotacionando" #: src/memory.c:5511 msgid "Free Rotation" msgstr "Rotação Livre" #: src/memory.c:6096 msgid "Scaling Image" msgstr "Escalonando Imagem" #: src/memory.c:7560 msgid "Counting Unique RGB Pixels" msgstr "Contar Pixels RGB Únicos" #: src/memory.c:7608 msgid "Applying Effect" msgstr "Aplicando Efeito" #: src/memory.c:8792 msgid "Kuwahara-Nagao Filter" msgstr "" #: src/memory.c:10456 src/otherwindow.c:2665 msgid "Skew" msgstr "" #: src/memory.c:10630 msgid "Segmentation Pass 1" msgstr "" #: src/memory.c:10757 msgid "Segmentation Pass 2" msgstr "" #: src/memory.c:11019 src/otherwindow.c:3156 msgid "Solid Noise" msgstr "" #: src/mygtk.c:134 src/mygtk.c:163 msgid "Please Wait ..." msgstr "Por Favor Aguarde ..." #: src/mygtk.c:141 msgid "STOP" msgstr "PARE" #: src/mygtk.c:504 msgid "Disabled" msgstr "" #: src/mygtk.c:504 src/toolbar.c:301 msgid "Screen" msgstr "Esconder" #: src/mygtk.c:504 msgid "Window" msgstr "" #: src/mygtk.c:508 msgid "Input" msgstr "" #: src/mygtk.c:512 msgid "Device:" msgstr "" #: src/mygtk.c:514 msgid "Mode:" msgstr "" #: src/mygtk.c:519 msgid "Axes" msgstr "" #: src/mygtk.c:524 msgid "X:" msgstr "" #: src/mygtk.c:525 msgid "Y:" msgstr "" #: src/mygtk.c:526 msgid "Pressure:" msgstr "" #: src/mygtk.c:527 msgid "X tilt:" msgstr "" #: src/mygtk.c:528 msgid "Y tilt:" msgstr "" #: src/mygtk.c:529 msgid "Wheel:" msgstr "" #: src/mygtk.c:579 msgid "none" msgstr "" #: src/otherwindow.c:236 msgid "24 bit RGB" msgstr "24 bit RGB" #: src/otherwindow.c:236 src/otherwindow.c:3179 msgid "Greyscale" msgstr "Escala de Cinza" #: src/otherwindow.c:237 msgid "Indexed Palette" msgstr "Paleta Indexada" #: src/otherwindow.c:237 msgid "From Clipboard" msgstr "" #: src/otherwindow.c:237 msgid "Grab Screenshot" msgstr "Capturar Imagem" #: src/otherwindow.c:242 src/toolbar.c:542 msgid "New Image" msgstr "Nova Imagem" #: src/otherwindow.c:246 src/otherwindow.c:3164 msgid "Colours" msgstr "Cores" #: src/otherwindow.c:409 msgid "Pattern Chooser" msgstr "Escolher Textura" #: src/otherwindow.c:497 msgid "Set Palette Size" msgstr "Definir Tamanho da Paleta" #: src/otherwindow.c:517 src/otherwindow.c:591 src/otherwindow.c:870 #: src/otherwindow.c:2538 src/otherwindow.c:2776 src/otherwindow.c:2939 #: src/prefs.c:338 src/prefs.c:538 msgid "Apply" msgstr "Aplicar" #: src/otherwindow.c:573 msgid "Luminance" msgstr "Luminância" #: src/otherwindow.c:573 src/otherwindow.c:814 msgid "Brightness" msgstr "Brilho" #: src/otherwindow.c:574 msgid "Distance to A" msgstr "" #: src/otherwindow.c:575 msgid "Projection to A->B" msgstr "" #: src/otherwindow.c:576 msgid "Frequency" msgstr "Frequência" #: src/otherwindow.c:580 msgid "Sort Palette Colours" msgstr "Ordenar Cores da Paleta" #: src/otherwindow.c:582 msgid "Start Index" msgstr "Iniciar Ãndice" #: src/otherwindow.c:583 msgid "End Index" msgstr "Concluir Ãndice" #: src/otherwindow.c:589 msgid "Reverse Order" msgstr "Ordem Reversa" #: src/otherwindow.c:805 msgid "Bitwise" msgstr "" #: src/otherwindow.c:805 msgid "Truncated" msgstr "" #: src/otherwindow.c:805 msgid "Rounded" msgstr "" #: src/otherwindow.c:809 src/toolbar.c:311 src/toolbar.c:558 msgid "Transform Colour" msgstr "Transformar Cor" #: src/otherwindow.c:812 msgid "Gamma" msgstr "Gama" #: src/otherwindow.c:816 msgid "Contrast" msgstr "Contraste" #: src/otherwindow.c:822 src/otherwindow.c:1674 msgid "Posterize" msgstr "Posterizar" #: src/otherwindow.c:831 msgid "Show Detail" msgstr "" #: src/otherwindow.c:836 msgid "Posterize type" msgstr "" #: src/otherwindow.c:857 msgid "Auto-Preview" msgstr "Auto-Visualização" #: src/otherwindow.c:869 msgid "Reset" msgstr "Resetar" #: src/otherwindow.c:931 msgid "New geometry is the same as now - nothing to do." msgstr "Nova geometria é a mesma que a atual - nada há fazer." #: src/otherwindow.c:980 msgid "The operating system cannot allocate the memory for this operation." msgstr "O sistema operacional não pode alocar a memória para essa aplicação." #: src/otherwindow.c:982 msgid "" "You have not allocated enough memory in the Preferences window for this " "operation." msgstr "" "Você não alocou memória suficiente na janela de Preferências para essa " "operação." #: src/otherwindow.c:993 src/otherwindow.c:2495 msgid "Mirror" msgstr "" #: src/otherwindow.c:993 src/otherwindow.c:994 msgid "Tile" msgstr "" #: src/otherwindow.c:993 msgid "Void" msgstr "" #: src/otherwindow.c:994 src/shifter.c:283 msgid "Clear" msgstr "" #: src/otherwindow.c:994 msgid "Mirror tile" msgstr "" #: src/otherwindow.c:996 msgid "Nearest Neighbour" msgstr "" #: src/otherwindow.c:997 msgid "Bilinear / Area Mapping" msgstr "" #: src/otherwindow.c:998 msgid "Bicubic" msgstr "" #: src/otherwindow.c:999 msgid "Bicubic edged" msgstr "" #: src/otherwindow.c:1000 msgid "Bicubic better" msgstr "" #: src/otherwindow.c:1001 msgid "Bicubic sharper" msgstr "" #: src/otherwindow.c:1002 msgid "Blackman-Harris" msgstr "" #: src/otherwindow.c:1008 msgid "Scale Canvas" msgstr "" #: src/otherwindow.c:1009 msgid "Resize Canvas" msgstr "" #: src/otherwindow.c:1012 msgid "Original " msgstr "Original " #: src/otherwindow.c:1013 msgid "New" msgstr "Novo" #: src/otherwindow.c:1014 msgid "Width " msgstr "Largura " #: src/otherwindow.c:1018 msgid "Height " msgstr "Altura " #: src/otherwindow.c:1023 src/otherwindow.c:2514 src/otherwindow.c:2672 #: src/toolbar.c:212 msgid "Offset" msgstr "Deslocamento" #: src/otherwindow.c:1026 src/otherwindow.c:1615 src/viewer.c:1209 msgid "Centre" msgstr "Centro" #: src/otherwindow.c:1033 src/otherwindow.c:1052 msgid "Fix Aspect Ratio" msgstr "" #: src/otherwindow.c:1039 src/otherwindow.c:2070 src/toolbar.c:312 msgid "Settings" msgstr "" #: src/otherwindow.c:1046 msgid "Sharper image reduction" msgstr "" #: src/otherwindow.c:1047 msgid "Boundary extension" msgstr "" #: src/otherwindow.c:1613 src/otherwindow.c:2302 msgid "HSV" msgstr "" #: src/otherwindow.c:1614 msgid "Highlight" msgstr "" #: src/otherwindow.c:1615 msgid "Limit" msgstr "" #: src/otherwindow.c:1616 msgid "Sphere" msgstr "" #: src/otherwindow.c:1616 src/otherwindow.c:2670 msgid "Angle" msgstr "" #: src/otherwindow.c:1616 msgid "Cube" msgstr "" #: src/otherwindow.c:1617 msgid "Opaque" msgstr "" #: src/otherwindow.c:1617 msgid "Border" msgstr "" #: src/otherwindow.c:1618 msgid "Transparent" msgstr "" #: src/otherwindow.c:1618 msgid "Tile " msgstr "" #: src/otherwindow.c:1618 msgid "Segment" msgstr "" #: src/otherwindow.c:1656 msgid "Scale" msgstr "" #: src/otherwindow.c:1657 src/otherwindow.c:3059 msgid "From" msgstr "" #: src/otherwindow.c:1659 src/otherwindow.c:3061 msgid "To" msgstr "" #: src/otherwindow.c:1699 msgid "Range" msgstr "" #: src/otherwindow.c:1702 msgid "Inverse" msgstr "" #: src/otherwindow.c:1710 msgid "Smart grid" msgstr "" #: src/otherwindow.c:1712 msgid "Tile grid" msgstr "" #: src/otherwindow.c:1714 msgid "Minimum grid zoom" msgstr "" #: src/otherwindow.c:1717 msgid "Tile width" msgstr "" #: src/otherwindow.c:1720 msgid "Tile height" msgstr "" #: src/otherwindow.c:1744 msgid "Palette Editor" msgstr "" #: src/otherwindow.c:1763 msgid "Configure Overlays" msgstr "" #: src/otherwindow.c:1782 msgid "Colour Editor" msgstr "Editor de Cores" #: src/otherwindow.c:1818 src/toolbar.c:430 msgid "Colour-Selective Mode" msgstr "" #: src/otherwindow.c:1843 msgid "Configure Grid" msgstr "" #: src/otherwindow.c:2045 msgid "Exact Conversion" msgstr "Conversão Exata" #: src/otherwindow.c:2045 msgid "Use Current Palette" msgstr "Usar Paleta Atual" #: src/otherwindow.c:2046 msgid "PNN Quantize (slow, better quality)" msgstr "" #: src/otherwindow.c:2047 msgid "Wu Quantize (fast)" msgstr "" #: src/otherwindow.c:2048 msgid "Max-Min Quantize (best for small palettes and dithering)" msgstr "" #: src/otherwindow.c:2049 src/otherwindow.c:2495 src/otherwindow.c:2756 #: src/png.c:2794 src/prefs.c:377 msgid "None" msgstr "" #: src/otherwindow.c:2049 msgid "Floyd-Steinberg" msgstr "Floyd-Steinberg" #: src/otherwindow.c:2049 msgid "Stucki" msgstr "" #: src/otherwindow.c:2052 msgid "Floyd-Steinberg (quick)" msgstr "" #: src/otherwindow.c:2052 msgid "Dithered (effect)" msgstr "" #: src/otherwindow.c:2053 msgid "Scattered (effect)" msgstr "" #: src/otherwindow.c:2054 msgid "Gamut" msgstr "" #: src/otherwindow.c:2054 msgid "Weakly" msgstr "" #: src/otherwindow.c:2054 msgid "Strongly" msgstr "" #: src/otherwindow.c:2055 msgid "Off" msgstr "" #: src/otherwindow.c:2055 msgid "Separate/Sum" msgstr "" #: src/otherwindow.c:2055 msgid "Separate/Split" msgstr "" #: src/otherwindow.c:2056 msgid "Length/Sum" msgstr "" #: src/otherwindow.c:2056 msgid "Length/Split" msgstr "" #: src/otherwindow.c:2057 msgid "Largest (Linf)" msgstr "" #: src/otherwindow.c:2057 msgid "Sum (L1)" msgstr "" #: src/otherwindow.c:2057 msgid "Euclidean (L2)" msgstr "" #: src/otherwindow.c:2061 msgid "Create Quantized" msgstr "" #: src/otherwindow.c:2062 msgid "Convert To Indexed" msgstr "Converter Para Indexado" #: src/otherwindow.c:2065 msgid "Indexed Colours To Use" msgstr "Cores Indexadas Para Usar" #: src/otherwindow.c:2078 msgid "Truncate palette" msgstr "" #: src/otherwindow.c:2079 msgid "Diameter based weighting" msgstr "" #: src/otherwindow.c:2084 msgid "Dither" msgstr "" #: src/otherwindow.c:2087 src/otherwindow.c:2584 src/otherwindow.c:2928 msgid "Colour space" msgstr "" #: src/otherwindow.c:2088 src/otherwindow.c:2929 msgid "Difference measure" msgstr "" #: src/otherwindow.c:2089 msgid "Reduce colour bleed" msgstr "" #: src/otherwindow.c:2090 msgid "Serpentine scan" msgstr "" #: src/otherwindow.c:2092 msgid "Error propagation, %" msgstr "" #: src/otherwindow.c:2093 msgid "Selective error propagation" msgstr "" #: src/otherwindow.c:2097 msgid "Full error precision" msgstr "" #: src/otherwindow.c:2302 msgid "Backward HSV" msgstr "" #: src/otherwindow.c:2303 src/otherwindow.c:2326 msgid "Constant" msgstr "" #: src/otherwindow.c:2307 msgid "Edit Gradient" msgstr "" #: src/otherwindow.c:2329 msgid "Points:" msgstr "" #: src/otherwindow.c:2493 msgid "Linear" msgstr "" #: src/otherwindow.c:2493 src/otherwindow.c:2703 msgid "Bilinear" msgstr "" #: src/otherwindow.c:2493 msgid "Radial" msgstr "" #: src/otherwindow.c:2494 msgid "Square" msgstr "" #: src/otherwindow.c:2494 msgid "Angular" msgstr "" #: src/otherwindow.c:2494 msgid "Conical" msgstr "" #: src/otherwindow.c:2495 msgid "Level " msgstr "" #: src/otherwindow.c:2495 msgid "Repeat" msgstr "" #: src/otherwindow.c:2496 msgid "A to B" msgstr "" #: src/otherwindow.c:2496 msgid "A to B (RGB)" msgstr "" #: src/otherwindow.c:2497 msgid "A to B (sRGB)" msgstr "" #: src/otherwindow.c:2497 msgid "A to B (HSV)" msgstr "" #: src/otherwindow.c:2497 msgid "A to B (backward HSV)" msgstr "" #: src/otherwindow.c:2498 msgid "A only" msgstr "" #: src/otherwindow.c:2498 src/otherwindow.c:2500 msgid "Custom" msgstr "" #: src/otherwindow.c:2499 msgid "Current to 0" msgstr "" #: src/otherwindow.c:2499 msgid "Current only" msgstr "" #: src/otherwindow.c:2504 msgid "Configure Gradient" msgstr "" #: src/otherwindow.c:2507 src/png.c:1001 msgid "Channel" msgstr "" #: src/otherwindow.c:2512 msgid "Length" msgstr "" #: src/otherwindow.c:2513 msgid "Repeat length" msgstr "" #: src/otherwindow.c:2515 msgid "Gradient type" msgstr "" #: src/otherwindow.c:2516 msgid "Extension type" msgstr "" #: src/otherwindow.c:2517 msgid "Distance type" msgstr "" #: src/otherwindow.c:2518 msgid "Preview opacity" msgstr "" #: src/otherwindow.c:2527 src/otherwindow.c:2533 src/toolbar.c:309 msgid "Reverse" msgstr "" #: src/otherwindow.c:2528 src/otherwindow.c:2534 msgid "Edit Custom" msgstr "" #: src/otherwindow.c:2592 msgid "Pick Gradient" msgstr "" #: src/otherwindow.c:2668 msgid "Horizontal " msgstr "" #: src/otherwindow.c:2674 msgid "At distance" msgstr "" #: src/otherwindow.c:2675 msgid "Vertical" msgstr "" #: src/otherwindow.c:2756 msgid "Unchanged" msgstr "" #: src/otherwindow.c:2761 msgid "Tracing Image" msgstr "" #: src/otherwindow.c:2763 src/toolbar.c:315 msgid "Source" msgstr "" #: src/otherwindow.c:2768 msgid "Origin" msgstr "" #: src/otherwindow.c:2771 msgid "Relative scale" msgstr "" #: src/otherwindow.c:2774 msgid "Display" msgstr "" #: src/otherwindow.c:2926 msgid "Segment Image" msgstr "" #: src/otherwindow.c:2931 src/toolbar.c:304 msgid "Threshold" msgstr "" #: src/otherwindow.c:2933 msgid "Level" msgstr "" #: src/otherwindow.c:2934 msgid "Minimum size" msgstr "" #: src/otherwindow.c:3053 msgid "Max" msgstr "" #: src/otherwindow.c:3053 msgid "Min" msgstr "" #: src/otherwindow.c:3057 msgid "Threshold Image" msgstr "" #: src/otherwindow.c:3158 msgid "Seed" msgstr "" #: src/otherwindow.c:3160 msgid "X span" msgstr "" #: src/otherwindow.c:3161 msgid "Y span" msgstr "" #: src/otherwindow.c:3162 msgid "Octaves" msgstr "" #: src/png.c:620 #, c-format msgid "Saving %s image" msgstr "" #: src/png.c:620 #, c-format msgid "Loading %s image" msgstr "" #: src/png.c:998 msgid "Layer" msgstr "Camada" #: src/png.c:3577 msgid "Lossless" msgstr "" #: src/png.c:3577 msgid "Default" msgstr "" #: src/png.c:3577 msgid "Picture" msgstr "" #: src/png.c:3577 msgid "Photo" msgstr "" #: src/png.c:3578 msgid "Drawing" msgstr "" #: src/png.c:3578 msgid "Icon" msgstr "" #: src/png.c:8370 msgid "Applying colour profile" msgstr "" #: src/png.c:8792 #, c-format msgid "%d out of %d frames could not be saved as %s - saved as PNG instead" msgstr "" #: src/png.c:8809 msgid "Explode frames" msgstr "" #: src/prefs.c:56 msgid "Default System Language" msgstr "Linguagem Padrão" #: src/prefs.c:57 msgid "Chinese (Simplified)" msgstr "" #: src/prefs.c:57 msgid "Chinese (Taiwanese)" msgstr "" #: src/prefs.c:57 msgid "Czech" msgstr "Tcheco" #: src/prefs.c:58 msgid "Dutch" msgstr "" #: src/prefs.c:58 msgid "English (UK)" msgstr "Inglês (GB)" #: src/prefs.c:58 msgid "French" msgstr "Francês" #: src/prefs.c:58 msgid "Galician" msgstr "" #: src/prefs.c:58 msgid "German" msgstr "" #: src/prefs.c:59 msgid "Hungarian" msgstr "" #: src/prefs.c:59 msgid "Italian" msgstr "" #: src/prefs.c:59 msgid "Japanese" msgstr "" #: src/prefs.c:59 msgid "Kabyle" msgstr "" #: src/prefs.c:59 msgid "Polish" msgstr "" #: src/prefs.c:60 msgid "Portuguese" msgstr "Português" #: src/prefs.c:60 msgid "Portuguese (Brazilian)" msgstr "Português (Brasileiro)" #: src/prefs.c:60 msgid "Russian" msgstr "" #: src/prefs.c:60 msgid "Slovak" msgstr "" #: src/prefs.c:61 msgid "Spanish" msgstr "Espanhol" #: src/prefs.c:61 msgid "Swedish" msgstr "" #: src/prefs.c:61 msgid "Tagalog" msgstr "" #: src/prefs.c:61 msgid "Turkish" msgstr "" #: src/prefs.c:81 msgid "Current Device" msgstr "Ferramenta Atual" #: src/prefs.c:135 msgid "Pressure" msgstr "Pressionar" #: src/prefs.c:149 msgid "Preferences" msgstr "Preferências" #: src/prefs.c:163 msgid "Max threads (0 to autodetect)" msgstr "" #: src/prefs.c:164 msgid "Min kpixels per render thread" msgstr "" #: src/prefs.c:171 msgid "Max memory used for undo (MB)" msgstr "Memória máxima usada para desfazer (MB)" #: src/prefs.c:172 msgid "Max undo levels" msgstr "" #: src/prefs.c:173 msgid "Communal layer undo space (%)" msgstr "" #: src/prefs.c:175 msgid "Bayer master pattern" msgstr "" #: src/prefs.c:178 msgid "Use gamma correction by default" msgstr "" #: src/prefs.c:179 msgid "Use gamma correction when painting" msgstr "" #: src/prefs.c:180 msgid "Separate patterns for A & B" msgstr "" #: src/prefs.c:183 msgid "Optimize alpha chequers" msgstr "" #: src/prefs.c:184 msgid "Disable view window transparencies" msgstr "" #: src/prefs.c:185 msgid "Enable overlays by layer" msgstr "" #: src/prefs.c:189 msgid "Language" msgstr "Linguagem" #: src/prefs.c:191 msgid "" "Select preferred language translation\n" "\n" "You will need to restart mtPaint\n" "for this to take full effect" msgstr "" "Selecione seu idioma preferido\n" "\n" "Você precisa reiniciar o mtPaint\n" "para ter efeito" #: src/prefs.c:198 msgid "Interface" msgstr "" #: src/prefs.c:200 msgid "Greyscale backdrop" msgstr "Fundo em Escala de Cinza" #: src/prefs.c:201 msgid "Selection nudge pixels" msgstr "" #: src/prefs.c:202 msgid "Max Pan Window Size" msgstr "Tamanho Máximo da Miniatura" #: src/prefs.c:204 msgid "Display clipboard while pasting" msgstr "Mostrar área de tranferência enquanto copiar" #: src/prefs.c:205 msgid "Mouse cursor = Tool" msgstr "Cursor do Mouse = Ferramenta" #: src/prefs.c:206 msgid "Confirm Exit" msgstr "Confirmar Saída" #: src/prefs.c:207 msgid "Q key quits mtPaint" msgstr "Tecla Q sai do mtPaint" #: src/prefs.c:208 msgid "Arrow keys scroll canvas" msgstr "" #: src/prefs.c:209 msgid "Changing tool commits paste" msgstr "" #: src/prefs.c:210 msgid "Centre tool settings dialogs" msgstr "" #: src/prefs.c:211 msgid "New image sets zoom to 100%" msgstr "Nova imagem seta o zoom para 100%" #: src/prefs.c:212 msgid "Zoom on cursor position" msgstr "" #: src/prefs.c:214 msgid "Mouse Scroll Wheel = Zoom" msgstr "Mouse Scroll = Zoom" #: src/prefs.c:215 msgid "Use menu icons" msgstr "" #: src/prefs.c:220 msgid "Files" msgstr "Arquivos" #: src/prefs.c:223 msgid "XBM X hotspot" msgstr "" #: src/prefs.c:224 msgid "XBM Y hotspot" msgstr "" #: src/prefs.c:228 msgid "Recently Used Files" msgstr "Arquivos Recentes" #: src/prefs.c:229 msgid "Progress bar silence limit" msgstr "" #: src/prefs.c:232 msgid "Read 16-bit TGAs as 5:6:5 BGR" msgstr "" #: src/prefs.c:233 msgid "Write TGAs in bottom-up row order" msgstr "" #: src/prefs.c:234 msgid "Undoable image loading" msgstr "" #: src/prefs.c:245 msgid "Compression (RGB)" msgstr "" #: src/prefs.c:246 msgid "Compression (indexed)" msgstr "" #: src/prefs.c:247 msgid "Compression (monochrome)" msgstr "" #: src/prefs.c:255 msgid "Enable predictor" msgstr "" #: src/prefs.c:262 msgid "Compression mode" msgstr "" #: src/prefs.c:271 msgid "Channel for Mask Plane" msgstr "" #: src/prefs.c:273 msgid "Ignore Transparent Colour" msgstr "" #: src/prefs.c:274 msgid "PackBits Compression" msgstr "" #: src/prefs.c:275 msgid "Write Indexed as Planar Bitmap (PBM)" msgstr "" #: src/prefs.c:280 msgid "Paths" msgstr "" #: src/prefs.c:281 msgid "Clipboard Files" msgstr "Arquivos da Ãrea de Transferência" #: src/prefs.c:281 msgid "Select Clipboard File" msgstr "Selecionar Ãrea de Transferência" #: src/prefs.c:283 msgid "HTML Browser Program" msgstr "" #: src/prefs.c:283 msgid "Select Browser Program" msgstr "" #: src/prefs.c:285 msgid "Location of Handbook index" msgstr "" #: src/prefs.c:285 msgid "Select Handbook Index File" msgstr "" #: src/prefs.c:287 msgid "Default Palette" msgstr "" #: src/prefs.c:287 msgid "Select Default Palette" msgstr "" #: src/prefs.c:289 msgid "Default Patterns" msgstr "" #: src/prefs.c:289 msgid "Select Default Patterns File" msgstr "" #: src/prefs.c:292 msgid "Default CSS" msgstr "" #: src/prefs.c:292 msgid "Select Default CSS File" msgstr "" #: src/prefs.c:295 msgid "Default Theme" msgstr "" #: src/prefs.c:295 msgid "Select Default Theme File" msgstr "" #: src/prefs.c:300 msgid "Status Bar" msgstr "Barra de Status" #: src/prefs.c:301 msgid "Canvas Geometry" msgstr "Geometria da Tela" #: src/prefs.c:302 msgid "Cursor X,Y" msgstr "Cursor X,Y" #: src/prefs.c:303 msgid "Pixel [I] {RGB}" msgstr "Pixel [I] {RGB}" #: src/prefs.c:304 msgid "Selection Geometry" msgstr "Geometria da Seleção" #: src/prefs.c:305 msgid "Undo / Redo" msgstr "Desfazer / Refazer" #: src/prefs.c:308 msgid "Tablet" msgstr "" #: src/prefs.c:309 msgid "Device Settings" msgstr "Opções de Ferramentas" #: src/prefs.c:313 msgid "Configure Device" msgstr "Configurar Dispositivo" #: src/prefs.c:319 msgid "Tool Variable" msgstr "Ferramenta Variável" #: src/prefs.c:322 src/toolbar.c:454 msgid "Flow" msgstr "" #: src/prefs.c:330 msgid "Test Area" msgstr "Ãrea de Teste" #: src/prefs.c:373 msgid "Factor" msgstr "Fator" #: src/prefs.c:459 msgid "This key is builtin" msgstr "" #: src/prefs.c:462 #, c-format msgid "" "This key is mapped to:\n" "\"%s\"" msgstr "" #: src/prefs.c:465 msgid "Remap" msgstr "" #: src/prefs.c:510 msgid "Keyboard Shortcuts" msgstr "" #: src/shifter.c:147 msgid "Frames" msgstr "" #: src/shifter.c:258 msgid "Palette Shifter" msgstr "" #: src/shifter.c:263 msgid "Start" msgstr "Iniciar" #: src/shifter.c:265 msgid "Finish" msgstr "Terminar" #: src/shifter.c:284 msgid "Fix Palette" msgstr "" #: src/spawn.c:651 msgid "Configure File Actions" msgstr "" #: src/spawn.c:657 src/spawn.c:663 msgid "Command" msgstr "" #: src/spawn.c:922 #, c-format msgid "Error %i reported when trying to run %s" msgstr "" #: src/spawn.c:979 msgid "" "I am unable to find the documentation. Either you need to download the " "mtPaint Handbook from the web site and install it, or you need to set the " "correct location in the Preferences window." msgstr "" #: src/spawn.c:1018 msgid "" "There was a problem running the HTML browser. You need to set the correct " "program name in the Preferences window." msgstr "" #: src/thread.c:361 msgid "Helper thread is not responding. Save your work and exit the program." msgstr "" #: src/toolbar.c:147 msgid "RGB Cube" msgstr "" #: src/toolbar.c:148 msgid "By image channel" msgstr "" #: src/toolbar.c:149 msgid "Gradient-driven" msgstr "" #: src/toolbar.c:157 msgid "Fill settings" msgstr "" #: src/toolbar.c:170 msgid "Respect opacity mode" msgstr "" #: src/toolbar.c:176 msgid "Smudge settings" msgstr "" #: src/toolbar.c:215 msgid "Aligned" msgstr "" #: src/toolbar.c:222 msgid "Clone settings" msgstr "" #: src/toolbar.c:228 msgid "By selection channel" msgstr "" #: src/toolbar.c:234 msgid "Lasso settings" msgstr "" #: src/toolbar.c:252 msgid "Brush spacing" msgstr "" #: src/toolbar.c:299 src/toolbar.c:341 msgid "Normal" msgstr "" #: src/toolbar.c:300 msgid "Colour" msgstr "Cor" #: src/toolbar.c:300 msgid "Saturate More" msgstr "" #: src/toolbar.c:301 msgid "Multiply" msgstr "Multiplicar" #: src/toolbar.c:301 msgid "Divide" msgstr "Dividir" #: src/toolbar.c:301 msgid "Dodge" msgstr "Sub-exposição" #: src/toolbar.c:302 msgid "Burn" msgstr "Super-exposição" #: src/toolbar.c:302 msgid "Hard Light" msgstr "Luz dura" #: src/toolbar.c:302 msgid "Soft Light" msgstr "Luz suave" #: src/toolbar.c:302 msgid "Difference" msgstr "Diferença" #: src/toolbar.c:303 msgid "Darken" msgstr "Escurecer" #: src/toolbar.c:303 msgid "Lighten" msgstr "Clarear" #: src/toolbar.c:303 msgid "Grain Extract" msgstr "Extrair grãos" #: src/toolbar.c:304 msgid "Grain Merge" msgstr "Mesclar grãos" #: src/toolbar.c:330 msgid "Blend mode" msgstr "" #: src/toolbar.c:417 msgid "Continuous Mode" msgstr "Modo Continuo" #: src/toolbar.c:421 msgid "Opacity Mode" msgstr "Modo de Opacidade" #: src/toolbar.c:424 msgid "Tint Mode" msgstr "" #: src/toolbar.c:427 msgid "Tint +-" msgstr "" #: src/toolbar.c:434 msgid "Blend Mode" msgstr "" #: src/toolbar.c:438 msgid "Disable All Masks" msgstr "Desabilitar todas as máscaras" #: src/toolbar.c:441 msgid "Gradient Mode" msgstr "Modo Degradê" #: src/toolbar.c:486 msgid "Settings Toolbar" msgstr "Barra de Preferências" #: src/toolbar.c:546 msgid "Cut" msgstr "Cortar" #: src/toolbar.c:548 msgid "Copy" msgstr "Copiar" #: src/toolbar.c:550 msgid "Paste" msgstr "Colar" #: src/toolbar.c:553 msgid "Undo" msgstr "Desfazer" #: src/toolbar.c:555 msgid "Redo" msgstr "Refazer" #: src/toolbar.c:559 src/viewer.c:328 msgid "Pan Window" msgstr "Miniatura" #: src/toolbar.c:560 src/toolbar.c:640 msgid "More..." msgstr "" #: src/toolbar.c:574 msgid "Paint" msgstr "Pintar" #: src/toolbar.c:580 msgid "Shuffle" msgstr "Misturar" #: src/toolbar.c:583 msgid "Flood Fill" msgstr "Preencher" #: src/toolbar.c:587 msgid "Straight Line" msgstr "Linha Reta" #: src/toolbar.c:590 msgid "Smudge" msgstr "Borrar" #: src/toolbar.c:594 msgid "Clone" msgstr "Clonar" #: src/toolbar.c:597 msgid "Make Selection" msgstr "Fazer Seleção" #: src/toolbar.c:600 msgid "Polygon Selection" msgstr "Selecionar Polígono" #: src/toolbar.c:603 msgid "Place Gradient" msgstr "" #: src/toolbar.c:606 msgid "Lasso Selection" msgstr "Seleção de Laço" #: src/toolbar.c:614 msgid "Ellipse Outline" msgstr "" #: src/toolbar.c:617 msgid "Filled Ellipse" msgstr "Elipse Preenchida" #: src/toolbar.c:620 msgid "Outline Selection" msgstr "Seleção de Contorno" #: src/toolbar.c:623 msgid "Fill Selection" msgstr "Preencher Seleção" #: src/toolbar.c:627 msgid "Flip Selection Vertically" msgstr "Girar Seleção Verticalmente" #: src/toolbar.c:630 msgid "Flip Selection Horizontally" msgstr "Girar Seleção Horizontalmente" #: src/toolbar.c:633 msgid "Rotate Selection Clockwise" msgstr "Rotacionar Seleção Sentido Horário" #: src/toolbar.c:636 msgid "Rotate Selection Anti-Clockwise" msgstr "Rotacionar Seleção Sentido Anti-Horário" #: src/vcode.c:5201 msgid "Browse" msgstr "Navegar" #: src/vcode.c:7886 msgid "New key ..." msgstr "" #: src/vcode.c:9909 #, c-format msgid "'%s' does not match any widget" msgstr "" #: src/vcode.c:9910 #, c-format msgid "'%s' value does not fit '%s' widget" msgstr "" #: src/viewer.c:115 msgid "About" msgstr "Sobre" #: src/viewer.c:1179 msgid "No font selected" msgstr "" #: src/viewer.c:1209 msgid "Left" msgstr "" #: src/viewer.c:1209 msgid "Right" msgstr "" #~ msgid "Create GIF frames" #~ msgstr "Criar Quadros do GIF" #~ msgid "File: %s invalid - palette not updated" #~ msgstr "Arquivo: %s inválido - paleta não está atualizada" #~ msgid "The palette does not contain enough colours to do a merge" #~ msgstr "A paleta não contém cores suficientes para ser mesclada" #~ msgid "There are too many identical palette items to be reduced." #~ msgstr "Existe muitos itens identicos para serem reduzidos." #~ msgid "/View/Command Line Window" #~ msgstr "/Ver/Janela de Linhas de Comando" #~ msgid "Zoom" #~ msgstr "Zoom" #~ msgid "%i Files on Command Line" #~ msgstr "%i Arquivos na Linha de Comando" #~ msgid "Not enough memory to rotate image" #~ msgstr "Memória insuficiente para rotacionar imagem" #~ msgid "Not enough memory to rotate clipboard" #~ msgstr "" #~ "Memória insuficiente para rotacionar a área de transferênciaMemória " #~ "insuficiente para rotacionar a área de transferência" #~ msgid "File is too big, must be <= to width=%i height=%i : %s" #~ msgstr "" #~ "Arquivo é muito grande, precisa ser <= %i de largura e %i de altura : %s" #~ msgid "Could not open %s: %s" #~ msgstr "Não é possível abrir %s: %s" #~ msgid "Error closing %s: %s" #~ msgstr "Erro fechando %s: %s" #~ msgid "Could not write to %s: %s" #~ msgstr "Não pode escrever para %s: %s" #~ msgid "patterns_user.c could not be opened in current directory" #~ msgstr "patterns_user.c não pode ser aberto no diretório atual" #~ msgid "Done" #~ msgstr "Pronto" #~ msgid "patterns_user.c created in current directory" #~ msgstr "patterns_user.c criado no diretório atual" #~ msgid "Current image is not 94x94x3 so I cannot create patterns_user.c" #~ msgstr "" #~ "A imagem atual não é de 94x94x3, então não é possivel criar a " #~ "patterns_user.c" #~ msgid "" #~ "You are trying to save an RGB image to an XPM file which is not " #~ "possible. I would suggest you save with a PNG extension." #~ msgstr "" #~ "Você está tentando salvar uma imagem RGB em arquivo XPM, que é " #~ "impossível. Eu sugiro que você salve como PNG." #~ msgid "" #~ "You are trying to save an RGB image to a GIF file which is not possible. " #~ "I would suggest you save with a PNG extension." #~ msgstr "" #~ "Você está tentando salvar uma imagem RGB em arquivo GIF, que é " #~ "impossível. Eu sugiro que você salve como PNG." #~ msgid "" #~ "You are trying to save an XBM file with a palette of more than 2 " #~ "colours. Either use another format or reduce the palette to 2 colours." #~ msgstr "" #~ "Você está tentando salvar um arquivo XBM com uma paleta com mais de 2 " #~ "cores. Tente um outro formato ou reduza a paleta para 2 cores." #~ msgid "/File/Actions/sep2" #~ msgstr "/Arquivo/Actions/sep2" #~ msgid "/Edit/Create Patterns" #~ msgstr "/Editar/Criar Modelo" #~ msgid "/Palette/Create Quantized (DL1)" #~ msgstr "/Paleta/Create Quantized (DL1)" #~ msgid "/Palette/Create Quantized (DL3)" #~ msgstr "/Paleta/Create Quantized (DL3)" #~ msgid "/Palette/Create Quantized (Wu)" #~ msgstr "/Paleta/Create Quantized (Wu)" #~ msgid "/File/%i" #~ msgstr "/Arquivo/%i" #~ msgid "/File/Actions/%i" #~ msgstr "/Arquivo/Actions/%i" #~ msgid "Loading PNG image" #~ msgstr "Carregando imagem PNG" #~ msgid "Loading clipboard image" #~ msgstr "Carregando imagem da área de transferência" #~ msgid "Saving PNG image" #~ msgstr "Salvando imagem PNG" #~ msgid "Saving Clipboard image" #~ msgstr "Salvando Imagem da Ãrea de Transferência" #~ msgid "Saving Layer image" #~ msgstr "Salvando Imagem da Camada" #~ msgid "Loading GIF image" #~ msgstr "Carregando imagem GIF" #~ msgid "Saving GIF image" #~ msgstr "Salvando imagem GIF" #~ msgid "Loading JPEG image" #~ msgstr "Carregando imagem JPEG" #~ msgid "Saving JPEG image" #~ msgstr "Salvando imagem JPEG" #~ msgid "Loading TIFF image" #~ msgstr "Carregando imagem TIFF" #~ msgid "Saving TIFF image" #~ msgstr "Salvando imagem TIFF" #~ msgid "Loading BMP image" #~ msgstr "Carregando imagem BMP" #~ msgid "Saving BMP image" #~ msgstr "Salvando imagem BMP" #~ msgid "Loading XPM image" #~ msgstr "Carregando imagem XPM" #~ msgid "Saving XPM image" #~ msgstr "Salvando imagem XPM" #~ msgid "Loading XBM image" #~ msgstr "Carregando imagem XBM" #~ msgid "Saving XBM image" #~ msgstr "Salvando imagem XBM" #~ msgid "Loading LSS16 image" #~ msgstr "Carregando imagem LSS16" #~ msgid "Saving LSS16 image" #~ msgstr "Salvando imagem LSS16" #~ msgid "Saving UNDO images" #~ msgstr "Salvando Imagens Desfeitas" #~ msgid "JPEG Save Quality (100=High) " #~ msgstr "Qualidade JPEG (100=Alta) " mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/po/ru.po000066400000000000000000003502071471325446300215660ustar00rootroot00000000000000# Russian translation for mtpaint # Copyright (c) (c) 2005 Canonical Ltd, and Rosetta Contributors 2005 # This file is distributed under the same license as the mtpaint package. # Sergei Irupin , 2008. # msgid "" msgstr "" "Project-Id-Version: mtpaint\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-01-04 21:31+0200\n" "PO-Revision-Date: 2020-05-07 13:54+0300\n" "Last-Translator: Dmitry Groshev \n" "Language-Team: \n" "Language: ru\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: src/ani.c:647 msgid "Animation Preview" msgstr "ПроÑмотр анимации" #: src/ani.c:650 src/shifter.c:275 msgid "Play" msgstr "ЗапуÑтить" #: src/ani.c:654 msgid "Fix" msgstr "ЗафикÑировать" #: src/ani.c:655 src/ani.c:1005 src/font.c:1624 src/font.c:1643 #: src/shifter.c:286 src/viewer.c:97 msgid "Close" msgstr "Закрыть" #: src/ani.c:709 src/ani.c:812 src/ani.c:1022 src/ani.c:1028 src/canvas.c:356 #: src/canvas.c:708 src/canvas.c:989 src/canvas.c:1353 src/canvas.c:1383 #: src/canvas.c:1470 src/canvas.c:1545 src/canvas.c:1988 src/canvas.c:1994 #: src/canvas.c:2077 src/canvas.c:2217 src/canvas.c:2240 src/font.c:1352 #: src/fpick.c:636 src/fpick.c:754 src/layer.c:524 src/layer.c:815 #: src/layer.c:970 src/mainwindow.c:341 src/mainwindow.c:370 #: src/mainwindow.c:534 src/mainwindow.c:578 src/mainwindow.c:604 #: src/mainwindow.c:3797 src/mainwindow.c:4045 src/otherwindow.c:931 #: src/otherwindow.c:980 src/otherwindow.c:982 src/prefs.c:459 src/spawn.c:924 #: src/spawn.c:978 src/spawn.c:1017 src/thread.c:360 src/vcode.c:9912 #: src/viewer.c:1161 src/viewer.c:1179 msgid "Error" msgstr "Ошибка" #: src/ani.c:709 msgid "Unable to create output directory" msgstr "Ðевозможно Ñоздать каталог Ð´Ð»Ñ Ð²Ñ‹Ð²Ð¾Ð´Ð°" #: src/ani.c:759 msgid "Creating Animation Frames" msgstr "Создание фреймов анимации" #: src/ani.c:812 msgid "Unable to save image" msgstr "Ðевозможно Ñохранить изображение" #: src/ani.c:840 src/canvas.c:1171 src/fpick.c:731 src/layer.c:311 #: src/layer.c:379 src/layer.c:826 src/layer.c:840 src/mainwindow.c:375 #: src/mainwindow.c:1026 src/png.c:8794 src/prefs.c:464 msgid "Warning" msgstr "Внимание" #: src/ani.c:840 msgid "" "Do you really want to clear all of the position and cycle data for all of " "the layers?" msgstr "" "Ð’Ñ‹ дейÑтвительно хотите очиÑтить вÑе данные Ð¿Ð¾Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð¸ циклов Ð´Ð»Ñ Ð²Ñех " "Ñлоев?" #: src/ani.c:841 src/fpick.c:731 src/layer.c:311 src/layer.c:842 #: src/mainwindow.c:375 msgid "No" msgstr "Ðет" #: src/ani.c:841 src/fpick.c:731 src/layer.c:311 src/layer.c:842 #: src/mainwindow.c:375 msgid "Yes" msgstr "Да" #: src/ani.c:954 msgid "Set Key Frame" msgstr "УÑтановить ключевой кадр" #: src/ani.c:961 msgid "Configure Animation" msgstr "ÐаÑтройка анимации" #: src/ani.c:964 msgid "Output Files" msgstr "Файл вывода" #: src/ani.c:967 msgid "Start frame" msgstr "Стартовый кадр" #: src/ani.c:969 msgid "End frame" msgstr "Конечный кадр" #: src/ani.c:971 src/shifter.c:267 msgid "Delay" msgstr "Задержка" #: src/ani.c:973 msgid "Output path" msgstr "Путь Ð´Ð»Ñ Ð²Ñ‹Ð²Ð¾Ð´Ð°" #: src/ani.c:973 src/font.c:1637 src/spawn.c:664 msgid "Select Directory" msgstr "Выбрать каталог" #: src/ani.c:976 msgid "File prefix" msgstr "ÐŸÑ€ÐµÑ„Ð¸ÐºÑ Ñ„Ð°Ð¹Ð»Ð°" #: src/ani.c:978 src/canvas.c:2096 msgid "File Format" msgstr "Формат файла" #: src/ani.c:982 msgid "Positions" msgstr "Позиции" #: src/ani.c:997 msgid "Cycling" msgstr "Циклы" #: src/ani.c:1006 msgid "Save" msgstr "Сохранить" #: src/ani.c:1007 src/font.c:1577 src/otherwindow.c:868 src/otherwindow.c:1615 #: src/otherwindow.c:1728 src/otherwindow.c:2938 src/otherwindow.c:3071 #: src/otherwindow.c:3170 msgid "Preview" msgstr "ПроÑмотр" #: src/ani.c:1008 src/shifter.c:285 msgid "Create Frames" msgstr "Создать кадры" #: src/ani.c:1022 msgid "You must have at least 2 layers to create an animation" msgstr "Ð’Ñ‹ должны иметь по крайней мере 2 ÑÐ»Ð¾Ñ Ð´Ð»Ñ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð°Ð½Ð¸Ð¼Ð°Ñ†Ð¸Ð¸" #: src/ani.c:1028 msgid "You must save your layers file before creating an animation" msgstr "Ð’Ñ‹ должны Ñохранить файл Ñлоев, прежде чем Ñоздавать анимацию" #: src/canvas.c:357 msgid "The image is too large to transform." msgstr "Изображение Ñлишком велико Ð´Ð»Ñ Ð¿Ñ€ÐµÐ¾Ð±Ñ€Ð°Ð·Ð¾Ð²Ð°Ð½Ð¸Ñ." #: src/canvas.c:393 src/canvas.c:430 src/otherwindow.c:1613 #: src/otherwindow.c:2524 src/otherwindow.c:2583 src/otherwindow.c:3179 msgid "Gradient" msgstr "Градиент" #: src/canvas.c:393 src/otherwindow.c:840 src/otherwindow.c:842 #: src/otherwindow.c:2074 src/otherwindow.c:3180 msgid "Palette" msgstr "Палитра" #: src/canvas.c:393 src/info.c:265 src/otherwindow.c:847 src/otherwindow.c:2757 #: src/otherwindow.c:3180 src/png.c:781 src/png.c:995 msgid "Clipboard" msgstr "Буфер обмена" #: src/canvas.c:394 src/cpick.c:831 src/toolbar.c:299 msgid "Value" msgstr "Значение" #: src/canvas.c:394 src/cpick.c:811 src/otherwindow.c:575 src/otherwindow.c:859 #: src/otherwindow.c:3053 src/toolbar.c:318 msgid "Red" msgstr "КраÑный" #: src/canvas.c:394 src/cpick.c:815 src/otherwindow.c:575 src/otherwindow.c:860 #: src/otherwindow.c:3053 src/toolbar.c:319 msgid "Green" msgstr "Зеленый" #: src/canvas.c:394 src/cpick.c:819 src/otherwindow.c:575 src/otherwindow.c:861 #: src/otherwindow.c:3053 src/toolbar.c:320 msgid "Blue" msgstr "Синий" #: src/canvas.c:399 msgid "From " msgstr "Из " #: src/canvas.c:403 msgid "To " msgstr "Ðа " #: src/canvas.c:410 msgid "Map" msgstr "Отобразить" #: src/canvas.c:429 msgid "MT" msgstr "МТ" #: src/canvas.c:429 msgid "Sobel" msgstr "Собел" #: src/canvas.c:429 msgid "Prewitt" msgstr "Превитт" #: src/canvas.c:429 msgid "Kirsch" msgstr "Кирш" #: src/canvas.c:430 msgid "Roberts" msgstr "РобертÑ" #: src/canvas.c:430 msgid "Laplace" msgstr "ЛаплаÑ" #: src/canvas.c:430 msgid "Morphological" msgstr "МорфологичеÑкий" #: src/canvas.c:442 msgid "Edge Detect" msgstr "Выделить границы" #: src/canvas.c:464 msgid "Edge Sharpen" msgstr "Резкие границы" #: src/canvas.c:472 msgid "Edge Soften" msgstr "Сглаженные границы" #: src/canvas.c:521 msgid "Different X/Y" msgstr "Отдельно по X и Y" #: src/canvas.c:522 src/canvas.c:562 src/canvas.c:603 src/canvas.c:637 #: src/canvas.c:722 src/otherwindow.c:1037 src/otherwindow.c:2685 msgid "Gamma corrected" msgstr "Гамма-коррекциÑ" #: src/canvas.c:530 src/memory.c:8219 msgid "Gaussian Blur" msgstr "ГауÑÑово размывание" #: src/canvas.c:558 msgid "Radius" msgstr "РадиуÑ" #: src/canvas.c:559 msgid "Amount" msgstr "Величина" #: src/canvas.c:560 msgid "Threshold " msgstr "Порог " #: src/canvas.c:570 src/memory.c:8360 msgid "Unsharp Mask" msgstr "ÐÐµÑ€ÐµÐ·ÐºÐ°Ñ Ð¼Ð°Ñка" #: src/canvas.c:599 msgid "Outer radius" msgstr "Ðаружный радиуÑ" #: src/canvas.c:600 msgid "Inner radius" msgstr "Внутренний радиуÑ" #: src/canvas.c:602 src/info.c:280 msgid "Normalize" msgstr "ÐормализациÑ" #: src/canvas.c:611 src/memory.c:8512 msgid "Difference of Gaussians" msgstr "Разница по ГауÑÑу" #: src/canvas.c:636 msgid "Protect details" msgstr "Защитить детали" #: src/canvas.c:645 msgid "Kuwahara-Nagao Blur" msgstr "Размывание Кувахары-Ðагао" #: src/canvas.c:709 msgid "The image is too large for this rotation." msgstr "Изображение Ñлишком велико Ð´Ð»Ñ Ð¿Ð¾Ð²Ð¾Ñ€Ð¾Ñ‚Ð°." #: src/canvas.c:723 msgid "Smooth" msgstr "Сглаживание" #: src/canvas.c:732 msgid "Free Rotate" msgstr "Поворот" #: src/canvas.c:989 src/viewer.c:1161 msgid "Not enough memory to create clipboard" msgstr "Ðе хватает памÑти Ð´Ð»Ñ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð±ÑƒÑ„ÐµÑ€Ð° обмена" #: src/canvas.c:1172 msgid "" "You have not allocated enough memory in the Preferences window to undo this " "action." msgstr "" "Ð’Ñ‹ не выделили доÑтаточно памÑти в окне наÑтроек Ð´Ð»Ñ Ð¾Ñ‚Ð¼ÐµÐ½Ñ‹ Ñтой операции." #: src/canvas.c:1353 msgid "Invalid palette file" msgstr "Ðеверный файл палитры" #: src/canvas.c:1383 msgid "Invalid channel file." msgstr "Ðеверный файл канала." #: src/canvas.c:1401 msgid "Raw frames" msgstr "Ðеобработанные кадры" #: src/canvas.c:1401 msgid "Composited frames" msgstr "Сведенные кадры" #: src/canvas.c:1402 msgid "Composited frames with nonzero delay" msgstr "Сведенные кадры Ñ Ð½ÐµÐ½ÑƒÐ»ÐµÐ²Ð¾Ð¹ задержкой" #: src/canvas.c:1406 msgid "Load Frames" msgstr "Загрузить кадры" #: src/canvas.c:1409 msgid "Load into Layers" msgstr "Загрузить в Ñлои" #: src/canvas.c:1415 msgid "Load First Frame" msgstr "Загрузить первый кадр" #: src/canvas.c:1416 msgid "Explode Frames" msgstr "РаÑпаковать кадры" #: src/canvas.c:1418 msgid "View Animation" msgstr "ПроÑмотреть анимацию" #: src/canvas.c:1434 #, c-format msgid "This is an animated %s file." msgstr "Это анимированный файл %s." #: src/canvas.c:1435 #, c-format msgid "This is a multipage %s file." msgstr "Это многоÑтраничный файл %s." #: src/canvas.c:1459 #, c-format msgid "File is too big, must be <= to width=%i height=%i" msgstr "Файл Ñлишком велик, должно быть <= ширина=%i выÑота=%i" #: src/canvas.c:1461 msgid "Unable to explode frames" msgstr "Ðе удалоÑÑŒ раÑпаковать кадры" #: src/canvas.c:1463 msgid "Unable to load file" msgstr "Ðе удалоÑÑŒ загрузить файл" #: src/canvas.c:1465 msgid "" "The file import library had to terminate due to a problem with the file " "(possibly corrupt image data or a truncated file). I have managed to load " "some data as the header seemed fine, but I would suggest you save this image " "to a new file to ensure this does not happen again." msgstr "" "Библиотека импорта файла вернула ошибку из-за проблемы Ñ Ñ„Ð°Ð¹Ð»Ð¾Ð¼ (возможно, " "повреждены данные изображениÑ, или файл уÑечен). ЧаÑть данных удалоÑÑŒ " "загрузить, но Ñледовало бы Ñохранить Ñту картинку в новом файле, чтобы " "проблема не повторилаÑÑŒ." #: src/canvas.c:1467 msgid "The animation is too long to load all of it into layers." msgstr "ÐÐ½Ð¸Ð¼Ð°Ñ†Ð¸Ñ Ñлишком Ð´Ð»Ð¸Ð½Ð½Ð°Ñ Ñ‡Ñ‚Ð¾Ð±Ñ‹ целиком загрузить ее в Ñлои." #: src/canvas.c:1469 msgid "Could not explode all the frames in the animation." msgstr "УдалоÑÑŒ раÑпаковать не вÑе кадры анимации." #: src/canvas.c:1481 src/font.c:1556 src/fpick.c:937 src/otherwindow.c:2765 #: src/prefs.c:321 src/toolbar.c:451 msgid "Size" msgstr "Размер" #: src/canvas.c:1484 src/otherwindow.c:244 msgid "Width" msgstr "Ширина" #: src/canvas.c:1485 src/otherwindow.c:245 msgid "Height" msgstr "Ð’Ñ‹Ñота" #: src/canvas.c:1489 src/channels.c:253 src/channels.c:317 src/fpick.c:666 #: src/fpick.c:957 src/mainwindow.c:3990 src/otherwindow.c:255 #: src/otherwindow.c:517 src/otherwindow.c:591 src/otherwindow.c:867 #: src/otherwindow.c:1058 src/otherwindow.c:1727 src/otherwindow.c:2101 #: src/otherwindow.c:2336 src/otherwindow.c:2538 src/otherwindow.c:2691 #: src/otherwindow.c:2776 src/otherwindow.c:2937 src/otherwindow.c:3070 #: src/otherwindow.c:3169 src/prefs.c:338 src/prefs.c:464 src/prefs.c:538 #: src/spawn.c:666 src/viewer.c:1258 msgid "Cancel" msgstr "Отменить" #: src/canvas.c:1490 src/channels.c:253 src/channels.c:317 src/fpick.c:956 #: src/info.c:297 src/mainwindow.c:3992 src/mygtk.c:233 src/mygtk.c:535 #: src/otherwindow.c:591 src/otherwindow.c:871 src/otherwindow.c:1058 #: src/otherwindow.c:1729 src/otherwindow.c:2101 src/otherwindow.c:2336 #: src/otherwindow.c:2538 src/otherwindow.c:2691 src/otherwindow.c:2776 #: src/otherwindow.c:3072 src/otherwindow.c:3171 src/prefs.c:338 #: src/prefs.c:538 src/spawn.c:666 msgid "OK" msgstr "OK" #: src/canvas.c:1504 #, c-format msgid "This is a scalable %s file." msgstr "Это маÑштабируемый файл %s." #: src/canvas.c:1545 msgid "Cannot open file" msgstr "Ðевозможно открыть файл" #: src/canvas.c:1546 msgid "Unsupported file format" msgstr "Ðеподдерживаемый формат файла" #: src/canvas.c:1673 #, c-format msgid "File: %s already exists. Do you want to overwrite it?" msgstr "Файл: %s уже ÑущеÑтвует. Ð’Ñ‹ хотите его перезапиÑать?" #: src/canvas.c:1674 msgid "File Found" msgstr "Файл найден" #: src/canvas.c:1674 src/mainwindow.c:1095 msgid "NO" msgstr "ÐЕТ" #: src/canvas.c:1674 src/mainwindow.c:1095 msgid "YES" msgstr "ДÐ" #: src/canvas.c:1988 msgid "Unable to export undo images" msgstr "Ðевозможно ÑкÑпортировать отмененные изображениÑ" #: src/canvas.c:1994 msgid "Unable to export ASCII file" msgstr "Ðевозможно ÑкÑпортировать ASCII файл" #: src/canvas.c:2076 src/layer.c:814 src/mainwindow.c:529 #, c-format msgid "Unable to save file: %s" msgstr "Ðевозможно Ñохранить файл: %s" #: src/canvas.c:2101 src/prefs.c:222 msgid "Transparency index" msgstr "Прозрачный цвет" #: src/canvas.c:2103 msgid "TIFF Compression" msgstr "TIFF Ñжатие" #: src/canvas.c:2105 src/prefs.c:225 msgid "JPEG Save Quality (100=High)" msgstr "JPEG качеÑтво (100=выÑшее)" #: src/canvas.c:2107 msgid "ZIP Compression (0=None)" msgstr "ZIP Ñжатие (0=нет)" #: src/canvas.c:2108 src/prefs.c:227 msgid "PNG Compression (0=None)" msgstr "PNG Ñжатие (0=нет)" #: src/canvas.c:2111 src/prefs.c:249 msgid "LZMA2 Compression (0=None)" msgstr "LZMA2 Ñжатие (0=нет)" #: src/canvas.c:2113 src/prefs.c:252 msgid "ZSTD Compression Level" msgstr "ZSTD уровень ÑжатиÑ" #: src/canvas.c:2115 src/prefs.c:231 msgid "TGA RLE Compression" msgstr "TGA RLE-Ñжатие" #: src/canvas.c:2117 msgid "LBM PackBits Compression" msgstr "LBM Ñжатие PackBits" #: src/canvas.c:2118 src/prefs.c:226 msgid "JPEG2000 Compression (0=Lossless)" msgstr "JPEG2000 Ñжатие (0=без потерь)" #: src/canvas.c:2120 msgid "WebP Compression" msgstr "WebP Ñжатие" #: src/canvas.c:2122 msgid "WebP Save Quality (100=High)" msgstr "WebP качеÑтво (100=выÑшее)" #: src/canvas.c:2123 src/prefs.c:263 msgid "V8 Save Quality (100=High)" msgstr "V8 качеÑтво (100=выÑшее)" #: src/canvas.c:2125 src/prefs.c:264 msgid "V8L Compression (0=None)" msgstr "V8L Ñжатие (0=нет)" #: src/canvas.c:2127 msgid "Hotspot at X =" msgstr "ГорÑÑ‡Ð°Ñ Ñ‚Ð¾Ñ‡ÐºÐ° at X =" #: src/canvas.c:2129 msgid "Y =" msgstr "Y =" #: src/canvas.c:2133 msgid "Animation delay" msgstr "Задержка анимации" #: src/canvas.c:2136 src/otherwindow.c:253 msgid "Undoable" msgstr "С отменой" #: src/canvas.c:2138 src/prefs.c:236 msgid "Apply colour profile" msgstr "Применить цветовой профиль" #: src/canvas.c:2176 src/toolbar.c:543 msgid "Load Image File" msgstr "Загрузить изображение" #: src/canvas.c:2191 src/toolbar.c:544 msgid "Save Image File" msgstr "Сохранить изображение" #: src/canvas.c:2196 msgid "Load Palette File" msgstr "Загрузить палитру" #: src/canvas.c:2202 msgid "Save Palette File" msgstr "Сохранить палитру" #: src/canvas.c:2207 msgid "Export Undo Images" msgstr "ЭкÑпортировать отмененные изображениÑ" #: src/canvas.c:2212 msgid "Export Undo Images (reversed)" msgstr "ЭкÑпортировать отмененные Ð¸Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ (Ñ Ð¿Ð¾Ñледнего)" #: src/canvas.c:2217 msgid "You must have 16 or fewer palette colours to export ASCII art." msgstr "" "Ð’Ñ‹ должны иметь не больше 16 цветов в палитре Ð´Ð»Ñ ÑкÑпорта ASCII картинки." #: src/canvas.c:2220 msgid "Export ASCII Art" msgstr "ЭкÑпортировать в ASCII" #: src/canvas.c:2224 msgid "Save Layer Files" msgstr "Сохранить файлы Ñлоев" #: src/canvas.c:2234 msgid "Choose frames directory" msgstr "Выберите каталог Ð´Ð»Ñ ÐºÐ°Ð´Ñ€Ð¾Ð²" #: src/canvas.c:2240 msgid "You must save at least one frame to create an animated GIF." msgstr "" "Ð’Ñ‹ должны Ñохранить по крайней мере один кадр Ð´Ð»Ñ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð°Ð½Ð¸Ð¼Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð½Ð¾Ð³Ð¾ " "GIF." #: src/canvas.c:2243 msgid "Export GIF animation" msgstr "ЭкÑпорт GIF анимации" #: src/canvas.c:2247 msgid "Load Channel" msgstr "Загрузить канал" #: src/canvas.c:2255 msgid "Save Channel" msgstr "Сохранить канал" #: src/canvas.c:2260 msgid "Save Composite Image" msgstr "Сохранить ÑоÑтавное изображение" #: src/channels.c:243 msgid "Create Channel" msgstr "Создать канал" #: src/channels.c:244 msgid "Channel Type" msgstr "Тип канала" #: src/channels.c:247 msgid "Initial Channel State" msgstr "Ðачальное ÑоÑтоÑние канала" #: src/channels.c:251 msgid "Inverted" msgstr "Инвертированный" #: src/channels.c:265 msgid "Cleared" msgstr "Очищен" #: src/channels.c:266 msgid "Set" msgstr "Заполнен" #: src/channels.c:267 msgid "Set colour A radius B" msgstr "Цвет A Ñ€Ð°Ð´Ð¸ÑƒÑ B" #: src/channels.c:268 msgid "Set blend A to B" msgstr "Переход от A к B" #: src/channels.c:269 msgid "Image Red" msgstr "Канал краÑного" #: src/channels.c:270 msgid "Image Green" msgstr "Канал зеленого" #: src/channels.c:271 msgid "Image Blue" msgstr "Канал Ñинего" #: src/channels.c:273 src/channels.c:313 src/mainwindow.c:67 #: src/otherwindow.c:1679 msgid "Alpha" msgstr "Ðльфа" #: src/channels.c:274 src/channels.c:314 src/mainwindow.c:67 #: src/otherwindow.c:1683 msgid "Selection" msgstr "Выделение" #: src/channels.c:275 src/channels.c:315 src/mainwindow.c:67 #: src/otherwindow.c:1687 msgid "Mask" msgstr "МаÑка" #: src/channels.c:312 msgid "Delete Channels" msgstr "Удалить каналы" #: src/channels.c:367 msgid "Threshold Channel" msgstr "Порог канала" #: src/cpick.c:823 src/otherwindow.c:573 src/otherwindow.c:820 #: src/toolbar.c:299 msgid "Hue" msgstr "Тон" #: src/cpick.c:827 src/otherwindow.c:573 src/otherwindow.c:818 #: src/toolbar.c:299 msgid "Saturation" msgstr "ÐаÑыщенноÑть" #: src/cpick.c:835 msgid "Hex" msgstr "" #: src/cpick.c:840 src/layer.c:1109 src/otherwindow.c:2530 src/prefs.c:323 #: src/toolbar.c:457 msgid "Opacity" msgstr "ÐепрозрачноÑть" #: src/font.c:982 msgid "Creating Font Index" msgstr "Создание индекÑа шрифтов" #: src/font.c:1353 msgid "You must select at least one directory to search for fonts." msgstr "Ð’Ñ‹ должны выбрать как минимум один каталог Ð´Ð»Ñ Ð¿Ð¾Ð¸Ñка шрифтов." #: src/font.c:1529 src/font.c:1624 src/toolbar.c:609 src/viewer.c:1213 #: src/viewer.c:1258 msgid "Paste Text" msgstr "Ð’Ñтавить текÑÑ‚" #: src/font.c:1533 src/font.c:1572 src/png.c:3578 msgid "Text" msgstr "ТекÑÑ‚" #: src/font.c:1540 msgid "Font" msgstr "Шрифт" #: src/font.c:1548 msgid "Style" msgstr "Стиль" #: src/font.c:1566 msgid "Filename" msgstr "Ð˜Ð¼Ñ Ñ„Ð°Ð¹Ð»Ð°" #: src/font.c:1567 msgid "Face" msgstr "Ðачертание" #: src/font.c:1587 src/viewer.c:1222 msgid "Antialias" msgstr "ÐнтиалиаÑинг" #: src/font.c:1590 src/viewer.c:1224 msgid "Invert" msgstr "Инвертировать" #: src/font.c:1593 src/viewer.c:1226 msgid "Background colour =" msgstr "Цвет фона =" #: src/font.c:1601 src/viewer.c:1233 msgid "DPI =" msgstr "" #: src/font.c:1610 msgid "Oblique" msgstr "Ðаклонный" #: src/font.c:1612 src/viewer.c:1244 msgid "Angle of rotation =" msgstr "Угол поворота =" #: src/font.c:1617 src/viewer.c:1248 msgid "Align" msgstr "Выравнивание" #: src/font.c:1620 src/viewer.c:1253 msgid "Spacing" msgstr "РазрÑдка" #: src/font.c:1629 msgid "Font Directories" msgstr "Каталоги шрифтов" #: src/font.c:1634 src/spawn.c:664 msgid "Directory" msgstr "Каталог" #: src/font.c:1637 msgid "New Directory" msgstr "Ðовый каталог" #: src/font.c:1644 src/prefs.c:532 msgid "Add" msgstr "Добавить" #: src/font.c:1645 src/prefs.c:533 msgid "Remove" msgstr "Удалить" #: src/font.c:1646 msgid "Create Index" msgstr "Создать индекÑ" #: src/font.c:1660 src/viewer.c:1267 msgid "Enter Text Here" msgstr "Введите текÑÑ‚ здеÑÑŒ" #: src/fpick.c:635 #, c-format msgid "Could not access directory %s" msgstr "Ðевозможно войти в каталог %s" #: src/fpick.c:668 src/fpick.c:698 msgid "Delete" msgstr "Удалить" #: src/fpick.c:669 src/fpick.c:698 msgid "Rename" msgstr "Переименовать" #: src/fpick.c:672 src/otherwindow.c:255 src/otherwindow.c:1666 msgid "Create" msgstr "Создать" #: src/fpick.c:699 msgid "Enter the new filename" msgstr "Введите новое Ð¸Ð¼Ñ Ñ„Ð°Ð¹Ð»Ð°" #: src/fpick.c:704 msgid "Create Directory" msgstr "Создать каталог" #: src/fpick.c:705 msgid "Enter the name of the new directory" msgstr "Введите Ð¸Ð¼Ñ Ð½Ð¾Ð²Ð¾Ð³Ð¾ каталога" #: src/fpick.c:729 #, c-format msgid "Do you really want to delete \"%s\" ?" msgstr "Ð’Ñ‹ дейÑтвительно хотите удалить \"%s\" ?" #: src/fpick.c:735 msgid "Unable to delete" msgstr "Ðевозможно удалить" #: src/fpick.c:741 msgid "Unable to rename" msgstr "Ðевозможно переименовать" #: src/fpick.c:750 msgid "Unable to create directory" msgstr "Ðевозможно Ñоздать каталог" #: src/fpick.c:924 msgid "Up" msgstr "Ðа уровень выше" #: src/fpick.c:925 msgid "Home" msgstr "Домашний каталог" #: src/fpick.c:926 msgid "Create New Directory" msgstr "Создать новый каталог" #: src/fpick.c:927 msgid "Show Hidden Files" msgstr "Показать Ñкрытые файлы" #: src/fpick.c:929 msgid "Case Insensitive Sort" msgstr "Ðе учитывать региÑтр" #: src/fpick.c:936 msgid "Name" msgstr "ИмÑ" #: src/fpick.c:938 msgid "Type" msgstr "Тип" #: src/fpick.c:939 msgid "Modified" msgstr "Изменен" #: src/help.c:25 src/prefs.c:160 msgid "General" msgstr "ОÑновное" #: src/help.c:26 msgid "Keyboard shortcuts" msgstr "Комбинации клавиш" #: src/help.c:27 msgid "Mouse shortcuts" msgstr "Комбинации мыши" #: src/help.c:28 msgid "Credits" msgstr "Разработчики" #: src/help.c:32 msgid "mtPaint 3.51 - Copyright (C) 2004-2021 The Authors\n" msgstr "mtPaint 3.51 - Copyright (C) 2004-2021 авторы\n" #: src/help.c:33 msgid "See 'Credits' section for a list of the authors.\n" msgstr "СпиÑок вÑех авторов Ñмотрите в закладке 'Разработчики'.\n" #: src/help.c:34 msgid "" "mtPaint 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.\n" msgstr "" "mtPaint - Ñвободное программное обеÑпечение, вы можете раÑпроÑтранÑть и/или " "изменÑть его на уÑловиÑÑ… GNU General Public License, опубликованной Free " "Software Foundation; либо верÑии 3 лицензии, либо (по вашему выбору) любой " "более поздней верÑии.\n" #: src/help.c:35 msgid "" "mtPaint 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.\n" msgstr "" "mtPaint раÑпроÑтранÑетÑÑ Ð² надежде, что он будет полезен, но БЕЗ КÐКИХ-ЛИБО " "ГÐРÐÐТИЙ; даже без подразумеваемых гарантий КОММЕРЧЕСКОЙ ПРИГОДÐОСТИ или " "ПРИГОДÐОСТИ ДЛЯ ОПРЕДЕЛЕÐÐОЙ ЦЕЛИ. Смотрите GNU General Public License Ð´Ð»Ñ " "более детальной информации.\n" #: src/help.c:36 msgid "" "mtPaint is a simple GTK+1/2/3 painting program designed for creating icons " "and pixel based artwork. It can edit indexed palette or 24 bit RGB images " "and offers basic painting and palette manipulation tools. It also has " "several other more powerful features such as channels, layers and animation. " "Due to its simplicity and lack of dependencies it runs well on GNU/Linux, " "Windows and older PC hardware.\n" msgstr "" "mtPaint - проÑÑ‚Ð°Ñ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð¼Ð° риÑÐ¾Ð²Ð°Ð½Ð¸Ñ Ð´Ð»Ñ GTK+1/2/3, Ð¿Ñ€ÐµÐ´Ð½Ð°Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ð°Ñ Ð´Ð»Ñ " "ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð¸ÐºÐ¾Ð½Ð¾Ðº и пикÑельной графики. Он может работать Ñ Ð¸Ð½Ð´ÐµÐºÑированными и " "24-битными RGB изображениÑми и предоÑтавлÑет базовые инÑтрументы Ð´Ð»Ñ " "риÑÐ¾Ð²Ð°Ð½Ð¸Ñ Ð¸ манипулÑций Ñ Ð¿Ð°Ð»Ð¸Ñ‚Ñ€Ð¾Ð¹. Он также имеет и более мощные функции, " "такие как каналы, Ñлои и анимациÑ. Из-за Ñвоей проÑтоты и отÑутÑÑ‚Ð²Ð¸Ñ " "завиÑимоÑтей программа хорошо работает под GNU/Linux, Windows и на " "компьютерах c уÑтаревшим железом.\n" #: src/help.c:37 msgid "" "There is full documentation of mtPaint's features contained in a handbook. " "If you don't already have this, you can download it from the mtPaint " "website.\n" msgstr "" "ÐŸÐ¾Ð»Ð½Ð°Ñ Ð´Ð¾ÐºÑƒÐ¼ÐµÐ½Ñ‚Ð°Ñ†Ð¸Ñ Ð¿Ð¾ возможноÑÑ‚Ñм mtPaint ÑодержитÑÑ Ð² РуководÑтве " "пользователÑ. ЕÑли у Ð²Ð°Ñ Ð½ÐµÑ‚ Ñтого РуководÑтва, вы можете Ñкачать его Ñ " "Ñайта mtPaint.\n" #: src/help.c:38 msgid "" "If you like mtPaint and you want to keep up to date with new releases, or " "you want to give some feedback, then the mailing lists may be of interest to " "you:\n" msgstr "" "ЕÑли вам понравитÑÑ mtPaint и вы хотите идти в ногу Ñ Ð½Ð¾Ð²Ñ‹Ð¼Ð¸ выпуÑками, или " "хотите поделитьÑÑ Ñвоим мнением, то Ñти ÑпиÑки раÑÑылки могут предÑтавлÑть " "Ð´Ð»Ñ Ð²Ð°Ñ Ð¸Ð½Ñ‚ÐµÑ€ÐµÑ:\n" #: src/help.c:39 msgid "http://sourceforge.net/mail/?group_id=155874" msgstr "http://sourceforge.net/mail/?group_id=155874" #: src/help.c:42 msgid " Ctrl-N Create new image" msgstr " Ctrl-N Создать новое изображение" #: src/help.c:43 msgid " Ctrl-O Open Image" msgstr " Ctrl-O Открыть изображение" #: src/help.c:44 msgid " Ctrl-S Save Image" msgstr " Ctrl-S Сохранить изображение" #: src/help.c:45 msgid " Ctrl-Shift-S Save layers file" msgstr " Ctrl-Shift-S Сохранить файл Ñлоев" #: src/help.c:46 msgid " Ctrl-Q Quit program\n" msgstr " Ctrl-Q Выйти из программы\n" #: src/help.c:47 msgid " Ctrl-A Select whole image" msgstr " Ctrl-A Выбрать вÑе изображение" #: src/help.c:48 msgid " Escape Select nothing, cancel paste box" msgstr " Escape Ðичего не выбирать, отменить вÑтавку" #: src/help.c:49 msgid " J Lasso selection\n" msgstr " J Выделение лаÑÑо\n" #: src/help.c:50 msgid " Ctrl-C Copy selection to clipboard" msgstr " Ctrl-C Копировать отмеченное в буфер обмена" #: src/help.c:51 msgid "" " Ctrl-X Copy selection to clipboard, and then paint current " "pattern to selection area" msgstr "" " Ctrl-X Копировать отмеченное в буфер обмена и закраÑить текущим " "шаблоном выбранную облаÑть" #: src/help.c:52 msgid " Ctrl-V Paste clipboard to centre of current view" msgstr " Ctrl-V Ð’Ñтавить буфер обмена в центр текущего проÑмотра" #: src/help.c:53 msgid " Ctrl-K Paste clipboard to location it was copied from" msgstr " Ctrl-K Ð’Ñтавить буфер обмена в меÑто копированиÑ" #: src/help.c:54 msgid " Ctrl-Shift-V Paste clipboard to new layer" msgstr " Ctrl-Shift-V Ð’Ñтавить буфер обмена в новый Ñлой" #: src/help.c:55 msgid " Enter/Return Commit paste to canvas" msgstr " Enter/Return ФикÑировать вÑтавку на холÑте" #: src/help.c:56 msgid " Shift+Enter/Return Commit paste and swap canvas into the clipboard\n" msgstr "" " Shift+Enter/Return ФикÑировать вÑтавку и Ñкопировать затертую ею облаÑть " "в буфер обмена\n" #: src/help.c:57 msgid " Arrow keys Paint Mode - Move the mouse pointer" msgstr " Стрелки Режим риÑÐ¾Ð²Ð°Ð½Ð¸Ñ - перемещение ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ»Ñ Ð¼Ñ‹ÑˆÐ¸" #: src/help.c:58 msgid "" " Arrow keys Selection Mode - Nudge selection box or paste box by one " "pixel" msgstr "" " Стрелки Режим Ð²Ñ‹Ð´ÐµÐ»ÐµÐ½Ð¸Ñ - перемещение прÑмоугольника выделениÑ" #: src/help.c:59 msgid "" " Shift+Arrow keys Nudge mouse pointer, selection box or paste box by x " "pixels - x is defined by the Preferences window" msgstr "" " Shift+Ñтрелки Перемещение мыши и Ð²Ñ‹Ð´ÐµÐ»ÐµÐ½Ð¸Ñ Ð½Ð° x пикÑелов - x " "определÑетÑÑ Ð² окне наÑтроек" #: src/help.c:60 msgid " Ctrl+Arrows Move layer or resize selection box" msgstr " Ctrl+Ñтрелки Перемещение ÑÐ»Ð¾Ñ Ð¸Ð»Ð¸ изменение размера выделениÑ" #: src/help.c:61 msgid " Ctrl+Shift+Arrows Move layer or resize selection box by x pixels\n" msgstr "" " Ctrl+Shift+Arrows Перемещение ÑÐ»Ð¾Ñ Ð¸Ð»Ð¸ изменение размера Ð²Ñ‹Ð´ÐµÐ»ÐµÐ½Ð¸Ñ Ð½Ð° x " "пикÑелов\n" #: src/help.c:62 msgid " Enter/Return Paint Mode - Simulate left click" msgstr " Enter/Return Режим риÑÐ¾Ð²Ð°Ð½Ð¸Ñ - Имитировать левую кнопку мыши" #: src/help.c:63 msgid " Backspace Paint Mode - Simulate right click\n" msgstr " Backspace Режим риÑÐ¾Ð²Ð°Ð½Ð¸Ñ - Имитировать правую кнопку мыши\n" #: src/help.c:64 msgid "" " [ or ] Change colour A to the next or previous palette item" msgstr "" " [ or ] Изменить цвет A на Ñледующий или предыдущий в палитре" #: src/help.c:65 msgid "" " Shift+[ or ] Change colour B to the next or previous palette item\n" msgstr "" " Shift+[ or ] Изменить цвет B на Ñледующий или предыдущий в палитре\n" #: src/help.c:66 msgid " Delete Crop image to selection" msgstr " Delete Обрезать изображение по размеру выделениÑ" #: src/help.c:67 msgid "" " Insert Transform colours - i.e. Brightness, Contrast, " "Saturation, Posterize, Gamma" msgstr "" " Insert Преобразование цветов - Ñ‚.e. ÑркоÑть, контраÑÑ‚, " "наÑыщенноÑть, поÑтеризациÑ, гамма" #: src/help.c:68 msgid " Ctrl-G Greyscale the image" msgstr " Ctrl-G Изображение - в градации Ñерого" #: src/help.c:69 msgid " Shift-Ctrl-G Greyscale the image (Gamma corrected)" msgstr "" " Shift-Ctrl-G Изображение - в градации Ñерого (Ñ Ð³Ð°Ð¼Ð¼Ð°-коррекцией)" #: src/help.c:70 msgid " Ctrl+M Mirror the image" msgstr " Ctrl+M Перевернуть изображение по горизонтали" #: src/help.c:71 msgid " Shift-Ctrl-I Invert the image\n" msgstr " Shift-Ctrl-I Инвертировать изображение\n" #: src/help.c:72 msgid "" " Ctrl-T Draw a rectangle around the selection area with the " "current fill" msgstr "" " Ctrl-T РиÑовать прÑмоугольник вокруг Ð²Ñ‹Ð´ÐµÐ»ÐµÐ½Ð¸Ñ Ñ Ñ‚ÐµÐºÑƒÑ‰Ð¸Ð¼ " "заполнением" #: src/help.c:73 msgid " Ctrl-Shift-T Fill in the selection area with the current fill" msgstr " Ctrl-Shift-T Заполнить выделенную облаÑть текущим заполнением" #: src/help.c:74 msgid " Ctrl-L Draw an ellipse spanning the selection area" msgstr " Ctrl-L РиÑовать ÑÐ»Ð»Ð¸Ð¿Ñ Ð² выделенной облаÑти" #: src/help.c:75 msgid " Ctrl-Shift-L Draw a filled ellipse spanning the selection area\n" msgstr " Ctrl-Shift-L РиÑовать заполненный ÑÐ»Ð»Ð¸Ð¿Ñ Ð² выделенной облаÑти\n" #: src/help.c:76 msgid " Ctrl-E Edit the RGB values for colours A & B" msgstr " Ctrl-E Редактировать Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ RGB Ð´Ð»Ñ Ñ†Ð²ÐµÑ‚Ð¾Ð² A и B" #: src/help.c:77 msgid " Ctrl-W Edit all palette colours\n" msgstr " Ctrl-W Редактировать вÑе цвета палитры\n" #: src/help.c:78 msgid " Ctrl-P Preferences" msgstr " Ctrl-P ÐаÑтройки" #: src/help.c:79 msgid " Ctrl-I Information\n" msgstr " Ctrl-I ИнформациÑ\n" #: src/help.c:80 msgid " Ctrl-Z Undo last action" msgstr " Ctrl-Z Отменить поÑледнее дейÑтвие" #: src/help.c:81 msgid " Ctrl-R Redo an undone action\n" msgstr " Ctrl-R Вернуть отмененное дейÑтвие\n" #: src/help.c:82 msgid " Shift-T Text Tool (GTK+)" msgstr " Shift-T Ð’Ñтавка текÑта (GTK+)" #: src/help.c:83 msgid " T Text Tool (FreeType)\n" msgstr " T Ð’Ñтавка текÑта (FreeType)\n" #: src/help.c:84 msgid " V View Window" msgstr " V Окно проÑмотра" #: src/help.c:85 msgid " L Layers Window\n" msgstr " L Окно Ñлоев\n" #: src/help.c:86 msgid " Ctrl-H Toggle Hide Image mode" msgstr " Ctrl-H Скрыть/показать изображение" #: src/help.c:87 msgid " B Toggle Snap to Tile Grid mode\n" msgstr " B Вкл/выкл прилипание к Ñетке тайлов\n" #: src/help.c:88 msgid " X Swap Colours A & B" msgstr " X ОбменÑть цвета A и B" #: src/help.c:89 msgid " E Choose Colour\n" msgstr " E Выбрать цвет\n" #: src/help.c:90 msgid "" " A Draw open arrow head when using the line tool (size set " "by flow setting)" msgstr "" " A ÐариÑовать открытую Ñтрелку в режиме риÑÐ¾Ð²Ð°Ð½Ð¸Ñ Ð»Ð¸Ð½Ð¸Ð¹ " "(размер задаетÑÑ Flow)" #: src/help.c:91 msgid "" " S Draw closed arrow head when using the line tool (size " "set by flow setting)\n" msgstr "" " S ÐариÑовать закрытую Ñтрелку в режиме риÑÐ¾Ð²Ð°Ð½Ð¸Ñ Ð»Ð¸Ð½Ð¸Ð¹ " "(размер задаетÑÑ Flow)\n" #: src/help.c:92 msgid " D Line Tool" msgstr " D ИнÑтрумент риÑÐ¾Ð²Ð°Ð½Ð¸Ñ Ð»Ð¸Ð½Ð¸Ð¹" #: src/help.c:93 msgid " F Flood Fill Tool\n" msgstr " F ИнÑтрумент заливки\n" #: src/help.c:94 msgid " +,= Main edit window - Zoom in" msgstr " +,= Увеличить маÑштаб главного окна" #: src/help.c:95 msgid " - Main edit window - Zoom out" msgstr " - Уменьшить маÑштаб главного окна" #: src/help.c:96 msgid " Shift +,= View window - Zoom in" msgstr " Shift +,= Увеличить маÑштаб проÑмотра" #: src/help.c:97 msgid " Shift - View window - Zoom out\n" msgstr " Shift - Уменьшить маÑштаб проÑмотра\n" #: src/help.c:98 #, c-format msgid " 1 10% zoom" msgstr " 1 МаÑштаб 10%" #: src/help.c:99 #, c-format msgid " 2 25% zoom" msgstr " 2 МаÑштаб 25%" #: src/help.c:100 #, c-format msgid " 3 50% zoom" msgstr " 3 МаÑштаб 50%" #: src/help.c:101 #, c-format msgid " 4 100% zoom" msgstr " 4 МаÑштаб 100%" #: src/help.c:102 #, c-format msgid " 5 400% zoom" msgstr " 5 МаÑштаб 400%" #: src/help.c:103 #, c-format msgid " 6 800% zoom" msgstr " 6 МаÑштаб 800%" #: src/help.c:104 #, c-format msgid " 7 1200% zoom" msgstr " 7 МаÑштаб 1200%" #: src/help.c:105 #, c-format msgid " 8 1600% zoom" msgstr " 8 МаÑштаб 1600%" #: src/help.c:106 #, c-format msgid " 9 2000% zoom\n" msgstr " 9 МаÑштаб 2000%\n" #: src/help.c:107 msgid " Shift + 1 Edit image channel" msgstr " Shift + 1 Редактировать канал изображениÑ" #: src/help.c:108 msgid " Shift + 2 Edit alpha channel" msgstr " Shift + 2 Редактировать альфа-канал" #: src/help.c:109 msgid " Shift + 3 Edit selection channel" msgstr " Shift + 3 Редактировать канал выделениÑ" #: src/help.c:110 msgid " Shift + 4 Edit mask channel\n" msgstr " Shift + 4 Редактировать канал маÑки\n" #: src/help.c:111 msgid " F1 Help" msgstr " F1 Справка" #: src/help.c:112 msgid " F2 Choose Pattern" msgstr " F2 Выбор шаблона" #: src/help.c:113 msgid " F3 Choose Brush" msgstr " F3 Выбор киÑти" #: src/help.c:114 msgid " F4 Paint Tool" msgstr " F4 ИнÑтрумент риÑованиÑ" #: src/help.c:115 msgid " F5 Toggle Main Toolbar" msgstr " F5 Вкл/выкл главную панель" #: src/help.c:116 msgid " F6 Toggle Tools Toolbar" msgstr " F6 Вкл/выкл панель инÑтрументов" #: src/help.c:117 msgid " F7 Toggle Settings Toolbar" msgstr " F7 Вкл/выкл панель уÑтановок" #: src/help.c:118 msgid " F8 Toggle Palette" msgstr " F8 Вкл/выкл палитру" #: src/help.c:119 msgid " F9 Selection Tool" msgstr " F9 ИнÑтрумент выбора" #: src/help.c:120 msgid " F12 Toggle Dock Area\n" msgstr " F12 Вкл/выкл боковую панель\n" #: src/help.c:121 msgid " Ctrl + F1 - F12 Save current clipboard to file 1-12" msgstr " Ctrl + F1 - F12 Сохранить буфер обмена в файл 1-12" #: src/help.c:122 msgid " Shift + F1 - F12 Load clipboard from file 1-12\n" msgstr " Shift + F1 - F12 Загрузить буфер обмена из файла 1-12\n" #: src/help.c:123 msgid "" " Ctrl + 1, 2, ... , 0 Set opacity to 10%, 20%, ... , 100% (main or keypad " "numbers)" msgstr "" " Ctrl + 1, 2, ... , 0 УÑтановить непрозрачноÑть 10%, 20%, ... , 100% " "(оÑновной или цифровой клавиатурой)" #: src/help.c:124 msgid " Ctrl + + or = Increase opacity by 1" msgstr " Ctrl + + or = Увеличение непрозрачноÑти на 1" #: src/help.c:125 msgid " Ctrl + - Decrease opacity by 1\n" msgstr " Ctrl + - Уменьшение непрозрачноÑти на 1\n" #: src/help.c:126 msgid "" " Home Show or hide main window menu/toolbar/status bar/palette" msgstr "" " Home Показать или Ñкрыть главное меню/панель инÑтрументов/" "Ñтроку ÑтатуÑа/палитру" #: src/help.c:127 msgid " Page Up Scale Image" msgstr " Page Up МаÑштабирование изображениÑ" #: src/help.c:128 msgid " Page Down Resize Image canvas" msgstr " Page Down Изменение размера холÑта" #: src/help.c:129 msgid " End Pan Window" msgstr " End Окно навигации" #: src/help.c:132 msgid " Left button Paint to canvas using the current tool" msgstr " Ð›ÐµÐ²Ð°Ñ ÐºÐ½Ð¾Ð¿ÐºÐ° РиÑовать на холÑте выбранным инÑтрументом" #: src/help.c:133 msgid "" " Middle button Selects the point which will be the centre of the " "image after the next zoom" msgstr "" " СреднÑÑ ÐºÐ½Ð¾Ð¿ÐºÐ° Выделить точку, ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ð±ÑƒÐ´ÐµÑ‚ в центре Ð¸Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ " "поÑле Ñледующего увеличениÑ" #: src/help.c:134 msgid "" " Right button Commit paste to canvas / Stop drawing current line / " "Cancel selection\n" msgstr "" " ÐŸÑ€Ð°Ð²Ð°Ñ ÐºÐ½Ð¾Ð¿ÐºÐ° ЗафикÑировать вÑтавку на холÑÑ‚ / ОÑтановить риÑование " "текущей линии / Отменить выделение\n" #: src/help.c:135 msgid "" " Scroll Wheel In GTK+2/3 the user can have the scroll wheel zoom in " "or out via the Preferences window\n" msgstr "" " КолеÑо мыши Ð’ GTK+2/3 пользователь может маÑштабировать " "изображение, включив Ñту возможноÑть в наÑтройках\n" #: src/help.c:136 msgid " Ctrl+Left button Choose colour A from under mouse pointer" msgstr " Ctrl+Ð›ÐµÐ²Ð°Ñ ÐºÐ½Ð¾Ð¿ÐºÐ° Выбрать цвет Риз-под ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ»Ñ Ð¼Ñ‹ÑˆÐ¸" #: src/help.c:137 msgid " Ctrl+Left button Clone tool - Select source" msgstr " Ctrl+Ð›ÐµÐ²Ð°Ñ ÐºÐ½Ð¾Ð¿ÐºÐ° Клонирование - выбрать иÑточник" #: src/help.c:138 msgid "" " Ctrl+Middle button Create colour A/B and pattern based on the RGB colour " "in A (RGB images only)" msgstr "" " Ctrl+СреднÑÑ ÐºÐ½Ð¾Ð¿ÐºÐ° Создать цвет A/B и шаблон на базе RGB цвета A (только " "Ð´Ð»Ñ RGB изображений)" #: src/help.c:139 msgid " Ctrl+Right button Choose colour B from under mouse pointer" msgstr " Ctrl+ÐŸÑ€Ð°Ð²Ð°Ñ ÐºÐ½Ð¾Ð¿ÐºÐ° Выбрать цвет B из-под ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ»Ñ Ð¼Ñ‹ÑˆÐ¸" #: src/help.c:140 msgid "" " Ctrl+Right button Polygon tool - Delete last point / Delete nearest " "point" msgstr "" " Ctrl+ÐŸÑ€Ð°Ð²Ð°Ñ ÐºÐ½Ð¾Ð¿ÐºÐ° Многоугольник - Удалить поÑледнюю/ближайшую вершину" #: src/help.c:141 msgid " Ctrl+Scroll Wheel Scroll the main edit window left or right\n" msgstr " Ctrl+КолеÑо мыши Прокручивать главное окно влево или вправо\n" #: src/help.c:142 msgid "" " Ctrl+Double click Set colour A or B to average colour under brush " "square or selection marquee (RGB only)\n" msgstr "" " Ctrl+Двойной щелчок УÑтановить цвет A или B в уÑредненный цвет облаÑти " "под киÑтью или в рамке Ð²Ñ‹Ð´ÐµÐ»ÐµÐ½Ð¸Ñ (только RGB)\n" #: src/help.c:143 msgid "" " Shift+Right button Selects the point which will be the centre of the " "image after the next zoom\n" "\n" msgstr "" " Shift+ÐŸÑ€Ð°Ð²Ð°Ñ ÐºÐ½Ð¾Ð¿ÐºÐ° Выбрать точку, ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ð±ÑƒÐ´ÐµÑ‚ в центре поÑле " "Ñледующего маÑштабированиÑ\n" "\n" #: src/help.c:144 msgid "You can fixate the X/Y co-ordinates while moving the mouse:\n" msgstr "Ð’Ñ‹ можете фикÑировать X/Y координаты при перемещении мыши:\n" #: src/help.c:145 msgid " Shift Constrain mouse movements to vertical line" msgstr " Shift Удержание Ð´Ð²Ð¸Ð¶ÐµÐ½Ð¸Ñ Ð¼Ñ‹ÑˆÐ¸ Ñтрого по вертикали" #: src/help.c:146 msgid " Shift+Ctrl Constrain mouse movements to horizontal line" msgstr " Shift+Ctrl Удержание Ð´Ð²Ð¸Ð¶ÐµÐ½Ð¸Ñ Ð¼Ñ‹ÑˆÐ¸ Ñтрого по горизонтали" #: src/help.c:149 msgid "mtPaint is maintained by Dmitry Groshev.\n" msgstr "mtPaint Ñопровождает Дмитрий Грошев.\n" #: src/help.c:150 msgid "wjaguar@users.sourceforge.net" msgstr "wjaguar@users.sourceforge.net" #: src/help.c:151 msgid "http://mtpaint.sourceforge.net/\n" msgstr "http://mtpaint.sourceforge.net/\n" #: src/help.c:152 msgid "" "The following people (in alphabetical order) have contributed directly to " "the project, and are therefore worthy of gracious thanks for their " "generosity and hard work:\n" "\n" msgstr "" "Следующие лица (в алфавитном порÑдке) внеÑли Ñвой вклад непоÑредÑтвенно в " "проект, и поÑтому заÑлуживает щедрой благодарноÑти за их великодушие и " "трудолюбие:\n" "\n" #: src/help.c:153 msgid "Authors\n" msgstr "Ðвторы\n" #: src/help.c:154 msgid "" "Dmitry Groshev - Contributing developer for version 2.30. Lead developer and " "maintainer from version 3.00 to the present." msgstr "" "Дмитрий Грошев - учаÑтник разработки верÑии 2.30. Ведущий разработчик и " "руководитель проекта Ñ Ð²ÐµÑ€Ñии 3.00 по наÑтоÑщее времÑ." #: src/help.c:155 msgid "" "Mark Tyler - Original author and maintainer up to version 3.00, occasional " "contributor thereafter." msgstr "" "Mark Tyler - автор программы и руководитель проекта до верÑии 3.00, " "продолжает делать Ñвой вклад Ð²Ñ€ÐµÐ¼Ñ Ð¾Ñ‚ времени." #: src/help.c:156 msgid "" "Xiaolin Wu - Wrote the Wu quantizing method - see wu.c for more " "information.\n" "\n" msgstr "" "Xiaolin Wu - напиÑал метод квантизации Wu - Ñмотрите wu.c Ð´Ð»Ñ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ " "дополнительной информации.\n" "\n" #: src/help.c:157 msgid "" "General Contributions (Feedback and Ideas for improvements unless otherwise " "stated)\n" msgstr "" "Общие вклады (Ð¾Ð±Ñ€Ð°Ñ‚Ð½Ð°Ñ ÑвÑзь и идеи Ð´Ð»Ñ ÑƒÐ»ÑƒÑ‡ÑˆÐµÐ½Ð¸Ð¹, еÑли не указано иное)\n" #: src/help.c:158 msgid "Abdulla Al Muhairi - Website redesign April 2005" msgstr "Abdulla Al Muhairi - редизайн Ñайта, апрель 2005" #: src/help.c:159 msgid "Alan Horkan" msgstr "" #: src/help.c:160 msgid "Alexandre Prokoudine" msgstr "ÐлекÑандр Прокудин" #: src/help.c:161 msgid "Antonio Andrea Bianco" msgstr "" #: src/help.c:162 msgid "Charlie Ledocq" msgstr "" #: src/help.c:163 msgid "Dennis Lee" msgstr "" #: src/help.c:164 msgid "Donald White" msgstr "" #: src/help.c:165 msgid "Ed Jason" msgstr "" #: src/help.c:166 msgid "" "Eddie Kohler - Created Gifsicle which is needed for the creation and viewing " "of animated GIF files http://www.lcdf.org/gifsicle/" msgstr "" "Eddie Kohler - Ñоздал Gifsicle, ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ð½ÐµÐ¾Ð±Ñ…Ð¾Ð´Ð¸Ð¼Ð° Ð´Ð»Ñ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð¸ проÑмотра " "анимированных GIF файлов http://www.lcdf.org/gifsicle/" #: src/help.c:167 msgid "" "Guadalinex Team (Junta de Andalucia) - man page, Launchpad/Rosetta " "registration" msgstr "" "Guadalinex Team (Junta de Andalucia) - Ñтраница руководÑтва, региÑÑ‚Ñ€Ð°Ñ†Ð¸Ñ Ð½Ð° " "Launchpad/Rosetta" #: src/help.c:168 msgid "Lou Afonso" msgstr "" #: src/help.c:169 msgid "Magnus Hjorth" msgstr "" #: src/help.c:170 msgid "Martin Zelaia" msgstr "" #: src/help.c:171 msgid "Pasi Kallinen" msgstr "" #: src/help.c:172 msgid "Pavel Ruzicka" msgstr "" #: src/help.c:173 msgid "Puppy Linux (Barry Kauler)" msgstr "" #: src/help.c:174 msgid "Victor Copovi" msgstr "" #: src/help.c:175 msgid "Vlastimil Krejcir" msgstr "" #: src/help.c:176 msgid "" "William Kern\n" "\n" msgstr "" #: src/help.c:177 msgid "Translations\n" msgstr "Переводы\n" #: src/help.c:178 msgid "Brazilian Portuguese - Paulo Trevizan, Valter Nazianzeno" msgstr "БразильÑкий португальÑкий - Paulo Trevizan, Valter Nazianzeno" #: src/help.c:179 msgid "Czech - Pavel Ruzicka, Martin Petricek, Roman Hornik, Pavel Fric" msgstr "ЧешÑкий - Pavel Ruzicka, Martin Petricek, Roman Hornik, Pavel Fric" #: src/help.c:180 msgid "Dutch - Hans Strijards, Pjotr" msgstr "ГолландÑкий - Hans Strijards, Pjotr" #: src/help.c:181 msgid "" "French - Nicolas Velin, Pascal Billard, Sylvain Cresto, Johan Serre, " "Philippe Etienne, Victor Copovi" msgstr "" "ФранцузÑкий - Nicolas Velin, Pascal Billard, Sylvain Cresto, Johan Serre, " "Philippe Etienne, Victor Copovi" #: src/help.c:182 msgid "Galician - Miguel Anxo Bouzada" msgstr "ГалиÑийÑкий - Miguel Anxo Bouzada" #: src/help.c:183 msgid "German - Oliver Frommel, B. Clausius, Ulrich Ringel, Simon Brixel" msgstr "Ðемецкий - Oliver Frommel, B. Clausius, Ulrich Ringel, Simon Brixel" #: src/help.c:184 msgid "Hungarian - Ur Balazs" msgstr "ВенгерÑкий - Ur Balazs" #: src/help.c:185 msgid "Italian - Angelo Gemmi" msgstr "ИтальÑнÑкий - Angelo Gemmi" #: src/help.c:186 msgid "Japanese - Norihiro YONEDA" msgstr "ЯпонÑкий - Norihiro YONEDA" #: src/help.c:187 msgid "Kabyle - Yacine Bouklif" msgstr "КабильÑкий - Yacine Bouklif" #: src/help.c:188 msgid "Polish - Bartosz Kaszubowski, LucaS" msgstr "ПольÑкий - Bartosz Kaszubowski, LucaS" #: src/help.c:189 msgid "Portuguese - Israel G. Lugo, Tiago Silva" msgstr "ПортугальÑкий - Israel G. Lugo, Tiago Silva" #: src/help.c:190 msgid "Russian - Sergey Irupin, Dmitry Groshev" msgstr "РуÑÑкий - Сергей Ирюпин, Дмитрий Грошев" #: src/help.c:191 msgid "Simplified Chinese - Cecc" msgstr "КитайÑкий - Cecc" #: src/help.c:192 msgid "Slovak - Jozef Riha" msgstr "Словацкий - Jozef Riha" #: src/help.c:193 msgid "" "Spanish - Guadalinex Team (Junta de Andalucia), Antonio Sanchez Leon, Miguel " "Anxo Bouzada, Francisco Jose Rey, Adolfo Jayme" msgstr "" "ИÑпанÑкий - Guadalinex Team (Junta de Andalucia), Antonio Sanchez Leon, " "Miguel Anxo Bouzada, Francisco Jose Rey, Adolfo Jayme" #: src/help.c:194 msgid "Swedish - Daniel Nylander, Daniel Eriksson" msgstr "ШведÑкий - Daniel Nylander, Daniel Eriksson" #: src/help.c:195 msgid "Tagalog - Anjelo delCarmen" msgstr "ТагальÑкий - Anjelo delCarmen" #: src/help.c:196 msgid "Taiwanese Chinese - Wei-Lun Chao" msgstr "ТайванÑкий китайÑкий - Wei-Lun Chao" #: src/help.c:197 msgid "Turkish - Muhammet Kara, Tutku Dalmaz" msgstr "Турецкий - Muhammet Kara, Tutku Dalmaz" #: src/info.c:258 msgid "Information" msgstr "ИнформациÑ" #: src/info.c:260 msgid "Memory" msgstr "ПамÑть" #: src/info.c:261 msgid "Total memory for main + undo images" msgstr "Ð’Ñего памÑти Ð´Ð»Ñ Ð³Ð»Ð°Ð²Ð½Ð¾Ð³Ð¾ Ð¸Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ + отмены" #: src/info.c:263 msgid "Undo / Redo / Max levels used" msgstr "Отмена/Возврат/МакÑÐ¸Ð¼Ð°Ð»ÑŒÐ½Ð°Ñ Ð³Ð»ÑƒÐ±Ð¸Ð½Ð° отмены" #: src/info.c:265 msgid "Unused" msgstr "ÐеиÑпользуемые" #: src/info.c:269 msgid "Unique RGB pixels" msgstr "Уникальные RGB пикÑелы" #: src/info.c:272 src/layer.c:121 msgid "Layers" msgstr "Слои" #: src/info.c:273 msgid "Total layer memory usage" msgstr "Ð’Ñего памÑти Ð´Ð»Ñ Ñлоев" #: src/info.c:277 msgid "Colour Histogram" msgstr "ГиÑтограмма цветов" #: src/info.c:289 src/otherwindow.c:1614 msgid "Index" msgstr "ИндекÑ" #: src/info.c:290 msgid "Canvas pixels" msgstr "ПикÑелов в изображении" #: src/info.c:328 #, c-format msgid "Clipboard = %i x %i" msgstr "Буфер обмена = %i x %i" #: src/info.c:328 #, c-format msgid "Clipboard = %i x %i x RGB" msgstr "Буфер обмена = %i x %i x RGB" #: src/info.c:377 msgid "Orphans" msgstr "ПикÑелов вне палитры" #: src/info.c:383 #, c-format msgid "Colour index totals - %i of %i used" msgstr "Итоги по палитре - иÑпользуетÑÑ %i из %i" #: src/inifile.c:966 msgid "" "Could not find home directory. Using current directory as home directory." msgstr "" "Ðе удалоÑÑŒ найти домашний каталог. ИÑпользую текущий каталог в качеÑтве " "домашнего." #: src/layer.c:63 msgid "Background" msgstr "Фон" #: src/layer.c:122 src/mainwindow.c:5931 msgid "(Modified)" msgstr "(изменено)" #: src/layer.c:123 src/mainwindow.c:5932 msgid "Untitled" msgstr "Без названиÑ" #: src/layer.c:308 #, c-format msgid "Do you really want to delete layer %i (%s) ?" msgstr "Ð’Ñ‹ дейÑтвительно хотите удалить Ñлой %i (%s) ?" #: src/layer.c:380 msgid "" "One or more of the layers contains changes that have not been saved. Do you " "really want to lose these changes?" msgstr "" "Ð˜Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð² одном или неÑкольких ÑлоÑÑ… не Ñохранены. Ð’Ñ‹ дейÑтвительно хотите " "потерÑть изменениÑ?" #: src/layer.c:381 src/mainwindow.c:1028 msgid "Cancel Operation" msgstr "Отменить операцию" #: src/layer.c:381 src/mainwindow.c:1028 msgid "Lose Changes" msgstr "ÐŸÐ¾Ñ‚ÐµÑ€Ñ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ð¹" #: src/layer.c:523 #, c-format msgid "%d layers failed to load" msgstr "%d Ñлоев загрузить не удалоÑÑŒ" #: src/layer.c:826 msgid "" "One or more of the image layers has not been saved. You must save each " "image individually before saving the layers text file in order to load this " "composite image in the future." msgstr "" "Один или неÑколько Ñлоев Ð¸Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ð½Ðµ были Ñохранены. Ð’Ñ‹ должны Ñохранить " "каждое Ð¸Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ð¿Ð¾ отдельноÑти перед Ñохранением файла Ñлоев Ð´Ð»Ñ Ð·Ð°Ð³Ñ€ÑƒÐ·ÐºÐ¸ " "Ñтого ÑоÑтавного Ð¸Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ð² будущем." #: src/layer.c:841 msgid "Do you really want to delete all of the layers?" msgstr "Ð’Ñ‹ дейÑтвительно хотите удалить вÑе Ñлои?" #: src/layer.c:970 msgid "You cannot add any more layers." msgstr "Ð’Ñ‹ не можете добавлÑть новые Ñлои." #: src/layer.c:1083 src/otherwindow.c:241 msgid "New Layer" msgstr "Ðовый Ñлой" #: src/layer.c:1085 msgid "Raise" msgstr "ПоднÑть" #: src/layer.c:1087 msgid "Lower" msgstr "ОпуÑтить" #: src/layer.c:1089 msgid "Duplicate Layer" msgstr "Дублировать Ñлой" #: src/layer.c:1091 msgid "Centralise Layer" msgstr "Центрировать Ñлой" #: src/layer.c:1093 msgid "Delete Layer" msgstr "Удалить Ñлой" #: src/layer.c:1095 msgid "Close Layers Window" msgstr "Закрыть окно Ñлоев" #: src/layer.c:1101 msgid "Layer Name" msgstr "Ð˜Ð¼Ñ ÑлоÑ" #: src/layer.c:1104 src/toolbar.c:209 msgid "Position" msgstr "ПозициÑ" #: src/layer.c:1112 msgid "Transparent Colour" msgstr "Прозрачный цвет" #: src/layer.c:1117 msgid "Show all layers in main window" msgstr "Показать вÑе Ñлои в главном окне" #: src/mainwindow.c:67 src/otherwindow.c:844 src/otherwindow.c:2756 #: src/toolbar.c:342 msgid "Image" msgstr "Изображение" #: src/mainwindow.c:69 src/mainwindow.c:489 src/otherwindow.c:1613 #: src/otherwindow.c:2302 msgid "RGB" msgstr "" #: src/mainwindow.c:69 src/otherwindow.c:1613 src/otherwindow.c:2302 msgid "sRGB" msgstr "" #: src/mainwindow.c:342 msgid "There were no unused colours to remove!" msgstr "ÐеиÑпользуемых цветов нет!" #: src/mainwindow.c:371 msgid "The palette does not contain 2 colours that have identical RGB values" msgstr "Палитра не Ñодержит цветов Ñ Ð¾Ð´Ð¸Ð½Ð°ÐºÐ¾Ð²Ñ‹Ð¼Ð¸ значениÑми RGB" #: src/mainwindow.c:374 #, c-format msgid "" "The palette contains %i colours that have identical RGB values. Do you " "really want to merge them into one index and realign the canvas?" msgstr "" "Палитра Ñодержит %i цветов Ñ Ð¾Ð´Ð¸Ð½Ð°ÐºÐ¾Ð²Ñ‹Ð¼Ð¸ значениÑми RGB. Ð’Ñ‹ дейÑтвительно " "хотите объединить их в один Ð¸Ð½Ð´ÐµÐºÑ Ð¸ обновить холÑÑ‚?" #: src/mainwindow.c:492 msgid "indexed" msgstr "Ñ Ð¿Ð°Ð»Ð¸Ñ‚Ñ€Ð¾Ð¹" #: src/mainwindow.c:498 #, c-format msgid "" "You are trying to save an %s image to an %s file which is not possible. I " "would suggest you save with a PNG extension." msgstr "" "Ð’Ñ‹ пытаетеÑÑŒ Ñохранить изображение %s в файл %s, что невозможно. Предлагаю " "вам Ñохранить его Ñ Ñ€Ð°Ñширением PNG." #: src/mainwindow.c:500 #, c-format msgid "" "You are trying to save an %s file with a palette of more than %d colours. " "Either use another format or reduce the palette to %d colours." msgstr "" "Ð’Ñ‹ пытаетеÑÑŒ Ñохранить %s файл Ñ Ð¿Ð°Ð»Ð¸Ñ‚Ñ€Ð¾Ð¹ более %d цветов. ИÑпользуйте " "другой формат либо уменьшите палитру до %d цветов." #: src/mainwindow.c:578 msgid "Unable to load clipboard" msgstr "Ðевозможно загрузить буфер обмена" #: src/mainwindow.c:604 msgid "Unable to save clipboard" msgstr "Ðевозможно Ñохранить буфер обмена" #: src/mainwindow.c:775 msgid "Zoom in" msgstr "Увеличить маÑштаб" #: src/mainwindow.c:777 msgid "Zoom out" msgstr "Уменьшить маÑштаб" #: src/mainwindow.c:779 #, c-format msgid "10% zoom" msgstr "МаÑштаб 10%" #: src/mainwindow.c:781 #, c-format msgid "25% zoom" msgstr "МаÑштаб 25%" #: src/mainwindow.c:783 #, c-format msgid "50% zoom" msgstr "МаÑштаб 50%" #: src/mainwindow.c:785 #, c-format msgid "100% zoom" msgstr "МаÑштаб 100%" #: src/mainwindow.c:787 #, c-format msgid "400% zoom" msgstr "МаÑштаб 400%" #: src/mainwindow.c:789 #, c-format msgid "600% zoom" msgstr "МаÑштаб 600%" #: src/mainwindow.c:791 #, c-format msgid "800% zoom" msgstr "МаÑштаб 800%" #: src/mainwindow.c:793 #, c-format msgid "1000% zoom" msgstr "МаÑштаб 1000%" #: src/mainwindow.c:795 #, c-format msgid "1200% zoom" msgstr "МаÑштаб 1200%" #: src/mainwindow.c:797 #, c-format msgid "1600% zoom" msgstr "МаÑштаб 1600%" #: src/mainwindow.c:799 #, c-format msgid "2000% zoom" msgstr "МаÑштаб 2000%" #: src/mainwindow.c:801 #, c-format msgid "4000% zoom" msgstr "МаÑштаб 4000%" #: src/mainwindow.c:803 #, c-format msgid "8000% zoom" msgstr "МаÑштаб 8000%" #: src/mainwindow.c:805 #, c-format msgid "10% opacity" msgstr "ÐепрозрачноÑть 10%" #: src/mainwindow.c:807 #, c-format msgid "20% opacity" msgstr "ÐепрозрачноÑть 20%" #: src/mainwindow.c:809 #, c-format msgid "30% opacity" msgstr "ÐепрозрачноÑть 30%" #: src/mainwindow.c:811 #, c-format msgid "40% opacity" msgstr "ÐепрозрачноÑть 40%" #: src/mainwindow.c:813 #, c-format msgid "50% opacity" msgstr "ÐепрозрачноÑть 50%" #: src/mainwindow.c:815 #, c-format msgid "60% opacity" msgstr "ÐепрозрачноÑть 60%" #: src/mainwindow.c:817 #, c-format msgid "70% opacity" msgstr "ÐепрозрачноÑть 70%" #: src/mainwindow.c:819 #, c-format msgid "80% opacity" msgstr "ÐепрозрачноÑть 80%" #: src/mainwindow.c:821 #, c-format msgid "90% opacity" msgstr "ÐепрозрачноÑть 90%" #: src/mainwindow.c:823 #, c-format msgid "100% opacity" msgstr "ÐепрозрачноÑть 100%" #: src/mainwindow.c:825 msgid "Increase opacity" msgstr "Увеличить непрозрачноÑть" #: src/mainwindow.c:827 msgid "Decrease opacity" msgstr "Уменьшить непрозрачноÑть" #: src/mainwindow.c:829 msgid "Draw open arrow head" msgstr "ÐариÑовать открытую Ñтрелку" #: src/mainwindow.c:831 msgid "Draw closed arrow head" msgstr "ÐариÑовать закрытую Ñтрелку" #: src/mainwindow.c:833 msgid "Previous colour A" msgstr "Предыдущий цвет A" #: src/mainwindow.c:835 msgid "Next colour A" msgstr "Следующий цвет A" #: src/mainwindow.c:837 msgid "Previous colour B" msgstr "Предыдущий цвет B" #: src/mainwindow.c:839 msgid "Next colour B" msgstr "Следующий цвет B" #: src/mainwindow.c:841 msgid "Previous pattern" msgstr "Предыдущий шаблон" #: src/mainwindow.c:843 msgid "Next pattern" msgstr "Следующий шаблон" #: src/mainwindow.c:845 msgid "Larger brush" msgstr "Увеличить киÑть" #: src/mainwindow.c:847 msgid "Smaller brush" msgstr "Уменьшить киÑть" #: src/mainwindow.c:849 msgid "View window - Zoom in" msgstr "Увеличить маÑштаб проÑмотра" #: src/mainwindow.c:851 msgid "View window - Zoom out" msgstr "Уменьшить маÑштаб проÑмотра" #: src/mainwindow.c:1027 msgid "" "This canvas/palette contains changes that have not been saved. Do you " "really want to lose these changes?" msgstr "" "Этот холÑÑ‚/палитра Ñодержит изменениÑ, которые не были Ñохранены. Ð’Ñ‹ " "дейÑтвительно хотите потерÑть Ñти изменениÑ?" #: src/mainwindow.c:1094 msgid "Do you really want to quit?" msgstr "Ð’Ñ‹ дейÑтвительно хотите выйти?" #: src/mainwindow.c:3754 msgid "Empty string or broken quoting" msgstr "ПуÑÑ‚Ð°Ñ Ñтрока или неверные кавычки" #: src/mainwindow.c:3755 msgid "Script must begin with a command" msgstr "Сценарий должен начинатьÑÑ Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ‹" #: src/mainwindow.c:3756 msgid "Script nesting limit exceeded" msgstr "Ð—Ð°Ð¿Ñ€ÐµÐ´ÐµÐ»ÑŒÐ½Ð°Ñ Ð³Ð»ÑƒÐ±Ð¸Ð½Ð° Ð²Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ñценариев" #: src/mainwindow.c:3765 #, c-format msgid "'%s' does not match any item" msgstr "'%s' не Ñовпало ни Ñ ÐºÐ°ÐºÐ¸Ð¼ Ñлементом" #: src/mainwindow.c:3767 #, c-format msgid "'%s' matches a non-scriptable item" msgstr "'%s' Ñовпало Ñ Ñлементом, недоÑтупным из ÑценариÑ" #: src/mainwindow.c:3769 #, c-format msgid "'%s' matches a disabled item" msgstr "'%s' Ñовпало Ñ Ð¾Ñ‚ÐºÐ»ÑŽÑ‡ÐµÐ½Ð½Ñ‹Ð¼ Ñлементом" #: src/mainwindow.c:3788 #, c-format msgid "'%s' value does not fit item" msgstr "'%s' значение не подошло Ñлементу" #: src/mainwindow.c:3969 msgid "Script" msgstr "Сценарий" #: src/mainwindow.c:3982 src/spawn.c:656 src/spawn.c:662 msgid "Action" msgstr "ДейÑтвие" #: src/mainwindow.c:3991 src/spawn.c:666 msgid "Execute" msgstr "Выполнить" #: src/mainwindow.c:4045 msgid "Unable to load script" msgstr "Ðевозможно загрузить Ñценарий" #: src/mainwindow.c:5182 msgid "/_File" msgstr "/_Файл" #: src/mainwindow.c:5184 msgid "//New" msgstr "//Ðовый" #: src/mainwindow.c:5186 msgid "//Open ..." msgstr "//Открыть ..." #: src/mainwindow.c:5188 src/mainwindow.c:5669 msgid "//Save" msgstr "//Сохранить" #: src/mainwindow.c:5190 src/mainwindow.c:5549 src/mainwindow.c:5627 #: src/mainwindow.c:5671 msgid "//Save As ..." msgstr "//Сохранить как ..." #: src/mainwindow.c:5192 msgid "//Export Undo Images ..." msgstr "//ЭкÑпорт отмененных изображений ..." #: src/mainwindow.c:5194 msgid "//Export Undo Images (reversed) ..." msgstr "//ЭкÑпорт отмененных изображений (Ñ ÐºÐ¾Ð½Ñ†Ð°) ..." #: src/mainwindow.c:5196 msgid "//Export ASCII Art ..." msgstr "//ЭкÑпорт ASCII картинки ..." #: src/mainwindow.c:5198 msgid "//Export Animated GIF ..." msgstr "//ЭкÑпорт анимированного GIF ..." #: src/mainwindow.c:5201 msgid "//Actions" msgstr "//ДейÑтвиÑ" #: src/mainwindow.c:5235 src/mainwindow.c:5488 msgid "///Configure" msgstr "///ÐаÑтроить" #: src/mainwindow.c:5290 msgid "//Quit" msgstr "//Выход" #: src/mainwindow.c:5293 msgid "/_Edit" msgstr "/_Правка" #: src/mainwindow.c:5295 msgid "//Undo" msgstr "//Отменить" #: src/mainwindow.c:5297 msgid "//Redo" msgstr "//Вернуть" #: src/mainwindow.c:5300 msgid "//Cut" msgstr "//Вырезать" #: src/mainwindow.c:5302 msgid "//Copy" msgstr "//Копировать" #: src/mainwindow.c:5304 msgid "//Copy To Palette" msgstr "//Копировать в палитру" #: src/mainwindow.c:5306 msgid "//Paste To Centre" msgstr "//Ð’Ñтавить в центр" #: src/mainwindow.c:5308 msgid "//Paste To New Layer" msgstr "//Ð’Ñтавить в новый Ñлой" #: src/mainwindow.c:5310 msgid "//Paste" msgstr "//Ð’Ñтавить" #: src/mainwindow.c:5312 msgid "//Paste Text" msgstr "//Ð’Ñтавить текÑÑ‚" #: src/mainwindow.c:5318 msgid "//Paste Text (FreeType)" msgstr "//Ð’Ñтавить текÑÑ‚ (FreeType)" #: src/mainwindow.c:5321 msgid "//Paste Palette" msgstr "//Ð’Ñтавить палитру" #: src/mainwindow.c:5323 msgid "//Load Clipboard" msgstr "//Загрузить буфер обмена" #: src/mainwindow.c:5350 msgid "//Save Clipboard" msgstr "//Сохранить буфер обмена" #: src/mainwindow.c:5377 msgid "//Import Clipboard from System" msgstr "//Заполнить буфер обмена из ÑиÑтемного" #: src/mainwindow.c:5378 msgid "//Export Clipboard to System" msgstr "//Передать буфер обмена в ÑиÑтемный" #: src/mainwindow.c:5381 msgid "//Choose Pattern ..." msgstr "//Выбрать шаблон ..." #: src/mainwindow.c:5383 msgid "//Choose Brush ..." msgstr "//Выбрать киÑть ..." #: src/mainwindow.c:5385 msgid "//Choose Colour ..." msgstr "//Выбрать цвет ..." #: src/mainwindow.c:5392 msgid "/_View" msgstr "/_Вид" #: src/mainwindow.c:5394 msgid "//Show Main Toolbar" msgstr "//ОÑÐ½Ð¾Ð²Ð½Ð°Ñ Ð¿Ð°Ð½ÐµÐ»ÑŒ" #: src/mainwindow.c:5396 msgid "//Show Tools Toolbar" msgstr "//Панель инÑтрументов" #: src/mainwindow.c:5399 msgid "//Show Settings Toolbar" msgstr "//Панель наÑтроек" #: src/mainwindow.c:5402 msgid "//Show Dock" msgstr "//Ð‘Ð¾ÐºÐ¾Ð²Ð°Ñ Ð¿Ð°Ð½ÐµÐ»ÑŒ" #: src/mainwindow.c:5404 msgid "//Show Palette" msgstr "//Палитра" #: src/mainwindow.c:5406 msgid "//Show Status Bar" msgstr "//Строка ÑтатуÑа" #: src/mainwindow.c:5409 msgid "//Toggle Image View" msgstr "//Режим проÑмотра" #: src/mainwindow.c:5413 msgid "//Centralize Image" msgstr "//Центрировать изображение" #: src/mainwindow.c:5414 msgid "//Show Zoom Grid" msgstr "//Показать Ñетку" #: src/mainwindow.c:5415 msgid "//Snap To Tile Grid" msgstr "//Прилипать к Ñетке тайлов" #: src/mainwindow.c:5417 msgid "//Configure Grid ..." msgstr "//ÐаÑтроить Ñетку ..." #: src/mainwindow.c:5418 msgid "//Tracing Image ..." msgstr "//Трафаретное изображение ..." #: src/mainwindow.c:5421 msgid "//View Window" msgstr "//Окно проÑмотра" #: src/mainwindow.c:5423 msgid "//Horizontal Split" msgstr "//Горизонтальное деление" #: src/mainwindow.c:5425 msgid "//Focus View Window" msgstr "//Ð¡Ð¸Ð½Ñ…Ñ€Ð¾Ð½Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð¾ÐºÐ½Ð° проÑмотра" #: src/mainwindow.c:5427 msgid "//Pan Window" msgstr "//Окно навигации" #: src/mainwindow.c:5430 msgid "//Layers Window" msgstr "//Окно Ñлоев" #: src/mainwindow.c:5433 msgid "/_Image" msgstr "/_Изображение" #: src/mainwindow.c:5436 msgid "//Convert To RGB" msgstr "//Преобразовать в RGB" #: src/mainwindow.c:5438 msgid "//Convert To Indexed ..." msgstr "//Преобразовать в индекÑированное ..." #: src/mainwindow.c:5441 msgid "//Scale Canvas ..." msgstr "//Размер Ð¸Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ ..." #: src/mainwindow.c:5443 msgid "//Resize Canvas ..." msgstr "//Размер холÑта ..." #: src/mainwindow.c:5445 msgid "//Crop" msgstr "//Обрезать" #: src/mainwindow.c:5448 src/mainwindow.c:5517 msgid "//Flip Vertically" msgstr "//Перевернуть по вертикали" #: src/mainwindow.c:5449 src/mainwindow.c:5519 msgid "//Flip Horizontally" msgstr "//Перевернуть по горизонтали" #: src/mainwindow.c:5452 src/mainwindow.c:5521 msgid "//Rotate Clockwise" msgstr "//Повернуть по чаÑовой" #: src/mainwindow.c:5453 src/mainwindow.c:5523 msgid "//Rotate Anti-Clockwise" msgstr "//Повернуть против чаÑовой" #: src/mainwindow.c:5454 msgid "//Free Rotate ..." msgstr "//Повернуть произвольно ..." #: src/mainwindow.c:5455 msgid "//Skew ..." msgstr "//Ðаклонить ..." #: src/mainwindow.c:5458 msgid "//Segment ..." msgstr "//Сегментировать ..." #: src/mainwindow.c:5462 msgid "//Script ..." msgstr "//Сценарий ..." #: src/mainwindow.c:5464 msgid "//Scripts" msgstr "//Сценарии" #: src/mainwindow.c:5491 msgid "//Information ..." msgstr "//Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ ..." #: src/mainwindow.c:5494 msgid "//Preferences ..." msgstr "//ÐаÑтройки ..." #: src/mainwindow.c:5497 msgid "/_Selection" msgstr "/Ð’_ыделение" #: src/mainwindow.c:5499 msgid "//Select All" msgstr "//Выделить вÑе" #: src/mainwindow.c:5501 msgid "//Select None (Esc)" msgstr "//Отменить выделение (Esc)" #: src/mainwindow.c:5503 msgid "//Lasso Selection" msgstr "//Выделение лаÑÑо" #: src/mainwindow.c:5505 msgid "//Lasso Selection Cut" msgstr "//Выделить+вырезать лаÑÑо" #: src/mainwindow.c:5508 msgid "//Outline Selection" msgstr "//Контур" #: src/mainwindow.c:5510 msgid "//Fill Selection" msgstr "//Заполнить" #: src/mainwindow.c:5512 msgid "//Outline Ellipse" msgstr "//Контур ÑллипÑа" #: src/mainwindow.c:5514 msgid "//Fill Ellipse" msgstr "//Заполненный ÑллипÑ" #: src/mainwindow.c:5526 msgid "//Horizontal Ramp" msgstr "//Горизонтальный переход цвета" #: src/mainwindow.c:5528 msgid "//Vertical Ramp" msgstr "//Вертикальный переход цвета" #: src/mainwindow.c:5531 msgid "//Alpha Blend A,B" msgstr "//Переход Ð->Ð’ в маÑку" #: src/mainwindow.c:5533 msgid "//Move Alpha to Mask" msgstr "//Сделать альфа-канал маÑкой" #: src/mainwindow.c:5535 msgid "//Mask Colour A,B" msgstr "//МаÑкировать цвета Ð,Ð’" #: src/mainwindow.c:5537 msgid "//Unmask Colour A,B" msgstr "//РазмаÑкировать цвета A,Ð’" #: src/mainwindow.c:5539 msgid "//Mask All Colours" msgstr "//МаÑкировать вÑе цвета" #: src/mainwindow.c:5541 msgid "//Clear Mask" msgstr "//ОчиÑтить маÑку" #: src/mainwindow.c:5544 msgid "/_Palette" msgstr "/_Палитра" #: src/mainwindow.c:5548 src/mainwindow.c:5626 msgid "//Load ..." msgstr "//Загрузить ..." #: src/mainwindow.c:5550 msgid "//Load Default" msgstr "//Загрузить по умолчанию" #: src/mainwindow.c:5552 msgid "//Mask All" msgstr "//МаÑкировать вÑе" #: src/mainwindow.c:5553 msgid "//Mask None" msgstr "//РазмаÑкировать вÑе" #: src/mainwindow.c:5555 msgid "//Swap A & B" msgstr "//ОбменÑть A Ñ B" #: src/mainwindow.c:5557 msgid "//Edit Colour A & B ..." msgstr "//Изменить A и B ..." #: src/mainwindow.c:5559 msgid "//Dither A" msgstr "//СмеÑÑŒ цветов Ð´Ð»Ñ A" #: src/mainwindow.c:5561 msgid "//Palette Editor ..." msgstr "//Редактор палитры ..." #: src/mainwindow.c:5563 msgid "//Set Palette Size ..." msgstr "//УÑтановить размер палитры ..." #: src/mainwindow.c:5564 msgid "//Merge Duplicate Colours" msgstr "//СлиÑние повторÑющихÑÑ Ñ†Ð²ÐµÑ‚Ð¾Ð²" #: src/mainwindow.c:5566 msgid "//Remove Unused Colours" msgstr "//Удаление неиÑпользуемых цветов" #: src/mainwindow.c:5569 msgid "//Create Quantized ..." msgstr "//Создать квантизацией ..." #: src/mainwindow.c:5572 msgid "//Sort Colours ..." msgstr "//Сортировать цвета ..." #: src/mainwindow.c:5573 msgid "//Palette Shifter ..." msgstr "//Сдвиг палитры ..." #: src/mainwindow.c:5574 msgid "//Pick Gradient ..." msgstr "//Подобрать градиент ..." #: src/mainwindow.c:5576 msgid "/Effe_cts" msgstr "/_Эффекты" #: src/mainwindow.c:5578 msgid "//Transform Colour ..." msgstr "//ТранÑÑ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ñ†Ð²ÐµÑ‚Ð¾Ð² ..." #: src/mainwindow.c:5580 msgid "//Invert" msgstr "//Инвертирование" #: src/mainwindow.c:5582 msgid "//Greyscale" msgstr "//Оттенки Ñерого" #: src/mainwindow.c:5584 msgid "//Greyscale (Gamma corrected)" msgstr "//Оттенки Ñерого (Ñ Ð³Ð°Ð¼Ð¼Ð°-коррекцией)" #: src/mainwindow.c:5586 msgid "//Normalize" msgstr "//Ðормировка" #: src/mainwindow.c:5587 src/mainwindow.c:5658 msgid "//Threshold ..." msgstr "//Порог ..." #: src/mainwindow.c:5588 msgid "//Map ..." msgstr "//Отобразить ..." #: src/mainwindow.c:5590 msgid "//Isometric Transformation" msgstr "//ИзометричеÑкое преобразование" #: src/mainwindow.c:5592 msgid "///Left Side Down" msgstr "///Левый край вниз" #: src/mainwindow.c:5593 msgid "///Right Side Down" msgstr "///Правый край вниз" #: src/mainwindow.c:5594 msgid "///Top Side Right" msgstr "///Верхний край вправо" #: src/mainwindow.c:5595 msgid "///Bottom Side Right" msgstr "///Ðижний край вправо" #: src/mainwindow.c:5598 msgid "//Edge Detect ..." msgstr "//Выделить границы ..." #: src/mainwindow.c:5600 msgid "//Difference of Gaussians ..." msgstr "//Разница по ГауÑÑу ..." #: src/mainwindow.c:5602 msgid "//Sharpen ..." msgstr "//РезкоÑть ..." #: src/mainwindow.c:5604 msgid "//Unsharp Mask ..." msgstr "//ÐÐµÑ€ÐµÐ·ÐºÐ°Ñ Ð¼Ð°Ñка ..." #: src/mainwindow.c:5606 msgid "//Soften ..." msgstr "//Сгладить ..." #: src/mainwindow.c:5608 msgid "//Gaussian Blur ..." msgstr "//ГауÑÑово размывание ..." #: src/mainwindow.c:5610 msgid "//Kuwahara-Nagao Blur ..." msgstr "//Размывание Кувахары-Ðагао ..." #: src/mainwindow.c:5612 msgid "//Emboss" msgstr "//Барельеф" #: src/mainwindow.c:5614 msgid "//Dilate" msgstr "//ДилатациÑ" #: src/mainwindow.c:5616 msgid "//Erode" msgstr "//ЭрозиÑ" #: src/mainwindow.c:5619 msgid "//Solid Noise ..." msgstr "//Сплошной шум ..." #: src/mainwindow.c:5620 msgid "//Bacteria ..." msgstr "//Бактерии ..." #: src/mainwindow.c:5623 msgid "/Cha_nnels" msgstr "/_Каналы" #: src/mainwindow.c:5625 msgid "//New ..." msgstr "//Ðовый ..." #: src/mainwindow.c:5628 msgid "//Delete ..." msgstr "//Удалить ..." #: src/mainwindow.c:5632 msgid "//Edit Image" msgstr "//Редактировать изображение" #: src/mainwindow.c:5635 msgid "//Edit Alpha" msgstr "//Редактировать альфа" #: src/mainwindow.c:5638 msgid "//Edit Selection" msgstr "//Редактировать выделение" #: src/mainwindow.c:5641 msgid "//Edit Mask" msgstr "//Редактировать маÑку" #: src/mainwindow.c:5645 msgid "//Hide Image" msgstr "//Скрыть изображение" #: src/mainwindow.c:5648 msgid "//Disable Alpha" msgstr "//Выключить альфа" #: src/mainwindow.c:5651 msgid "//Disable Selection" msgstr "//Выключить выделение" #: src/mainwindow.c:5654 msgid "//Disable Mask" msgstr "//Выключить маÑку" #: src/mainwindow.c:5657 msgid "//Couple RGBA Operations" msgstr "//Разрешить RGBA операции" #: src/mainwindow.c:5659 msgid "//Unassociate Alpha" msgstr "//Отделить альфа" #: src/mainwindow.c:5663 msgid "//View Alpha as an Overlay" msgstr "//Показать альфа как наложение" #: src/mainwindow.c:5664 msgid "//Configure Overlays ..." msgstr "//ÐаÑтроить наложение ..." #: src/mainwindow.c:5666 msgid "/_Layers" msgstr "/_Слои" #: src/mainwindow.c:5668 msgid "//New Layer" msgstr "//Ðовый Ñлой" #: src/mainwindow.c:5672 msgid "//Save Composite Image ..." msgstr "//Сохранить ÑоÑтавное изображение ..." #: src/mainwindow.c:5673 msgid "//Composite to New Layer" msgstr "//СоÑтавное изображение в новый Ñлой" #: src/mainwindow.c:5674 msgid "//Remove All Layers" msgstr "//Удалить вÑе Ñлои" #: src/mainwindow.c:5676 msgid "//Configure Animation ..." msgstr "//ÐаÑтроить анимацию ..." #: src/mainwindow.c:5677 msgid "//Preview Animation ..." msgstr "//ПроÑмотр анимации ..." #: src/mainwindow.c:5678 msgid "//Set Key Frame ..." msgstr "//УÑтановить ключевой кадр ..." #: src/mainwindow.c:5679 msgid "//Remove All Key Frames ..." msgstr "//Удалить вÑе ключевые кадры ..." #: src/mainwindow.c:5681 msgid "/More..." msgstr "/Дальше..." #: src/mainwindow.c:5683 msgid "/_Help" msgstr "/С_правка" #: src/mainwindow.c:5684 msgid "//Documentation" msgstr "//ДокументациÑ" #: src/mainwindow.c:5686 msgid "//About" msgstr "//О программе" #: src/mainwindow.c:5689 msgid "//Keyboard Shortcuts ..." msgstr "//ГорÑчие клавиши ..." #: src/mainwindow.c:5690 msgid "//Rebind Shortcut Keycodes" msgstr "//Переопределить горÑчие клавиши" #: src/memory.c:2800 msgid "Quantize Pass 1" msgstr "ÐšÐ²Ð°Ð½Ñ‚Ð¸Ð·Ð°Ñ†Ð¸Ñ - проход 1" #: src/memory.c:2854 msgid "Quantize Pass 2" msgstr "ÐšÐ²Ð°Ð½Ñ‚Ð¸Ð·Ð°Ñ†Ð¸Ñ - проход 2" #: src/memory.c:3073 src/memory.c:3458 msgid "Converting to Indexed Palette" msgstr "Преобразование в индекÑированную палитру" #: src/memory.c:5135 src/otherwindow.c:540 msgid "Bacteria Effect" msgstr "Эффект Бактерии" #: src/memory.c:5170 msgid "Rotating" msgstr "Поворот" #: src/memory.c:5511 msgid "Free Rotation" msgstr "Произвольный поворот" #: src/memory.c:6096 msgid "Scaling Image" msgstr "МаÑштабирование изображениÑ" #: src/memory.c:7560 msgid "Counting Unique RGB Pixels" msgstr "ПодÑчет уникальных RGB пикÑелей" #: src/memory.c:7608 msgid "Applying Effect" msgstr "Применение Ñффекта" #: src/memory.c:8792 msgid "Kuwahara-Nagao Filter" msgstr "Фильтр Кувахары-Ðагао" #: src/memory.c:10456 src/otherwindow.c:2665 msgid "Skew" msgstr "Ðаклон" #: src/memory.c:10630 msgid "Segmentation Pass 1" msgstr "Сегментирование - проход 1" #: src/memory.c:10757 msgid "Segmentation Pass 2" msgstr "Сегментирование - проход 2" #: src/memory.c:11019 src/otherwindow.c:3156 msgid "Solid Noise" msgstr "Сплошной шум" #: src/mygtk.c:134 src/mygtk.c:163 msgid "Please Wait ..." msgstr "Подождите ..." #: src/mygtk.c:141 msgid "STOP" msgstr "СТОП" #: src/mygtk.c:504 msgid "Disabled" msgstr "Выключен" #: src/mygtk.c:504 src/toolbar.c:301 msgid "Screen" msgstr "Экран" #: src/mygtk.c:504 msgid "Window" msgstr "Окно" #: src/mygtk.c:508 msgid "Input" msgstr "Ввод" #: src/mygtk.c:512 msgid "Device:" msgstr "УÑтройÑтво:" #: src/mygtk.c:514 msgid "Mode:" msgstr "Режим:" #: src/mygtk.c:519 msgid "Axes" msgstr "ОÑи" #: src/mygtk.c:524 msgid "X:" msgstr "" #: src/mygtk.c:525 msgid "Y:" msgstr "" #: src/mygtk.c:526 msgid "Pressure:" msgstr "Ðажим:" #: src/mygtk.c:527 msgid "X tilt:" msgstr "Ðаклон по X:" #: src/mygtk.c:528 msgid "Y tilt:" msgstr "Ðаклон по Y:" #: src/mygtk.c:529 msgid "Wheel:" msgstr "КолеÑо:" #: src/mygtk.c:579 msgid "none" msgstr "нет" #: src/otherwindow.c:236 msgid "24 bit RGB" msgstr "24-битный RGB" #: src/otherwindow.c:236 src/otherwindow.c:3179 msgid "Greyscale" msgstr "Оттенки Ñерого" #: src/otherwindow.c:237 msgid "Indexed Palette" msgstr "ИндекÑÐ¸Ñ€Ð¾Ð²Ð°Ð½Ð½Ð°Ñ Ð¿Ð°Ð»Ð¸Ñ‚Ñ€Ð°" #: src/otherwindow.c:237 msgid "From Clipboard" msgstr "Из буфера обмена" #: src/otherwindow.c:237 msgid "Grab Screenshot" msgstr "Снимок Ñкрана" #: src/otherwindow.c:242 src/toolbar.c:542 msgid "New Image" msgstr "Ðовое изображение" #: src/otherwindow.c:246 src/otherwindow.c:3164 msgid "Colours" msgstr "Цвета" #: src/otherwindow.c:409 msgid "Pattern Chooser" msgstr "Выбор шаблона" #: src/otherwindow.c:497 msgid "Set Palette Size" msgstr "УÑтановить размер палитры" #: src/otherwindow.c:517 src/otherwindow.c:591 src/otherwindow.c:870 #: src/otherwindow.c:2538 src/otherwindow.c:2776 src/otherwindow.c:2939 #: src/prefs.c:338 src/prefs.c:538 msgid "Apply" msgstr "Применить" #: src/otherwindow.c:573 msgid "Luminance" msgstr "ЯркоÑть" #: src/otherwindow.c:573 src/otherwindow.c:814 msgid "Brightness" msgstr "ЯркоÑть" #: src/otherwindow.c:574 msgid "Distance to A" msgstr "РаÑÑтоÑние до Ð" #: src/otherwindow.c:575 msgid "Projection to A->B" msgstr "ÐŸÑ€Ð¾ÐµÐºÑ†Ð¸Ñ Ð½Ð° A->B" #: src/otherwindow.c:576 msgid "Frequency" msgstr "Ð’ÑтречаемоÑть" #: src/otherwindow.c:580 msgid "Sort Palette Colours" msgstr "Сортировать цвета палитры" #: src/otherwindow.c:582 msgid "Start Index" msgstr "Ðачальный индекÑ" #: src/otherwindow.c:583 msgid "End Index" msgstr "Конечный индекÑ" #: src/otherwindow.c:589 msgid "Reverse Order" msgstr "Ð’ обратном порÑдке" #: src/otherwindow.c:805 msgid "Bitwise" msgstr "ПобитоваÑ" #: src/otherwindow.c:805 msgid "Truncated" msgstr "УÑеченнаÑ" #: src/otherwindow.c:805 msgid "Rounded" msgstr "ОкругленнаÑ" #: src/otherwindow.c:809 src/toolbar.c:311 src/toolbar.c:558 msgid "Transform Colour" msgstr "ТранÑÑ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ñ†Ð²ÐµÑ‚Ð¾Ð²" #: src/otherwindow.c:812 msgid "Gamma" msgstr "Гамма" #: src/otherwindow.c:816 msgid "Contrast" msgstr "КонтраÑÑ‚" #: src/otherwindow.c:822 src/otherwindow.c:1674 #, fuzzy msgid "Posterize" msgstr "ПоÑтеризациÑ" #: src/otherwindow.c:831 msgid "Show Detail" msgstr "Показать детали" #: src/otherwindow.c:836 msgid "Posterize type" msgstr "Тип поÑтеризации" #: src/otherwindow.c:857 msgid "Auto-Preview" msgstr "Ðвто-предпроÑмотр" #: src/otherwindow.c:869 msgid "Reset" msgstr "СброÑить" #: src/otherwindow.c:931 msgid "New geometry is the same as now - nothing to do." msgstr "ÐÐ¾Ð²Ð°Ñ Ð³ÐµÐ¾Ð¼ÐµÑ‚Ñ€Ð¸Ñ Ñ‚Ð° же что и ÑÐµÐ¹Ñ‡Ð°Ñ - ничего не делать." #: src/otherwindow.c:980 msgid "The operating system cannot allocate the memory for this operation." msgstr "ÐžÐ¿ÐµÑ€Ð°Ñ†Ð¸Ð¾Ð½Ð½Ð°Ñ ÑиÑтема не может выделить памÑть Ð´Ð»Ñ Ñтой операции." #: src/otherwindow.c:982 msgid "" "You have not allocated enough memory in the Preferences window for this " "operation." msgstr "Ð’Ñ‹ не выделили доÑтаточно памÑти в окне наÑтроек Ð´Ð»Ñ Ñтой операции." #: src/otherwindow.c:993 src/otherwindow.c:2495 msgid "Mirror" msgstr "Зеркало" #: src/otherwindow.c:993 src/otherwindow.c:994 msgid "Tile" msgstr "Черепица" #: src/otherwindow.c:993 msgid "Void" msgstr "ПуÑтота" #: src/otherwindow.c:994 src/shifter.c:283 msgid "Clear" msgstr "ОчиÑтить" #: src/otherwindow.c:994 msgid "Mirror tile" msgstr "Ð—ÐµÑ€ÐºÐ°Ð»ÑŒÐ½Ð°Ñ Ñ‡ÐµÑ€ÐµÐ¿Ð¸Ñ†Ð°" #: src/otherwindow.c:996 msgid "Nearest Neighbour" msgstr "Ближайший" #: src/otherwindow.c:997 msgid "Bilinear / Area Mapping" msgstr "Билинейный/Площадь" #: src/otherwindow.c:998 msgid "Bicubic" msgstr "БикубичеÑкий" #: src/otherwindow.c:999 msgid "Bicubic edged" msgstr "БикубичеÑкий контурный" #: src/otherwindow.c:1000 msgid "Bicubic better" msgstr "БикубичеÑкий улучшенный" #: src/otherwindow.c:1001 msgid "Bicubic sharper" msgstr "БикубичеÑкий резкий" #: src/otherwindow.c:1002 msgid "Blackman-Harris" msgstr "БлÑкман-ХарриÑ" #: src/otherwindow.c:1008 msgid "Scale Canvas" msgstr "МаÑштабирование холÑта" #: src/otherwindow.c:1009 msgid "Resize Canvas" msgstr "Изменение размера холÑта" #: src/otherwindow.c:1012 msgid "Original " msgstr "ИÑходный " #: src/otherwindow.c:1013 msgid "New" msgstr "Ðовый" #: src/otherwindow.c:1014 msgid "Width " msgstr "Ширина " #: src/otherwindow.c:1018 msgid "Height " msgstr "Ð’Ñ‹Ñота " #: src/otherwindow.c:1023 src/otherwindow.c:2514 src/otherwindow.c:2672 #: src/toolbar.c:212 msgid "Offset" msgstr "Смещение" #: src/otherwindow.c:1026 src/otherwindow.c:1615 src/viewer.c:1209 msgid "Centre" msgstr "Центр" #: src/otherwindow.c:1033 src/otherwindow.c:1052 msgid "Fix Aspect Ratio" msgstr "ФикÑировать Ñоотношение Ñторон" #: src/otherwindow.c:1039 src/otherwindow.c:2070 src/toolbar.c:312 msgid "Settings" msgstr "ÐаÑтройки" #: src/otherwindow.c:1046 msgid "Sharper image reduction" msgstr "ПовыÑить четкоÑть при уменьшении" #: src/otherwindow.c:1047 msgid "Boundary extension" msgstr "Продолжение за границы" #: src/otherwindow.c:1613 src/otherwindow.c:2302 msgid "HSV" msgstr "HSV" #: src/otherwindow.c:1614 msgid "Highlight" msgstr "ПодÑветка" #: src/otherwindow.c:1615 msgid "Limit" msgstr "Предел" #: src/otherwindow.c:1616 msgid "Sphere" msgstr "Сфера" #: src/otherwindow.c:1616 src/otherwindow.c:2670 msgid "Angle" msgstr "Угол" #: src/otherwindow.c:1616 msgid "Cube" msgstr "Куб" #: src/otherwindow.c:1617 msgid "Opaque" msgstr "Ðепрозрачный" #: src/otherwindow.c:1617 msgid "Border" msgstr "Граница" #: src/otherwindow.c:1618 msgid "Transparent" msgstr "Прозрачный" #: src/otherwindow.c:1618 msgid "Tile " msgstr "Тайл" #: src/otherwindow.c:1618 msgid "Segment" msgstr "Сегмент" #: src/otherwindow.c:1656 msgid "Scale" msgstr "Переход" #: src/otherwindow.c:1657 src/otherwindow.c:3059 msgid "From" msgstr "От" #: src/otherwindow.c:1659 src/otherwindow.c:3061 msgid "To" msgstr "До" #: src/otherwindow.c:1699 msgid "Range" msgstr "ДиÑтанциÑ" #: src/otherwindow.c:1702 msgid "Inverse" msgstr "Инвертировать" #: src/otherwindow.c:1710 msgid "Smart grid" msgstr "\"Ð£Ð¼Ð½Ð°Ñ Ñетка\"" #: src/otherwindow.c:1712 msgid "Tile grid" msgstr "Сетка тайлов" #: src/otherwindow.c:1714 msgid "Minimum grid zoom" msgstr "Минимальный маÑштаб Ð´Ð»Ñ Ñетки" #: src/otherwindow.c:1717 msgid "Tile width" msgstr "Ширина тайлов" #: src/otherwindow.c:1720 msgid "Tile height" msgstr "Ð’Ñ‹Ñота тайлов" #: src/otherwindow.c:1744 msgid "Palette Editor" msgstr "Редактор палитры" #: src/otherwindow.c:1763 msgid "Configure Overlays" msgstr "ÐаÑтройка наложениÑ" #: src/otherwindow.c:1782 msgid "Colour Editor" msgstr "Редактор цветов" #: src/otherwindow.c:1818 src/toolbar.c:430 msgid "Colour-Selective Mode" msgstr "Режим выбора по цвету" #: src/otherwindow.c:1843 msgid "Configure Grid" msgstr "ÐаÑтроить Ñетку" #: src/otherwindow.c:2045 msgid "Exact Conversion" msgstr "Точное ÑоответÑтвие" #: src/otherwindow.c:2045 msgid "Use Current Palette" msgstr "Ð¢ÐµÐºÑƒÑ‰Ð°Ñ Ð¿Ð°Ð»Ð¸Ñ‚Ñ€Ð°" #: src/otherwindow.c:2046 msgid "PNN Quantize (slow, better quality)" msgstr "PNN ÐºÐ²Ð°Ð½Ñ‚Ð¸Ð·Ð°Ñ†Ð¸Ñ (медленно но качеÑтвенно)" #: src/otherwindow.c:2047 msgid "Wu Quantize (fast)" msgstr "ÐšÐ²Ð°Ð½Ñ‚Ð¸Ð·Ð°Ñ†Ð¸Ñ Wu (быÑтро)" #: src/otherwindow.c:2048 msgid "Max-Min Quantize (best for small palettes and dithering)" msgstr "Max-Min ÐºÐ²Ð°Ð½Ñ‚Ð¸Ð·Ð°Ñ†Ð¸Ñ (Ð»ÑƒÑ‡ÑˆÐ°Ñ Ð´Ð»Ñ Ð½ÐµÐ±Ð¾Ð»ÑŒÑˆÐ¸Ñ… палитр и dithering'а)" #: src/otherwindow.c:2049 src/otherwindow.c:2495 src/otherwindow.c:2756 #: src/png.c:2794 src/prefs.c:377 msgid "None" msgstr "Ðет" #: src/otherwindow.c:2049 msgid "Floyd-Steinberg" msgstr "Флойд-Стейнберг" #: src/otherwindow.c:2049 msgid "Stucki" msgstr "Stucki" #: src/otherwindow.c:2052 msgid "Floyd-Steinberg (quick)" msgstr "Флойд-Стейнберг (быÑтрый)" #: src/otherwindow.c:2052 msgid "Dithered (effect)" msgstr "Dithered (Ñффект)" #: src/otherwindow.c:2053 msgid "Scattered (effect)" msgstr "Scattered (Ñффект)" #: src/otherwindow.c:2054 msgid "Gamut" msgstr "Гамут" #: src/otherwindow.c:2054 msgid "Weakly" msgstr "Слабо" #: src/otherwindow.c:2054 msgid "Strongly" msgstr "Сильно" #: src/otherwindow.c:2055 msgid "Off" msgstr "Ðет" #: src/otherwindow.c:2055 msgid "Separate/Sum" msgstr "Раздельно/Сумма" #: src/otherwindow.c:2055 msgid "Separate/Split" msgstr "Раздельно/СброÑ" #: src/otherwindow.c:2056 msgid "Length/Sum" msgstr "Длина/Сумма" #: src/otherwindow.c:2056 msgid "Length/Split" msgstr "Длина/СброÑ" #: src/otherwindow.c:2057 msgid "Largest (Linf)" msgstr "Ðаибольшее (Linf)" #: src/otherwindow.c:2057 msgid "Sum (L1)" msgstr "Сумма (L1)" #: src/otherwindow.c:2057 msgid "Euclidean (L2)" msgstr "Эвклидово (L2)" #: src/otherwindow.c:2061 msgid "Create Quantized" msgstr "Создать квантизацией" #: src/otherwindow.c:2062 msgid "Convert To Indexed" msgstr "Преобразовать в индекÑированное" #: src/otherwindow.c:2065 msgid "Indexed Colours To Use" msgstr "ЧиÑло цветов" #: src/otherwindow.c:2078 msgid "Truncate palette" msgstr "Обрезать палитру" #: src/otherwindow.c:2079 msgid "Diameter based weighting" msgstr "Ð’ÐµÑ ÐºÐ°Ðº диаметр" #: src/otherwindow.c:2084 msgid "Dither" msgstr "Dither" #: src/otherwindow.c:2087 src/otherwindow.c:2584 src/otherwindow.c:2928 msgid "Colour space" msgstr "Цветовое проÑтранÑтво" #: src/otherwindow.c:2088 src/otherwindow.c:2929 msgid "Difference measure" msgstr "Мера раÑÑтоÑниÑ" #: src/otherwindow.c:2089 msgid "Reduce colour bleed" msgstr "Ограничить раÑтекание" #: src/otherwindow.c:2090 msgid "Serpentine scan" msgstr "Сканирование зигзагом" #: src/otherwindow.c:2092 msgid "Error propagation, %" msgstr "РаÑпроÑтранение ошибки, %" #: src/otherwindow.c:2093 msgid "Selective error propagation" msgstr "Выборочное раÑпроÑтранение ошибки" #: src/otherwindow.c:2097 msgid "Full error precision" msgstr "ÐŸÐ¾Ð»Ð½Ð°Ñ Ñ‚Ð¾Ñ‡Ð½Ð¾Ñть ошибки" #: src/otherwindow.c:2302 msgid "Backward HSV" msgstr "Обратный HSV" #: src/otherwindow.c:2303 src/otherwindow.c:2326 msgid "Constant" msgstr "ПоÑтоÑнный" #: src/otherwindow.c:2307 msgid "Edit Gradient" msgstr "Редактировать градиент" #: src/otherwindow.c:2329 msgid "Points:" msgstr "Точек:" #: src/otherwindow.c:2493 msgid "Linear" msgstr "Линейный" #: src/otherwindow.c:2493 src/otherwindow.c:2703 msgid "Bilinear" msgstr "Билинейный" #: src/otherwindow.c:2493 msgid "Radial" msgstr "Круговой" #: src/otherwindow.c:2494 msgid "Square" msgstr "Квадратный" #: src/otherwindow.c:2494 msgid "Angular" msgstr "Угловой" #: src/otherwindow.c:2494 msgid "Conical" msgstr "КоничеÑкий" #: src/otherwindow.c:2495 msgid "Level " msgstr "Удерживать" #: src/otherwindow.c:2495 msgid "Repeat" msgstr "Повторить" #: src/otherwindow.c:2496 msgid "A to B" msgstr "От A к B" #: src/otherwindow.c:2496 msgid "A to B (RGB)" msgstr "От A к B (RGB)" #: src/otherwindow.c:2497 msgid "A to B (sRGB)" msgstr "От A к B (sRGB)" #: src/otherwindow.c:2497 msgid "A to B (HSV)" msgstr "От A к B (HSV)" #: src/otherwindow.c:2497 msgid "A to B (backward HSV)" msgstr "От A к B (обратный HSV)" #: src/otherwindow.c:2498 msgid "A only" msgstr "Только A" #: src/otherwindow.c:2498 src/otherwindow.c:2500 msgid "Custom" msgstr "ПользовательÑкий" #: src/otherwindow.c:2499 msgid "Current to 0" msgstr "От текущего до 0" #: src/otherwindow.c:2499 msgid "Current only" msgstr "Только текущий" #: src/otherwindow.c:2504 msgid "Configure Gradient" msgstr "ÐаÑтройка градиента" #: src/otherwindow.c:2507 src/png.c:1001 msgid "Channel" msgstr "Канал" #: src/otherwindow.c:2512 msgid "Length" msgstr "Длина" #: src/otherwindow.c:2513 msgid "Repeat length" msgstr "Длина повтора" #: src/otherwindow.c:2515 msgid "Gradient type" msgstr "Тип градиента" #: src/otherwindow.c:2516 msgid "Extension type" msgstr "Тип продолжениÑ" #: src/otherwindow.c:2517 msgid "Distance type" msgstr "Тип раÑÑтоÑниÑ" #: src/otherwindow.c:2518 msgid "Preview opacity" msgstr "ÐепрозрачноÑть при проÑмотре" #: src/otherwindow.c:2527 src/otherwindow.c:2533 src/toolbar.c:309 msgid "Reverse" msgstr "Обратный" #: src/otherwindow.c:2528 src/otherwindow.c:2534 msgid "Edit Custom" msgstr "Редактировать" #: src/otherwindow.c:2592 msgid "Pick Gradient" msgstr "Подбор градиента" #: src/otherwindow.c:2668 msgid "Horizontal " msgstr "Горизонтальный " #: src/otherwindow.c:2674 msgid "At distance" msgstr "Ðа раÑÑтоÑнии" #: src/otherwindow.c:2675 msgid "Vertical" msgstr "Вертикальный" #: src/otherwindow.c:2756 msgid "Unchanged" msgstr "Ðе менÑетÑÑ" #: src/otherwindow.c:2761 msgid "Tracing Image" msgstr "Трафаретное изображение" #: src/otherwindow.c:2763 src/toolbar.c:315 msgid "Source" msgstr "ИÑточник" #: src/otherwindow.c:2768 msgid "Origin" msgstr "Ðачало координат" #: src/otherwindow.c:2771 msgid "Relative scale" msgstr "ОтноÑительный маÑштаб" #: src/otherwindow.c:2774 msgid "Display" msgstr "Показать" #: src/otherwindow.c:2926 msgid "Segment Image" msgstr "Сегментирование изображениÑ" #: src/otherwindow.c:2931 src/toolbar.c:304 msgid "Threshold" msgstr "Порог" #: src/otherwindow.c:2933 msgid "Level" msgstr "Уровень" #: src/otherwindow.c:2934 msgid "Minimum size" msgstr "Минимальный размер" #: src/otherwindow.c:3053 msgid "Max" msgstr "Ðаибольшее" #: src/otherwindow.c:3053 msgid "Min" msgstr "Ðаименьшее" #: src/otherwindow.c:3057 msgid "Threshold Image" msgstr "Порог" #: src/otherwindow.c:3158 msgid "Seed" msgstr "Зерно" #: src/otherwindow.c:3160 msgid "X span" msgstr "Шаг по X" #: src/otherwindow.c:3161 msgid "Y span" msgstr "Шаг по Y" #: src/otherwindow.c:3162 msgid "Octaves" msgstr "Октавы" #: src/png.c:620 #, c-format msgid "Saving %s image" msgstr "Сохранение изображениÑ: %s" #: src/png.c:620 #, c-format msgid "Loading %s image" msgstr "Загрузка изображениÑ: %s" #: src/png.c:998 msgid "Layer" msgstr "Слой" #: src/png.c:3577 msgid "Lossless" msgstr "Без потерь" #: src/png.c:3577 msgid "Default" msgstr "По умолчанию" #: src/png.c:3577 msgid "Picture" msgstr "Картина" #: src/png.c:3577 msgid "Photo" msgstr "Фото" #: src/png.c:3578 msgid "Drawing" msgstr "РиÑунок" #: src/png.c:3578 msgid "Icon" msgstr "Иконка" #: src/png.c:8370 msgid "Applying colour profile" msgstr "Применение цветового профилÑ" #: src/png.c:8792 #, c-format msgid "%d out of %d frames could not be saved as %s - saved as PNG instead" msgstr "%d из %d кадров Ð½ÐµÐ»ÑŒÐ·Ñ Ð±Ñ‹Ð»Ð¾ Ñохранить в %s - Ñохранены в PNG" #: src/png.c:8809 msgid "Explode frames" msgstr "РаÑпаковка кадров" #: src/prefs.c:56 msgid "Default System Language" msgstr "Язык ÑиÑтемы по умолчанию" #: src/prefs.c:57 msgid "Chinese (Simplified)" msgstr "КитайÑкий" #: src/prefs.c:57 msgid "Chinese (Taiwanese)" msgstr "КитайÑкий (ТайванÑкий)" #: src/prefs.c:57 msgid "Czech" msgstr "ЧешÑкий" #: src/prefs.c:58 msgid "Dutch" msgstr "ГолландÑкий" #: src/prefs.c:58 msgid "English (UK)" msgstr "ÐнглийÑкий (UK)" #: src/prefs.c:58 msgid "French" msgstr "ФранцузÑкий" #: src/prefs.c:58 msgid "Galician" msgstr "ГалиÑийÑкий" #: src/prefs.c:58 msgid "German" msgstr "Ðемецкий" #: src/prefs.c:59 msgid "Hungarian" msgstr "ВенгерÑкий" #: src/prefs.c:59 msgid "Italian" msgstr "ИтальÑнÑкий" #: src/prefs.c:59 msgid "Japanese" msgstr "ЯпонÑкий" #: src/prefs.c:59 msgid "Kabyle" msgstr "КабильÑкий" #: src/prefs.c:59 msgid "Polish" msgstr "ПольÑкий" #: src/prefs.c:60 msgid "Portuguese" msgstr "ПортугальÑкий" #: src/prefs.c:60 msgid "Portuguese (Brazilian)" msgstr "ПортугальÑкий (БразильÑкий)" #: src/prefs.c:60 msgid "Russian" msgstr "РуÑÑкий" #: src/prefs.c:60 msgid "Slovak" msgstr "Словацкий" #: src/prefs.c:61 msgid "Spanish" msgstr "ИÑпанÑкий" #: src/prefs.c:61 msgid "Swedish" msgstr "ШведÑкий" #: src/prefs.c:61 msgid "Tagalog" msgstr "ТагальÑкий" #: src/prefs.c:61 msgid "Turkish" msgstr "Турецкий" #: src/prefs.c:81 msgid "Current Device" msgstr "Текущее уÑтройÑтво" #: src/prefs.c:135 msgid "Pressure" msgstr "Давление" #: src/prefs.c:149 msgid "Preferences" msgstr "ÐаÑтройки" #: src/prefs.c:163 msgid "Max threads (0 to autodetect)" msgstr "ЧиÑло потоков (0 - определить)" #: src/prefs.c:164 msgid "Min kpixels per render thread" msgstr "Минимум тыÑ.пикÑелов на поток отриÑовки" #: src/prefs.c:171 msgid "Max memory used for undo (MB)" msgstr "МакÑимум памÑти Ð´Ð»Ñ Ð¾Ñ‚Ð¼ÐµÐ½Ñ‹ (МБ)" #: src/prefs.c:172 msgid "Max undo levels" msgstr "МакÑимум уровней отмены" #: src/prefs.c:173 msgid "Communal layer undo space (%)" msgstr "ÐžÐ±Ñ‰Ð°Ñ Ð´Ð»Ñ Ð²Ñех Ñлоев облаÑть отмены (%)" #: src/prefs.c:175 msgid "Bayer master pattern" msgstr "Базовый шаблон Байера" #: src/prefs.c:178 msgid "Use gamma correction by default" msgstr "Включать гамма-коррекцию по умолчанию" #: src/prefs.c:179 msgid "Use gamma correction when painting" msgstr "Гамма-ÐºÐ¾Ñ€Ñ€ÐµÐºÑ†Ð¸Ñ Ð¿Ñ€Ð¸ риÑовании" #: src/prefs.c:180 msgid "Separate patterns for A & B" msgstr "Отдельные шаблоны Ð´Ð»Ñ A и B" #: src/prefs.c:183 msgid "Optimize alpha chequers" msgstr "Оптимизировать клетки фона" #: src/prefs.c:184 msgid "Disable view window transparencies" msgstr "Отключить прозрачноÑть в окне проÑмотра" #: src/prefs.c:185 msgid "Enable overlays by layer" msgstr "Включать наложение отдельно Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð³Ð¾ ÑлоÑ" #: src/prefs.c:189 msgid "Language" msgstr "Язык" #: src/prefs.c:191 msgid "" "Select preferred language translation\n" "\n" "You will need to restart mtPaint\n" "for this to take full effect" msgstr "" "Выберите Ñзык\n" "\n" "Вам нужно будет перезапуÑтить mtPaint\n" "чтобы Ñзык полноÑтью ÑменилÑÑ" #: src/prefs.c:198 msgid "Interface" msgstr "ИнтерфейÑ" #: src/prefs.c:200 msgid "Greyscale backdrop" msgstr "Серый фон" #: src/prefs.c:201 msgid "Selection nudge pixels" msgstr "Шаг Ð¿ÐµÑ€ÐµÐ¼ÐµÑ‰ÐµÐ½Ð¸Ñ Ð²Ñ‹Ð´ÐµÐ»ÐµÐ½Ð¸Ñ" #: src/prefs.c:202 msgid "Max Pan Window Size" msgstr "Размер окна навигации" #: src/prefs.c:204 msgid "Display clipboard while pasting" msgstr "Показывать буфер обмена при вÑтавке" #: src/prefs.c:205 msgid "Mouse cursor = Tool" msgstr "Показывать инÑтрумент на курÑоре" #: src/prefs.c:206 msgid "Confirm Exit" msgstr "Подтверждать выход" #: src/prefs.c:207 msgid "Q key quits mtPaint" msgstr "Выход по клавише Q" #: src/prefs.c:208 msgid "Arrow keys scroll canvas" msgstr "Прокрутка холÑта Ñтрелками" #: src/prefs.c:209 msgid "Changing tool commits paste" msgstr "Ð’Ñтавка при Ñмене инÑтрумента" #: src/prefs.c:210 msgid "Centre tool settings dialogs" msgstr "Центрировать диалоги наÑтроек" #: src/prefs.c:211 msgid "New image sets zoom to 100%" msgstr "МаÑштаб 100% Ð´Ð»Ñ Ð½Ð¾Ð²Ñ‹Ñ… изображений" #: src/prefs.c:212 msgid "Zoom on cursor position" msgstr "Центрировать маÑштаб на позиции курÑора" #: src/prefs.c:214 msgid "Mouse Scroll Wheel = Zoom" msgstr "КолеÑо прокрутки менÑет маÑштаб" #: src/prefs.c:215 msgid "Use menu icons" msgstr "Показывать иконки в меню" #: src/prefs.c:220 msgid "Files" msgstr "Файлы" #: src/prefs.c:223 msgid "XBM X hotspot" msgstr "X горÑчей точки XBM" #: src/prefs.c:224 msgid "XBM Y hotspot" msgstr "Y горÑчей точки XBM" #: src/prefs.c:228 msgid "Recently Used Files" msgstr "Ðедавно открытые файлы" #: src/prefs.c:229 msgid "Progress bar silence limit" msgstr "Предел когда показывать прогреÑÑбар" #: src/prefs.c:232 msgid "Read 16-bit TGAs as 5:6:5 BGR" msgstr "Загружать 16-битные TGA как 5:6:5 BGR" #: src/prefs.c:233 msgid "Write TGAs in bottom-up row order" msgstr "СохранÑть TGA Ñ Ð¿Ð¾Ñ€Ñдком Ñтрок Ñнизу вверх" #: src/prefs.c:234 msgid "Undoable image loading" msgstr "ОтменÑÐµÐ¼Ð°Ñ Ð·Ð°Ð³Ñ€ÑƒÐ·ÐºÐ° изображений" #: src/prefs.c:245 msgid "Compression (RGB)" msgstr "Сжатие (RGB)" #: src/prefs.c:246 msgid "Compression (indexed)" msgstr "Сжатие (индекÑированные)" #: src/prefs.c:247 msgid "Compression (monochrome)" msgstr "Сжатие (монохромные)" #: src/prefs.c:255 msgid "Enable predictor" msgstr "Включить предÑказатель" #: src/prefs.c:262 msgid "Compression mode" msgstr "Режим ÑжатиÑ" #: src/prefs.c:271 msgid "Channel for Mask Plane" msgstr "Канал Ð´Ð»Ñ Ð¿Ð»Ð¾ÑкоÑти маÑки" #: src/prefs.c:273 msgid "Ignore Transparent Colour" msgstr "Игнорировать прозрачный цвет" #: src/prefs.c:274 msgid "PackBits Compression" msgstr "Сжатие PackBits" #: src/prefs.c:275 msgid "Write Indexed as Planar Bitmap (PBM)" msgstr "СохранÑть индекÑированные как Planar Bitmap (PBM)" #: src/prefs.c:280 msgid "Paths" msgstr "Пути" #: src/prefs.c:281 msgid "Clipboard Files" msgstr "Файлы буфера обмена" #: src/prefs.c:281 msgid "Select Clipboard File" msgstr "Выберите файл буфера обмена" #: src/prefs.c:283 msgid "HTML Browser Program" msgstr "Программа проÑмотра HTML" #: src/prefs.c:283 msgid "Select Browser Program" msgstr "Выбрать программу проÑиотра" #: src/prefs.c:285 msgid "Location of Handbook index" msgstr "Путь к РуководÑтву пользователÑ" #: src/prefs.c:285 msgid "Select Handbook Index File" msgstr "Выбрать index-файл РуководÑтва пользователÑ" #: src/prefs.c:287 msgid "Default Palette" msgstr "Палитра по умолчанию" #: src/prefs.c:287 msgid "Select Default Palette" msgstr "Выбрать палитру по умолчанию" #: src/prefs.c:289 msgid "Default Patterns" msgstr "Шаблоны по умолчанию" #: src/prefs.c:289 msgid "Select Default Patterns File" msgstr "Выбрать файл шаблонов по умолчанию" #: src/prefs.c:292 msgid "Default CSS" msgstr "CSS по умолчанию" #: src/prefs.c:292 msgid "Select Default CSS File" msgstr "Выбрать файл CSS по умолчанию" #: src/prefs.c:295 msgid "Default Theme" msgstr "Тема по умолчанию" #: src/prefs.c:295 msgid "Select Default Theme File" msgstr "Выбрать файл темы по умолчанию" #: src/prefs.c:300 msgid "Status Bar" msgstr "Строка ÑтатуÑа" #: src/prefs.c:301 msgid "Canvas Geometry" msgstr "Размеры холÑта" #: src/prefs.c:302 msgid "Cursor X,Y" msgstr "Координаты курÑора" #: src/prefs.c:303 msgid "Pixel [I] {RGB}" msgstr "Цвет пикÑела" #: src/prefs.c:304 msgid "Selection Geometry" msgstr "Размеры выделениÑ" #: src/prefs.c:305 msgid "Undo / Redo" msgstr "Отменить/Вернуть" #: src/prefs.c:308 msgid "Tablet" msgstr "Планшет" #: src/prefs.c:309 msgid "Device Settings" msgstr "ÐаÑтройки уÑтройÑтва" #: src/prefs.c:313 msgid "Configure Device" msgstr "ÐšÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ñ ÑƒÑтройÑтва" #: src/prefs.c:319 msgid "Tool Variable" msgstr "ПеременнаÑ" #: src/prefs.c:322 src/toolbar.c:454 msgid "Flow" msgstr "Поток" #: src/prefs.c:330 msgid "Test Area" msgstr "ТеÑÑ‚Ð¾Ð²Ð°Ñ Ð¾Ð±Ð»Ð°Ñть" #: src/prefs.c:373 msgid "Factor" msgstr "Множитель" #: src/prefs.c:459 msgid "This key is builtin" msgstr "Эта клавиша вÑтроена в код" #: src/prefs.c:462 #, c-format msgid "" "This key is mapped to:\n" "\"%s\"" msgstr "" "Эта клавиша привÑзана к:\n" "\"%s\"" #: src/prefs.c:465 msgid "Remap" msgstr "ПерепривÑзать" #: src/prefs.c:510 msgid "Keyboard Shortcuts" msgstr "ГорÑчие клавиши" #: src/shifter.c:147 msgid "Frames" msgstr "Кадры" #: src/shifter.c:258 msgid "Palette Shifter" msgstr "Сдвиг палитры" #: src/shifter.c:263 msgid "Start" msgstr "Ðачало" #: src/shifter.c:265 msgid "Finish" msgstr "Конец" #: src/shifter.c:284 msgid "Fix Palette" msgstr "ЗафикÑировать палитру" #: src/spawn.c:651 msgid "Configure File Actions" msgstr "ÐаÑтроить дейÑÑ‚Ð²Ð¸Ñ Ñ Ñ„Ð°Ð¹Ð»Ð°Ð¼Ð¸" #: src/spawn.c:657 src/spawn.c:663 msgid "Command" msgstr "Команда" #: src/spawn.c:922 #, c-format msgid "Error %i reported when trying to run %s" msgstr "Ошибка %i при попытке запуÑтить %s" #: src/spawn.c:979 msgid "" "I am unable to find the documentation. Either you need to download the " "mtPaint Handbook from the web site and install it, or you need to set the " "correct location in the Preferences window." msgstr "" "Ð”Ð¾ÐºÑƒÐ¼ÐµÐ½Ñ‚Ð°Ñ†Ð¸Ñ Ð½Ðµ найдена. Либо вам нужно Ñкачать РуководÑтво Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ñ " "Ñайта программы и уÑтановить его, либо указать правильный путь к нему в окне " "наÑтроек." #: src/spawn.c:1018 msgid "" "There was a problem running the HTML browser. You need to set the correct " "program name in the Preferences window." msgstr "" "Ðе удалоÑÑŒ запуÑтить программу проÑмотра HTML. Вам нужно указать правильное " "Ð¸Ð¼Ñ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð¼Ñ‹ в окне наÑтроек." #: src/thread.c:361 msgid "Helper thread is not responding. Save your work and exit the program." msgstr "" "Ð’Ñпомогательный поток не отвечает. Сохраните файлы и выйдите из программы." #: src/toolbar.c:147 msgid "RGB Cube" msgstr "RGB-куб" #: src/toolbar.c:148 msgid "By image channel" msgstr "По каналу изображениÑ" #: src/toolbar.c:149 msgid "Gradient-driven" msgstr "По градиенту" #: src/toolbar.c:157 msgid "Fill settings" msgstr "ÐаÑтройки заливки" #: src/toolbar.c:170 msgid "Respect opacity mode" msgstr "Учитывать режим непрозрачноÑти" #: src/toolbar.c:176 msgid "Smudge settings" msgstr "ÐаÑтройки размазываниÑ" #: src/toolbar.c:215 msgid "Aligned" msgstr "С выравниванием" #: src/toolbar.c:222 msgid "Clone settings" msgstr "ÐаÑтройки клонированиÑ" #: src/toolbar.c:228 msgid "By selection channel" msgstr "По каналу выделениÑ" #: src/toolbar.c:234 msgid "Lasso settings" msgstr "ÐаÑтройки лаÑÑо" #: src/toolbar.c:252 msgid "Brush spacing" msgstr "Шаг киÑти" #: src/toolbar.c:299 src/toolbar.c:341 msgid "Normal" msgstr "Обычный" #: src/toolbar.c:300 msgid "Colour" msgstr "Цвет" #: src/toolbar.c:300 msgid "Saturate More" msgstr "ПовыÑить наÑыщенноÑть" #: src/toolbar.c:301 msgid "Multiply" msgstr "Умножение" #: src/toolbar.c:301 msgid "Divide" msgstr "Деление" #: src/toolbar.c:301 msgid "Dodge" msgstr "ОÑветление" #: src/toolbar.c:302 msgid "Burn" msgstr "Затемнение" #: src/toolbar.c:302 msgid "Hard Light" msgstr "Ðаправленный Ñвет" #: src/toolbar.c:302 msgid "Soft Light" msgstr "РаÑÑеÑнный Ñвет" #: src/toolbar.c:302 msgid "Difference" msgstr "Разница" #: src/toolbar.c:303 msgid "Darken" msgstr "Замена темным" #: src/toolbar.c:303 msgid "Lighten" msgstr "Замена Ñветлым" #: src/toolbar.c:303 msgid "Grain Extract" msgstr "Извлечение зерна" #: src/toolbar.c:304 msgid "Grain Merge" msgstr "Объединение зерна" #: src/toolbar.c:330 msgid "Blend mode" msgstr "Режим ÑмешиваниÑ" #: src/toolbar.c:417 msgid "Continuous Mode" msgstr "Режим непрерывноÑти" #: src/toolbar.c:421 msgid "Opacity Mode" msgstr "Режим непрозрачноÑти" #: src/toolbar.c:424 msgid "Tint Mode" msgstr "Режим оттенков" #: src/toolbar.c:427 msgid "Tint +-" msgstr "Оттенок +-" #: src/toolbar.c:434 msgid "Blend Mode" msgstr "Режим ÑмешиваниÑ" #: src/toolbar.c:438 msgid "Disable All Masks" msgstr "Отключить вÑе маÑки" #: src/toolbar.c:441 msgid "Gradient Mode" msgstr "Режим градиента" #: src/toolbar.c:486 msgid "Settings Toolbar" msgstr "Панель уÑтановок" #: src/toolbar.c:546 msgid "Cut" msgstr "Вырезать" #: src/toolbar.c:548 msgid "Copy" msgstr "Копировать" #: src/toolbar.c:550 msgid "Paste" msgstr "Ð’Ñтавить" #: src/toolbar.c:553 msgid "Undo" msgstr "Отменить" #: src/toolbar.c:555 msgid "Redo" msgstr "Вернуть" #: src/toolbar.c:559 src/viewer.c:328 msgid "Pan Window" msgstr "Окно навигации" #: src/toolbar.c:560 src/toolbar.c:640 msgid "More..." msgstr "Дальше..." #: src/toolbar.c:574 msgid "Paint" msgstr "РиÑовать" #: src/toolbar.c:580 msgid "Shuffle" msgstr "ПеретаÑовка" #: src/toolbar.c:583 msgid "Flood Fill" msgstr "Заливка" #: src/toolbar.c:587 msgid "Straight Line" msgstr "ПрÑÐ¼Ð°Ñ Ð»Ð¸Ð½Ð¸Ñ" #: src/toolbar.c:590 msgid "Smudge" msgstr "Размазывание" #: src/toolbar.c:594 msgid "Clone" msgstr "Клонирование" #: src/toolbar.c:597 msgid "Make Selection" msgstr "Выделение прÑмоугольником" #: src/toolbar.c:600 msgid "Polygon Selection" msgstr "Выделение многоугольником" #: src/toolbar.c:603 msgid "Place Gradient" msgstr "РазмеÑтить градиент" #: src/toolbar.c:606 msgid "Lasso Selection" msgstr "Выделение лаÑÑо" #: src/toolbar.c:614 msgid "Ellipse Outline" msgstr "Контур ÑллипÑа" #: src/toolbar.c:617 msgid "Filled Ellipse" msgstr "Заполненный ÑллипÑ" #: src/toolbar.c:620 msgid "Outline Selection" msgstr "ОбвеÑти выделение" #: src/toolbar.c:623 msgid "Fill Selection" msgstr "Заполнить выделенное" #: src/toolbar.c:627 msgid "Flip Selection Vertically" msgstr "Перевернуть выделение по вертикали" #: src/toolbar.c:630 msgid "Flip Selection Horizontally" msgstr "Перевернуть выделение по горизонтали" #: src/toolbar.c:633 msgid "Rotate Selection Clockwise" msgstr "Повернуть выделение по чаÑовой" #: src/toolbar.c:636 msgid "Rotate Selection Anti-Clockwise" msgstr "Повернуть выделение против чаÑовой" #: src/vcode.c:5201 msgid "Browse" msgstr "Выбрать" #: src/vcode.c:7886 msgid "New key ..." msgstr "ÐÐ¾Ð²Ð°Ñ ÐºÐ»Ð°Ð²Ð¸ÑˆÐ° ..." #: src/vcode.c:9909 #, c-format msgid "'%s' does not match any widget" msgstr "'%s' не Ñовпало ни Ñ ÐºÐ°ÐºÐ¸Ð¼ виджетом" #: src/vcode.c:9910 #, c-format msgid "'%s' value does not fit '%s' widget" msgstr "Значение '%s' не подходит виджету '%s'" #: src/viewer.c:115 msgid "About" msgstr "О программе" #: src/viewer.c:1179 msgid "No font selected" msgstr "Шрифт не выбран" #: src/viewer.c:1209 msgid "Left" msgstr "Влево" #: src/viewer.c:1209 msgid "Right" msgstr "Вправо" #, fuzzy #~ msgid "" #~ "You are trying to save an XPM file with more than 4096 colours. Either " #~ "use another format or posterize the image to 4 bits, or otherwise reduce " #~ "the number of colours." #~ msgstr "" #~ "Ð’Ñ‹ пытаетеÑÑŒ Ñохранить XPM файл Ñ Ð±Ð¾Ð»ÐµÐµ чем 4096 цветов. ИÑпользуйте " #~ "другой формат, либо поÑтеризуйте изображение в 4 бита, либо иным образом " #~ "уменьшите количеÑтво цветов." #~ msgid "Create GIF frames" #~ msgstr "Создать GIF кадры" #~ msgid "Store Values" #~ msgstr "Сохранить значениÑ" #~ msgid "File: %s invalid - palette not updated" #~ msgstr "Файл: %s неверный - палитра не обновлÑлаÑÑŒ" #~ msgid "Distance to A+B" #~ msgstr "РаÑÑтоÑние до Ð+B" #~ msgid "Edit Frames" #~ msgstr "Редактировать кадры" #~ msgid " C Command Line Window" #~ msgstr " C Окно командной Ñтроки" #~ msgid "The palette does not contain enough colours to do a merge" #~ msgstr "Ð’ палитре недоÑтаточно цветов Ð´Ð»Ñ ÑлиÑниÑ" #~ msgid "There are too many identical palette items to be reduced." #~ msgstr "Ð’ палитре Ñлишком много одинаковых цветов." #~ msgid "/View/Command Line Window" #~ msgstr "/Вид/Окно командной Ñтроки" #~ msgid "Grid colour RGB" #~ msgstr "Цвет Ñетки (RGB)" #~ msgid "Zoom" #~ msgstr "МаÑштаб" #~ msgid "%i Files on Command Line" #~ msgstr "%i файлов в командной Ñтроке" mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/po/sk.po000066400000000000000000003173631471325446300215630ustar00rootroot00000000000000# translation of sk.po to Slovak # Slovak translations for mtpaint package. # Copyright (C) 2005 THE mtpaint'S COPYRIGHT HOLDER # This file is distributed under the same license as the mtpaint package. # # Jozef Riha , 2007, 2021. msgid "" msgstr "" "Project-Id-Version: sk\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-02-06 22:09+0200\n" "PO-Revision-Date: 2021-01-24 21:36+0100\n" "Last-Translator: Jose Riha \n" "Language-Team: Slovak \n" "Language: sk\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\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" "X-Generator: Poedit 2.4.1\n" #: src/ani.c:647 msgid "Animation Preview" msgstr "Náhľad animácie" #: src/ani.c:650 src/shifter.c:275 msgid "Play" msgstr "PrehraÅ¥" #: src/ani.c:654 msgid "Fix" msgstr "ZafixovaÅ¥" #: src/ani.c:655 src/ani.c:1003 src/font.c:1624 src/font.c:1643 #: src/shifter.c:286 src/viewer.c:97 msgid "Close" msgstr "ZavrieÅ¥" #: src/ani.c:709 src/ani.c:810 src/ani.c:1020 src/ani.c:1026 src/canvas.c:356 #: src/canvas.c:708 src/canvas.c:989 src/canvas.c:1353 src/canvas.c:1383 #: src/canvas.c:1470 src/canvas.c:1545 src/canvas.c:1988 src/canvas.c:1994 #: src/canvas.c:2077 src/canvas.c:2217 src/canvas.c:2240 src/font.c:1352 #: src/fpick.c:636 src/fpick.c:754 src/layer.c:524 src/layer.c:815 #: src/layer.c:970 src/mainwindow.c:341 src/mainwindow.c:370 #: src/mainwindow.c:534 src/mainwindow.c:578 src/mainwindow.c:604 #: src/mainwindow.c:3786 src/mainwindow.c:4034 src/otherwindow.c:927 #: src/otherwindow.c:976 src/otherwindow.c:978 src/prefs.c:459 src/spawn.c:924 #: src/spawn.c:978 src/spawn.c:1017 src/thread.c:360 src/vcode.c:9912 #: src/viewer.c:1161 src/viewer.c:1179 msgid "Error" msgstr "Chyba" #: src/ani.c:709 msgid "Unable to create output directory" msgstr "Nepodarilo sa vytvoriÅ¥ výstupný adresár" #: src/ani.c:759 msgid "Creating Animation Frames" msgstr "Vytváram snímky animácie" #: src/ani.c:810 msgid "Unable to save image" msgstr "Nepodarilo sa uložiÅ¥ obrázok" #: src/ani.c:838 src/canvas.c:1171 src/fpick.c:731 src/layer.c:311 #: src/layer.c:379 src/layer.c:826 src/layer.c:840 src/mainwindow.c:375 #: src/mainwindow.c:1026 src/png.c:9091 src/prefs.c:464 msgid "Warning" msgstr "Varovanie" #: src/ani.c:838 msgid "" "Do you really want to clear all of the position and cycle data for all of " "the layers?" msgstr "" "Naozaj chcete vyÄistiÅ¥ vÅ¡etky údaje o pozíciach a cykloch pre vÅ¡etky vrstvy?" #: src/ani.c:839 src/fpick.c:731 src/layer.c:311 src/layer.c:842 #: src/mainwindow.c:375 msgid "No" msgstr "Nie" #: src/ani.c:839 src/fpick.c:731 src/layer.c:311 src/layer.c:842 #: src/mainwindow.c:375 msgid "Yes" msgstr "Ãno" #: src/ani.c:952 msgid "Set Key Frame" msgstr "NastaviÅ¥ kľúÄovú snímku" #: src/ani.c:959 msgid "Configure Animation" msgstr "NastaviÅ¥ animáciu" #: src/ani.c:962 msgid "Output Files" msgstr "Výstupné súbory" #: src/ani.c:965 msgid "Start frame" msgstr "Prvá snímka" #: src/ani.c:967 msgid "End frame" msgstr "Posledná snímka" #: src/ani.c:969 src/shifter.c:267 msgid "Delay" msgstr "Oneskorenie" #: src/ani.c:971 msgid "Output path" msgstr "Výstupná cesta" #: src/ani.c:971 src/font.c:1637 src/spawn.c:664 msgid "Select Directory" msgstr "Vyberte adresár" #: src/ani.c:974 msgid "File prefix" msgstr "Predpona súboru" #: src/ani.c:976 src/canvas.c:2096 msgid "File Format" msgstr "Typ súboru" #: src/ani.c:980 msgid "Positions" msgstr "Pozície" #: src/ani.c:995 msgid "Cycling" msgstr "Cyklus" #: src/ani.c:1004 msgid "Save" msgstr "UložiÅ¥" #: src/ani.c:1005 src/font.c:1577 src/otherwindow.c:864 src/otherwindow.c:1602 #: src/otherwindow.c:1715 src/otherwindow.c:2921 src/otherwindow.c:3054 #: src/otherwindow.c:3153 msgid "Preview" msgstr "Náhľad" #: src/ani.c:1006 src/shifter.c:285 msgid "Create Frames" msgstr "VytvoriÅ¥ snímky" #: src/ani.c:1020 msgid "You must have at least 2 layers to create an animation" msgstr "Na vytvorenie animácie potrebujete aspoň 2 vrstvy" #: src/ani.c:1026 msgid "You must save your layers file before creating an animation" msgstr "Pred vytvorením animácie musíte najprv uložiÅ¥ súbor vrstiev" #: src/canvas.c:357 msgid "The image is too large to transform." msgstr "Obrázok je pre transformáciu príliÅ¡ veľký." #: src/canvas.c:393 src/canvas.c:430 src/otherwindow.c:1600 #: src/otherwindow.c:2507 src/otherwindow.c:2566 src/otherwindow.c:3162 msgid "Gradient" msgstr "Prechod" #: src/canvas.c:393 src/otherwindow.c:836 src/otherwindow.c:838 #: src/otherwindow.c:2057 src/otherwindow.c:3163 msgid "Palette" msgstr "Paleta" #: src/canvas.c:393 src/info.c:265 src/otherwindow.c:843 src/otherwindow.c:2740 #: src/otherwindow.c:3163 src/png.c:778 src/png.c:992 msgid "Clipboard" msgstr "Schránka" #: src/canvas.c:394 src/cpick.c:831 src/toolbar.c:299 msgid "Value" msgstr "Jas" #: src/canvas.c:394 src/cpick.c:811 src/otherwindow.c:571 src/otherwindow.c:855 #: src/otherwindow.c:3036 src/toolbar.c:318 msgid "Red" msgstr "ÄŒervená" #: src/canvas.c:394 src/cpick.c:815 src/otherwindow.c:571 src/otherwindow.c:856 #: src/otherwindow.c:3036 src/toolbar.c:319 msgid "Green" msgstr "Zelená" #: src/canvas.c:394 src/cpick.c:819 src/otherwindow.c:571 src/otherwindow.c:857 #: src/otherwindow.c:3036 src/toolbar.c:320 msgid "Blue" msgstr "Modrá" #: src/canvas.c:399 msgid "From " msgstr "Od " #: src/canvas.c:403 msgid "To " msgstr "Do " #: src/canvas.c:410 msgid "Map" msgstr "Mapa" #: src/canvas.c:429 msgid "MT" msgstr "MT" #: src/canvas.c:429 msgid "Sobel" msgstr "Sobel" #: src/canvas.c:429 msgid "Prewitt" msgstr "Prewitt" #: src/canvas.c:429 msgid "Kirsch" msgstr "Kirsch" #: src/canvas.c:430 msgid "Roberts" msgstr "Roberts" #: src/canvas.c:430 msgid "Laplace" msgstr "Laplace" #: src/canvas.c:430 msgid "Morphological" msgstr "Morfologické" #: src/canvas.c:442 msgid "Edge Detect" msgstr "Detekcia hrán" #: src/canvas.c:464 msgid "Edge Sharpen" msgstr "Zaostrenie hrán" #: src/canvas.c:472 msgid "Edge Soften" msgstr "Zjemnenie hrán" #: src/canvas.c:521 msgid "Different X/Y" msgstr "Rozdielne X/Y" #: src/canvas.c:522 src/canvas.c:562 src/canvas.c:603 src/canvas.c:637 #: src/canvas.c:722 src/otherwindow.c:1033 src/otherwindow.c:2668 msgid "Gamma corrected" msgstr "S Gamma korekciou" #: src/canvas.c:530 src/memory.c:8256 msgid "Gaussian Blur" msgstr "Gaussove rozmazanie" #: src/canvas.c:558 msgid "Radius" msgstr "Polomer" #: src/canvas.c:559 msgid "Amount" msgstr "Množstvo" #: src/canvas.c:560 msgid "Threshold " msgstr "Prah " #: src/canvas.c:570 src/memory.c:8397 msgid "Unsharp Mask" msgstr "Zaostrovacia maska" #: src/canvas.c:599 msgid "Outer radius" msgstr "Vonkajší polomer" #: src/canvas.c:600 msgid "Inner radius" msgstr "Vnútorný polomer" #: src/canvas.c:602 src/info.c:280 msgid "Normalize" msgstr "NormalizovaÅ¥" #: src/canvas.c:611 src/memory.c:8549 msgid "Difference of Gaussians" msgstr "Gaussov rozdiel" #: src/canvas.c:636 msgid "Protect details" msgstr "ChrániÅ¥ podrobnosti" #: src/canvas.c:645 msgid "Kuwahara-Nagao Blur" msgstr "Rozostrenie Kuwahara-Nagao" #: src/canvas.c:709 msgid "The image is too large for this rotation." msgstr "Obrázok je príliÅ¡ veľký pre túto rotáciu." #: src/canvas.c:723 msgid "Smooth" msgstr "VyhladiÅ¥" #: src/canvas.c:732 msgid "Free Rotate" msgstr "Ľubovoľná rotácia" #: src/canvas.c:989 src/viewer.c:1161 msgid "Not enough memory to create clipboard" msgstr "Nedostatok pamäte na vytvorenie schránky" #: src/canvas.c:1172 msgid "" "You have not allocated enough memory in the Preferences window to undo this " "action." msgstr "" "V nastaveniach ste nepridelili dostatok pamäte na vrátenie tejto operácie." #: src/canvas.c:1353 msgid "Invalid palette file" msgstr "Neplatný súbor palety" #: src/canvas.c:1383 msgid "Invalid channel file." msgstr "Neplatný súbor kanálov." #: src/canvas.c:1401 msgid "Raw frames" msgstr "Nespracované snímky" #: src/canvas.c:1401 msgid "Composited frames" msgstr "Zložené snímky" #: src/canvas.c:1402 msgid "Composited frames with nonzero delay" msgstr "Zložené snímky s nenulovým oneskorením" #: src/canvas.c:1406 msgid "Load Frames" msgstr "NaÄítaÅ¥ snímky" #: src/canvas.c:1409 msgid "Load into Layers" msgstr "NaÄítaÅ¥ do vrstiev" #: src/canvas.c:1415 msgid "Load First Frame" msgstr "NaÄítaÅ¥ prvú snímku" #: src/canvas.c:1416 msgid "Explode Frames" msgstr "RozbaliÅ¥ snímky" #: src/canvas.c:1418 msgid "View Animation" msgstr "ZobraziÅ¥ animáciu" #: src/canvas.c:1434 #, c-format msgid "This is an animated %s file." msgstr "Toto je animovaný súbor %s." #: src/canvas.c:1435 #, c-format msgid "This is a multipage %s file." msgstr "Toto je viacstranový súbor %s." #: src/canvas.c:1459 #, c-format msgid "File is too big, must be <= to width=%i height=%i" msgstr "Súbor je príliÅ¡ veľký, musí byÅ¥ <= šírka=%i výška=%i" #: src/canvas.c:1461 msgid "Unable to explode frames" msgstr "Nie je možné rozbaliÅ¥ snímky" #: src/canvas.c:1463 msgid "Unable to load file" msgstr "Nie je možné naÄítaÅ¥ súbor" #: src/canvas.c:1465 msgid "" "The file import library had to terminate due to a problem with the file " "(possibly corrupt image data or a truncated file). I have managed to load " "some data as the header seemed fine, but I would suggest you save this image " "to a new file to ensure this does not happen again." msgstr "" "Knižnica pre import súborov skonÄila z dôvodu problémov so súborom (možno " "poÅ¡kodené obrazové dáta alebo skrátený súbor). Podarilo sa naÄítaÅ¥ nejaké " "údaje, pretože hlaviÄka vyzerá byÅ¥ v poriadku, ale doporuÄujem uložiÅ¥ tento " "obrázok do nového súboru, aby sa situácia neopakovala." #: src/canvas.c:1467 msgid "The animation is too long to load all of it into layers." msgstr "" "Animácia je príliÅ¡ dlhá na to, aby ju bolo celú možné nahraÅ¥ do vrstiev." #: src/canvas.c:1469 msgid "Could not explode all the frames in the animation." msgstr "Nepodarilo sa rozbaliÅ¥ vÅ¡etky snímky v animácii." #: src/canvas.c:1481 src/font.c:1556 src/fpick.c:937 src/otherwindow.c:2748 #: src/prefs.c:321 src/toolbar.c:451 msgid "Size" msgstr "VeľkosÅ¥" #: src/canvas.c:1484 src/otherwindow.c:244 msgid "Width" msgstr "Šírka" #: src/canvas.c:1485 src/otherwindow.c:245 msgid "Height" msgstr "Výška" #: src/canvas.c:1489 src/channels.c:253 src/channels.c:317 src/fpick.c:666 #: src/fpick.c:957 src/mainwindow.c:3979 src/otherwindow.c:255 #: src/otherwindow.c:513 src/otherwindow.c:587 src/otherwindow.c:863 #: src/otherwindow.c:1054 src/otherwindow.c:1714 src/otherwindow.c:2084 #: src/otherwindow.c:2319 src/otherwindow.c:2521 src/otherwindow.c:2674 #: src/otherwindow.c:2759 src/otherwindow.c:2920 src/otherwindow.c:3053 #: src/otherwindow.c:3152 src/prefs.c:338 src/prefs.c:464 src/prefs.c:538 #: src/spawn.c:666 src/viewer.c:1258 msgid "Cancel" msgstr "ZruÅ¡iÅ¥" #: src/canvas.c:1490 src/channels.c:253 src/channels.c:317 src/fpick.c:956 #: src/info.c:297 src/mainwindow.c:3981 src/mygtk.c:233 src/mygtk.c:535 #: src/otherwindow.c:587 src/otherwindow.c:867 src/otherwindow.c:1054 #: src/otherwindow.c:1716 src/otherwindow.c:2084 src/otherwindow.c:2319 #: src/otherwindow.c:2521 src/otherwindow.c:2674 src/otherwindow.c:2759 #: src/otherwindow.c:3055 src/otherwindow.c:3154 src/prefs.c:338 #: src/prefs.c:538 src/spawn.c:666 msgid "OK" msgstr "OK" #: src/canvas.c:1504 #, c-format msgid "This is a scalable %s file." msgstr "Toto je Å¡kálovateľný súbor %s." #: src/canvas.c:1545 msgid "Cannot open file" msgstr "Nie je možné otvoriÅ¥ súbor" #: src/canvas.c:1546 msgid "Unsupported file format" msgstr "Nepodporovaný typ súboru" #: src/canvas.c:1673 #, c-format msgid "File: %s already exists. Do you want to overwrite it?" msgstr "Súbor: %s už existuje. Chcete ho prepísaÅ¥?" #: src/canvas.c:1674 msgid "File Found" msgstr "Súbor nájdený" #: src/canvas.c:1674 src/mainwindow.c:1095 msgid "NO" msgstr "NIE" #: src/canvas.c:1674 src/mainwindow.c:1095 msgid "YES" msgstr "ÃNO" #: src/canvas.c:1988 msgid "Unable to export undo images" msgstr "Nepodarilo sa exportovaÅ¥ obrázky histórie" #: src/canvas.c:1994 msgid "Unable to export ASCII file" msgstr "Nepodarilo sa exportovaÅ¥ do ASCII súboru" #: src/canvas.c:2076 src/layer.c:814 src/mainwindow.c:529 #, c-format msgid "Unable to save file: %s" msgstr "Nepodarilo sa uložiÅ¥ súbor: %s" #: src/canvas.c:2101 src/prefs.c:222 msgid "Transparency index" msgstr "Index priehľadnosti" #: src/canvas.c:2103 msgid "TIFF Compression" msgstr "Kompresia TIFF" #: src/canvas.c:2105 src/prefs.c:225 msgid "JPEG Save Quality (100=High)" msgstr "Kvalita ukladania JPEGu (100=Vysoká)" #: src/canvas.c:2107 msgid "ZIP Compression (0=None)" msgstr "Kompresia SIP (0=Žiadna)" #: src/canvas.c:2108 src/prefs.c:227 msgid "PNG Compression (0=None)" msgstr "Kompresia PNG (0=Žiadna)" #: src/canvas.c:2111 src/prefs.c:249 msgid "LZMA2 Compression (0=None)" msgstr "Kompresia LZMA2 (0=Žiadna)" #: src/canvas.c:2113 src/prefs.c:252 msgid "ZSTD Compression Level" msgstr "Úroveň kompresie ZSTD" #: src/canvas.c:2115 src/prefs.c:231 msgid "TGA RLE Compression" msgstr "Kompresia TGA RLE" #: src/canvas.c:2117 msgid "LBM PackBits Compression" msgstr "Kompresia LBM PackBits" #: src/canvas.c:2118 src/prefs.c:226 msgid "JPEG2000 Compression (0=Lossless)" msgstr "Kompresia JPEG2000 (0=Bezstratová)" #: src/canvas.c:2120 msgid "WebP Compression" msgstr "Kompresia WebP" #: src/canvas.c:2122 msgid "WebP Save Quality (100=High)" msgstr "Kvalita ukladania WebP (100=Vysoká)" #: src/canvas.c:2123 src/prefs.c:263 msgid "V8 Save Quality (100=High)" msgstr "Kvalita ukladania V8 (100=Vysoká)" #: src/canvas.c:2125 src/prefs.c:264 msgid "V8L Compression (0=None)" msgstr "Kompresia V8L (0=Žiadna)" #: src/canvas.c:2127 msgid "Hotspot at X =" msgstr "Aktívny bod na X =" #: src/canvas.c:2129 msgid "Y =" msgstr "Y =" #: src/canvas.c:2133 msgid "Animation delay" msgstr "Oneskorenie animácie" #: src/canvas.c:2136 src/otherwindow.c:253 msgid "Undoable" msgstr "Vrátiteľné" #: src/canvas.c:2138 src/prefs.c:236 msgid "Apply colour profile" msgstr "PoužiÅ¥ farebný profil" #: src/canvas.c:2176 src/toolbar.c:543 msgid "Load Image File" msgstr "NaÄítaÅ¥ súbor s obrázkom" #: src/canvas.c:2191 src/toolbar.c:544 msgid "Save Image File" msgstr "UložiÅ¥ súbor s obrázkom" #: src/canvas.c:2196 msgid "Load Palette File" msgstr "NaÄítaÅ¥ súbor s paletou" #: src/canvas.c:2202 msgid "Save Palette File" msgstr "UložiÅ¥ súbor s paletou" #: src/canvas.c:2207 msgid "Export Undo Images" msgstr "ExportovaÅ¥ obrázky histórie" #: src/canvas.c:2212 msgid "Export Undo Images (reversed)" msgstr "ExportovaÅ¥ obrázky histórie (reverzne)" #: src/canvas.c:2217 msgid "You must have 16 or fewer palette colours to export ASCII art." msgstr "" "Ak chcete exportovaÅ¥ ASCII kresbu, vaÅ¡a paleta môže obsahovaÅ¥ nanajvýš 16 " "farieb." #: src/canvas.c:2220 msgid "Export ASCII Art" msgstr "ExportovaÅ¥ ako ASCII kresbu" #: src/canvas.c:2224 msgid "Save Layer Files" msgstr "UložiÅ¥ súbor vrstiev" #: src/canvas.c:2234 msgid "Choose frames directory" msgstr "Vyberte adresár snímkov" #: src/canvas.c:2240 msgid "You must save at least one frame to create an animated GIF." msgstr "Aby ste vytvorili animovaný GIF, musíte uložiÅ¥ aspoň jednu snímku." #: src/canvas.c:2243 msgid "Export GIF animation" msgstr "ExportovaÅ¥ GIF animáciu" #: src/canvas.c:2247 msgid "Load Channel" msgstr "NaÄítaÅ¥ kanál" #: src/canvas.c:2255 msgid "Save Channel" msgstr "UložiÅ¥ kanál" #: src/canvas.c:2260 msgid "Save Composite Image" msgstr "UložiÅ¥ kompozitný obrázok" #: src/channels.c:243 msgid "Create Channel" msgstr "VytvoriÅ¥ kanál" #: src/channels.c:244 msgid "Channel Type" msgstr "Typ kanála" #: src/channels.c:247 msgid "Initial Channel State" msgstr "PoÄiatoÄný stav kanála" #: src/channels.c:251 msgid "Inverted" msgstr "Invertovaný" #: src/channels.c:265 msgid "Cleared" msgstr "Vynulovaný" #: src/channels.c:266 msgid "Set" msgstr "Nastavený" #: src/channels.c:267 msgid "Set colour A radius B" msgstr "Nastavená farba A polomer B" #: src/channels.c:268 msgid "Set blend A to B" msgstr "Nastavené mieÅ¡anie A do B" #: src/channels.c:269 msgid "Image Red" msgstr "ÄŒervená obrázka" #: src/channels.c:270 msgid "Image Green" msgstr "Zelená obrázka" #: src/channels.c:271 msgid "Image Blue" msgstr "Modrá obrázka" #: src/channels.c:273 src/channels.c:313 src/mainwindow.c:67 #: src/otherwindow.c:1666 msgid "Alpha" msgstr "Alfa" #: src/channels.c:274 src/channels.c:314 src/mainwindow.c:67 #: src/otherwindow.c:1670 msgid "Selection" msgstr "Výber" #: src/channels.c:275 src/channels.c:315 src/mainwindow.c:67 #: src/otherwindow.c:1674 msgid "Mask" msgstr "Maska" #: src/channels.c:312 msgid "Delete Channels" msgstr "VymazaÅ¥ kanály" #: src/channels.c:367 msgid "Threshold Channel" msgstr "Prah kanála" #: src/cpick.c:823 src/otherwindow.c:569 src/otherwindow.c:816 #: src/toolbar.c:299 msgid "Hue" msgstr "Odtieň" #: src/cpick.c:827 src/otherwindow.c:569 src/otherwindow.c:814 #: src/toolbar.c:299 msgid "Saturation" msgstr "Saturácia" #: src/cpick.c:835 msgid "Hex" msgstr "Hex" #: src/cpick.c:840 src/layer.c:1109 src/otherwindow.c:2513 src/prefs.c:323 #: src/toolbar.c:457 msgid "Opacity" msgstr "NepriehľadnosÅ¥" #: src/font.c:982 msgid "Creating Font Index" msgstr "Vytvára sa zoznam s písmami" #: src/font.c:1353 msgid "You must select at least one directory to search for fonts." msgstr "Musíte vybraÅ¥ aspoň jeden adresár, v ktorom sa budú hľadaÅ¥ písma." #: src/font.c:1529 src/font.c:1624 src/toolbar.c:609 src/viewer.c:1213 #: src/viewer.c:1258 msgid "Paste Text" msgstr "PrilepiÅ¥ text" #: src/font.c:1533 src/font.c:1572 src/png.c:3897 msgid "Text" msgstr "Text" #: src/font.c:1540 msgid "Font" msgstr "Písmo" #: src/font.c:1548 msgid "Style" msgstr "Å týl" #: src/font.c:1566 msgid "Filename" msgstr "Názov súboru" #: src/font.c:1567 msgid "Face" msgstr "Rez" #: src/font.c:1587 src/viewer.c:1222 msgid "Antialias" msgstr "Vyhladenie" #: src/font.c:1590 src/viewer.c:1224 msgid "Invert" msgstr "InvertovaÅ¥" #: src/font.c:1593 src/viewer.c:1226 msgid "Background colour =" msgstr "Farba pozadia =" #: src/font.c:1601 src/viewer.c:1233 msgid "DPI =" msgstr "DPI =" #: src/font.c:1610 msgid "Oblique" msgstr "Å ikmé" #: src/font.c:1612 src/viewer.c:1244 msgid "Angle of rotation =" msgstr "Uhol rotácie =" #: src/font.c:1617 src/viewer.c:1248 msgid "Align" msgstr "ZarovnaÅ¥" #: src/font.c:1620 src/viewer.c:1253 msgid "Spacing" msgstr "Rozostupy" #: src/font.c:1629 msgid "Font Directories" msgstr "Adresáre s písmom" #: src/font.c:1634 src/spawn.c:664 msgid "Directory" msgstr "Adresár" #: src/font.c:1637 msgid "New Directory" msgstr "Nový adresár" #: src/font.c:1644 src/prefs.c:532 msgid "Add" msgstr "PridaÅ¥" #: src/font.c:1645 src/prefs.c:533 msgid "Remove" msgstr "OdstrániÅ¥" #: src/font.c:1646 msgid "Create Index" msgstr "VytvoriÅ¥ zoznam" #: src/font.c:1660 src/viewer.c:1267 msgid "Enter Text Here" msgstr "Sem zadajte text" #: src/fpick.c:635 #, c-format msgid "Could not access directory %s" msgstr "Prístup do adresára %s nie je možný" #: src/fpick.c:668 src/fpick.c:698 msgid "Delete" msgstr "OdstrániÅ¥" #: src/fpick.c:669 src/fpick.c:698 msgid "Rename" msgstr "PremenovaÅ¥" #: src/fpick.c:672 src/otherwindow.c:255 src/otherwindow.c:1653 msgid "Create" msgstr "VytvoriÅ¥" #: src/fpick.c:699 msgid "Enter the new filename" msgstr "Zadajte nový názov súboru" #: src/fpick.c:704 msgid "Create Directory" msgstr "VytvoriÅ¥ adresár" #: src/fpick.c:705 msgid "Enter the name of the new directory" msgstr "Zadajte nový názov adresára" #: src/fpick.c:729 #, c-format msgid "Do you really want to delete \"%s\" ?" msgstr "Naozaj chcete odstrániÅ¥ \"%s\" ?" #: src/fpick.c:735 msgid "Unable to delete" msgstr "Nepodarilo sa odstrániÅ¥" #: src/fpick.c:741 msgid "Unable to rename" msgstr "Nepodarilo sa premenovaÅ¥" #: src/fpick.c:750 msgid "Unable to create directory" msgstr "Nepodarilo sa vytvoriÅ¥ adresár" #: src/fpick.c:924 msgid "Up" msgstr "Hore" #: src/fpick.c:925 msgid "Home" msgstr "Domovský adresár" #: src/fpick.c:926 msgid "Create New Directory" msgstr "VytvoriÅ¥ nový adresár" #: src/fpick.c:927 msgid "Show Hidden Files" msgstr "ZobraziÅ¥ skryté súbory" #: src/fpick.c:929 msgid "Case Insensitive Sort" msgstr "Triedenie bez rozliÅ¡ovania veľkosti písmen" #: src/fpick.c:936 msgid "Name" msgstr "Názov" #: src/fpick.c:938 msgid "Type" msgstr "Typ" #: src/fpick.c:939 msgid "Modified" msgstr "Zmenené" #: src/help.c:25 src/prefs.c:160 msgid "General" msgstr "VÅ¡eobecné" #: src/help.c:26 msgid "Keyboard shortcuts" msgstr "Klávesové skratky" #: src/help.c:27 msgid "Mouse shortcuts" msgstr "Skratky myÅ¡i" #: src/help.c:28 msgid "Credits" msgstr "PoÄakovanie" #: src/help.c:32 msgid "mtPaint 3.51 - Copyright (C) 2004-2021 The Authors\n" msgstr "mtPaint 3.51 - Copyright (C) 2004-2021 Autori\n" #: src/help.c:33 msgid "See 'Credits' section for a list of the authors.\n" msgstr "Zoznam autorov nájdete v záložke PoÄakovanie.\n" #: src/help.c:34 msgid "" "mtPaint 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.\n" msgstr "" "mtPaint je slobodný software; môžete ho šíriÅ¥ a/alebo modifikovaÅ¥ v súlade s " "GNU General Public Licenciou tak, ako bola publikovaná Free Software " "Foundation: buÄ verziou 3 alebo (podľa vášho uváženia) akoukoľvek ÄalÅ¡ou " "verziou.\n" #: src/help.c:35 msgid "" "mtPaint 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.\n" msgstr "" "mtPaint je distribuovaný v nádeji, že bude používaný, ale BEZ AKEJKOĽVEK " "ZÃRUKY; a taktiež bez samozrejmej záruky PREDAJNOSTI alebo SCHOPNOSTI PLNIŤ " "Å PECIÃLNE ÚČELY. Pre ÄalÅ¡ie podrobnosti si preÄítajte GNU General Public " "Licenciu.\n" #: src/help.c:36 msgid "" "mtPaint is a simple GTK+1/2/3 painting program designed for creating icons " "and pixel based artwork. It can edit indexed palette or 24 bit RGB images " "and offers basic painting and palette manipulation tools. It also has " "several other more powerful features such as channels, layers and animation. " "Due to its simplicity and lack of dependencies it runs well on GNU/Linux, " "Windows and older PC hardware.\n" msgstr "" "mtPaint je jednoduchý GTK+1/2/3 kresliaci program navrhnutý na vytváranie " "ikon a kresieb tvorených pixelmi. Dokáže upravovaÅ¥ obrázky s indexovanou " "alebo 24 bitovou RGB paletou a ponúknuÅ¥ základné kresliace a manipulaÄné " "nástroje. Má tiež mnoho Äalších mocných nástrojov ako kanály, vrstvy a " "animácie. Vzhľadom ku svojej jednoduchosti a bez závislostí beží dobre na " "GNU/Linuxe, Windows a starÅ¡om PC hardvéri.\n" #: src/help.c:37 msgid "" "There is full documentation of mtPaint's features contained in a handbook. " "If you don't already have this, you can download it from the mtPaint " "website.\n" msgstr "" "Kompletná dokumentácia funkcií mtPaintu je k dispozícii v príruÄke. Ak ju " "eÅ¡te nemáte, môžete si ju stiahnuÅ¥ z webových stránok mtPaintu.\n" #: src/help.c:38 msgid "" "If you like mtPaint and you want to keep up to date with new releases, or " "you want to give some feedback, then the mailing lists may be of interest to " "you:\n" msgstr "" "Ak sa vám mtPaint páÄi a chcete maÅ¥ vždy najnovÅ¡iu verziu alebo chcete daÅ¥ " "vedieÅ¥ svoj názor, môže byÅ¥ pre vás zaujímava táto mailová konferencia:\n" #: src/help.c:39 msgid "http://sourceforge.net/mail/?group_id=155874" msgstr "http://sourceforge.net/mail/?group_id=155874" #: src/help.c:42 msgid " Ctrl-N Create new image" msgstr " Ctrl-N VytvoriÅ¥ nový obrázok" #: src/help.c:43 msgid " Ctrl-O Open Image" msgstr " Ctrl-O OtvoriÅ¥ obrázok" #: src/help.c:44 msgid " Ctrl-S Save Image" msgstr " Ctrl-S UložiÅ¥ obrázok" #: src/help.c:45 msgid " Ctrl-Shift-S Save layers file" msgstr " Ctrl-Shift-S UložiÅ¥ súbor vrstiev" #: src/help.c:46 msgid " Ctrl-Q Quit program\n" msgstr " Ctrl-Q UkonÄiÅ¥ program\n" #: src/help.c:47 msgid " Ctrl-A Select whole image" msgstr " Ctrl-A VybraÅ¥ celý obrázok" #: src/help.c:48 msgid " Escape Select nothing, cancel paste box" msgstr " Escape ZruÅ¡iÅ¥ výber, zruÅ¡iÅ¥ oblasÅ¥" #: src/help.c:49 msgid " J Lasso selection\n" msgstr " J Výber lasom\n" #: src/help.c:50 msgid " Ctrl-C Copy selection to clipboard" msgstr " Ctrl-C SkopírovaÅ¥ výber do schránky" #: src/help.c:51 msgid "" " Ctrl-X Copy selection to clipboard, and then paint current " "pattern to selection area" msgstr "" " Ctrl-X SkopírovaÅ¥ výber do schránky a potom vyplniÅ¥ oblasÅ¥ " "výberu aktuálnym vzorom" #: src/help.c:52 msgid " Ctrl-V Paste clipboard to centre of current view" msgstr " Ctrl-V VložiÅ¥ obsah schránky do stredu obrázka" #: src/help.c:53 msgid " Ctrl-K Paste clipboard to location it was copied from" msgstr "" " Ctrl-K VložiÅ¥ obsah schránky na miesto, odkiaľ bola kopírovaná" #: src/help.c:54 msgid " Ctrl-Shift-V Paste clipboard to new layer" msgstr " Ctrl-Shift-V VložiÅ¥ obsah schránky do novej vrstvy" #: src/help.c:55 msgid " Enter/Return Commit paste to canvas" msgstr " Enter/Return PotvrdiÅ¥ vloženie na plátno" #: src/help.c:56 msgid " Shift+Enter/Return Commit paste and swap canvas into the clipboard\n" msgstr " Shift+Enter/Return PotvrdiÅ¥ vloženie a vymeniÅ¥ plátno do schránky\n" #: src/help.c:57 msgid " Arrow keys Paint Mode - Move the mouse pointer" msgstr " Klávesy Å¡ipiek Režim kreslenia - Presunúť kurzor myÅ¡i" #: src/help.c:58 msgid "" " Arrow keys Selection Mode - Nudge selection box or paste box by one " "pixel" msgstr "" " Klávesy Å¡ipiek Režim výberu - Posun oblasti výberu alebo vkladania o " "jeden pixel" #: src/help.c:59 msgid "" " Shift+Arrow keys Nudge mouse pointer, selection box or paste box by x " "pixels - x is defined by the Preferences window" msgstr "" " Shift+šípky Posunúť kurzor myÅ¡i, oblasti výberu alebo vkladanie o x " "pixelov - x je definované v okne s nastaveniami" #: src/help.c:60 msgid " Ctrl+Arrows Move layer or resize selection box" msgstr " Ctrl+šípky Presunúť vrstvu alebo zmeniÅ¥ veľkosÅ¥ oblasti výberu" #: src/help.c:61 msgid " Ctrl+Shift+Arrows Move layer or resize selection box by x pixels\n" msgstr "" " Ctrl+Shift+Arrows Presunúť vrstvu alebo zmeniÅ¥ veľkosÅ¥ oblasti výberu o x " "pixelov\n" #: src/help.c:62 msgid " Enter/Return Paint Mode - Simulate left click" msgstr "" " Enter/Return Režim kreslenia - NapodobniÅ¥ kliknutie ľavým tlaÄidlom" #: src/help.c:63 msgid " Backspace Paint Mode - Simulate right click\n" msgstr "" " Backspace Režim kreslenia - NapodobniÅ¥ kliknutie pravým tlaÄidlom\n" #: src/help.c:64 msgid "" " [ or ] Change colour A to the next or previous palette item" msgstr "" " [ or ] ZmeniÅ¥ farbu A na ÄalÅ¡iu alebo predchádzajúcu položku " "palety" #: src/help.c:65 msgid "" " Shift+[ or ] Change colour B to the next or previous palette item\n" msgstr "" " Shift+[ or ] ZmeniÅ¥ farbu B na ÄalÅ¡iu alebo predchádzajúcu položku " "palety\n" #: src/help.c:66 msgid " Delete Crop image to selection" msgstr " Delete OrezaÅ¥ obrázok podľa výberu" #: src/help.c:67 msgid "" " Insert Transform colours - i.e. Brightness, Contrast, " "Saturation, Posterize, Gamma" msgstr "" " Insert TransformovaÅ¥ farby - t. j. jas, kontrast, saturáciu, " "bitov na farbu, Gammu" #: src/help.c:68 msgid " Ctrl-G Greyscale the image" msgstr " Ctrl-G PreviesÅ¥ do Å¡edej Å¡kály" #: src/help.c:69 msgid " Shift-Ctrl-G Greyscale the image (Gamma corrected)" msgstr " Shift-Ctrl-G Prevést do Å¡edej Å¡kály (S Gamma korekciou)" #: src/help.c:70 msgid " Ctrl+M Mirror the image" msgstr " Ctrl+M ZrkadliÅ¥ obrázok" #: src/help.c:71 msgid " Shift-Ctrl-I Invert the image\n" msgstr " Shift-Ctrl-I InvertovaÅ¥ obrázok\n" #: src/help.c:72 msgid "" " Ctrl-T Draw a rectangle around the selection area with the " "current fill" msgstr "" " Ctrl-T NakresliÅ¥ obdĺžnik okolo oblasti výberu aktuálnou výplňou" #: src/help.c:73 msgid " Ctrl-Shift-T Fill in the selection area with the current fill" msgstr " Ctrl-Shift-T VyplniÅ¥ oblasÅ¥ výberu aktuálnou výplňou" #: src/help.c:74 msgid " Ctrl-L Draw an ellipse spanning the selection area" msgstr " Ctrl-L NakresliÅ¥ elipsu vnútri oblasti výberu" #: src/help.c:75 msgid " Ctrl-Shift-L Draw a filled ellipse spanning the selection area\n" msgstr " Ctrl-Shift-L NakresliÅ¥ vyplnenú elipsu vnútri oblasti výberu\n" #: src/help.c:76 msgid " Ctrl-E Edit the RGB values for colours A & B" msgstr " Ctrl-E UpraviÅ¥ RGB hodnoty pre farby A a B" #: src/help.c:77 msgid " Ctrl-W Edit all palette colours\n" msgstr " Ctrl-W UpraviÅ¥ vÅ¡etky farby palety\n" #: src/help.c:78 msgid " Ctrl-P Preferences" msgstr " Ctrl-P Nastavenia" #: src/help.c:79 msgid " Ctrl-I Information\n" msgstr " Ctrl-I Informácie\n" #: src/help.c:80 msgid " Ctrl-Z Undo last action" msgstr " Ctrl-Z VrátiÅ¥ poslednú akciu" #: src/help.c:81 msgid " Ctrl-R Redo an undone action\n" msgstr " Ctrl-R Znovu vykonaÅ¥ vrátenú akciu\n" #: src/help.c:82 msgid " Shift-T Text Tool (GTK+)" msgstr " Shift-T Nástroj textu (GTK+)" #: src/help.c:83 msgid " T Text Tool (FreeType)\n" msgstr " T Nástroj textu (FreeType)\n" #: src/help.c:84 msgid " V View Window" msgstr " V Okno zobrazenia" #: src/help.c:85 msgid " L Layers Window\n" msgstr " L Okno vrstiev\n" #: src/help.c:86 msgid " Ctrl-H Toggle Hide Image mode" msgstr " Ctrl-H Prepnúť režim skrytia obrázka" #: src/help.c:87 msgid " B Toggle Snap to Tile Grid mode\n" msgstr " B Prepnúť režim prichytávania na mriežku\n" #: src/help.c:88 msgid " X Swap Colours A & B" msgstr " X PrehodiÅ¥ farby A a B" #: src/help.c:89 msgid " E Choose Colour\n" msgstr " E VybraÅ¥ farbu\n" #: src/help.c:90 msgid "" " A Draw open arrow head when using the line tool (size set " "by flow setting)" msgstr "" " A Pri použití nástroja Äiary kresliÅ¥ otvorenú šípku " "(veľkosÅ¥ urÄená nastavením toku)" #: src/help.c:91 msgid "" " S Draw closed arrow head when using the line tool (size " "set by flow setting)\n" msgstr "" " S Pri použití nástroja Äiary kresliÅ¥ uzatvorenú šípku " "(veľkosÅ¥ urÄená nastavením toku)\n" #: src/help.c:92 msgid " D Line Tool" msgstr " D Nástroj Äiary" #: src/help.c:93 msgid " F Flood Fill Tool\n" msgstr " F Nástroj pre vyplnenie farbou\n" #: src/help.c:94 msgid " +,= Main edit window - Zoom in" msgstr " +,= Hlavné editaÄné okno - PriblížiÅ¥" #: src/help.c:95 msgid " - Main edit window - Zoom out" msgstr " - Hlavné editaÄné okno - OddialiÅ¥" #: src/help.c:96 msgid " Shift +,= View window - Zoom in" msgstr " Shift +,= Okno zobrazenia - PriblížiÅ¥" #: src/help.c:97 msgid " Shift - View window - Zoom out\n" msgstr " Shift - Okno zobrazenía - OddialiÅ¥\n" #: src/help.c:98 #, c-format msgid " 1 10% zoom" msgstr " 1 10% priblíženie" #: src/help.c:99 #, c-format msgid " 2 25% zoom" msgstr " 2 25% priblíženie" #: src/help.c:100 #, c-format msgid " 3 50% zoom" msgstr " 3 50% priblíženie" #: src/help.c:101 #, c-format msgid " 4 100% zoom" msgstr " 4 100% priblíženie" #: src/help.c:102 #, c-format msgid " 5 400% zoom" msgstr " 5 400% priblíženie" #: src/help.c:103 #, c-format msgid " 6 800% zoom" msgstr " 6 800% priblíženie" #: src/help.c:104 #, c-format msgid " 7 1200% zoom" msgstr " 7 1200% priblíženie" #: src/help.c:105 #, c-format msgid " 8 1600% zoom" msgstr " 8 1600% priblíženie" #: src/help.c:106 #, c-format msgid " 9 2000% zoom\n" msgstr " 9 2000% priblíženie\n" #: src/help.c:107 msgid " Shift + 1 Edit image channel" msgstr " Shift + 1 UpraviÅ¥ kanál obrázka" #: src/help.c:108 msgid " Shift + 2 Edit alpha channel" msgstr " Shift + 2 UpraviÅ¥ alfakanál" #: src/help.c:109 msgid " Shift + 3 Edit selection channel" msgstr " Shift + 3 UpraviÅ¥ kanál výberu" #: src/help.c:110 msgid " Shift + 4 Edit mask channel\n" msgstr " Shift + 4 UpraviÅ¥ kanál masky\n" #: src/help.c:111 msgid " F1 Help" msgstr " F1 Pomocník" #: src/help.c:112 msgid " F2 Choose Pattern" msgstr " F2 VybraÅ¥ vzor" #: src/help.c:113 msgid " F3 Choose Brush" msgstr " F3 VybraÅ¥ Å¡tetec" #: src/help.c:114 msgid " F4 Paint Tool" msgstr " F4 Nástroj maľovania" #: src/help.c:115 msgid " F5 Toggle Main Toolbar" msgstr " F5 Hlavná liÅ¡ta" #: src/help.c:116 msgid " F6 Toggle Tools Toolbar" msgstr " F6 Nástrojová liÅ¡ta" #: src/help.c:117 msgid " F7 Toggle Settings Toolbar" msgstr " F7 LiÅ¡ta nastavení" #: src/help.c:118 msgid " F8 Toggle Palette" msgstr " F8 Paleta" #: src/help.c:119 msgid " F9 Selection Tool" msgstr " F9 Nástroj výberu" #: src/help.c:120 msgid " F12 Toggle Dock Area\n" msgstr " F12 Zapnúť/vypnúť oblasÅ¥ ukotvenia\n" #: src/help.c:121 msgid " Ctrl + F1 - F12 Save current clipboard to file 1-12" msgstr " Ctrl + F1 - F12 Uloží aktuálnu schránku do súboru 1-12" #: src/help.c:122 msgid " Shift + F1 - F12 Load clipboard from file 1-12\n" msgstr " Shift + F1 - F12 NaÄíta súbor 1-12 do schránky\n" #: src/help.c:123 msgid "" " Ctrl + 1, 2, ... , 0 Set opacity to 10%, 20%, ... , 100% (main or keypad " "numbers)" msgstr "" " Ctrl + 1, 2, ... , 0 Nastaví nepriesvitnosÅ¥ na 10%, 20%, ... , 100% " "(hlavná aj numerická klávesnica)" #: src/help.c:124 msgid " Ctrl + + or = Increase opacity by 1" msgstr " Ctrl + + or = Zvýši nepriesvitnosÅ¥ o 1" #: src/help.c:125 msgid " Ctrl + - Decrease opacity by 1\n" msgstr " Ctrl + - Zníži nepriesvitnosÅ¥ o 1\n" #: src/help.c:126 msgid "" " Home Show or hide main window menu/toolbar/status bar/palette" msgstr "" " Home Zobrazí alebo skryje hlavnú ponuku, panely, nástroje a " "paletu" #: src/help.c:127 msgid " Page Up Scale Image" msgstr " Page Up Zmena mierky obrázka" #: src/help.c:128 msgid " Page Down Resize Image canvas" msgstr " Page Down Zmena veľkosti plátna" #: src/help.c:129 msgid " End Pan Window" msgstr " End Prehľadové okno" #: src/help.c:132 msgid " Left button Paint to canvas using the current tool" msgstr " Ľavé tlaÄidlo Maľuje na plátno pomocou vybraného nástroja" #: src/help.c:133 msgid "" " Middle button Selects the point which will be the centre of the " "image after the next zoom" msgstr "" " Stredné tlaÄidlo Nastaví bod, ktorý bude stredom obrázku pri ÄalÅ¡ej " "zmene zoomu" #: src/help.c:134 msgid "" " Right button Commit paste to canvas / Stop drawing current line / " "Cancel selection\n" msgstr "" " Pravé tlaÄidlo Potvrdí vloženie na plátno / Preruší kreslenie " "Äiary / Zruší výber oblasti\n" #: src/help.c:135 msgid "" " Scroll Wheel In GTK+2/3 the user can have the scroll wheel zoom in " "or out via the Preferences window\n" msgstr "" " Koliesko myÅ¡i V GTK+2/3 môže používateľ použiÅ¥ koliesko na zmenu " "priblíženia nastavením v okne volieb\n" #: src/help.c:136 msgid " Ctrl+Left button Choose colour A from under mouse pointer" msgstr " Ctrl+Ľavé tlaÄidlo Výber farby A spod kurzora myÅ¡i" #: src/help.c:137 msgid " Ctrl+Left button Clone tool - Select source" msgstr " Ctrl+Ľavé tlaÄidlo Nástroj peÄiatky - Výber zdroja" #: src/help.c:138 msgid "" " Ctrl+Middle button Create colour A/B and pattern based on the RGB colour " "in A (RGB images only)" msgstr "" " Ctrl+Stredné tlaÄidlo Vytvorenie farby A/B a vzoru založenéno na RGB farbe " "v A (iba RGB obrázky)" #: src/help.c:139 msgid " Ctrl+Right button Choose colour B from under mouse pointer" msgstr " Ctrl+Pravé tlaÄidlo Výber farby B spod kurzora myÅ¡i" #: src/help.c:140 msgid "" " Ctrl+Right button Polygon tool - Delete last point / Delete nearest " "point" msgstr "" " Ctrl+Pravé tlaÄidlo Nástroj polygónu - Odstráni posledný bod/Odstráni " "najbližší bod" #: src/help.c:141 msgid " Ctrl+Scroll Wheel Scroll the main edit window left or right\n" msgstr "" " Ctrl+koliesko Posúva hlavné editaÄné okno doľava alebo doprava\n" #: src/help.c:142 msgid "" " Ctrl+Double click Set colour A or B to average colour under brush " "square or selection marquee (RGB only)\n" msgstr "" " Ctrl+Dvojklik Nastaví farbu A alebo B na priemer farby pod Å¡tvorcom " "Å¡tetca alebo v oznaÄenej oblasti (iba RGB)\n" #: src/help.c:143 msgid "" " Shift+Right button Selects the point which will be the centre of the " "image after the next zoom\n" "\n" msgstr "" " Shift+Pravé tlaÄidlo Nastaví bod, ktorý bude stredom obrázku pri ÄalÅ¡ej " "zmene priblíženie\n" "\n" #: src/help.c:144 msgid "You can fixate the X/Y co-ordinates while moving the mouse:\n" msgstr "Pri posúvaní myÅ¡i môžete zablokovaÅ¥ osi X/Y takto:\n" #: src/help.c:145 msgid " Shift Constrain mouse movements to vertical line" msgstr " Shift Obmedzí posuny myší na vertikálnu os" #: src/help.c:146 msgid " Shift+Ctrl Constrain mouse movements to horizontal line" msgstr " Shift+Ctrl Obmedzí posuny myší na horizontálnu os" #: src/help.c:149 msgid "mtPaint is maintained by Dmitry Groshev.\n" msgstr "mtPaint aktuálne spravuje Dmitry Groshev.\n" #: src/help.c:150 msgid "wjaguar@users.sourceforge.net" msgstr "wjaguar@users.sourceforge.net" #: src/help.c:151 msgid "http://mtpaint.sourceforge.net/\n" msgstr "http://mtpaint.sourceforge.net/\n" #: src/help.c:152 msgid "" "The following people (in alphabetical order) have contributed directly to " "the project, and are therefore worthy of gracious thanks for their " "generosity and hard work:\n" "\n" msgstr "" "Nasledujúci ľudia (v abecednom poradí) sa priamo podieľajú na projekte a " "preto im patrí veľká vÄaka za ich veľkorysosÅ¥ a Å¥ažkú prácu:\n" "\n" #: src/help.c:153 msgid "Authors\n" msgstr "Autori\n" #: src/help.c:154 msgid "" "Dmitry Groshev - Contributing developer for version 2.30. Lead developer and " "maintainer from version 3.00 to the present." msgstr "" "Dmitry Groshev - Prispievajúci vývojár pre verziu 2.30. Vedúci vývojár a " "správca od verze 3.00 do dneÅ¡ka." #: src/help.c:155 msgid "" "Mark Tyler - Original author and maintainer up to version 3.00, occasional " "contributor thereafter." msgstr "" "Mark Tyler - Pôvodný autor a správca do verzie 3.00 a od toho Äasu obÄasný " "prispievateľ." #: src/help.c:156 msgid "" "Xiaolin Wu - Wrote the Wu quantizing method - see wu.c for more " "information.\n" "\n" msgstr "" "Xiaolin Wu - Napísal Wu quantovaciu metódu - viac informácií v súbore wu.c\n" "\n" #: src/help.c:157 msgid "" "General Contributions (Feedback and Ideas for improvements unless otherwise " "stated)\n" msgstr "" "Základní prispievatelia (Spätná väzba a nápady na vylepÅ¡enie, ak nie je " "uvedené inak)\n" #: src/help.c:158 msgid "Abdulla Al Muhairi - Website redesign April 2005" msgstr "Abdulla Al Muhairi - Redesign stránok - apríl 2005" #: src/help.c:159 msgid "Alan Horkan" msgstr "Alan Horkan" #: src/help.c:160 msgid "Alexandre Prokoudine" msgstr "Alexandre Prokoudine" #: src/help.c:161 msgid "Antonio Andrea Bianco" msgstr "Antonio Andrea Bianco" #: src/help.c:162 msgid "Charlie Ledocq" msgstr "Charlie Ledocq" #: src/help.c:163 msgid "Dennis Lee" msgstr "Dennis Lee" #: src/help.c:164 msgid "Donald White" msgstr "Donald White" #: src/help.c:165 msgid "Ed Jason" msgstr "Ed Jason" #: src/help.c:166 msgid "" "Eddie Kohler - Created Gifsicle which is needed for the creation and viewing " "of animated GIF files http://www.lcdf.org/gifsicle/" msgstr "" "Eddie Kohler - Vytvoril Gifsicle, který je potrebný na vytvorenie a " "zobrazenie animovaných GIFov http://www.lcdf.org/gifsicle/" #: src/help.c:167 msgid "" "Guadalinex Team (Junta de Andalucia) - man page, Launchpad/Rosetta " "registration" msgstr "" "Guadalinex Team (Junta de Andalucia) - manuálová stránka, Launchpad/Rosetta " "registrácia" #: src/help.c:168 msgid "Lou Afonso" msgstr "Lou Afonso" #: src/help.c:169 msgid "Magnus Hjorth" msgstr "Magnus Hjorth" #: src/help.c:170 msgid "Martin Zelaia" msgstr "Martin Zelaia" #: src/help.c:171 msgid "Pasi Kallinen" msgstr "Pasi Kallinen" #: src/help.c:172 msgid "Pavel Ruzicka" msgstr "Pavel Ruzicka" #: src/help.c:173 msgid "Puppy Linux (Barry Kauler)" msgstr "Puppy Linux (Barry Kauler)" #: src/help.c:174 msgid "Victor Copovi" msgstr "Victor Copovi" #: src/help.c:175 msgid "Vlastimil Krejcir" msgstr "Vlastimil Krejcir" #: src/help.c:176 msgid "" "William Kern\n" "\n" msgstr "" "William Kern\n" "\n" #: src/help.c:177 msgid "Translations\n" msgstr "Preklady\n" #: src/help.c:178 msgid "Brazilian Portuguese - Paulo Trevizan, Valter Nazianzeno" msgstr "Brazílska PortugalÄina - Paulo Trevizan, Valter Nazianzeno" #: src/help.c:179 msgid "Czech - Pavel Ruzicka, Martin Petricek, Roman Hornik, Pavel Fric" msgstr "ÄŒeÅ¡tina - Pavel Ruzicka, Martin Petricek, Roman Hornik, Pavel Fric" #: src/help.c:180 msgid "Dutch - Hans Strijards, Pjotr" msgstr "HolandÄina - Hans Strijards, Pjotr" #: src/help.c:181 msgid "" "French - Nicolas Velin, Pascal Billard, Sylvain Cresto, Johan Serre, " "Philippe Etienne, Victor Copovi" msgstr "" "FrancúzÅ¡tina - Nicolas Velin, Pascal Billard, Sylvain Cresto, Johan Serre, " "Philippe Etienne, Victor Copovi" #: src/help.c:182 msgid "Galician - Miguel Anxo Bouzada" msgstr "GalícijÄina - Miguel Anxo Bouzada" #: src/help.c:183 msgid "German - Oliver Frommel, B. Clausius, Ulrich Ringel, Simon Brixel" msgstr "NemÄina - Oliver Frommel, B. Clausius, Ulrich Ringel, Simon Brixel" #: src/help.c:184 msgid "Hungarian - Ur Balazs" msgstr "MaÄarÄina - Urs Balazs" #: src/help.c:185 msgid "Italian - Angelo Gemmi" msgstr "TalianÄina - Angelo Gemmi" #: src/help.c:186 msgid "Japanese - Norihiro YONEDA" msgstr "JaponÄina - Norihiro YONEDA" #: src/help.c:187 msgid "Kabyle - Yacine Bouklif" msgstr "Kabyle - Yacine Bouklif" #: src/help.c:188 msgid "Polish - Bartosz Kaszubowski, LucaS" msgstr "Poľština - Bartosz Kaszubowski, LucaS" #: src/help.c:189 msgid "Portuguese - Israel G. Lugo, Tiago Silva" msgstr "PortugalÄina - Israel G. Lugo, Tiago Silva" #: src/help.c:190 msgid "Russian - Sergey Irupin, Dmitry Groshev" msgstr "RuÅ¡tina - Sergey Irupin, Dmitry Groshev" #: src/help.c:191 msgid "Simplified Chinese - Cecc" msgstr "ZjednoduÅ¡ená ÄínÅ¡tina - Cecc" #: src/help.c:192 msgid "Slovak - Jozef Riha" msgstr "SlovenÄina - Jozef Riha" #: src/help.c:193 msgid "" "Spanish - Guadalinex Team (Junta de Andalucia), Antonio Sanchez Leon, Miguel " "Anxo Bouzada, Francisco Jose Rey, Adolfo Jayme" msgstr "" "Å panielÄina - Guadalinex Team (Junta de Andalucia), Antonio Sanchez Leon, " "Miguel Anxo Bouzada, Francisco Jose Rey, Adolfo Jayme" #: src/help.c:194 msgid "Swedish - Daniel Nylander, Daniel Eriksson" msgstr "Å védÄina - Daniel Nylander, Daniel Eriksson" #: src/help.c:195 msgid "Tagalog - Anjelo delCarmen" msgstr "Tagalog - Anjelo delCarmen" #: src/help.c:196 msgid "Taiwanese Chinese - Wei-Lun Chao" msgstr "Taiwanská ÄínÅ¡tina - Wei-Lun Chao" #: src/help.c:197 msgid "Turkish - Muhammet Kara, Tutku Dalmaz" msgstr "TureÄtina - Muhammet Kara, Tutku Dalmaz" #: src/info.c:258 msgid "Information" msgstr "Informácie" #: src/info.c:260 msgid "Memory" msgstr "Pamäť" #: src/info.c:261 msgid "Total memory for main + undo images" msgstr "Celková pamäť pre hlavné obrázky a históriu" #: src/info.c:263 msgid "Undo / Redo / Max levels used" msgstr "Späť / Znovu / Max poÄet úrovní" #: src/info.c:265 msgid "Unused" msgstr "Nepoužité" #: src/info.c:269 msgid "Unique RGB pixels" msgstr "Unikátnych RGB pixelov" #: src/info.c:272 src/layer.c:121 msgid "Layers" msgstr "Vrstvy" #: src/info.c:273 msgid "Total layer memory usage" msgstr "Spotreba pamäte vÅ¡etkých vrstiev" #: src/info.c:277 msgid "Colour Histogram" msgstr "Histogram farieb" #: src/info.c:289 src/otherwindow.c:1601 msgid "Index" msgstr "Index" #: src/info.c:290 msgid "Canvas pixels" msgstr "Pixelov na plátne" #: src/info.c:328 #, c-format msgid "Clipboard = %i x %i" msgstr "Schránka = %i x %i" #: src/info.c:328 #, c-format msgid "Clipboard = %i x %i x RGB" msgstr "Schránka = %i x %i x RGB" #: src/info.c:377 msgid "Orphans" msgstr "Sirôt" #: src/info.c:383 #, c-format msgid "Colour index totals - %i of %i used" msgstr "Farebný index celkom - použité %i z %i" #: src/inifile.c:966 msgid "" "Could not find home directory. Using current directory as home directory." msgstr "" "Nepodarilo sa nájsÅ¥ domovský adresár. Použijem aktuálny adresár ako domovský." #: src/layer.c:63 msgid "Background" msgstr "Pozadie" #: src/layer.c:122 src/mainwindow.c:5920 msgid "(Modified)" msgstr "(Zmenené)" #: src/layer.c:123 src/mainwindow.c:5921 msgid "Untitled" msgstr "Bez názvu" #: src/layer.c:308 #, c-format msgid "Do you really want to delete layer %i (%s) ?" msgstr "SkutoÄne chcete odstrániÅ¥ vrstvu %i (%s)?" #: src/layer.c:380 msgid "" "One or more of the layers contains changes that have not been saved. Do you " "really want to lose these changes?" msgstr "" "Jedna alebo viacero vrstiev obsahuje zmeny, ktoré neboli uložené. SkutoÄne " "ich chcete stratiÅ¥?" #: src/layer.c:381 src/mainwindow.c:1028 msgid "Cancel Operation" msgstr "ZruÅ¡iÅ¥ akciu" #: src/layer.c:381 src/mainwindow.c:1028 msgid "Lose Changes" msgstr "ZahodiÅ¥ zmeny" #: src/layer.c:523 #, c-format msgid "%d layers failed to load" msgstr "%d vrstiev sa nepodarilo naÄítaÅ¥" #: src/layer.c:826 msgid "" "One or more of the image layers has not been saved. You must save each " "image individually before saving the layers text file in order to load this " "composite image in the future." msgstr "" "Jedna alebo viacero vrstiev nebolo uložených. Musíte uložiÅ¥ každý obrázok " "samostatne predtým, než uložíte textový súbor s vrstvami, aby ste mohli v " "budúcnosti otvoriÅ¥ tento zložený obrázok." #: src/layer.c:841 msgid "Do you really want to delete all of the layers?" msgstr "SkutoÄne chcete odstrániÅ¥ vÅ¡etky vrstvy?" #: src/layer.c:970 msgid "You cannot add any more layers." msgstr "Nemôžete už pridaÅ¥ žiadne ÄalÅ¡ie vrstvy." #: src/layer.c:1083 src/otherwindow.c:241 msgid "New Layer" msgstr "Nová vrstva" #: src/layer.c:1085 msgid "Raise" msgstr "Vyššie" #: src/layer.c:1087 msgid "Lower" msgstr "Nižšie" #: src/layer.c:1089 msgid "Duplicate Layer" msgstr "DuplikovaÅ¥ vrstvu" #: src/layer.c:1091 msgid "Centralise Layer" msgstr "VycentrovaÅ¥ vrstvu" #: src/layer.c:1093 msgid "Delete Layer" msgstr "OdstrániÅ¥ vrstvu" #: src/layer.c:1095 msgid "Close Layers Window" msgstr "ZavrieÅ¥ okno vrstiev" #: src/layer.c:1101 msgid "Layer Name" msgstr "Názov vrstvy" #: src/layer.c:1104 src/toolbar.c:209 msgid "Position" msgstr "Pozícia" #: src/layer.c:1112 msgid "Transparent Colour" msgstr "Priehľadná farba" #: src/layer.c:1117 msgid "Show all layers in main window" msgstr "ZobraziÅ¥ vÅ¡etky vrstvy v hlavnom okne" #: src/mainwindow.c:67 src/otherwindow.c:840 src/otherwindow.c:2739 #: src/toolbar.c:342 msgid "Image" msgstr "Obrázok" #: src/mainwindow.c:69 src/mainwindow.c:489 src/otherwindow.c:1600 #: src/otherwindow.c:2285 msgid "RGB" msgstr "RGB" #: src/mainwindow.c:69 src/otherwindow.c:1600 src/otherwindow.c:2285 msgid "sRGB" msgstr "sRGB" #: src/mainwindow.c:342 msgid "There were no unused colours to remove!" msgstr "Nie sú žiadne nepoužité farby na odstránenie!" #: src/mainwindow.c:371 msgid "The palette does not contain 2 colours that have identical RGB values" msgstr "Paleta neobsahuje žiadne farby s identickými RGB hodnotami" #: src/mainwindow.c:374 #, c-format msgid "" "The palette contains %i colours that have identical RGB values. Do you " "really want to merge them into one index and realign the canvas?" msgstr "" "Paleta obsahuje %i farieb s rovnakými RGB hodnotami. SkutoÄne ich chcete " "zlúÄiÅ¥ do jednej a upraviÅ¥ plátno?" #: src/mainwindow.c:492 msgid "indexed" msgstr "indexované" #: src/mainwindow.c:498 #, c-format msgid "" "You are trying to save an %s image to an %s file which is not possible. I " "would suggest you save with a PNG extension." msgstr "" "Pokúšate sa uložiÅ¥ %s obrázok do súboru %s, Äo nie je možné. Navrhujem vám " "uložiÅ¥ ho s príponou PNG." #: src/mainwindow.c:500 #, c-format msgid "" "You are trying to save an %s file with a palette of more than %d colours. " "Either use another format or reduce the palette to %d colours." msgstr "" "Pokúšate sa uložiÅ¥ %s obrázok s paletou obsahujúcou viac ako %d farieb. BuÄ " "použite inýformát alebo znížte poÄet farieb v palete na %d farieb." #: src/mainwindow.c:578 msgid "Unable to load clipboard" msgstr "Nie je možné naÄítaÅ¥ schránku" #: src/mainwindow.c:604 msgid "Unable to save clipboard" msgstr "Nie je možné uložiÅ¥ schránku" #: src/mainwindow.c:775 msgid "Zoom in" msgstr "PriblížiÅ¥" #: src/mainwindow.c:777 msgid "Zoom out" msgstr "OddialiÅ¥" #: src/mainwindow.c:779 #, c-format msgid "10% zoom" msgstr "10% priblíženie" #: src/mainwindow.c:781 #, c-format msgid "25% zoom" msgstr "25% priblíženie" #: src/mainwindow.c:783 #, c-format msgid "50% zoom" msgstr "50% priblíženie" #: src/mainwindow.c:785 #, c-format msgid "100% zoom" msgstr "100% priblíženie" #: src/mainwindow.c:787 #, c-format msgid "400% zoom" msgstr "400% priblíženie" #: src/mainwindow.c:789 #, c-format msgid "600% zoom" msgstr "600% priblíženie" #: src/mainwindow.c:791 #, c-format msgid "800% zoom" msgstr "800% priblíženie" #: src/mainwindow.c:793 #, c-format msgid "1000% zoom" msgstr "1000% priblíženie" #: src/mainwindow.c:795 #, c-format msgid "1200% zoom" msgstr "1200% priblíženie" #: src/mainwindow.c:797 #, c-format msgid "1600% zoom" msgstr "1600% priblíženie" #: src/mainwindow.c:799 #, c-format msgid "2000% zoom" msgstr "2000% priblíženie" #: src/mainwindow.c:801 #, c-format msgid "4000% zoom" msgstr "4000% priblíženie" #: src/mainwindow.c:803 #, c-format msgid "8000% zoom" msgstr "8000% priblíženie" #: src/mainwindow.c:805 #, c-format msgid "10% opacity" msgstr "10% nepriehľadnosÅ¥" #: src/mainwindow.c:807 #, c-format msgid "20% opacity" msgstr "20% nepriehľadnosÅ¥" #: src/mainwindow.c:809 #, c-format msgid "30% opacity" msgstr "30% nepriehľadnosÅ¥" #: src/mainwindow.c:811 #, c-format msgid "40% opacity" msgstr "40% nepriehľadnosÅ¥" #: src/mainwindow.c:813 #, c-format msgid "50% opacity" msgstr "50% nepriehľadnosÅ¥" #: src/mainwindow.c:815 #, c-format msgid "60% opacity" msgstr "60% nepriehľadnosÅ¥" #: src/mainwindow.c:817 #, c-format msgid "70% opacity" msgstr "70% nepriehľadnosÅ¥" #: src/mainwindow.c:819 #, c-format msgid "80% opacity" msgstr "80% nepriehľadnosÅ¥" #: src/mainwindow.c:821 #, c-format msgid "90% opacity" msgstr "90% nepriehľadnosÅ¥" #: src/mainwindow.c:823 #, c-format msgid "100% opacity" msgstr "100% nepriehľadnosÅ¥" #: src/mainwindow.c:825 msgid "Increase opacity" msgstr "ZvýšiÅ¥ nepriehľadnosÅ¥" #: src/mainwindow.c:827 msgid "Decrease opacity" msgstr "ZnížiÅ¥ nepriehľadnosÅ¥" #: src/mainwindow.c:829 msgid "Draw open arrow head" msgstr "NakresliÅ¥ otvorenú šípku" #: src/mainwindow.c:831 msgid "Draw closed arrow head" msgstr "NakresliÅ¥ uzatvorenú šípku" #: src/mainwindow.c:833 msgid "Previous colour A" msgstr "Predchádzajúca farba A" #: src/mainwindow.c:835 msgid "Next colour A" msgstr "Nasledujúca farba A" #: src/mainwindow.c:837 msgid "Previous colour B" msgstr "Predchádzajúca farba B" #: src/mainwindow.c:839 msgid "Next colour B" msgstr "Nasledujúca farba B" #: src/mainwindow.c:841 msgid "Previous pattern" msgstr "Predchádzajúci vzor" #: src/mainwindow.c:843 msgid "Next pattern" msgstr "Nasledujúci vzor" #: src/mainwindow.c:845 msgid "Larger brush" msgstr "VäÄší Å¡tetec" #: src/mainwindow.c:847 msgid "Smaller brush" msgstr "Menší Å¡tetec" #: src/mainwindow.c:849 msgid "View window - Zoom in" msgstr "Okno zobrazenia - PriblížiÅ¥" #: src/mainwindow.c:851 msgid "View window - Zoom out" msgstr "Okno zobrazenia - OddialiÅ¥" #: src/mainwindow.c:1027 msgid "" "This canvas/palette contains changes that have not been saved. Do you " "really want to lose these changes?" msgstr "Plátno/paleta obsahuje neuložené zmeny. SkutoÄne o ne chcete prísÅ¥?" #: src/mainwindow.c:1094 msgid "Do you really want to quit?" msgstr "SkutoÄne chcete skonÄiÅ¥?" #: src/mainwindow.c:3743 msgid "Empty string or broken quoting" msgstr "Prázdny reÅ¥azec alebo chýbajúce párové úvodzovky" #: src/mainwindow.c:3744 msgid "Script must begin with a command" msgstr "Skript musí zaÄínaÅ¥ príkazom" #: src/mainwindow.c:3745 msgid "Script nesting limit exceeded" msgstr "Skript prekroÄil limit vnorení" #: src/mainwindow.c:3754 #, c-format msgid "'%s' does not match any item" msgstr "'%s' nezodpovedá žiadnej položke" #: src/mainwindow.c:3756 #, c-format msgid "'%s' matches a non-scriptable item" msgstr "'%s' zodpovedá neskriptovateľnej položke" #: src/mainwindow.c:3758 #, c-format msgid "'%s' matches a disabled item" msgstr "'%s' zodpovedá vypnutej položke" #: src/mainwindow.c:3777 #, c-format msgid "'%s' value does not fit item" msgstr "Hodnota '%s' nie je vhodná pre túto položku" #: src/mainwindow.c:3958 msgid "Script" msgstr "Skript" #: src/mainwindow.c:3971 src/spawn.c:656 src/spawn.c:662 msgid "Action" msgstr "Akcia" #: src/mainwindow.c:3980 src/spawn.c:666 msgid "Execute" msgstr "SpustiÅ¥" #: src/mainwindow.c:4034 msgid "Unable to load script" msgstr "Nepodarilo sa naÄítaÅ¥ skript" #: src/mainwindow.c:5171 msgid "/_File" msgstr "/_Súbor" #: src/mainwindow.c:5173 msgid "//New" msgstr "//Nový" #: src/mainwindow.c:5175 msgid "//Open ..." msgstr "//OtvoriÅ¥..." #: src/mainwindow.c:5177 src/mainwindow.c:5658 msgid "//Save" msgstr "//UložiÅ¥" #: src/mainwindow.c:5179 src/mainwindow.c:5538 src/mainwindow.c:5616 #: src/mainwindow.c:5660 msgid "//Save As ..." msgstr "//UložiÅ¥ ako..." #: src/mainwindow.c:5181 msgid "//Export Undo Images ..." msgstr "//ExportovaÅ¥ obrázky histórie..." #: src/mainwindow.c:5183 msgid "//Export Undo Images (reversed) ..." msgstr "//ExportovaÅ¥ obrázky histórie (v opaÄnom poradí)..." #: src/mainwindow.c:5185 msgid "//Export ASCII Art ..." msgstr "//ExportovaÅ¥ ako ASCII kresbu..." #: src/mainwindow.c:5187 msgid "//Export Animated GIF ..." msgstr "//ExportovaÅ¥ ako animovaný GIF..." #: src/mainwindow.c:5190 msgid "//Actions" msgstr "//Akcie" #: src/mainwindow.c:5224 src/mainwindow.c:5477 msgid "///Configure" msgstr "///NastaviÅ¥" #: src/mainwindow.c:5279 msgid "//Quit" msgstr "//UkonÄiÅ¥" #: src/mainwindow.c:5282 msgid "/_Edit" msgstr "/_UpraviÅ¥" #: src/mainwindow.c:5284 msgid "//Undo" msgstr "//Späť" #: src/mainwindow.c:5286 msgid "//Redo" msgstr "//Dopredu" #: src/mainwindow.c:5289 msgid "//Cut" msgstr "//Vystrihnúť" #: src/mainwindow.c:5291 msgid "//Copy" msgstr "//KopírovaÅ¥" #: src/mainwindow.c:5293 msgid "//Copy To Palette" msgstr "//KopírovaÅ¥ do palety" #: src/mainwindow.c:5295 msgid "//Paste To Centre" msgstr "//PrilepiÅ¥ do stredu" #: src/mainwindow.c:5297 msgid "//Paste To New Layer" msgstr "//PrilepiÅ¥ ako novú vrstvu" #: src/mainwindow.c:5299 msgid "//Paste" msgstr "//PrilepiÅ¥" #: src/mainwindow.c:5301 msgid "//Paste Text" msgstr "//PrilepiÅ¥ text" #: src/mainwindow.c:5307 msgid "//Paste Text (FreeType)" msgstr "//PrilepiÅ¥ text (FreeType)" #: src/mainwindow.c:5310 msgid "//Paste Palette" msgstr "//PrilepiÅ¥ paletu" #: src/mainwindow.c:5312 msgid "//Load Clipboard" msgstr "//NaÄítaÅ¥ schránku" #: src/mainwindow.c:5339 msgid "//Save Clipboard" msgstr "//UložiÅ¥ schránku" #: src/mainwindow.c:5366 msgid "//Import Clipboard from System" msgstr "//ImportovaÅ¥ schránku zo systému" #: src/mainwindow.c:5367 msgid "//Export Clipboard to System" msgstr "//ExportovaÅ¥ schránku do systému" #: src/mainwindow.c:5370 msgid "//Choose Pattern ..." msgstr "//VybraÅ¥ vzor..." #: src/mainwindow.c:5372 msgid "//Choose Brush ..." msgstr "//VybraÅ¥ Å¡tetec..." #: src/mainwindow.c:5374 msgid "//Choose Colour ..." msgstr "//VybraÅ¥ farbu..." #: src/mainwindow.c:5381 msgid "/_View" msgstr "/_ZobraziÅ¥" #: src/mainwindow.c:5383 msgid "//Show Main Toolbar" msgstr "//ZobraziÅ¥ hlavnú liÅ¡tu" #: src/mainwindow.c:5385 msgid "//Show Tools Toolbar" msgstr "//ZobraziÅ¥ nástrojovú liÅ¡tu" #: src/mainwindow.c:5388 msgid "//Show Settings Toolbar" msgstr "//ZobraziÅ¥ liÅ¡tu nastavení" #: src/mainwindow.c:5391 msgid "//Show Dock" msgstr "//ZobraziÅ¥ oblasÅ¥ ukotvenia" #: src/mainwindow.c:5393 msgid "//Show Palette" msgstr "//ZobraziÅ¥ paletu" #: src/mainwindow.c:5395 msgid "//Show Status Bar" msgstr "//ZobraziÅ¥ stavovú liÅ¡tu" #: src/mainwindow.c:5398 msgid "//Toggle Image View" msgstr "//Prepnúť zobrazenie obrázka" #: src/mainwindow.c:5402 msgid "//Centralize Image" msgstr "//VycentrovaÅ¥ obrázok" #: src/mainwindow.c:5403 msgid "//Show Zoom Grid" msgstr "//Raster pri zväÄÅ¡ení" #: src/mainwindow.c:5404 msgid "//Snap To Tile Grid" msgstr "//PrichytávaÅ¥ k mriežke dlaždíc" #: src/mainwindow.c:5406 msgid "//Configure Grid ..." msgstr "//NastaviÅ¥ mriežku..." #: src/mainwindow.c:5407 msgid "//Tracing Image ..." msgstr "//ObkresliÅ¥ obrázok..." #: src/mainwindow.c:5410 msgid "//View Window" msgstr "//Okno zobrazenia" #: src/mainwindow.c:5412 msgid "//Horizontal Split" msgstr "//Vodorovné delenie" #: src/mainwindow.c:5414 msgid "//Focus View Window" msgstr "//Okno priblíženia" #: src/mainwindow.c:5416 msgid "//Pan Window" msgstr "//Prehľadové okno" #: src/mainwindow.c:5419 msgid "//Layers Window" msgstr "//Okno vrstiev" #: src/mainwindow.c:5422 msgid "/_Image" msgstr "/_Obrázok" #: src/mainwindow.c:5425 msgid "//Convert To RGB" msgstr "//PreviesÅ¥ na RGB" #: src/mainwindow.c:5427 msgid "//Convert To Indexed ..." msgstr "//PreviesÅ¥ na indexovaný..." #: src/mainwindow.c:5430 msgid "//Scale Canvas ..." msgstr "//ZmeniÅ¥ mierku plátna..." #: src/mainwindow.c:5432 msgid "//Resize Canvas ..." msgstr "//ZmeniÅ¥ veľkosÅ¥ plátna..." #: src/mainwindow.c:5434 msgid "//Crop" msgstr "//OrezaÅ¥" #: src/mainwindow.c:5437 src/mainwindow.c:5506 msgid "//Flip Vertically" msgstr "//OtoÄiÅ¥ zvisle" #: src/mainwindow.c:5438 src/mainwindow.c:5508 msgid "//Flip Horizontally" msgstr "//OtoÄiÅ¥ vodorovne" #: src/mainwindow.c:5441 src/mainwindow.c:5510 msgid "//Rotate Clockwise" msgstr "//OtoÄiÅ¥ v smere ruÄiÄiek" #: src/mainwindow.c:5442 src/mainwindow.c:5512 msgid "//Rotate Anti-Clockwise" msgstr "//OtoÄiÅ¥ proti smeru ruÄiÄiek" #: src/mainwindow.c:5443 msgid "//Free Rotate ..." msgstr "//OtoÄiÅ¥ ľubovoľne..." #: src/mainwindow.c:5444 msgid "//Skew ..." msgstr "//NakloniÅ¥..." #: src/mainwindow.c:5447 msgid "//Segment ..." msgstr "//RozdeliÅ¥ na Äasti..." #: src/mainwindow.c:5451 msgid "//Script ..." msgstr "//Skript..." #: src/mainwindow.c:5453 msgid "//Scripts" msgstr "//Skripty" #: src/mainwindow.c:5480 msgid "//Information ..." msgstr "//Informácie..." #: src/mainwindow.c:5483 msgid "//Preferences ..." msgstr "//Nastavenia..." #: src/mainwindow.c:5486 msgid "/_Selection" msgstr "/_Výber" #: src/mainwindow.c:5488 msgid "//Select All" msgstr "//VybraÅ¥ vÅ¡etko" #: src/mainwindow.c:5490 msgid "//Select None (Esc)" msgstr "//ZruÅ¡iÅ¥ výber (Esc)" #: src/mainwindow.c:5492 msgid "//Lasso Selection" msgstr "//Výber lasom" #: src/mainwindow.c:5494 msgid "//Lasso Selection Cut" msgstr "//Vystrihnúť lasom" #: src/mainwindow.c:5497 msgid "//Outline Selection" msgstr "//OrámovaÅ¥ výber" #: src/mainwindow.c:5499 msgid "//Fill Selection" msgstr "//VyplniÅ¥ výber" #: src/mainwindow.c:5501 msgid "//Outline Ellipse" msgstr "//OrámovaÅ¥ elipsu" #: src/mainwindow.c:5503 msgid "//Fill Ellipse" msgstr "//VyplniÅ¥ elipsu" #: src/mainwindow.c:5515 msgid "//Horizontal Ramp" msgstr "//Vodorovná rampa" #: src/mainwindow.c:5517 msgid "//Vertical Ramp" msgstr "//Zvislá rampa" #: src/mainwindow.c:5520 msgid "//Alpha Blend A,B" msgstr "//Alfa prechod medzi A,B" #: src/mainwindow.c:5522 msgid "//Move Alpha to Mask" msgstr "//Presun Alfa do masky" #: src/mainwindow.c:5524 msgid "//Mask Colour A,B" msgstr "//MaskovaÅ¥ farby A,B" #: src/mainwindow.c:5526 msgid "//Unmask Colour A,B" msgstr "//OdmaskovaÅ¥ farby A,B" #: src/mainwindow.c:5528 msgid "//Mask All Colours" msgstr "//MaskovaÅ¥ vÅ¡etky farby" #: src/mainwindow.c:5530 msgid "//Clear Mask" msgstr "//ZruÅ¡iÅ¥ masku" #: src/mainwindow.c:5533 msgid "/_Palette" msgstr "/_Paleta" #: src/mainwindow.c:5537 src/mainwindow.c:5615 msgid "//Load ..." msgstr "//NaÄítaÅ¥..." #: src/mainwindow.c:5539 msgid "//Load Default" msgstr "//NaÄítaÅ¥ predvolenú" #: src/mainwindow.c:5541 msgid "//Mask All" msgstr "//MaskovaÅ¥ vÅ¡etky farby" #: src/mainwindow.c:5542 msgid "//Mask None" msgstr "//NemaskovaÅ¥ žiadnu farbu" #: src/mainwindow.c:5544 msgid "//Swap A & B" msgstr "//PrehodiÅ¥ A a B" #: src/mainwindow.c:5546 msgid "//Edit Colour A & B ..." msgstr "//UpraviÅ¥ farby A a B..." #: src/mainwindow.c:5548 msgid "//Dither A" msgstr "//Raster A" #: src/mainwindow.c:5550 msgid "//Palette Editor ..." msgstr "//Editor farieb..." #: src/mainwindow.c:5552 msgid "//Set Palette Size ..." msgstr "//NastaviÅ¥ poÄet farieb..." #: src/mainwindow.c:5553 msgid "//Merge Duplicate Colours" msgstr "//ZlúÄiÅ¥ duplicitné farby" #: src/mainwindow.c:5555 msgid "//Remove Unused Colours" msgstr "//OdstrániÅ¥ nepoužité farby" #: src/mainwindow.c:5558 msgid "//Create Quantized ..." msgstr "//VytvoriÅ¥ kvantované..." #: src/mainwindow.c:5561 msgid "//Sort Colours ..." msgstr "//UsporiadaÅ¥ farby..." #: src/mainwindow.c:5562 msgid "//Palette Shifter ..." msgstr "//PosunovaÄ palety ..." #: src/mainwindow.c:5563 msgid "//Pick Gradient ..." msgstr "//VybraÅ¥ prechod..." #: src/mainwindow.c:5565 msgid "/Effe_cts" msgstr "/_Efekty" #: src/mainwindow.c:5567 msgid "//Transform Colour ..." msgstr "//TransformovaÅ¥ farby..." #: src/mainwindow.c:5569 msgid "//Invert" msgstr "//InvertovaÅ¥" #: src/mainwindow.c:5571 msgid "//Greyscale" msgstr "//Å edá Å¡kála" #: src/mainwindow.c:5573 msgid "//Greyscale (Gamma corrected)" msgstr "//Å edá Å¡kála (s Gamma korekciou)" #: src/mainwindow.c:5575 msgid "//Normalize" msgstr "//NormalizovaÅ¥" #: src/mainwindow.c:5576 src/mainwindow.c:5647 msgid "//Threshold ..." msgstr "//Prah..." #: src/mainwindow.c:5577 msgid "//Map ..." msgstr "//Mapa..." #: src/mainwindow.c:5579 msgid "//Isometric Transformation" msgstr "//Izometrická transformácia" #: src/mainwindow.c:5581 msgid "///Left Side Down" msgstr "///Ľavá strana dole" #: src/mainwindow.c:5582 msgid "///Right Side Down" msgstr "///Pravá strana dole" #: src/mainwindow.c:5583 msgid "///Top Side Right" msgstr "///Horná strana vpravo" #: src/mainwindow.c:5584 msgid "///Bottom Side Right" msgstr "///Spodná strana vpravo" #: src/mainwindow.c:5587 msgid "//Edge Detect ..." msgstr "//Detekcia hrán..." #: src/mainwindow.c:5589 msgid "//Difference of Gaussians ..." msgstr "//Gaussov rozdiel..." #: src/mainwindow.c:5591 msgid "//Sharpen ..." msgstr "//ZaostriÅ¥..." #: src/mainwindow.c:5593 msgid "//Unsharp Mask ..." msgstr "//Zaostrovacia maska..." #: src/mainwindow.c:5595 msgid "//Soften ..." msgstr "//ZjemniÅ¥..." #: src/mainwindow.c:5597 msgid "//Gaussian Blur ..." msgstr "//Gaussove rozmazanie..." #: src/mainwindow.c:5599 msgid "//Kuwahara-Nagao Blur ..." msgstr "//Rozmazanie Kuwahara-Nagao" #: src/mainwindow.c:5601 msgid "//Emboss" msgstr "//Reliéfy" #: src/mainwindow.c:5603 msgid "//Dilate" msgstr "//DeliatovaÅ¥" #: src/mainwindow.c:5605 msgid "//Erode" msgstr "//ErodovaÅ¥" #: src/mainwindow.c:5608 msgid "//Solid Noise ..." msgstr "//Pevný Å¡um..." #: src/mainwindow.c:5609 msgid "//Bacteria ..." msgstr "//Baktérie..." #: src/mainwindow.c:5612 msgid "/Cha_nnels" msgstr "/Ka_nály" #: src/mainwindow.c:5614 msgid "//New ..." msgstr "//Nový..." #: src/mainwindow.c:5617 msgid "//Delete ..." msgstr "//OdstrániÅ¥..." #: src/mainwindow.c:5621 msgid "//Edit Image" msgstr "//UpraviÅ¥ obrázok" #: src/mainwindow.c:5624 msgid "//Edit Alpha" msgstr "//UpraviÅ¥ alfakanál" #: src/mainwindow.c:5627 msgid "//Edit Selection" msgstr "//UpraviÅ¥ výber" #: src/mainwindow.c:5630 msgid "//Edit Mask" msgstr "//UpraviÅ¥ masku" #: src/mainwindow.c:5634 msgid "//Hide Image" msgstr "//SkryÅ¥ obrázok" #: src/mainwindow.c:5637 msgid "//Disable Alpha" msgstr "//Vypnúť alfakanál" #: src/mainwindow.c:5640 msgid "//Disable Selection" msgstr "//Vypnúť výber" #: src/mainwindow.c:5643 msgid "//Disable Mask" msgstr "//Vypnúť masku" #: src/mainwindow.c:5646 msgid "//Couple RGBA Operations" msgstr "//PárovaÅ¥ RGBA operácie" #: src/mainwindow.c:5648 msgid "//Unassociate Alpha" msgstr "//Nespojitá Alfa" #: src/mainwindow.c:5652 msgid "//View Alpha as an Overlay" msgstr "//ZobraziÅ¥ alfakanál ako prekrytie" #: src/mainwindow.c:5653 msgid "//Configure Overlays ..." msgstr "//KonfigurovaÅ¥ prekrytia..." #: src/mainwindow.c:5655 msgid "/_Layers" msgstr "/_Vrstvy" #: src/mainwindow.c:5657 msgid "//New Layer" msgstr "//Nová vrstva" #: src/mainwindow.c:5661 msgid "//Save Composite Image ..." msgstr "//UložiÅ¥ kompozitný obrázok..." #: src/mainwindow.c:5662 msgid "//Composite to New Layer" msgstr "//SpojiÅ¥ do novej vrstvy" #: src/mainwindow.c:5663 msgid "//Remove All Layers" msgstr "//OdstrániÅ¥ vÅ¡etky vrstvy" #: src/mainwindow.c:5665 msgid "//Configure Animation ..." msgstr "//NastaviÅ¥ animáciu..." #: src/mainwindow.c:5666 msgid "//Preview Animation ..." msgstr "//Náhľad animácie..." #: src/mainwindow.c:5667 msgid "//Set Key Frame ..." msgstr "//NastaviÅ¥ kľúÄovú snímku..." #: src/mainwindow.c:5668 msgid "//Remove All Key Frames ..." msgstr "//OdstrániÅ¥ vÅ¡etky kľúÄové snímky..." #: src/mainwindow.c:5670 msgid "/More..." msgstr "/Viac..." #: src/mainwindow.c:5672 msgid "/_Help" msgstr "/Po_mocník" #: src/mainwindow.c:5673 msgid "//Documentation" msgstr "//Dokumentácia" #: src/mainwindow.c:5675 msgid "//About" msgstr "//O programe" #: src/mainwindow.c:5678 msgid "//Keyboard Shortcuts ..." msgstr "//Klávesové skratky..." #: src/mainwindow.c:5679 msgid "//Rebind Shortcut Keycodes" msgstr "//PreviazaÅ¥ klávesové skratky" #: src/memory.c:2821 msgid "Quantize Pass 1" msgstr "Prechod kvantizácie 1" #: src/memory.c:2875 msgid "Quantize Pass 2" msgstr "Prechod kvantizácie 2" #: src/memory.c:3094 src/memory.c:3479 msgid "Converting to Indexed Palette" msgstr "Prevádza sa na indexovanú paletu" #: src/memory.c:5161 src/otherwindow.c:536 msgid "Bacteria Effect" msgstr "Efekt baktérie" #: src/memory.c:5196 msgid "Rotating" msgstr "OtáÄa sa" #: src/memory.c:5537 msgid "Free Rotation" msgstr "Voľné otáÄanie" #: src/memory.c:6122 msgid "Scaling Image" msgstr "Mení sa mierku obrázka" #: src/memory.c:7645 msgid "Applying Effect" msgstr "Aplikuje sa efekt" #: src/memory.c:8829 msgid "Kuwahara-Nagao Filter" msgstr "Filter Kuwahara-Nagao" #: src/memory.c:10493 src/otherwindow.c:2648 msgid "Skew" msgstr "NakloniÅ¥" #: src/memory.c:10667 msgid "Segmentation Pass 1" msgstr "Prechod rozdelenia na Äasti 1" #: src/memory.c:10794 msgid "Segmentation Pass 2" msgstr "Prechod rozdelenia na Äasti 2" #: src/memory.c:11056 src/otherwindow.c:3139 msgid "Solid Noise" msgstr "Pevný Å¡um" #: src/mygtk.c:134 src/mygtk.c:163 msgid "Please Wait ..." msgstr "Prosím Äakajte..." #: src/mygtk.c:141 msgid "STOP" msgstr "ZASTAVIŤ" #: src/mygtk.c:504 msgid "Disabled" msgstr "Vypnuté" #: src/mygtk.c:504 src/toolbar.c:301 msgid "Screen" msgstr "Obraz" #: src/mygtk.c:504 msgid "Window" msgstr "Okno" #: src/mygtk.c:508 msgid "Input" msgstr "Vstup" #: src/mygtk.c:512 msgid "Device:" msgstr "Zariadenie:" #: src/mygtk.c:514 msgid "Mode:" msgstr "Režim:" #: src/mygtk.c:519 msgid "Axes" msgstr "Osi" #: src/mygtk.c:524 msgid "X:" msgstr "X:" #: src/mygtk.c:525 msgid "Y:" msgstr "Y:" #: src/mygtk.c:526 msgid "Pressure:" msgstr "Tlak:" #: src/mygtk.c:527 msgid "X tilt:" msgstr "Naklonenie X:" #: src/mygtk.c:528 msgid "Y tilt:" msgstr "Naklonenie Y:" #: src/mygtk.c:529 msgid "Wheel:" msgstr "Koliesko:" #: src/mygtk.c:579 msgid "none" msgstr "žiadne" #: src/otherwindow.c:236 msgid "24 bit RGB" msgstr "24bitové RGB" #: src/otherwindow.c:236 src/otherwindow.c:3162 msgid "Greyscale" msgstr "Å edá Å¡kála" #: src/otherwindow.c:237 msgid "Indexed Palette" msgstr "Indexovaná paleta" #: src/otherwindow.c:237 msgid "From Clipboard" msgstr "Zo schránky" #: src/otherwindow.c:237 msgid "Grab Screenshot" msgstr "UrobiÅ¥ snímku obrazovky" #: src/otherwindow.c:242 src/toolbar.c:542 msgid "New Image" msgstr "Nový obrázok" #: src/otherwindow.c:246 src/otherwindow.c:3147 msgid "Colours" msgstr "Farieb" #: src/otherwindow.c:405 msgid "Pattern Chooser" msgstr "Výber vzoru" #: src/otherwindow.c:493 msgid "Set Palette Size" msgstr "NastaviÅ¥ poÄet farieb" #: src/otherwindow.c:513 src/otherwindow.c:587 src/otherwindow.c:866 #: src/otherwindow.c:2521 src/otherwindow.c:2759 src/otherwindow.c:2922 #: src/prefs.c:338 src/prefs.c:538 msgid "Apply" msgstr "PoužiÅ¥" #: src/otherwindow.c:569 msgid "Luminance" msgstr "Jas" #: src/otherwindow.c:569 src/otherwindow.c:810 msgid "Brightness" msgstr "Jas" #: src/otherwindow.c:570 msgid "Distance to A" msgstr "VzdialenosÅ¥ k A" #: src/otherwindow.c:571 msgid "Projection to A->B" msgstr "Projekcia do A->B" #: src/otherwindow.c:572 msgid "Frequency" msgstr "Frekvencia" #: src/otherwindow.c:576 msgid "Sort Palette Colours" msgstr "ZoradiÅ¥ farby v palete" #: src/otherwindow.c:578 msgid "Start Index" msgstr "Od indexu" #: src/otherwindow.c:579 msgid "End Index" msgstr "Do indexu" #: src/otherwindow.c:585 msgid "Reverse Order" msgstr "OpaÄné radenie" #: src/otherwindow.c:801 msgid "Bitwise" msgstr "Bitový" #: src/otherwindow.c:801 msgid "Truncated" msgstr "Skrátený" #: src/otherwindow.c:801 msgid "Rounded" msgstr "Zaokrúhlený" #: src/otherwindow.c:805 src/toolbar.c:311 src/toolbar.c:558 msgid "Transform Colour" msgstr "TransformovaÅ¥ farby" #: src/otherwindow.c:808 msgid "Gamma" msgstr "Gamma" #: src/otherwindow.c:812 msgid "Contrast" msgstr "Kontrast" #: src/otherwindow.c:818 src/otherwindow.c:1661 msgid "Posterize" msgstr "PosterizovaÅ¥" #: src/otherwindow.c:827 msgid "Show Detail" msgstr "ZobraziÅ¥ podrobnosti" #: src/otherwindow.c:832 msgid "Posterize type" msgstr "Typ posterizácie" #: src/otherwindow.c:853 msgid "Auto-Preview" msgstr "Automatický náhľad" #: src/otherwindow.c:865 msgid "Reset" msgstr "ObnoviÅ¥" #: src/otherwindow.c:927 msgid "New geometry is the same as now - nothing to do." msgstr "Nové rozmery sú rovnaké ako pôvodné - nie je Äo robiÅ¥." #: src/otherwindow.c:976 msgid "The operating system cannot allocate the memory for this operation." msgstr "OperaÄný systém nemôže alokovaÅ¥ pamäť pre túto operáciu." #: src/otherwindow.c:978 msgid "" "You have not allocated enough memory in the Preferences window for this " "operation." msgstr "Pre túto operáciu ste nealokovali dostatok pamäte v okne Voľby." #: src/otherwindow.c:989 src/otherwindow.c:2478 msgid "Mirror" msgstr "Zrkadlovo" #: src/otherwindow.c:989 src/otherwindow.c:990 msgid "Tile" msgstr "Dlaždice" #: src/otherwindow.c:989 msgid "Void" msgstr "Prázdne" #: src/otherwindow.c:990 src/shifter.c:283 msgid "Clear" msgstr "VyÄistiÅ¥" #: src/otherwindow.c:990 msgid "Mirror tile" msgstr "Zrkadlové dlaždice" #: src/otherwindow.c:992 msgid "Nearest Neighbour" msgstr "Najbližší sused" #: src/otherwindow.c:993 msgid "Bilinear / Area Mapping" msgstr "Bilineárne / Mapovanie oblasti" #: src/otherwindow.c:994 msgid "Bicubic" msgstr "Bikubické" #: src/otherwindow.c:995 msgid "Bicubic edged" msgstr "Bikubické s hranami" #: src/otherwindow.c:996 msgid "Bicubic better" msgstr "LepÅ¡ie bikubické" #: src/otherwindow.c:997 msgid "Bicubic sharper" msgstr "Bikubické ostrejÅ¡ie" #: src/otherwindow.c:998 msgid "Blackman-Harris" msgstr "Blackman-Harris" #: src/otherwindow.c:1004 msgid "Scale Canvas" msgstr "ZmeniÅ¥ mierku obrázka" #: src/otherwindow.c:1005 msgid "Resize Canvas" msgstr "Zmena veľkosti plátna" #: src/otherwindow.c:1008 msgid "Original " msgstr "Originál " #: src/otherwindow.c:1009 msgid "New" msgstr "Nový" #: src/otherwindow.c:1010 msgid "Width " msgstr "Šírka " #: src/otherwindow.c:1014 msgid "Height " msgstr "Výška " #: src/otherwindow.c:1019 src/otherwindow.c:2497 src/otherwindow.c:2655 #: src/toolbar.c:212 msgid "Offset" msgstr "Posun" #: src/otherwindow.c:1022 src/otherwindow.c:1602 src/viewer.c:1209 msgid "Centre" msgstr "VycentrovaÅ¥" #: src/otherwindow.c:1029 src/otherwindow.c:1048 msgid "Fix Aspect Ratio" msgstr "DodržaÅ¥ pomer strán" #: src/otherwindow.c:1035 src/otherwindow.c:2053 src/toolbar.c:312 msgid "Settings" msgstr "Nastavenia" #: src/otherwindow.c:1042 msgid "Sharper image reduction" msgstr "ÄŒisté zmenÅ¡enie obrázka" #: src/otherwindow.c:1043 msgid "Boundary extension" msgstr "Rozšírenie hraníc" #: src/otherwindow.c:1600 src/otherwindow.c:2285 msgid "HSV" msgstr "HSV" #: src/otherwindow.c:1601 msgid "Highlight" msgstr "Zvýraznenie" #: src/otherwindow.c:1602 msgid "Limit" msgstr "Limit" #: src/otherwindow.c:1603 msgid "Sphere" msgstr "Guľa" #: src/otherwindow.c:1603 src/otherwindow.c:2653 msgid "Angle" msgstr "Uhol" #: src/otherwindow.c:1603 msgid "Cube" msgstr "Kocka" #: src/otherwindow.c:1604 msgid "Opaque" msgstr "Nepriehľadné" #: src/otherwindow.c:1604 msgid "Border" msgstr "Okraj" #: src/otherwindow.c:1605 msgid "Transparent" msgstr "Priehľadné" #: src/otherwindow.c:1605 msgid "Tile " msgstr "Dlaždica " #: src/otherwindow.c:1605 msgid "Segment" msgstr "Segment" #: src/otherwindow.c:1643 msgid "Scale" msgstr "Mierka" #: src/otherwindow.c:1644 src/otherwindow.c:3042 msgid "From" msgstr "Od" #: src/otherwindow.c:1646 src/otherwindow.c:3044 msgid "To" msgstr "Do" #: src/otherwindow.c:1686 msgid "Range" msgstr "Rozsah" #: src/otherwindow.c:1689 msgid "Inverse" msgstr "Inverzia" #: src/otherwindow.c:1697 msgid "Smart grid" msgstr "Inteligentná mriežka" #: src/otherwindow.c:1699 msgid "Tile grid" msgstr "Mriežka dlaždice" #: src/otherwindow.c:1701 msgid "Minimum grid zoom" msgstr "Raster pri priblížení aspoň" #: src/otherwindow.c:1704 msgid "Tile width" msgstr "Šírka dlaždice" #: src/otherwindow.c:1707 msgid "Tile height" msgstr "Výška dlaždice" #: src/otherwindow.c:1731 msgid "Palette Editor" msgstr "Editor farieb" #: src/otherwindow.c:1744 msgid "Configure Overlays" msgstr "NastaviÅ¥ prekrytia" #: src/otherwindow.c:1763 msgid "Colour Editor" msgstr "Editor farieb" #: src/otherwindow.c:1799 src/toolbar.c:430 msgid "Colour-Selective Mode" msgstr "Režim výberu farby" #: src/otherwindow.c:1824 msgid "Configure Grid" msgstr "NastaviÅ¥ mriežku" #: src/otherwindow.c:2028 msgid "Exact Conversion" msgstr "Presná konverzia" #: src/otherwindow.c:2028 msgid "Use Current Palette" msgstr "PoužiÅ¥ aktuálnu paletu" #: src/otherwindow.c:2029 msgid "PNN Quantize (slow, better quality)" msgstr "PNN kvantizácia (pomalÅ¡ia, lepÅ¡ia kvalita)" #: src/otherwindow.c:2030 msgid "Wu Quantize (fast)" msgstr "Wu kvantizácia (rýchla)" #: src/otherwindow.c:2031 msgid "Max-Min Quantize (best for small palettes and dithering)" msgstr "" "Max-Min kvantizácia (najlepÅ¡ia pre palety s malým množstvom farieb a " "dithering)" #: src/otherwindow.c:2032 src/otherwindow.c:2478 src/otherwindow.c:2739 #: src/png.c:3136 src/prefs.c:377 msgid "None" msgstr "Žiadny" #: src/otherwindow.c:2032 msgid "Floyd-Steinberg" msgstr "Floyd-Steinberg" #: src/otherwindow.c:2032 msgid "Stucki" msgstr "Stucki" #: src/otherwindow.c:2035 msgid "Floyd-Steinberg (quick)" msgstr "Floyd-Steinberg (rýchly)" #: src/otherwindow.c:2035 msgid "Dithered (effect)" msgstr "Rozmazaný (efekt)" #: src/otherwindow.c:2036 msgid "Scattered (effect)" msgstr "Rozptýlený (efekt)" #: src/otherwindow.c:2037 msgid "Gamut" msgstr "Gamut" #: src/otherwindow.c:2037 msgid "Weakly" msgstr "Slabo" #: src/otherwindow.c:2037 msgid "Strongly" msgstr "Silno" #: src/otherwindow.c:2038 msgid "Off" msgstr "Vypnuté" #: src/otherwindow.c:2038 msgid "Separate/Sum" msgstr "SeparovaÅ¥/SÄítaÅ¥" #: src/otherwindow.c:2038 msgid "Separate/Split" msgstr "SeparovaÅ¥/RozdeliÅ¥" #: src/otherwindow.c:2039 msgid "Length/Sum" msgstr "Dĺžka/SÄítaÅ¥" #: src/otherwindow.c:2039 msgid "Length/Split" msgstr "Dĺžka/RozdeliÅ¥" #: src/otherwindow.c:2040 msgid "Largest (Linf)" msgstr "NajväÄší (Linf)" #: src/otherwindow.c:2040 msgid "Sum (L1)" msgstr "Suma (L1)" #: src/otherwindow.c:2040 msgid "Euclidean (L2)" msgstr "Euklidovský (L2)" #: src/otherwindow.c:2044 msgid "Create Quantized" msgstr "VytvoriÅ¥ kvantované" #: src/otherwindow.c:2045 msgid "Convert To Indexed" msgstr "Prevod na indexovaný" #: src/otherwindow.c:2048 msgid "Indexed Colours To Use" msgstr "PoÄet indexovaných farieb" #: src/otherwindow.c:2061 msgid "Truncate palette" msgstr "SkrátiÅ¥ paletu" #: src/otherwindow.c:2062 msgid "Diameter based weighting" msgstr "Váha založená na priemere" #: src/otherwindow.c:2067 msgid "Dither" msgstr "RozochvieÅ¥" #: src/otherwindow.c:2070 src/otherwindow.c:2567 src/otherwindow.c:2911 msgid "Colour space" msgstr "Farebný priestor" #: src/otherwindow.c:2071 src/otherwindow.c:2912 msgid "Difference measure" msgstr "Rozdiel merania" #: src/otherwindow.c:2072 msgid "Reduce colour bleed" msgstr "RedukovaÅ¥ plytvanie farbami" #: src/otherwindow.c:2073 msgid "Serpentine scan" msgstr "Serpentínový sken" #: src/otherwindow.c:2075 msgid "Error propagation, %" msgstr "Chyba propagácie, %" #: src/otherwindow.c:2076 msgid "Selective error propagation" msgstr "Selektívna chyba propagácie" #: src/otherwindow.c:2080 msgid "Full error precision" msgstr "Plná chybová presnosÅ¥" #: src/otherwindow.c:2285 msgid "Backward HSV" msgstr "Spätný HSV" #: src/otherwindow.c:2286 src/otherwindow.c:2309 msgid "Constant" msgstr "KonÅ¡tantný" #: src/otherwindow.c:2290 msgid "Edit Gradient" msgstr "UpraviÅ¥ prechod" #: src/otherwindow.c:2312 msgid "Points:" msgstr "Bodov:" #: src/otherwindow.c:2476 msgid "Linear" msgstr "Lineárny" #: src/otherwindow.c:2476 src/otherwindow.c:2686 msgid "Bilinear" msgstr "Bilineárny" #: src/otherwindow.c:2476 msgid "Radial" msgstr "Radiálny" #: src/otherwindow.c:2477 msgid "Square" msgstr "Å tvorcový" #: src/otherwindow.c:2477 msgid "Angular" msgstr "Uhlový" #: src/otherwindow.c:2477 msgid "Conical" msgstr "Kuželový" #: src/otherwindow.c:2478 msgid "Level " msgstr "Úroveň " #: src/otherwindow.c:2478 msgid "Repeat" msgstr "OpakovaÅ¥" #: src/otherwindow.c:2479 msgid "A to B" msgstr "A do B" #: src/otherwindow.c:2479 msgid "A to B (RGB)" msgstr "A do B (RGB)" #: src/otherwindow.c:2480 msgid "A to B (sRGB)" msgstr "A do B (sRGB)" #: src/otherwindow.c:2480 msgid "A to B (HSV)" msgstr "A do B (HSV)" #: src/otherwindow.c:2480 msgid "A to B (backward HSV)" msgstr "A do B (spätne HSV)" #: src/otherwindow.c:2481 msgid "A only" msgstr "Iba A" #: src/otherwindow.c:2481 src/otherwindow.c:2483 msgid "Custom" msgstr "Vlastný" #: src/otherwindow.c:2482 msgid "Current to 0" msgstr "Aktuálny do 0" #: src/otherwindow.c:2482 msgid "Current only" msgstr "Iba aktuálny" #: src/otherwindow.c:2487 msgid "Configure Gradient" msgstr "Nastavenie prechodu" #: src/otherwindow.c:2490 src/png.c:998 msgid "Channel" msgstr "Kanál" #: src/otherwindow.c:2495 msgid "Length" msgstr "Dĺžka" #: src/otherwindow.c:2496 msgid "Repeat length" msgstr "Dĺžka opakovania" #: src/otherwindow.c:2498 msgid "Gradient type" msgstr "Typ prechodu" #: src/otherwindow.c:2499 msgid "Extension type" msgstr "Typ rozšírenia" #: src/otherwindow.c:2500 msgid "Distance type" msgstr "Typ vzdialenosti" #: src/otherwindow.c:2501 msgid "Preview opacity" msgstr "NepriehľadnosÅ¥ náhľadu" #: src/otherwindow.c:2510 src/otherwindow.c:2516 src/toolbar.c:309 msgid "Reverse" msgstr "Obrátene" #: src/otherwindow.c:2511 src/otherwindow.c:2517 msgid "Edit Custom" msgstr "UpraviÅ¥ vlastný" #: src/otherwindow.c:2575 msgid "Pick Gradient" msgstr "VybraÅ¥ prechod" #: src/otherwindow.c:2651 msgid "Horizontal " msgstr "Vodorovný" #: src/otherwindow.c:2657 msgid "At distance" msgstr "Vo vzdialenosti" #: src/otherwindow.c:2658 msgid "Vertical" msgstr "Zvislý" #: src/otherwindow.c:2739 msgid "Unchanged" msgstr "Nezmenený" #: src/otherwindow.c:2744 msgid "Tracing Image" msgstr "Obkreslenie obrázka" #: src/otherwindow.c:2746 src/toolbar.c:315 msgid "Source" msgstr "Zdroj" #: src/otherwindow.c:2751 msgid "Origin" msgstr "Pôvod" #: src/otherwindow.c:2754 msgid "Relative scale" msgstr "Relatívna mierka" #: src/otherwindow.c:2757 msgid "Display" msgstr "ZobraziÅ¥" #: src/otherwindow.c:2909 msgid "Segment Image" msgstr "RozdeliÅ¥ obrázok na Äasti" #: src/otherwindow.c:2914 src/toolbar.c:304 msgid "Threshold" msgstr "Prah" #: src/otherwindow.c:2916 msgid "Level" msgstr "Úroveň" #: src/otherwindow.c:2917 msgid "Minimum size" msgstr "NajmenÅ¡ia veľkosÅ¥" #: src/otherwindow.c:3036 msgid "Max" msgstr "Max" #: src/otherwindow.c:3036 msgid "Min" msgstr "Min" #: src/otherwindow.c:3040 msgid "Threshold Image" msgstr "Prah obrázka" #: src/otherwindow.c:3141 msgid "Seed" msgstr "Náhodná báza" #: src/otherwindow.c:3143 msgid "X span" msgstr "X rozpätie" #: src/otherwindow.c:3144 msgid "Y span" msgstr "Y rozpätie" #: src/otherwindow.c:3145 msgid "Octaves" msgstr "Oktávy" #: src/png.c:617 #, c-format msgid "Saving %s image" msgstr "Ukladá sa obrázok %s" #: src/png.c:617 #, c-format msgid "Loading %s image" msgstr "NaÄítava sa obrázok %s" #: src/png.c:995 msgid "Layer" msgstr "Vrstva" #: src/png.c:3896 msgid "Lossless" msgstr "Bezstratový" #: src/png.c:3896 msgid "Default" msgstr "Predvolený" #: src/png.c:3896 msgid "Picture" msgstr "Obrázok" #: src/png.c:3896 msgid "Photo" msgstr "Fotografia" #: src/png.c:3897 msgid "Drawing" msgstr "Kresba" #: src/png.c:3897 msgid "Icon" msgstr "Ikona" #: src/png.c:8671 msgid "Applying colour profile" msgstr "Aplikuje sa farebný profil" #: src/png.c:9089 #, c-format msgid "%d out of %d frames could not be saved as %s - saved as PNG instead" msgstr "" "%d z %d snímok sa nepodarilo uložiÅ¥ ako %s - miesto toho boli uložené ako PNG" #: src/png.c:9106 msgid "Explode frames" msgstr "RozbaliÅ¥ snímky" #: src/prefs.c:56 msgid "Default System Language" msgstr "Predvolený jazyk systému" #: src/prefs.c:57 msgid "Chinese (Simplified)" msgstr "Čínsky (ZjednoduÅ¡ená)" #: src/prefs.c:57 msgid "Chinese (Taiwanese)" msgstr "Čínsky (Taiwan)" #: src/prefs.c:57 msgid "Czech" msgstr "ÄŒesky" #: src/prefs.c:58 msgid "Dutch" msgstr "Holandsky" #: src/prefs.c:58 msgid "English (UK)" msgstr "Anglicky (UK)" #: src/prefs.c:58 msgid "French" msgstr "Francúzsky" #: src/prefs.c:58 msgid "Galician" msgstr "Galícijsky" #: src/prefs.c:58 msgid "German" msgstr "Nemecky" #: src/prefs.c:59 msgid "Hungarian" msgstr "MaÄarsky" #: src/prefs.c:59 msgid "Italian" msgstr "Taliansky" #: src/prefs.c:59 msgid "Japanese" msgstr "Japonsky" #: src/prefs.c:59 msgid "Kabyle" msgstr "Kabyle" #: src/prefs.c:59 msgid "Polish" msgstr "Poľsky" #: src/prefs.c:60 msgid "Portuguese" msgstr "Portugalsky" #: src/prefs.c:60 msgid "Portuguese (Brazilian)" msgstr "Portugalsky (Brazília)" #: src/prefs.c:60 msgid "Russian" msgstr "Rusky" #: src/prefs.c:60 msgid "Slovak" msgstr "Slovensky" #: src/prefs.c:61 msgid "Spanish" msgstr "Å panielsky" #: src/prefs.c:61 msgid "Swedish" msgstr "Å védsky" #: src/prefs.c:61 msgid "Tagalog" msgstr "Tagalogsky" #: src/prefs.c:61 msgid "Turkish" msgstr "Turecky" #: src/prefs.c:81 msgid "Current Device" msgstr "Aktuálne zariadenie" #: src/prefs.c:135 msgid "Pressure" msgstr "Tlak" #: src/prefs.c:149 msgid "Preferences" msgstr "Voľby" #: src/prefs.c:163 msgid "Max threads (0 to autodetect)" msgstr "Najviac vlákien (0 pre autodetekciu)" #: src/prefs.c:164 msgid "Min kpixels per render thread" msgstr "Najmenej kpixelov na vlákno vykresľovania" #: src/prefs.c:171 msgid "Max memory used for undo (MB)" msgstr "NajväÄÅ¡ie množstvo pamäte použitá pre históriu (MB)" #: src/prefs.c:172 msgid "Max undo levels" msgstr "NajväÄší poÄet krokov späť" #: src/prefs.c:173 msgid "Communal layer undo space (%)" msgstr "Vrátiteľný priestor spoloÄný pre vÅ¡etky vrstvy (%)" #: src/prefs.c:175 msgid "Bayer master pattern" msgstr "Hlavná Bayerova Å¡ablóna" #: src/prefs.c:178 msgid "Use gamma correction by default" msgstr "PoužiÅ¥ gamma korekciu ako predvolenú" #: src/prefs.c:179 msgid "Use gamma correction when painting" msgstr "Pri kreslení používaÅ¥ korekciu Gamma" #: src/prefs.c:180 msgid "Separate patterns for A & B" msgstr "Samostatné vzory pre A a B" #: src/prefs.c:183 msgid "Optimize alpha chequers" msgstr "OptimalizovaÅ¥ Å¡achovnicu alfakanálu" #: src/prefs.c:184 msgid "Disable view window transparencies" msgstr "Vypnúť priehľadnosÅ¥ v okne zobrazenia" #: src/prefs.c:185 msgid "Enable overlays by layer" msgstr "PovoliÅ¥ prekrytie podľa vrstvy" #: src/prefs.c:189 msgid "Language" msgstr "Jazyk" #: src/prefs.c:191 msgid "" "Select preferred language translation\n" "\n" "You will need to restart mtPaint\n" "for this to take full effect" msgstr "" "Vyberte váš obľúbený jazyk\n" "\n" "Aby se prejavili vÅ¡etky zmeny,\n" "je potrebné mtPaint reÅ¡tartovaÅ¥." #: src/prefs.c:198 msgid "Interface" msgstr "Rozhranie" #: src/prefs.c:200 msgid "Greyscale backdrop" msgstr "Odtieň Å¡edého pozadia" #: src/prefs.c:201 msgid "Selection nudge pixels" msgstr "Posun pixelov výberu" #: src/prefs.c:202 msgid "Max Pan Window Size" msgstr "VeľkosÅ¥ prehľadového okna" #: src/prefs.c:204 msgid "Display clipboard while pasting" msgstr "ZobrazovaÅ¥ schránku pri vkladaní" #: src/prefs.c:205 msgid "Mouse cursor = Tool" msgstr "Kurzor myÅ¡i = Nástroj" #: src/prefs.c:206 msgid "Confirm Exit" msgstr "PotvrdiÅ¥ ukonÄenie" #: src/prefs.c:207 msgid "Q key quits mtPaint" msgstr "Kláves Q ukonÄí mtPaint" #: src/prefs.c:208 msgid "Arrow keys scroll canvas" msgstr "Kurzorové šípky posúvajú plátno" #: src/prefs.c:209 msgid "Changing tool commits paste" msgstr "Zmena nástroja potvrdí prilepenie" #: src/prefs.c:210 msgid "Centre tool settings dialogs" msgstr "VystrediÅ¥ dialógy nastavenia nástrojov" #: src/prefs.c:211 msgid "New image sets zoom to 100%" msgstr "Nový obrázok nastaví priblíženie na 100%" #: src/prefs.c:212 msgid "Zoom on cursor position" msgstr "PriblížiÅ¥ pri pozícii kurzora" #: src/prefs.c:214 msgid "Mouse Scroll Wheel = Zoom" msgstr "Koliesko myÅ¡i = Priblíženie" #: src/prefs.c:215 msgid "Use menu icons" msgstr "PoužiÅ¥ ikony ponuky" #: src/prefs.c:220 msgid "Files" msgstr "Súbory" #: src/prefs.c:223 msgid "XBM X hotspot" msgstr "XBM X aktívny bod" #: src/prefs.c:224 msgid "XBM Y hotspot" msgstr "XBM Y aktívny bod" #: src/prefs.c:228 msgid "Recently Used Files" msgstr "Naposledy použité súbory" #: src/prefs.c:229 msgid "Progress bar silence limit" msgstr "Tichý limit ukazateľa priebehu" #: src/prefs.c:232 msgid "Read 16-bit TGAs as 5:6:5 BGR" msgstr "NaÄítaÅ¥ 16bitové obrázky TGA ako 5:6:5 BGR" #: src/prefs.c:233 msgid "Write TGAs in bottom-up row order" msgstr "ZapísaÅ¥ obrázky TGA zospodu nahor" #: src/prefs.c:234 msgid "Undoable image loading" msgstr "Vrátiteľné naÄítanie obrázka" #: src/prefs.c:245 msgid "Compression (RGB)" msgstr "Kompresia (RGB)" #: src/prefs.c:246 msgid "Compression (indexed)" msgstr "Kompresia (indexovaný)" #: src/prefs.c:247 msgid "Compression (monochrome)" msgstr "Kompresia (monochromatický)" #: src/prefs.c:255 msgid "Enable predictor" msgstr "PovoliÅ¥ prediktor" #: src/prefs.c:262 msgid "Compression mode" msgstr "Režim kompresie" #: src/prefs.c:271 msgid "Channel for Mask Plane" msgstr "Kanál pre plochu masky" #: src/prefs.c:273 msgid "Ignore Transparent Colour" msgstr "IgnorovaÅ¥ priesvitnú farbu" #: src/prefs.c:274 msgid "PackBits Compression" msgstr "Kompresia PackBits" #: src/prefs.c:275 msgid "Write Indexed as Planar Bitmap (PBM)" msgstr "ZapísaÅ¥ indexovanú ako planárnu bitmapu (PBM)" #: src/prefs.c:280 msgid "Paths" msgstr "Cesty" #: src/prefs.c:281 msgid "Clipboard Files" msgstr "Súbory schránky" #: src/prefs.c:281 msgid "Select Clipboard File" msgstr "Výber súboru schránky" #: src/prefs.c:283 msgid "HTML Browser Program" msgstr "HTML PrehliadaÄ" #: src/prefs.c:283 msgid "Select Browser Program" msgstr "Vyberte webový prehliadaÄ" #: src/prefs.c:285 msgid "Location of Handbook index" msgstr "Umiestnenie indexu príruÄky" #: src/prefs.c:285 msgid "Select Handbook Index File" msgstr "Vyberte index súboru príruÄky" #: src/prefs.c:287 msgid "Default Palette" msgstr "Predvolená palenta" #: src/prefs.c:287 msgid "Select Default Palette" msgstr "Vyberte predvolenú paletu" #: src/prefs.c:289 msgid "Default Patterns" msgstr "Predvolené vzory" #: src/prefs.c:289 msgid "Select Default Patterns File" msgstr "Vyberte súbor s predvolenými vzormi" #: src/prefs.c:292 msgid "Default CSS" msgstr "Predvolené CSS Å¡týly" #: src/prefs.c:292 msgid "Select Default CSS File" msgstr "Vyberte súbor s predvolenými CSS Å¡týlmi" #: src/prefs.c:295 msgid "Default Theme" msgstr "Predvolený motív" #: src/prefs.c:295 msgid "Select Default Theme File" msgstr "Vyberte súbor s predvoleným motívom" #: src/prefs.c:300 msgid "Status Bar" msgstr "Stavová liÅ¡ta" #: src/prefs.c:301 msgid "Canvas Geometry" msgstr "Geometria plátna" #: src/prefs.c:302 msgid "Cursor X,Y" msgstr "Kurzor X,Y" #: src/prefs.c:303 msgid "Pixel [I] {RGB}" msgstr "Pixel [I] {RGB}" #: src/prefs.c:304 msgid "Selection Geometry" msgstr "Geometria výberu" #: src/prefs.c:305 msgid "Undo / Redo" msgstr "Späť / Vpred" #: src/prefs.c:308 msgid "Tablet" msgstr "Tablet" #: src/prefs.c:309 msgid "Device Settings" msgstr "Nastavenia zariadenia" #: src/prefs.c:313 msgid "Configure Device" msgstr "Konfigurácia zariadenia" #: src/prefs.c:319 msgid "Tool Variable" msgstr "Variabilita nástroja" #: src/prefs.c:322 src/toolbar.c:454 msgid "Flow" msgstr "Tok" #: src/prefs.c:330 msgid "Test Area" msgstr "Testovacia plocha" #: src/prefs.c:373 msgid "Factor" msgstr "Koeficient" #: src/prefs.c:459 msgid "This key is builtin" msgstr "Tento kláves je vstavaný" #: src/prefs.c:462 #, c-format msgid "" "This key is mapped to:\n" "\"%s\"" msgstr "" "Tento kláves je namapovaný na:\n" "\"%s\"" #: src/prefs.c:465 msgid "Remap" msgstr "PremapovaÅ¥" #: src/prefs.c:510 msgid "Keyboard Shortcuts" msgstr "Klávesové skratky" #: src/shifter.c:147 msgid "Frames" msgstr "Snímkov" #: src/shifter.c:258 msgid "Palette Shifter" msgstr "PosunovaÄ palety" #: src/shifter.c:263 msgid "Start" msgstr "Å tart" #: src/shifter.c:265 msgid "Finish" msgstr "Koniec" #: src/shifter.c:284 msgid "Fix Palette" msgstr "UpraviÅ¥ paletu" #: src/spawn.c:651 msgid "Configure File Actions" msgstr "NastaviÅ¥ operácie so súbormi" #: src/spawn.c:657 src/spawn.c:663 msgid "Command" msgstr "Príkaz" #: src/spawn.c:922 #, c-format msgid "Error %i reported when trying to run %s" msgstr "Nastala chyba %i pri pokuse o spustenie %s" #: src/spawn.c:979 msgid "" "I am unable to find the documentation. Either you need to download the " "mtPaint Handbook from the web site and install it, or you need to set the " "correct location in the Preferences window." msgstr "" "Nie je možné nájsÅ¥ dokumentáciu. BuÄ potrebujete stiahnuÅ¥ príruÄku mtPaintu " "z webu a nainÅ¡talovaÅ¥ ju alebo musíte nastaviÅ¥ správnu cestu v okne s " "nastaveniami." #: src/spawn.c:1018 msgid "" "There was a problem running the HTML browser. You need to set the correct " "program name in the Preferences window." msgstr "" "Objavil sa problém so spustením HTML prehliadaÄa. Musíte nastaviÅ¥ správny " "názov programu v okne s nastaveniami." #: src/thread.c:361 msgid "Helper thread is not responding. Save your work and exit the program." msgstr "Vlákno pomocníka neodpovedá. Uložte prácu a ukonÄite program." #: src/toolbar.c:147 msgid "RGB Cube" msgstr "RGB kocka" #: src/toolbar.c:148 msgid "By image channel" msgstr "Kanálom obrázku" #: src/toolbar.c:149 msgid "Gradient-driven" msgstr "Prechodom" #: src/toolbar.c:157 msgid "Fill settings" msgstr "Nastavenie výplne" #: src/toolbar.c:170 msgid "Respect opacity mode" msgstr "ReÅ¡pektovaÅ¥ režim nepriehľadnosti" #: src/toolbar.c:176 msgid "Smudge settings" msgstr "Nastavenie rozmazania" #: src/toolbar.c:215 msgid "Aligned" msgstr "Zarovnané" #: src/toolbar.c:222 msgid "Clone settings" msgstr "Nastavenie peÄiatky" #: src/toolbar.c:228 msgid "By selection channel" msgstr "Podľa kanálu výberu" #: src/toolbar.c:234 msgid "Lasso settings" msgstr "Nastavenia lasa" #: src/toolbar.c:252 msgid "Brush spacing" msgstr "Odstupy Å¡tetca" #: src/toolbar.c:299 src/toolbar.c:341 msgid "Normal" msgstr "Normálne" #: src/toolbar.c:300 msgid "Colour" msgstr "Farba" #: src/toolbar.c:300 msgid "Saturate More" msgstr "Viac sýtosti" #: src/toolbar.c:301 msgid "Multiply" msgstr "Násobenie" #: src/toolbar.c:301 msgid "Divide" msgstr "Delenie" #: src/toolbar.c:301 msgid "Dodge" msgstr "ZosvetliÅ¥" #: src/toolbar.c:302 msgid "Burn" msgstr "StmaviÅ¥" #: src/toolbar.c:302 msgid "Hard Light" msgstr "Ostré svetlo" #: src/toolbar.c:302 msgid "Soft Light" msgstr "Mierne svetlo" #: src/toolbar.c:302 msgid "Difference" msgstr "Rozdiely" #: src/toolbar.c:303 msgid "Darken" msgstr "Len stmavenie" #: src/toolbar.c:303 msgid "Lighten" msgstr "Len zosvetlenie" #: src/toolbar.c:303 msgid "Grain Extract" msgstr "Extrakcia zrnitosti" #: src/toolbar.c:304 msgid "Grain Merge" msgstr "ZlúÄenie zrnitosti" #: src/toolbar.c:330 msgid "Blend mode" msgstr "Režim mieÅ¡ania" #: src/toolbar.c:417 msgid "Continuous Mode" msgstr "Súvislý režim" #: src/toolbar.c:421 msgid "Opacity Mode" msgstr "Režim nepriesvitnosti" #: src/toolbar.c:424 msgid "Tint Mode" msgstr "Režim kolorovania" #: src/toolbar.c:427 msgid "Tint +-" msgstr "Kolorovanie +-" #: src/toolbar.c:434 msgid "Blend Mode" msgstr "Režim mieÅ¡ania" #: src/toolbar.c:438 msgid "Disable All Masks" msgstr "Vypnúť vÅ¡etky masky" #: src/toolbar.c:441 msgid "Gradient Mode" msgstr "Režim prechodu" #: src/toolbar.c:486 msgid "Settings Toolbar" msgstr "LiÅ¡ta nastavení" #: src/toolbar.c:546 msgid "Cut" msgstr "Vystrihnúť" #: src/toolbar.c:548 msgid "Copy" msgstr "KopírovaÅ¥" #: src/toolbar.c:550 msgid "Paste" msgstr "PrilepiÅ¥" #: src/toolbar.c:553 msgid "Undo" msgstr "Späť" #: src/toolbar.c:555 msgid "Redo" msgstr "Vpred" #: src/toolbar.c:559 src/viewer.c:328 msgid "Pan Window" msgstr "Prehľadové okno" #: src/toolbar.c:560 src/toolbar.c:640 msgid "More..." msgstr "Viac..." #: src/toolbar.c:574 msgid "Paint" msgstr "Maľovanie" #: src/toolbar.c:580 msgid "Shuffle" msgstr "Poprehadzovanie" #: src/toolbar.c:583 msgid "Flood Fill" msgstr "Vyplnenie" #: src/toolbar.c:587 msgid "Straight Line" msgstr "Rovná Äiara" #: src/toolbar.c:590 msgid "Smudge" msgstr "RozmazaÅ¥" #: src/toolbar.c:594 msgid "Clone" msgstr "KlonovaÅ¥" #: src/toolbar.c:597 msgid "Make Selection" msgstr "OznaÄiÅ¥ výber" #: src/toolbar.c:600 msgid "Polygon Selection" msgstr "Výber polygónom" #: src/toolbar.c:603 msgid "Place Gradient" msgstr "VložiÅ¥ prechod" #: src/toolbar.c:606 msgid "Lasso Selection" msgstr "Výber lasom" #: src/toolbar.c:614 msgid "Ellipse Outline" msgstr "Prázdna elipsa" #: src/toolbar.c:617 msgid "Filled Ellipse" msgstr "Vyplnená elipsa" #: src/toolbar.c:620 msgid "Outline Selection" msgstr "OrámovaÅ¥ výber" #: src/toolbar.c:623 msgid "Fill Selection" msgstr "VyplniÅ¥ výber" #: src/toolbar.c:627 msgid "Flip Selection Vertically" msgstr "OtoÄiÅ¥ výber vertikálne" #: src/toolbar.c:630 msgid "Flip Selection Horizontally" msgstr "OtoÄiÅ¥ výber horizontálne" #: src/toolbar.c:633 msgid "Rotate Selection Clockwise" msgstr "OtoÄiÅ¥ výber v smere ruÄiÄiek" #: src/toolbar.c:636 msgid "Rotate Selection Anti-Clockwise" msgstr "OtoÄiÅ¥ výber proti smeru ruÄiÄiek" #: src/vcode.c:5201 msgid "Browse" msgstr "PrehliadaÅ¥" #: src/vcode.c:7886 msgid "New key ..." msgstr "Nový kláves..." #: src/vcode.c:9909 #, c-format msgid "'%s' does not match any widget" msgstr "'%s' nezodpovedá žiadnemu ovládaciemu prvku" #: src/vcode.c:9910 #, c-format msgid "'%s' value does not fit '%s' widget" msgstr "Hodnota '%s' sa nehodí k ovládaciemu prvku '%s'" #: src/viewer.c:115 msgid "About" msgstr "O programe" #: src/viewer.c:1179 msgid "No font selected" msgstr "Nevybrali ste žiadne písmo" #: src/viewer.c:1209 msgid "Left" msgstr "Doľava" #: src/viewer.c:1209 msgid "Right" msgstr "Doprava" #~ msgid "Counting Unique RGB Pixels" #~ msgstr "PoÄítajú sa unikátne RGB pixely" #~ msgid "Create GIF frames" #~ msgstr "VytvoriÅ¥ snímky GIF" #~ msgid "File: %s invalid - palette not updated" #~ msgstr "Súbor: %s je neplatný - paleta nebola aktualizovaná" #~ msgid "Distance to A+B" #~ msgstr "VzdialenosÅ¥ k A+B" #~ msgid "Edit Frames" #~ msgstr "UpraviÅ¥ snímky" #~ msgid " C Command Line Window" #~ msgstr " C Okno príkazového riadka" #~ msgid "The palette does not contain enough colours to do a merge" #~ msgstr "Paleta neobsahuje dostatok farieb pre uskutoÄnenie zlúÄenia" #~ msgid "There are too many identical palette items to be reduced." #~ msgstr "PríliÅ¡ mnoho identických položiek palety k redukcii." #~ msgid "/View/Command Line Window" #~ msgstr "/ZobraziÅ¥/Okno príkazového riadku" #~ msgid "Grid colour RGB" #~ msgstr "RGB farba rastra" #~ msgid "Zoom" #~ msgstr "Zoom" #~ msgid "%i Files on Command Line" #~ msgstr "%i súborov na príkazovom riadku" #~ msgid "Not enough memory to rotate image" #~ msgstr "Nedostatok pamäte pre rotáciu obrázku" #~ msgid "Not enough memory to rotate clipboard" #~ msgstr "Nedostatok pamäte pre rotáciu schránky" #~ msgid "File is too big, must be <= to width=%i height=%i : %s" #~ msgstr "Súbor je príliÅ¡ veľký, musí byÅ¥ <= šírka=%i výška=%i : %s" #~ msgid "" #~ "Dennis Lee - Wrote the two quantizing methods DL1 & 3 - see quantizer.c " #~ "for more information." #~ msgstr "" #~ "Dennis Lee - napísal dve kvantovacie metódy DL1 & 3 - Pre viac informácii " #~ "sa pozrite do quantizer.c" #~ msgid "Magnus Hjorth - Wrote inifile.c/h, from mhWaveEdit 1.3.0." #~ msgstr "Magnus Hjorth - Napísal inifile.c/h, v programe mhWaveEdit 1.3.0." #~ msgid "Could not open %s: %s" #~ msgstr "Nepodarilo sa otvoriÅ¥ %s: %s" #~ msgid "Error closing %s: %s" #~ msgstr "Chyba pri zatváraní %s: %s" #~ msgid "Could not write to %s: %s" #~ msgstr "Nepodarilo sa zapísaÅ¥ do %s: %s" #~ msgid "patterns_user.c could not be opened in current directory" #~ msgstr "patterns_user.c sa nepodarilo otvoriÅ¥ v aktuálnom adresári" #~ msgid "Done" #~ msgstr "Hotovo" #~ msgid "patterns_user.c created in current directory" #~ msgstr "patterns_user.c vytvorené v aktuálnom adresári" #~ msgid "Current image is not 94x94x3 so I cannot create patterns_user.c" #~ msgstr "" #~ "Aktuálny obrázok nie je 94x94x3, takže nie je možné vytvoriÅ¥ " #~ "patterns_user.c" #~ msgid "" #~ "You are trying to save an RGB image to an XPM file which is not " #~ "possible. I would suggest you save with a PNG extension." #~ msgstr "" #~ "Pokúšate sa uložiÅ¥ RGB obrázok do XPM súboru, Äo nie je možné. " #~ "DoporuÄujem uložiÅ¥ s príponou PNG." #~ msgid "" #~ "You are trying to save an RGB image to a GIF file which is not possible. " #~ "I would suggest you save with a PNG extension." #~ msgstr "" #~ "Pokúšate sa uložiÅ¥ RGB obrázok do GIF souboru, Äo nie je možné. " #~ "DoporuÄujem uložiÅ¥ s príponou PNG." #~ msgid "" #~ "You are trying to save an XBM file with a palette of more than 2 " #~ "colours. Either use another format or reduce the palette to 2 colours." #~ msgstr "" #~ "Pokúšate sa uložiÅ¥ XBM súbor s paletou s viac než 2 farbami. Použite iný " #~ "formát alebo znížte poÄet farieb v palete na 2." #~ msgid "" #~ "You are trying to save an indexed canvas to a JPEG file which is not " #~ "possible. I would suggest you save with a PNG extension." #~ msgstr "" #~ "Pokúšate sa uložiÅ¥ indexované plátno do JPEG súboru, Äo nie je možné. " #~ "DoporuÄujem uložiÅ¥ s príponou PNG." #~ msgid "" #~ "You are trying to save an LSS16 file with a palette of more than 16 " #~ "colours. Either use another format or reduce the palette to 16 colours." #~ msgstr "" #~ "Pokúšate sa uložiÅ¥ LSS16 súbor s paletou s viac než 16 farbami. Použite " #~ "iný formát alebo znížte poÄet farieb v palete na 16." #~ msgid "/Edit/Create Patterns" #~ msgstr "/UpraviÅ¥/VytvoriÅ¥ vzory" #~ msgid "/Palette/Create Quantized (DL1)" #~ msgstr "/Paleta/VytvoriÅ¥ kvantované (DL1)" #~ msgid "/Palette/Create Quantized (DL3)" #~ msgstr "/Paleta/VytvoriÅ¥ kvantované (DL3)" #~ msgid "/Palette/Create Quantized (Wu)" #~ msgstr "/Paleta/VytvoriÅ¥ kvantované (Wu)" #~ msgid "/File/%i" #~ msgstr "/Súbor/%i" #~ msgid "Lanczos3" #~ msgstr "Lanczos3" #~ msgid "DL1 Quantize (fastest)" #~ msgstr "DL1 Kvantovanie (najrýchlejÅ¡ie)" #~ msgid "DL3 Quantize (very slow, better quality)" #~ msgstr "DL3 Kvantovanie (veľmi pomalé, lepÅ¡ia kvalita)" #~ msgid "Wu Quantize (best method for small palettes)" #~ msgstr "Wu Kvantovanie (najlepÅ¡ia metóda pre malé palety)" #~ msgid "Loading PNG image" #~ msgstr "NaÄítam PNG obrázok" #~ msgid "Loading clipboard image" #~ msgstr "NaÄítam obrázok zo schránky" #~ msgid "Saving PNG image" #~ msgstr "Ukladám PNG obrázok" #~ msgid "Saving Clipboard image" #~ msgstr "Ukladám obrázok zo schránky" #~ msgid "Saving Layer image" #~ msgstr "Uloženie obrázku vrstvy" #~ msgid "Saving Channel image" #~ msgstr "Ukladám kanálový obrázok" #~ msgid "Loading GIF image" #~ msgstr "NaÄítam GIF obrázok" #~ msgid "Saving GIF image" #~ msgstr "Ukladám GIF obrázok" #~ msgid "Loading JPEG image" #~ msgstr "NaÄítam JPEG obrázok" #~ msgid "Saving JPEG image" #~ msgstr "Ukladám JPEG obrázok" #~ msgid "Loading TIFF image" #~ msgstr "NaÄítam TIFF obrázok" #~ msgid "Saving TIFF image" #~ msgstr "Ukladám TIFF obrázok" #~ msgid "Loading BMP image" #~ msgstr "NaÄítam BMP obrázok" #~ msgid "Saving BMP image" #~ msgstr "Ukladám BMP obrázok" #~ msgid "Loading XPM image" #~ msgstr "NaÄítam XPM obrázok" #~ msgid "Saving XPM image" #~ msgstr "Ukladám XPM obrázok" #~ msgid "Loading XBM image" #~ msgstr "NaÄítam XBM obrázok" #~ msgid "Saving XBM image" #~ msgstr "Ukladám XBM obrázok" #~ msgid "Loading LSS16 image" #~ msgstr "NaÄítam LSS16 obrázok" #~ msgid "Saving LSS16 image" #~ msgstr "Ukladám LSS16 obrázok" #~ msgid "Saving UNDO images" #~ msgstr "Ukladám obrázky histórie" #~ msgid "JPEG Save Quality (100=High) " #~ msgstr "JPEG Kvalita ukladania (100=NajlepÅ¡ia) " mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/po/sv.po000066400000000000000000002650141471325446300215710ustar00rootroot00000000000000# Swedish translation for mtpaint # Copyright (c) (c) 2005 Canonical Ltd, and Rosetta Contributors 2005 # This file is distributed under the same license as the mtpaint package. # FIRST AUTHOR , 2005. # msgid "" msgstr "" "Project-Id-Version: mtpaint\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-01-04 21:31+0200\n" "PO-Revision-Date: 2009-02-13 14:54+0000\n" "Last-Translator: Daniel Nylander \n" "Language-Team: Swedish \n" "Language: sv\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Launchpad-Export-Date: 2009-02-14 18:20+0000\n" "X-Generator: Launchpad (build Unknown)\n" "X-Rosetta-Version: 0.1\n" #: src/ani.c:647 msgid "Animation Preview" msgstr "Förhansvisning Animation" #: src/ani.c:650 src/shifter.c:275 msgid "Play" msgstr "Spela upp" #: src/ani.c:654 msgid "Fix" msgstr "Rätta till" #: src/ani.c:655 src/ani.c:1005 src/font.c:1624 src/font.c:1643 #: src/shifter.c:286 src/viewer.c:97 msgid "Close" msgstr "Stäng" #: src/ani.c:709 src/ani.c:812 src/ani.c:1022 src/ani.c:1028 src/canvas.c:356 #: src/canvas.c:708 src/canvas.c:989 src/canvas.c:1353 src/canvas.c:1383 #: src/canvas.c:1470 src/canvas.c:1545 src/canvas.c:1988 src/canvas.c:1994 #: src/canvas.c:2077 src/canvas.c:2217 src/canvas.c:2240 src/font.c:1352 #: src/fpick.c:636 src/fpick.c:754 src/layer.c:524 src/layer.c:815 #: src/layer.c:970 src/mainwindow.c:341 src/mainwindow.c:370 #: src/mainwindow.c:534 src/mainwindow.c:578 src/mainwindow.c:604 #: src/mainwindow.c:3797 src/mainwindow.c:4045 src/otherwindow.c:931 #: src/otherwindow.c:980 src/otherwindow.c:982 src/prefs.c:459 src/spawn.c:924 #: src/spawn.c:978 src/spawn.c:1017 src/thread.c:360 src/vcode.c:9912 #: src/viewer.c:1161 src/viewer.c:1179 msgid "Error" msgstr "Fel" #: src/ani.c:709 msgid "Unable to create output directory" msgstr "Kunde inte skapa utdatakatalogen" #: src/ani.c:759 msgid "Creating Animation Frames" msgstr "Skapar Animationsbildrutor" #: src/ani.c:812 msgid "Unable to save image" msgstr "Kunde inte spara bild" #: src/ani.c:840 src/canvas.c:1171 src/fpick.c:731 src/layer.c:311 #: src/layer.c:379 src/layer.c:826 src/layer.c:840 src/mainwindow.c:375 #: src/mainwindow.c:1026 src/png.c:8794 src/prefs.c:464 msgid "Warning" msgstr "Varning" #: src/ani.c:840 msgid "" "Do you really want to clear all of the position and cycle data for all of " "the layers?" msgstr "" "Är du säker pÃ¥ att du vill rensa all positions och cykeldata för alla lager?" #: src/ani.c:841 src/fpick.c:731 src/layer.c:311 src/layer.c:842 #: src/mainwindow.c:375 msgid "No" msgstr "Nej" #: src/ani.c:841 src/fpick.c:731 src/layer.c:311 src/layer.c:842 #: src/mainwindow.c:375 msgid "Yes" msgstr "Ja" #: src/ani.c:954 msgid "Set Key Frame" msgstr "Sätt Nyckelbildruta" #: src/ani.c:961 msgid "Configure Animation" msgstr "Konfigurera animering" #: src/ani.c:964 msgid "Output Files" msgstr "Utdatafiler" #: src/ani.c:967 msgid "Start frame" msgstr "Startruta" #: src/ani.c:969 msgid "End frame" msgstr "Slutruta" #: src/ani.c:971 src/shifter.c:267 msgid "Delay" msgstr "Fördröjning" #: src/ani.c:973 msgid "Output path" msgstr "Sökväg för utmatning" #: src/ani.c:973 src/font.c:1637 src/spawn.c:664 msgid "Select Directory" msgstr "Välj katalog" #: src/ani.c:976 msgid "File prefix" msgstr "Filprefix" #: src/ani.c:978 src/canvas.c:2096 msgid "File Format" msgstr "Filformat" #: src/ani.c:982 msgid "Positions" msgstr "Positioner" #: src/ani.c:997 msgid "Cycling" msgstr "" #: src/ani.c:1006 msgid "Save" msgstr "Spara" #: src/ani.c:1007 src/font.c:1577 src/otherwindow.c:868 src/otherwindow.c:1615 #: src/otherwindow.c:1728 src/otherwindow.c:2938 src/otherwindow.c:3071 #: src/otherwindow.c:3170 msgid "Preview" msgstr "Förhandsvisa" #: src/ani.c:1008 src/shifter.c:285 msgid "Create Frames" msgstr "Skapa Bildrutor" #: src/ani.c:1022 msgid "You must have at least 2 layers to create an animation" msgstr "Du mÃ¥ste ha minst 2 lager för att skapa en animering" #: src/ani.c:1028 msgid "You must save your layers file before creating an animation" msgstr "Du mÃ¥ste spara din lagerfil innan en animering skapas" #: src/canvas.c:357 msgid "The image is too large to transform." msgstr "Bilden är för stor för att transformera." #: src/canvas.c:393 src/canvas.c:430 src/otherwindow.c:1613 #: src/otherwindow.c:2524 src/otherwindow.c:2583 src/otherwindow.c:3179 msgid "Gradient" msgstr "Gradient" #: src/canvas.c:393 src/otherwindow.c:840 src/otherwindow.c:842 #: src/otherwindow.c:2074 src/otherwindow.c:3180 msgid "Palette" msgstr "Palett" #: src/canvas.c:393 src/info.c:265 src/otherwindow.c:847 src/otherwindow.c:2757 #: src/otherwindow.c:3180 src/png.c:781 src/png.c:995 msgid "Clipboard" msgstr "Urklipp" #: src/canvas.c:394 src/cpick.c:831 src/toolbar.c:299 msgid "Value" msgstr "Värde" #: src/canvas.c:394 src/cpick.c:811 src/otherwindow.c:575 src/otherwindow.c:859 #: src/otherwindow.c:3053 src/toolbar.c:318 msgid "Red" msgstr "Röd" #: src/canvas.c:394 src/cpick.c:815 src/otherwindow.c:575 src/otherwindow.c:860 #: src/otherwindow.c:3053 src/toolbar.c:319 msgid "Green" msgstr "Grön" #: src/canvas.c:394 src/cpick.c:819 src/otherwindow.c:575 src/otherwindow.c:861 #: src/otherwindow.c:3053 src/toolbar.c:320 msgid "Blue" msgstr "BlÃ¥" #: src/canvas.c:399 msgid "From " msgstr "" #: src/canvas.c:403 msgid "To " msgstr "" #: src/canvas.c:410 msgid "Map" msgstr "" #: src/canvas.c:429 msgid "MT" msgstr "MT" #: src/canvas.c:429 msgid "Sobel" msgstr "Sobel" #: src/canvas.c:429 msgid "Prewitt" msgstr "Prewitt" #: src/canvas.c:429 msgid "Kirsch" msgstr "Kirsch" #: src/canvas.c:430 msgid "Roberts" msgstr "Roberts" #: src/canvas.c:430 msgid "Laplace" msgstr "Laplace" #: src/canvas.c:430 msgid "Morphological" msgstr "Morfologiska" #: src/canvas.c:442 msgid "Edge Detect" msgstr "Kantdetektering" #: src/canvas.c:464 msgid "Edge Sharpen" msgstr "Gör Kanter Skarpare" #: src/canvas.c:472 msgid "Edge Soften" msgstr "Gör Kanter Mjukare" #: src/canvas.c:521 msgid "Different X/Y" msgstr "Olika X/Y" #: src/canvas.c:522 src/canvas.c:562 src/canvas.c:603 src/canvas.c:637 #: src/canvas.c:722 src/otherwindow.c:1037 src/otherwindow.c:2685 msgid "Gamma corrected" msgstr "Gamma korrigerad" #: src/canvas.c:530 src/memory.c:8219 msgid "Gaussian Blur" msgstr "Gaussisk oskärpa" #: src/canvas.c:558 msgid "Radius" msgstr "Radie" #: src/canvas.c:559 msgid "Amount" msgstr "Mängd" #: src/canvas.c:560 msgid "Threshold " msgstr "Tröskelvärde " #: src/canvas.c:570 src/memory.c:8360 msgid "Unsharp Mask" msgstr "Oskarp mask" #: src/canvas.c:599 msgid "Outer radius" msgstr "Yttre radie" #: src/canvas.c:600 msgid "Inner radius" msgstr "Innerradie" #: src/canvas.c:602 src/info.c:280 msgid "Normalize" msgstr "Normalisera" #: src/canvas.c:611 src/memory.c:8512 msgid "Difference of Gaussians" msgstr "Gaussisk differens" #: src/canvas.c:636 msgid "Protect details" msgstr "" #: src/canvas.c:645 msgid "Kuwahara-Nagao Blur" msgstr "Kuwahara-Nagao Oskärpa" #: src/canvas.c:709 msgid "The image is too large for this rotation." msgstr "Bilden är för stor för denna rotering." #: src/canvas.c:723 msgid "Smooth" msgstr "Mjuk" #: src/canvas.c:732 msgid "Free Rotate" msgstr "Fri Rotering" #: src/canvas.c:989 src/viewer.c:1161 msgid "Not enough memory to create clipboard" msgstr "Inte tillräckligt mycket minne för att skapa urklipp" #: src/canvas.c:1172 msgid "" "You have not allocated enough memory in the Preferences window to undo this " "action." msgstr "" #: src/canvas.c:1353 msgid "Invalid palette file" msgstr "" #: src/canvas.c:1383 msgid "Invalid channel file." msgstr "Ogiltig kanalfil." #: src/canvas.c:1401 msgid "Raw frames" msgstr "" #: src/canvas.c:1401 msgid "Composited frames" msgstr "" #: src/canvas.c:1402 msgid "Composited frames with nonzero delay" msgstr "" #: src/canvas.c:1406 msgid "Load Frames" msgstr "" #: src/canvas.c:1409 msgid "Load into Layers" msgstr "" #: src/canvas.c:1415 msgid "Load First Frame" msgstr "" #: src/canvas.c:1416 msgid "Explode Frames" msgstr "" #: src/canvas.c:1418 msgid "View Animation" msgstr "Visa animering" #: src/canvas.c:1434 #, c-format msgid "This is an animated %s file." msgstr "Detta är en animerad %s-fil." #: src/canvas.c:1435 #, c-format msgid "This is a multipage %s file." msgstr "" #: src/canvas.c:1459 #, c-format msgid "File is too big, must be <= to width=%i height=%i" msgstr "Filen är för stor, mÃ¥ste vara <= till bredd=%i höjd=%i" #: src/canvas.c:1461 msgid "Unable to explode frames" msgstr "" #: src/canvas.c:1463 msgid "Unable to load file" msgstr "Kunde inte läsa in filen" #: src/canvas.c:1465 msgid "" "The file import library had to terminate due to a problem with the file " "(possibly corrupt image data or a truncated file). I have managed to load " "some data as the header seemed fine, but I would suggest you save this image " "to a new file to ensure this does not happen again." msgstr "" "Filimportsbiblioteket avslutades p.g.a. ett problem med fil (möjligen " "beroende pÃ¥ korrupt fildata eller avskärd fil). Jag har lyckats ladda en del " "data eftersom huvudet verkar korrekt, men jag skulle reckommendera att spara " "bilden till en ny fil för att försäkra att detta inte händer igen." #: src/canvas.c:1467 msgid "The animation is too long to load all of it into layers." msgstr "" #: src/canvas.c:1469 msgid "Could not explode all the frames in the animation." msgstr "" #: src/canvas.c:1481 src/font.c:1556 src/fpick.c:937 src/otherwindow.c:2765 #: src/prefs.c:321 src/toolbar.c:451 msgid "Size" msgstr "Storlek" #: src/canvas.c:1484 src/otherwindow.c:244 msgid "Width" msgstr "Bredd" #: src/canvas.c:1485 src/otherwindow.c:245 msgid "Height" msgstr "Höjd" #: src/canvas.c:1489 src/channels.c:253 src/channels.c:317 src/fpick.c:666 #: src/fpick.c:957 src/mainwindow.c:3990 src/otherwindow.c:255 #: src/otherwindow.c:517 src/otherwindow.c:591 src/otherwindow.c:867 #: src/otherwindow.c:1058 src/otherwindow.c:1727 src/otherwindow.c:2101 #: src/otherwindow.c:2336 src/otherwindow.c:2538 src/otherwindow.c:2691 #: src/otherwindow.c:2776 src/otherwindow.c:2937 src/otherwindow.c:3070 #: src/otherwindow.c:3169 src/prefs.c:338 src/prefs.c:464 src/prefs.c:538 #: src/spawn.c:666 src/viewer.c:1258 msgid "Cancel" msgstr "Avbryt" #: src/canvas.c:1490 src/channels.c:253 src/channels.c:317 src/fpick.c:956 #: src/info.c:297 src/mainwindow.c:3992 src/mygtk.c:233 src/mygtk.c:535 #: src/otherwindow.c:591 src/otherwindow.c:871 src/otherwindow.c:1058 #: src/otherwindow.c:1729 src/otherwindow.c:2101 src/otherwindow.c:2336 #: src/otherwindow.c:2538 src/otherwindow.c:2691 src/otherwindow.c:2776 #: src/otherwindow.c:3072 src/otherwindow.c:3171 src/prefs.c:338 #: src/prefs.c:538 src/spawn.c:666 msgid "OK" msgstr "OK" #: src/canvas.c:1504 #, c-format msgid "This is a scalable %s file." msgstr "" #: src/canvas.c:1545 msgid "Cannot open file" msgstr "Kan inte öppna filen" #: src/canvas.c:1546 msgid "Unsupported file format" msgstr "Filformatet stöds inte" #: src/canvas.c:1673 #, c-format msgid "File: %s already exists. Do you want to overwrite it?" msgstr "Filen %s finns redan. Vill du skriva över den?" #: src/canvas.c:1674 msgid "File Found" msgstr "Filen hittades" #: src/canvas.c:1674 src/mainwindow.c:1095 msgid "NO" msgstr "NEJ" #: src/canvas.c:1674 src/mainwindow.c:1095 msgid "YES" msgstr "JA" #: src/canvas.c:1988 msgid "Unable to export undo images" msgstr "Kunde inte exportera Ã¥ngra-historik" #: src/canvas.c:1994 msgid "Unable to export ASCII file" msgstr "Kunde inte exportera ASCII-filen" #: src/canvas.c:2076 src/layer.c:814 src/mainwindow.c:529 #, c-format msgid "Unable to save file: %s" msgstr "Kunde inte spara filen: %s" #: src/canvas.c:2101 src/prefs.c:222 msgid "Transparency index" msgstr "Genomskinlighetsindex" #: src/canvas.c:2103 msgid "TIFF Compression" msgstr "" #: src/canvas.c:2105 src/prefs.c:225 msgid "JPEG Save Quality (100=High)" msgstr "Kvalitet pÃ¥ JPEG-fil (100=Hög)" #: src/canvas.c:2107 msgid "ZIP Compression (0=None)" msgstr "" #: src/canvas.c:2108 src/prefs.c:227 msgid "PNG Compression (0=None)" msgstr "PNG-komprimering (0=ingen)" #: src/canvas.c:2111 src/prefs.c:249 msgid "LZMA2 Compression (0=None)" msgstr "" #: src/canvas.c:2113 src/prefs.c:252 msgid "ZSTD Compression Level" msgstr "" #: src/canvas.c:2115 src/prefs.c:231 msgid "TGA RLE Compression" msgstr "TGA RLE-komprimering" #: src/canvas.c:2117 msgid "LBM PackBits Compression" msgstr "" #: src/canvas.c:2118 src/prefs.c:226 msgid "JPEG2000 Compression (0=Lossless)" msgstr "JPEG2000-komprimering (0=förlustfri)" #: src/canvas.c:2120 msgid "WebP Compression" msgstr "" #: src/canvas.c:2122 msgid "WebP Save Quality (100=High)" msgstr "" #: src/canvas.c:2123 src/prefs.c:263 msgid "V8 Save Quality (100=High)" msgstr "" #: src/canvas.c:2125 src/prefs.c:264 msgid "V8L Compression (0=None)" msgstr "" #: src/canvas.c:2127 msgid "Hotspot at X =" msgstr "Klickpunkt pÃ¥ X =" #: src/canvas.c:2129 msgid "Y =" msgstr "Y =" #: src/canvas.c:2133 msgid "Animation delay" msgstr "Animationsfördröjning" #: src/canvas.c:2136 src/otherwindow.c:253 msgid "Undoable" msgstr "Ã…ngras" #: src/canvas.c:2138 src/prefs.c:236 msgid "Apply colour profile" msgstr "" #: src/canvas.c:2176 src/toolbar.c:543 msgid "Load Image File" msgstr "Läs in bildfil" #: src/canvas.c:2191 src/toolbar.c:544 msgid "Save Image File" msgstr "Spara bildfil" #: src/canvas.c:2196 msgid "Load Palette File" msgstr "Läs in palettfil" #: src/canvas.c:2202 msgid "Save Palette File" msgstr "Spara palettfil" #: src/canvas.c:2207 msgid "Export Undo Images" msgstr "Exportera Ã…ngra-historik" #: src/canvas.c:2212 msgid "Export Undo Images (reversed)" msgstr "Exportera Ã…ngra-historik (omvänd)" #: src/canvas.c:2217 msgid "You must have 16 or fewer palette colours to export ASCII art." msgstr "" "Du mÃ¥ste ha 16 eller mindre palettfärger för att exportera ASCII-grafik." #: src/canvas.c:2220 msgid "Export ASCII Art" msgstr "Exportera ASCII-grafik" #: src/canvas.c:2224 msgid "Save Layer Files" msgstr "Spara lagerfiler" #: src/canvas.c:2234 msgid "Choose frames directory" msgstr "Välj katalog för bildrutor" #: src/canvas.c:2240 msgid "You must save at least one frame to create an animated GIF." msgstr "Du mÃ¥ste spara minst en bildruta för att skapa en animerad GIF." #: src/canvas.c:2243 msgid "Export GIF animation" msgstr "Exportera GIF-animering" #: src/canvas.c:2247 msgid "Load Channel" msgstr "Läs in kanal" #: src/canvas.c:2255 msgid "Save Channel" msgstr "Spara kanal" #: src/canvas.c:2260 msgid "Save Composite Image" msgstr "Spara sammansatt bild" #: src/channels.c:243 msgid "Create Channel" msgstr "Skapa kanal" #: src/channels.c:244 msgid "Channel Type" msgstr "Kanaltyp" #: src/channels.c:247 msgid "Initial Channel State" msgstr "Ursprunglig kanalinställning" #: src/channels.c:251 msgid "Inverted" msgstr "Inverterad" #: src/channels.c:265 msgid "Cleared" msgstr "Rensad" #: src/channels.c:266 msgid "Set" msgstr "Ange" #: src/channels.c:267 msgid "Set colour A radius B" msgstr "Sätt färg A radie B" #: src/channels.c:268 msgid "Set blend A to B" msgstr "Sätt blandning A till B" #: src/channels.c:269 msgid "Image Red" msgstr "Bild Röd" #: src/channels.c:270 msgid "Image Green" msgstr "Bild Grön" #: src/channels.c:271 msgid "Image Blue" msgstr "Bild BlÃ¥" #: src/channels.c:273 src/channels.c:313 src/mainwindow.c:67 #: src/otherwindow.c:1679 msgid "Alpha" msgstr "Alfa" #: src/channels.c:274 src/channels.c:314 src/mainwindow.c:67 #: src/otherwindow.c:1683 msgid "Selection" msgstr "Markering" #: src/channels.c:275 src/channels.c:315 src/mainwindow.c:67 #: src/otherwindow.c:1687 msgid "Mask" msgstr "Mask" #: src/channels.c:312 msgid "Delete Channels" msgstr "Ta bort kanaler" #: src/channels.c:367 msgid "Threshold Channel" msgstr "Tröskel kanal" #: src/cpick.c:823 src/otherwindow.c:573 src/otherwindow.c:820 #: src/toolbar.c:299 msgid "Hue" msgstr "Nyans" #: src/cpick.c:827 src/otherwindow.c:573 src/otherwindow.c:818 #: src/toolbar.c:299 msgid "Saturation" msgstr "Mättnad" #: src/cpick.c:835 msgid "Hex" msgstr "Hex" #: src/cpick.c:840 src/layer.c:1109 src/otherwindow.c:2530 src/prefs.c:323 #: src/toolbar.c:457 msgid "Opacity" msgstr "Opacitet" #: src/font.c:982 msgid "Creating Font Index" msgstr "Skapar typsnittsindex" #: src/font.c:1353 msgid "You must select at least one directory to search for fonts." msgstr "Du mÃ¥ste välj minst en katalog att söka i efter typsnitt." #: src/font.c:1529 src/font.c:1624 src/toolbar.c:609 src/viewer.c:1213 #: src/viewer.c:1258 msgid "Paste Text" msgstr "Klistra in text" #: src/font.c:1533 src/font.c:1572 src/png.c:3578 msgid "Text" msgstr "Text" #: src/font.c:1540 msgid "Font" msgstr "Typsnitt" #: src/font.c:1548 msgid "Style" msgstr "Stil" #: src/font.c:1566 msgid "Filename" msgstr "Filnamn" #: src/font.c:1567 msgid "Face" msgstr "Typsnitt" #: src/font.c:1587 src/viewer.c:1222 msgid "Antialias" msgstr "Kantutjämning" #: src/font.c:1590 src/viewer.c:1224 msgid "Invert" msgstr "Invertera" #: src/font.c:1593 src/viewer.c:1226 msgid "Background colour =" msgstr "Bakgrundsfärg =" #: src/font.c:1601 src/viewer.c:1233 msgid "DPI =" msgstr "" #: src/font.c:1610 msgid "Oblique" msgstr "Oblik" #: src/font.c:1612 src/viewer.c:1244 msgid "Angle of rotation =" msgstr "Vinkel pÃ¥ rotering =" #: src/font.c:1617 src/viewer.c:1248 msgid "Align" msgstr "" #: src/font.c:1620 src/viewer.c:1253 msgid "Spacing" msgstr "" #: src/font.c:1629 msgid "Font Directories" msgstr "Typsnittskataloger" #: src/font.c:1634 src/spawn.c:664 msgid "Directory" msgstr "Katalog" #: src/font.c:1637 msgid "New Directory" msgstr "Ny katalog" #: src/font.c:1644 src/prefs.c:532 msgid "Add" msgstr "Lägg till" #: src/font.c:1645 src/prefs.c:533 msgid "Remove" msgstr "Ta bort" #: src/font.c:1646 msgid "Create Index" msgstr "Skapa index" #: src/font.c:1660 src/viewer.c:1267 msgid "Enter Text Here" msgstr "Ange text här" #: src/fpick.c:635 #, c-format msgid "Could not access directory %s" msgstr "Kunde inte komma Ã¥t katalogen %s" #: src/fpick.c:668 src/fpick.c:698 msgid "Delete" msgstr "Ta bort" #: src/fpick.c:669 src/fpick.c:698 msgid "Rename" msgstr "Byt namn" #: src/fpick.c:672 src/otherwindow.c:255 src/otherwindow.c:1666 msgid "Create" msgstr "Skapa" #: src/fpick.c:699 msgid "Enter the new filename" msgstr "Ange nytt filnamn" #: src/fpick.c:704 msgid "Create Directory" msgstr "Skapa katalog" #: src/fpick.c:705 msgid "Enter the name of the new directory" msgstr "Ange namnet pÃ¥ nya katalogen" #: src/fpick.c:729 #, c-format msgid "Do you really want to delete \"%s\" ?" msgstr "Vill du verkligen ta bort \"%s\"?" #: src/fpick.c:735 msgid "Unable to delete" msgstr "Kunde inte ta bort" #: src/fpick.c:741 msgid "Unable to rename" msgstr "Kunde inte byta namn" #: src/fpick.c:750 msgid "Unable to create directory" msgstr "Kunde inte skapa katalogen" #: src/fpick.c:924 msgid "Up" msgstr "UppÃ¥t" #: src/fpick.c:925 msgid "Home" msgstr "Hem" #: src/fpick.c:926 msgid "Create New Directory" msgstr "Skapa ny katalog" #: src/fpick.c:927 msgid "Show Hidden Files" msgstr "Visa dolda filer" #: src/fpick.c:929 msgid "Case Insensitive Sort" msgstr "Skiftlägesokänslig sortering" #: src/fpick.c:936 msgid "Name" msgstr "Namn" #: src/fpick.c:938 msgid "Type" msgstr "Typ" #: src/fpick.c:939 msgid "Modified" msgstr "Ändrad" #: src/help.c:25 src/prefs.c:160 msgid "General" msgstr "Allmänt" #: src/help.c:26 msgid "Keyboard shortcuts" msgstr "Tangentbordsgenvägar" #: src/help.c:27 msgid "Mouse shortcuts" msgstr "Musgenvägar" #: src/help.c:28 msgid "Credits" msgstr "Tack till" #: src/help.c:32 msgid "mtPaint 3.51 - Copyright (C) 2004-2021 The Authors\n" msgstr "mtPaint 3.51 - Copyright © 2004-2021 Upphovsmännen\n" #: src/help.c:33 msgid "See 'Credits' section for a list of the authors.\n" msgstr "Se \"Tack till\"-avsnittet för en lista över upphovsmännen.\n" #: src/help.c:34 msgid "" "mtPaint 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.\n" msgstr "" "mtPaint är fri programvara. Du kan distribuera det och/eller modifiera det " "under villkoren i GNU General Public License, publicerad av Free Software " "Foundation, antingen version 3 eller (om du sÃ¥ vill) nÃ¥gon senare version.\n" #: src/help.c:35 msgid "" "mtPaint 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.\n" msgstr "" "mtPaint distribueras i hopp om att det ska vara användbart, men UTAN NÃ…GON " "SOM HELST GARANTI, även utan underförstÃ¥dd garanti om SÄLJBARHET eller " "LÄMPLIGHET FÖR NÃ…GOT SPECIELLT ÄNDAMÃ…L. Se GNU General Public License för " "ytterligare information.\n" #: src/help.c:36 msgid "" "mtPaint is a simple GTK+1/2/3 painting program designed for creating icons " "and pixel based artwork. It can edit indexed palette or 24 bit RGB images " "and offers basic painting and palette manipulation tools. It also has " "several other more powerful features such as channels, layers and animation. " "Due to its simplicity and lack of dependencies it runs well on GNU/Linux, " "Windows and older PC hardware.\n" msgstr "" "mtPaint är ett enkelt ritprogram som använder GTK+1/2/3 och är designat för " "att skapa ikoner och bildpunktsbaserad grafik. Det kan redigera indexerade " "paletter eller 24-bitars RGB-bilder och erbjuder grundläggande verktyg för " "att rita och ändra paletter. Det innehÃ¥ller även flera andra kraftfullare " "funktioner som kanaler, lager och animering. PÃ¥ grund av dess enkelhet och " "avsaknad av beroenden sÃ¥ fungerar det bra pÃ¥ GNU/Linux, Windows och äldre PC-" "datorer.\n" #: src/help.c:37 msgid "" "There is full documentation of mtPaint's features contained in a handbook. " "If you don't already have this, you can download it from the mtPaint " "website.\n" msgstr "" "Det finns fullständig dokumentation över mtPaints funktioner i en handbok. " "Om du inte redan har den sÃ¥ kan du hämta den frÃ¥n mtPaints webbplats.\n" #: src/help.c:38 msgid "" "If you like mtPaint and you want to keep up to date with new releases, or " "you want to give some feedback, then the mailing lists may be of interest to " "you:\n" msgstr "" "Om du tycker om mtPaint och vill hÃ¥lla dig uppdaterad med nya utgÃ¥vor, eller " "om du vill ge förslag pÃ¥ ändringar, sÃ¥ kan sändlistorna vara intressanta för " "dig:\n" #: src/help.c:39 msgid "http://sourceforge.net/mail/?group_id=155874" msgstr "http://sourceforge.net/mail/?group_id=155874" #: src/help.c:42 msgid " Ctrl-N Create new image" msgstr " Ctrl-N Skapa ny bild" #: src/help.c:43 msgid " Ctrl-O Open Image" msgstr " Ctrl-O Öppna bild" #: src/help.c:44 msgid " Ctrl-S Save Image" msgstr " Ctrl-S Spara bild" #: src/help.c:45 msgid " Ctrl-Shift-S Save layers file" msgstr "" #: src/help.c:46 msgid " Ctrl-Q Quit program\n" msgstr " Ctrl-Q Avsluta programmet\n" #: src/help.c:47 msgid " Ctrl-A Select whole image" msgstr " Ctrl-A Markera hela bilden" #: src/help.c:48 msgid " Escape Select nothing, cancel paste box" msgstr " Escape Markera ingenting, avbryt inklistringsruta" #: src/help.c:49 msgid " J Lasso selection\n" msgstr "" #: src/help.c:50 msgid " Ctrl-C Copy selection to clipboard" msgstr " Ctrl-C Kopiera markering till urklipp" #: src/help.c:51 msgid "" " Ctrl-X Copy selection to clipboard, and then paint current " "pattern to selection area" msgstr "" " Ctrl-X Kopiera markering till urklipp och rita sedan ut " "aktuellt mönster till markeringsytan" #: src/help.c:52 msgid " Ctrl-V Paste clipboard to centre of current view" msgstr " Ctrl-V Klistra in urklipp till mitten av aktuell vy" #: src/help.c:53 msgid " Ctrl-K Paste clipboard to location it was copied from" msgstr "" " Ctrl-K Klistra in urklipp till platsen den kopierades frÃ¥n" #: src/help.c:54 msgid " Ctrl-Shift-V Paste clipboard to new layer" msgstr "" #: src/help.c:55 msgid " Enter/Return Commit paste to canvas" msgstr " Enter/Return Verkställ inklistring till rityta" #: src/help.c:56 msgid " Shift+Enter/Return Commit paste and swap canvas into the clipboard\n" msgstr "" #: src/help.c:57 msgid " Arrow keys Paint Mode - Move the mouse pointer" msgstr " Piltangenter Ritläge - Flytta muspekaren" #: src/help.c:58 msgid "" " Arrow keys Selection Mode - Nudge selection box or paste box by one " "pixel" msgstr "" " Piltangenter Markeringsläge - Flytta markeringsrutan eller " "inklistringsrutan med en bildpunkt" #: src/help.c:59 msgid "" " Shift+Arrow keys Nudge mouse pointer, selection box or paste box by x " "pixels - x is defined by the Preferences window" msgstr "" " Shift+Piltangenter Knuffa muspekaren, urvalsboxen eller inklistringsboxen " "med x pixlar - x är definierat i Inställningsfönstret" #: src/help.c:60 msgid " Ctrl+Arrows Move layer or resize selection box" msgstr " Ctrl+Piltangenter Flytta lager eller ändra storlek pÃ¥ urvalsboxen" #: src/help.c:61 msgid " Ctrl+Shift+Arrows Move layer or resize selection box by x pixels\n" msgstr "" #: src/help.c:62 msgid " Enter/Return Paint Mode - Simulate left click" msgstr "" #: src/help.c:63 msgid " Backspace Paint Mode - Simulate right click\n" msgstr "" #: src/help.c:64 msgid "" " [ or ] Change colour A to the next or previous palette item" msgstr "" " [ eller ] Ändra färg A till nästa eller föregÃ¥ende färg i paletten" #: src/help.c:65 msgid "" " Shift+[ or ] Change colour B to the next or previous palette item\n" msgstr "" " Shift+[ eller ] Ändra färg A till nästa eller föregÃ¥ende färg i " "paletten\n" #: src/help.c:66 msgid " Delete Crop image to selection" msgstr " Delete Beskär bilden till markeringen" #: src/help.c:67 msgid "" " Insert Transform colours - i.e. Brightness, Contrast, " "Saturation, Posterize, Gamma" msgstr "" #: src/help.c:68 msgid " Ctrl-G Greyscale the image" msgstr " Ctrl-G Ändra bilden till grÃ¥skala" #: src/help.c:69 msgid " Shift-Ctrl-G Greyscale the image (Gamma corrected)" msgstr " Shift-Ctrl-G Ändra bilden till grÃ¥skala (Tillrättad gamma)" #: src/help.c:70 msgid " Ctrl+M Mirror the image" msgstr "" #: src/help.c:71 msgid " Shift-Ctrl-I Invert the image\n" msgstr "" #: src/help.c:72 msgid "" " Ctrl-T Draw a rectangle around the selection area with the " "current fill" msgstr "" " Ctrl-T Rita en rektangel runt det valda omrÃ¥det med vald " "fyllning" #: src/help.c:73 msgid " Ctrl-Shift-T Fill in the selection area with the current fill" msgstr " Ctrl-Shift-T Fyll det valda omrÃ¥det med vald fyllning" #: src/help.c:74 msgid " Ctrl-L Draw an ellipse spanning the selection area" msgstr "" #: src/help.c:75 msgid " Ctrl-Shift-L Draw a filled ellipse spanning the selection area\n" msgstr "" #: src/help.c:76 msgid " Ctrl-E Edit the RGB values for colours A & B" msgstr "" #: src/help.c:77 msgid " Ctrl-W Edit all palette colours\n" msgstr " Ctrl-W Redigera alla palettfärger\n" #: src/help.c:78 msgid " Ctrl-P Preferences" msgstr " Ctrl-P Inställningar" #: src/help.c:79 msgid " Ctrl-I Information\n" msgstr " Ctrl-I Information\n" #: src/help.c:80 msgid " Ctrl-Z Undo last action" msgstr " Ctrl-Z Ã…ngra senaste Ã¥tgärd" #: src/help.c:81 msgid " Ctrl-R Redo an undone action\n" msgstr " Ctrl-R Gör om en Ã¥ngrad Ã¥tgärd\n" #: src/help.c:82 msgid " Shift-T Text Tool (GTK+)" msgstr "" #: src/help.c:83 msgid " T Text Tool (FreeType)\n" msgstr "" #: src/help.c:84 msgid " V View Window" msgstr " V Visningsfönster" #: src/help.c:85 msgid " L Layers Window\n" msgstr " L Lagerfönster\n" #: src/help.c:86 msgid " Ctrl-H Toggle Hide Image mode" msgstr "" #: src/help.c:87 msgid " B Toggle Snap to Tile Grid mode\n" msgstr "" #: src/help.c:88 msgid " X Swap Colours A & B" msgstr "" #: src/help.c:89 msgid " E Choose Colour\n" msgstr "" #: src/help.c:90 msgid "" " A Draw open arrow head when using the line tool (size set " "by flow setting)" msgstr "" " A Rita öppet pilhuvud vid användande av linjeverktyget " "(storlek sätts av flödesinställning)" #: src/help.c:91 msgid "" " S Draw closed arrow head when using the line tool (size " "set by flow setting)\n" msgstr "" " S Rita stängt pilhuvud vid användande av linjeverktyget " "(storlek sätts av flödesinställning)\n" #: src/help.c:92 msgid " D Line Tool" msgstr "" #: src/help.c:93 msgid " F Flood Fill Tool\n" msgstr "" #: src/help.c:94 msgid " +,= Main edit window - Zoom in" msgstr " +,= Huvudredigeringsfönster - Zooma in" #: src/help.c:95 msgid " - Main edit window - Zoom out" msgstr " - Huvudredigeringsfönster - Zooma ut" #: src/help.c:96 msgid " Shift +,= View window - Zoom in" msgstr " Shift +,= Visningsfönster - Zooma in" #: src/help.c:97 msgid " Shift - View window - Zoom out\n" msgstr " Shift - Visningsfönster - Zooma ut\n" #: src/help.c:98 #, c-format msgid " 1 10% zoom" msgstr " 1 10% zoom" #: src/help.c:99 #, c-format msgid " 2 25% zoom" msgstr " 2 25% zoom" #: src/help.c:100 #, c-format msgid " 3 50% zoom" msgstr " 3 50% zoom" #: src/help.c:101 #, c-format msgid " 4 100% zoom" msgstr " 4 100% zoom" #: src/help.c:102 #, c-format msgid " 5 400% zoom" msgstr " 5 400% zoom" #: src/help.c:103 #, c-format msgid " 6 800% zoom" msgstr " 6 800% zoom" #: src/help.c:104 #, c-format msgid " 7 1200% zoom" msgstr " 7 1200% zoom" #: src/help.c:105 #, c-format msgid " 8 1600% zoom" msgstr " 8 1600% zoom" #: src/help.c:106 #, c-format msgid " 9 2000% zoom\n" msgstr " 9 2000% zoom\n" #: src/help.c:107 msgid " Shift + 1 Edit image channel" msgstr " Shift + 1 Redigera bildkanal" #: src/help.c:108 msgid " Shift + 2 Edit alpha channel" msgstr " Shift + 2 Redigera alfakanal" #: src/help.c:109 msgid " Shift + 3 Edit selection channel" msgstr " Shift + 3 Redigera markeringskanal" #: src/help.c:110 msgid " Shift + 4 Edit mask channel\n" msgstr " Shift + 4 Redigera maskkanal\n" #: src/help.c:111 msgid " F1 Help" msgstr " F1 Hjälp" #: src/help.c:112 msgid " F2 Choose Pattern" msgstr " F2 Välj mönster" #: src/help.c:113 msgid " F3 Choose Brush" msgstr " F3 Välj pensel" #: src/help.c:114 msgid " F4 Paint Tool" msgstr " F4 Ritverktyg" #: src/help.c:115 msgid " F5 Toggle Main Toolbar" msgstr " F5 Växla huvudverktygsrad" #: src/help.c:116 msgid " F6 Toggle Tools Toolbar" msgstr " F6 Växla Verktygsrad" #: src/help.c:117 msgid " F7 Toggle Settings Toolbar" msgstr " F7 Växla Inställningsrad" #: src/help.c:118 msgid " F8 Toggle Palette" msgstr " F8 Växla palett" #: src/help.c:119 msgid " F9 Selection Tool" msgstr " F9 Markeringsverktyg" #: src/help.c:120 msgid " F12 Toggle Dock Area\n" msgstr " F12 Växla DockningsomrÃ¥de\n" #: src/help.c:121 msgid " Ctrl + F1 - F12 Save current clipboard to file 1-12" msgstr " Ctrl + F1 - F12 Spara aktuellt urklipp till fil 1-12" #: src/help.c:122 msgid " Shift + F1 - F12 Load clipboard from file 1-12\n" msgstr " Shift + F1 - F12 Läs in urklipp frÃ¥n fil 1-12\n" #: src/help.c:123 msgid "" " Ctrl + 1, 2, ... , 0 Set opacity to 10%, 20%, ... , 100% (main or keypad " "numbers)" msgstr "" " Ctrl + 1, 2, ... , 0 Ställ in opacitet till 10%, 20%, ... , 100% (huvud- " "eller numeriska tangenter)" #: src/help.c:124 msgid " Ctrl + + or = Increase opacity by 1" msgstr " Ctrl + + eller = Öka opacitet med 1" #: src/help.c:125 msgid " Ctrl + - Decrease opacity by 1\n" msgstr " Ctrl + - Minska opacitet med 1\n" #: src/help.c:126 msgid "" " Home Show or hide main window menu/toolbar/status bar/palette" msgstr "" " Home Visa eller dölj huvudfönsrets meny/verktygsrad/statusrad/" "palett" #: src/help.c:127 msgid " Page Up Scale Image" msgstr " Page Up Skala bild" #: src/help.c:128 msgid " Page Down Resize Image canvas" msgstr " Page Down Ändra storlek pÃ¥ bildens rityta" #: src/help.c:129 msgid " End Pan Window" msgstr " End Panorera Fönster" #: src/help.c:132 msgid " Left button Paint to canvas using the current tool" msgstr " Vänster knapp Rita till kanvas med valt verktyg" #: src/help.c:133 msgid "" " Middle button Selects the point which will be the centre of the " "image after the next zoom" msgstr "" " Mittknappen Väljer punkten som kommer att bli bildens center " "efter nästa zoom" #: src/help.c:134 msgid "" " Right button Commit paste to canvas / Stop drawing current line / " "Cancel selection\n" msgstr "" " Höger knapp Utför inklistring till kanvas / Sluta rita linje / " "Avbryt val\n" #: src/help.c:135 msgid "" " Scroll Wheel In GTK+2/3 the user can have the scroll wheel zoom in " "or out via the Preferences window\n" msgstr "" " Skrollhjulet I GITK+2 kan användaren välja att lÃ¥ta scrollhjulet " "zooma in och ut i Inställningsfönstret\n" #: src/help.c:136 msgid " Ctrl+Left button Choose colour A from under mouse pointer" msgstr " Ctrl+Vänster knapp Välj färg A frÃ¥n där muspekaren är" #: src/help.c:137 msgid " Ctrl+Left button Clone tool - Select source" msgstr "" #: src/help.c:138 msgid "" " Ctrl+Middle button Create colour A/B and pattern based on the RGB colour " "in A (RGB images only)" msgstr "" " Ctrl+Mittenknappen Skapa färg A/B och mönster baserat pÃ¥ RGB-färg i A " "(Endast för RGB-bilder)" #: src/help.c:139 msgid " Ctrl+Right button Choose colour B from under mouse pointer" msgstr " Ctrl+Höger knapp Välj färg B frÃ¥n där muspekaren är" #: src/help.c:140 msgid "" " Ctrl+Right button Polygon tool - Delete last point / Delete nearest " "point" msgstr "" #: src/help.c:141 msgid " Ctrl+Scroll Wheel Scroll the main edit window left or right\n" msgstr " Ctrl+Skrollhjul Skorlla huvudfönstret höger eller vänster\n" #: src/help.c:142 msgid "" " Ctrl+Double click Set colour A or B to average colour under brush " "square or selection marquee (RGB only)\n" msgstr "" #: src/help.c:143 msgid "" " Shift+Right button Selects the point which will be the centre of the " "image after the next zoom\n" "\n" msgstr "" " Shift+Höger knapp Väljer den punkt som kommer att vara center av bilden " "efter nästa zoom\n" "\n" #: src/help.c:144 msgid "You can fixate the X/Y co-ordinates while moving the mouse:\n" msgstr "Du kan lÃ¥sa fast X/Y kordinaterna medans du flyttar musen:\n" #: src/help.c:145 msgid " Shift Constrain mouse movements to vertical line" msgstr " Shift Begränsa musrörelser till vertikal linje" #: src/help.c:146 msgid " Shift+Ctrl Constrain mouse movements to horizontal line" msgstr " Shift+Ctrl Begränsa musrörelser till horisontel linje" #: src/help.c:149 msgid "mtPaint is maintained by Dmitry Groshev.\n" msgstr "mtPaint underhÃ¥lls av Dmitry Groshev.\n" #: src/help.c:150 msgid "wjaguar@users.sourceforge.net" msgstr "wjaguar@users.sourceforge.net" #: src/help.c:151 msgid "http://mtpaint.sourceforge.net/\n" msgstr "http://mtpaint.sourceforge.net/\n" #: src/help.c:152 msgid "" "The following people (in alphabetical order) have contributed directly to " "the project, and are therefore worthy of gracious thanks for their " "generosity and hard work:\n" "\n" msgstr "" "Följande personer (i alfabetisk ordning) har bidragit direkt till projektet " "och är därför värda ett stort tack för deras generösitet och hÃ¥rda arbete:\n" "\n" #: src/help.c:153 msgid "Authors\n" msgstr "Upphovsmän\n" #: src/help.c:154 msgid "" "Dmitry Groshev - Contributing developer for version 2.30. Lead developer and " "maintainer from version 3.00 to the present." msgstr "" "Dmitry Groshev - Bidragande utvecklare för version 2.30. Huvudutvecklare och " "ansvarig frÃ¥n version 3.00 till nuvarande." #: src/help.c:155 msgid "" "Mark Tyler - Original author and maintainer up to version 3.00, occasional " "contributor thereafter." msgstr "" "Mark Tyler - Ursprunglig upphovsman och ansvarig upp till version 3.00, " "stundtals bidragsgivare efter det." #: src/help.c:156 msgid "" "Xiaolin Wu - Wrote the Wu quantizing method - see wu.c for more " "information.\n" "\n" msgstr "" "Xiaolin Wu - Skrev Wu-kvantiseringsmetoden - se wu.c för mer information.\n" "\n" #: src/help.c:157 msgid "" "General Contributions (Feedback and Ideas for improvements unless otherwise " "stated)\n" msgstr "" "Allmänna bidrag (Ã¥terkoppling och idéer för förbättringar om inte annat har " "angivits)\n" #: src/help.c:158 msgid "Abdulla Al Muhairi - Website redesign April 2005" msgstr "Abdulla Al Muhairi - Designade om webbplatsen i april 2005" #: src/help.c:159 msgid "Alan Horkan" msgstr "Alan Horkan" #: src/help.c:160 msgid "Alexandre Prokoudine" msgstr "Alexandre Prokoudine" #: src/help.c:161 msgid "Antonio Andrea Bianco" msgstr "Antonio Andrea Bianco" #: src/help.c:162 msgid "Charlie Ledocq" msgstr "" #: src/help.c:163 msgid "Dennis Lee" msgstr "Dennis Lee" #: src/help.c:164 msgid "Donald White" msgstr "" #: src/help.c:165 msgid "Ed Jason" msgstr "Ed Jason" #: src/help.c:166 msgid "" "Eddie Kohler - Created Gifsicle which is needed for the creation and viewing " "of animated GIF files http://www.lcdf.org/gifsicle/" msgstr "" "Eddie Kohler - Skapade Gifsicle som behövs för att skapa och visa animerade " "GIF-filer, http://www.lcdf.org/gifsicle/" #: src/help.c:167 msgid "" "Guadalinex Team (Junta de Andalucia) - man page, Launchpad/Rosetta " "registration" msgstr "" "Guadalinex Team (Junta de Andalucia) - manualsida, Launchpad/Rosetta-" "registrering" #: src/help.c:168 msgid "Lou Afonso" msgstr "Lou Afonso" #: src/help.c:169 msgid "Magnus Hjorth" msgstr "Magnus Hjorth" #: src/help.c:170 msgid "Martin Zelaia" msgstr "Martin Zelaia" #: src/help.c:171 msgid "Pasi Kallinen" msgstr "" #: src/help.c:172 msgid "Pavel Ruzicka" msgstr "Pavel Ruzicka" #: src/help.c:173 msgid "Puppy Linux (Barry Kauler)" msgstr "Puppy Linux (Barry Kauler)" #: src/help.c:174 msgid "Victor Copovi" msgstr "" #: src/help.c:175 msgid "Vlastimil Krejcir" msgstr "Vlastimil Krejcir" #: src/help.c:176 msgid "" "William Kern\n" "\n" msgstr "" "William Kern\n" "\n" #: src/help.c:177 msgid "Translations\n" msgstr "Översättningar\n" #: src/help.c:178 msgid "Brazilian Portuguese - Paulo Trevizan, Valter Nazianzeno" msgstr "Brasilisk portugisiska - Paulo Trevizan, Valter Nazianzeno" #: src/help.c:179 msgid "Czech - Pavel Ruzicka, Martin Petricek, Roman Hornik, Pavel Fric" msgstr "Tjeckiska - Pavel Ruzicka, Martin Petricek, Roman Hornik, Pavel Fric" #: src/help.c:180 msgid "Dutch - Hans Strijards, Pjotr" msgstr "Nederländska - Hans Strijards, Pjotr" #: src/help.c:181 msgid "" "French - Nicolas Velin, Pascal Billard, Sylvain Cresto, Johan Serre, " "Philippe Etienne, Victor Copovi" msgstr "" "Franska - Nicolas Velin, Pascal Billard, Sylvain Cresto, Johan Serre, " "Philippe Etienne, Victor Copovi" #: src/help.c:182 msgid "Galician - Miguel Anxo Bouzada" msgstr "Galiciska - Miguel Anxo Bouzada" #: src/help.c:183 msgid "German - Oliver Frommel, B. Clausius, Ulrich Ringel, Simon Brixel" msgstr "Tyyska - Oliver Frommel, B. Clausius, Ulrich Ringel, Simon Brixel" #: src/help.c:184 msgid "Hungarian - Ur Balazs" msgstr "" #: src/help.c:185 msgid "Italian - Angelo Gemmi" msgstr "Italienska - Angelo Gemmi" #: src/help.c:186 msgid "Japanese - Norihiro YONEDA" msgstr "Japanska - Norihiro YONEDA" #: src/help.c:187 msgid "Kabyle - Yacine Bouklif" msgstr "" #: src/help.c:188 msgid "Polish - Bartosz Kaszubowski, LucaS" msgstr "Polska - Bartosz Kaszubowski, LucaS" #: src/help.c:189 msgid "Portuguese - Israel G. Lugo, Tiago Silva" msgstr "Portugisiska - Israel G. Lugo, Tiago Silva" #: src/help.c:190 msgid "Russian - Sergey Irupin, Dmitry Groshev" msgstr "Ryska - Sergey Irupin, Dmitry Groshev" #: src/help.c:191 msgid "Simplified Chinese - Cecc" msgstr "Förenklad kinesiska - Cecc" #: src/help.c:192 msgid "Slovak - Jozef Riha" msgstr "Slovakiska - Jozef Riha" #: src/help.c:193 msgid "" "Spanish - Guadalinex Team (Junta de Andalucia), Antonio Sanchez Leon, Miguel " "Anxo Bouzada, Francisco Jose Rey, Adolfo Jayme" msgstr "" "Spanska - Guadalinex Team (Junta de Andalucia), Antonio Sanchez Leon, Miguel " "Anxo Bouzada, Francisco Jose Rey, Adolfo Jayme" #: src/help.c:194 msgid "Swedish - Daniel Nylander, Daniel Eriksson" msgstr "Svenska - Daniel Nylander, Daniel Eriksson" #: src/help.c:195 msgid "Tagalog - Anjelo delCarmen" msgstr "" #: src/help.c:196 msgid "Taiwanese Chinese - Wei-Lun Chao" msgstr "Taiwanesisk kinesiska - Wei-Lun Chao" #: src/help.c:197 msgid "Turkish - Muhammet Kara, Tutku Dalmaz" msgstr "Turkiska - Muhammet Kara, Tutku Dalmaz" #: src/info.c:258 msgid "Information" msgstr "Information" #: src/info.c:260 msgid "Memory" msgstr "Minne" #: src/info.c:261 msgid "Total memory for main + undo images" msgstr "Totalt minne för huvud + Ã¥ngra-bilder" #: src/info.c:263 msgid "Undo / Redo / Max levels used" msgstr "Ã…ngra / Ã…terskapa / Max nivÃ¥er använda" #: src/info.c:265 msgid "Unused" msgstr "Oanvänt" #: src/info.c:269 msgid "Unique RGB pixels" msgstr "Unika RGB pixlar" #: src/info.c:272 src/layer.c:121 msgid "Layers" msgstr "Lager" #: src/info.c:273 msgid "Total layer memory usage" msgstr "Totalt använt minne för lager" #: src/info.c:277 msgid "Colour Histogram" msgstr "Färghistogram" #: src/info.c:289 src/otherwindow.c:1614 msgid "Index" msgstr "Index" #: src/info.c:290 msgid "Canvas pixels" msgstr "" #: src/info.c:328 #, c-format msgid "Clipboard = %i x %i" msgstr "Urklipp = %i x %i" #: src/info.c:328 #, c-format msgid "Clipboard = %i x %i x RGB" msgstr "Urklipp = %i x %i x RGB" #: src/info.c:377 msgid "Orphans" msgstr "" #: src/info.c:383 #, c-format msgid "Colour index totals - %i of %i used" msgstr "Färgindexnummer totalbeloppen - %i av %i används" #: src/inifile.c:966 msgid "" "Could not find home directory. Using current directory as home directory." msgstr "" "Kunde inte hitta hemkatalogen. Använder aktuell katalog som hemkatalog." #: src/layer.c:63 msgid "Background" msgstr "Bakgrund" #: src/layer.c:122 src/mainwindow.c:5931 msgid "(Modified)" msgstr "(Ändrad)" #: src/layer.c:123 src/mainwindow.c:5932 msgid "Untitled" msgstr "Namnlös" #: src/layer.c:308 #, c-format msgid "Do you really want to delete layer %i (%s) ?" msgstr "Vill du verkligen ta bort lagret %i (%s) ?" #: src/layer.c:380 msgid "" "One or more of the layers contains changes that have not been saved. Do you " "really want to lose these changes?" msgstr "" "Ett eller flera av lagren innehÃ¥ller ändringar som inte har sparats. Vill du " "verkligen förlora dessa ändringar?" #: src/layer.c:381 src/mainwindow.c:1028 msgid "Cancel Operation" msgstr "Avbryt Ã¥tgärd" #: src/layer.c:381 src/mainwindow.c:1028 msgid "Lose Changes" msgstr "Förlora ändringar" #: src/layer.c:523 #, c-format msgid "%d layers failed to load" msgstr "%d lager gick inte att läsa in" #: src/layer.c:826 msgid "" "One or more of the image layers has not been saved. You must save each " "image individually before saving the layers text file in order to load this " "composite image in the future." msgstr "" "Ett eller flera av bildlagren har inte sparats. Du mÃ¥ste spara varje bild " "individuellt innan du sparar lagrens textfil för att kunna läsa in denna " "kompositbild i framtiden." #: src/layer.c:841 msgid "Do you really want to delete all of the layers?" msgstr "Vill du verkligen ta bort alla lagren?" #: src/layer.c:970 msgid "You cannot add any more layers." msgstr "Du kan inte lägga till fler lager." #: src/layer.c:1083 src/otherwindow.c:241 msgid "New Layer" msgstr "Nytt lager" #: src/layer.c:1085 msgid "Raise" msgstr "Höj" #: src/layer.c:1087 msgid "Lower" msgstr "Sänk" #: src/layer.c:1089 msgid "Duplicate Layer" msgstr "Duplicera lager" #: src/layer.c:1091 msgid "Centralise Layer" msgstr "Centrera lager" #: src/layer.c:1093 msgid "Delete Layer" msgstr "Ta bort lager" #: src/layer.c:1095 msgid "Close Layers Window" msgstr "Stäng lagerfönster" #: src/layer.c:1101 msgid "Layer Name" msgstr "Lagernamn" #: src/layer.c:1104 src/toolbar.c:209 msgid "Position" msgstr "Position" #: src/layer.c:1112 msgid "Transparent Colour" msgstr "Transparent färg" #: src/layer.c:1117 msgid "Show all layers in main window" msgstr "Visa alla lager i huvudfönstret" #: src/mainwindow.c:67 src/otherwindow.c:844 src/otherwindow.c:2756 #: src/toolbar.c:342 msgid "Image" msgstr "Bild" #: src/mainwindow.c:69 src/mainwindow.c:489 src/otherwindow.c:1613 #: src/otherwindow.c:2302 msgid "RGB" msgstr "RGB" #: src/mainwindow.c:69 src/otherwindow.c:1613 src/otherwindow.c:2302 msgid "sRGB" msgstr "" #: src/mainwindow.c:342 msgid "There were no unused colours to remove!" msgstr "Det fanns inga oanvända färger att ta bort!" #: src/mainwindow.c:371 msgid "The palette does not contain 2 colours that have identical RGB values" msgstr "Paletten innehÃ¥ller inte tvÃ¥ färger som har identiska RGB-värden" #: src/mainwindow.c:374 #, c-format msgid "" "The palette contains %i colours that have identical RGB values. Do you " "really want to merge them into one index and realign the canvas?" msgstr "" "Paletten innehÃ¥ller %i färger som har identiska RGB-värden. Vill du " "verkligen sammanfoga dem till ett index och justera om ritytan?" #: src/mainwindow.c:492 msgid "indexed" msgstr "indexerad" #: src/mainwindow.c:498 #, c-format msgid "" "You are trying to save an %s image to an %s file which is not possible. I " "would suggest you save with a PNG extension." msgstr "" "Du försöker att spara en %s-bild till en %s-fil, vilket inte är möjligt. Jag " "föreslÃ¥r att du sparar med en PNG-ändelse." #: src/mainwindow.c:500 #, c-format msgid "" "You are trying to save an %s file with a palette of more than %d colours. " "Either use another format or reduce the palette to %d colours." msgstr "" "Du försöker att spara en %s-fil med en palett med fler än %d färger. Använd " "antingen ett annat format eller minska paletten till %d färger." #: src/mainwindow.c:578 msgid "Unable to load clipboard" msgstr "Kunde inte läsa in urklipp" #: src/mainwindow.c:604 msgid "Unable to save clipboard" msgstr "Kunde inte spara urklipp" #: src/mainwindow.c:775 msgid "Zoom in" msgstr "" #: src/mainwindow.c:777 msgid "Zoom out" msgstr "" #: src/mainwindow.c:779 #, c-format msgid "10% zoom" msgstr "" #: src/mainwindow.c:781 #, c-format msgid "25% zoom" msgstr "" #: src/mainwindow.c:783 #, c-format msgid "50% zoom" msgstr "" #: src/mainwindow.c:785 #, c-format msgid "100% zoom" msgstr "" #: src/mainwindow.c:787 #, c-format msgid "400% zoom" msgstr "" #: src/mainwindow.c:789 #, c-format msgid "600% zoom" msgstr "" #: src/mainwindow.c:791 #, c-format msgid "800% zoom" msgstr "" #: src/mainwindow.c:793 #, c-format msgid "1000% zoom" msgstr "" #: src/mainwindow.c:795 #, c-format msgid "1200% zoom" msgstr "" #: src/mainwindow.c:797 #, c-format msgid "1600% zoom" msgstr "" #: src/mainwindow.c:799 #, c-format msgid "2000% zoom" msgstr "" #: src/mainwindow.c:801 #, c-format msgid "4000% zoom" msgstr "" #: src/mainwindow.c:803 #, c-format msgid "8000% zoom" msgstr "" #: src/mainwindow.c:805 #, c-format msgid "10% opacity" msgstr "" #: src/mainwindow.c:807 #, c-format msgid "20% opacity" msgstr "" #: src/mainwindow.c:809 #, c-format msgid "30% opacity" msgstr "" #: src/mainwindow.c:811 #, c-format msgid "40% opacity" msgstr "" #: src/mainwindow.c:813 #, c-format msgid "50% opacity" msgstr "" #: src/mainwindow.c:815 #, c-format msgid "60% opacity" msgstr "" #: src/mainwindow.c:817 #, c-format msgid "70% opacity" msgstr "" #: src/mainwindow.c:819 #, c-format msgid "80% opacity" msgstr "" #: src/mainwindow.c:821 #, c-format msgid "90% opacity" msgstr "" #: src/mainwindow.c:823 #, c-format msgid "100% opacity" msgstr "" #: src/mainwindow.c:825 msgid "Increase opacity" msgstr "" #: src/mainwindow.c:827 msgid "Decrease opacity" msgstr "" #: src/mainwindow.c:829 msgid "Draw open arrow head" msgstr "" #: src/mainwindow.c:831 msgid "Draw closed arrow head" msgstr "" #: src/mainwindow.c:833 msgid "Previous colour A" msgstr "" #: src/mainwindow.c:835 msgid "Next colour A" msgstr "" #: src/mainwindow.c:837 msgid "Previous colour B" msgstr "" #: src/mainwindow.c:839 msgid "Next colour B" msgstr "" #: src/mainwindow.c:841 msgid "Previous pattern" msgstr "" #: src/mainwindow.c:843 msgid "Next pattern" msgstr "" #: src/mainwindow.c:845 msgid "Larger brush" msgstr "" #: src/mainwindow.c:847 msgid "Smaller brush" msgstr "" #: src/mainwindow.c:849 msgid "View window - Zoom in" msgstr "" #: src/mainwindow.c:851 msgid "View window - Zoom out" msgstr "" #: src/mainwindow.c:1027 msgid "" "This canvas/palette contains changes that have not been saved. Do you " "really want to lose these changes?" msgstr "" "Denna rityta/palett innehÃ¥ller ändringar som inte har sparats. Vill du " "verkligen förlora dessa ändringar?" #: src/mainwindow.c:1094 msgid "Do you really want to quit?" msgstr "Vill du verkligen avsluta?" #: src/mainwindow.c:3754 msgid "Empty string or broken quoting" msgstr "" #: src/mainwindow.c:3755 msgid "Script must begin with a command" msgstr "" #: src/mainwindow.c:3756 msgid "Script nesting limit exceeded" msgstr "" #: src/mainwindow.c:3765 #, c-format msgid "'%s' does not match any item" msgstr "" #: src/mainwindow.c:3767 #, c-format msgid "'%s' matches a non-scriptable item" msgstr "" #: src/mainwindow.c:3769 #, c-format msgid "'%s' matches a disabled item" msgstr "" #: src/mainwindow.c:3788 #, c-format msgid "'%s' value does not fit item" msgstr "" #: src/mainwindow.c:3969 msgid "Script" msgstr "" #: src/mainwindow.c:3982 src/spawn.c:656 src/spawn.c:662 msgid "Action" msgstr "Ã…tgärd" #: src/mainwindow.c:3991 src/spawn.c:666 msgid "Execute" msgstr "Kör" #: src/mainwindow.c:4045 msgid "Unable to load script" msgstr "" #: src/mainwindow.c:5182 msgid "/_File" msgstr "/_Arkiv" #: src/mainwindow.c:5184 msgid "//New" msgstr "//Ny" #: src/mainwindow.c:5186 msgid "//Open ..." msgstr "//Öppna ..." #: src/mainwindow.c:5188 src/mainwindow.c:5669 msgid "//Save" msgstr "//Spara" #: src/mainwindow.c:5190 src/mainwindow.c:5549 src/mainwindow.c:5627 #: src/mainwindow.c:5671 msgid "//Save As ..." msgstr "//Spara som ..." #: src/mainwindow.c:5192 msgid "//Export Undo Images ..." msgstr "//Exportera Ã…ngra-historik ..." #: src/mainwindow.c:5194 msgid "//Export Undo Images (reversed) ..." msgstr "//Exportera Ã…ngra-historik (omvänd) ..." #: src/mainwindow.c:5196 msgid "//Export ASCII Art ..." msgstr "//Exportera ASCII-grafik ..." #: src/mainwindow.c:5198 msgid "//Export Animated GIF ..." msgstr "//Exportera animerad GIF ..." #: src/mainwindow.c:5201 msgid "//Actions" msgstr "//Ã…tgärder" #: src/mainwindow.c:5235 src/mainwindow.c:5488 msgid "///Configure" msgstr "///Konfigurera" #: src/mainwindow.c:5290 msgid "//Quit" msgstr "//Avsluta" #: src/mainwindow.c:5293 msgid "/_Edit" msgstr "/_Redigera" #: src/mainwindow.c:5295 msgid "//Undo" msgstr "//Ã…ngra" #: src/mainwindow.c:5297 msgid "//Redo" msgstr "//Gör om" #: src/mainwindow.c:5300 msgid "//Cut" msgstr "//Klipp ut" #: src/mainwindow.c:5302 msgid "//Copy" msgstr "//Kopiera" #: src/mainwindow.c:5304 msgid "//Copy To Palette" msgstr "//Kopiera till palett" #: src/mainwindow.c:5306 msgid "//Paste To Centre" msgstr "//Klistra in i mitten" #: src/mainwindow.c:5308 msgid "//Paste To New Layer" msgstr "//Klistra in i nytt lager" #: src/mainwindow.c:5310 msgid "//Paste" msgstr "//Klistra in" #: src/mainwindow.c:5312 msgid "//Paste Text" msgstr "//Klistra in text" #: src/mainwindow.c:5318 msgid "//Paste Text (FreeType)" msgstr "//Klistra in text (FreeType)" #: src/mainwindow.c:5321 msgid "//Paste Palette" msgstr "//Klistra in palett" #: src/mainwindow.c:5323 msgid "//Load Clipboard" msgstr "//Läs in urklipp" #: src/mainwindow.c:5350 msgid "//Save Clipboard" msgstr "//Spara urklipp" #: src/mainwindow.c:5377 msgid "//Import Clipboard from System" msgstr "//Importera urklipp frÃ¥n systemet" #: src/mainwindow.c:5378 msgid "//Export Clipboard to System" msgstr "//Exportera urklipp till systemet" #: src/mainwindow.c:5381 msgid "//Choose Pattern ..." msgstr "//Välj mönster ..." #: src/mainwindow.c:5383 msgid "//Choose Brush ..." msgstr "//Välj pensel ..." #: src/mainwindow.c:5385 msgid "//Choose Colour ..." msgstr "" #: src/mainwindow.c:5392 msgid "/_View" msgstr "/_Visa" #: src/mainwindow.c:5394 msgid "//Show Main Toolbar" msgstr "//Visa huvudverktygsrad" #: src/mainwindow.c:5396 msgid "//Show Tools Toolbar" msgstr "//Visa verktygsrad" #: src/mainwindow.c:5399 msgid "//Show Settings Toolbar" msgstr "//Visa inställningsrad" #: src/mainwindow.c:5402 msgid "//Show Dock" msgstr "//Visa docka" #: src/mainwindow.c:5404 msgid "//Show Palette" msgstr "//Visa palett" #: src/mainwindow.c:5406 msgid "//Show Status Bar" msgstr "//Visa statusrad" #: src/mainwindow.c:5409 msgid "//Toggle Image View" msgstr "//Växla bildvy" #: src/mainwindow.c:5413 msgid "//Centralize Image" msgstr "//Centrera bild" #: src/mainwindow.c:5414 msgid "//Show Zoom Grid" msgstr "" #: src/mainwindow.c:5415 msgid "//Snap To Tile Grid" msgstr "" #: src/mainwindow.c:5417 msgid "//Configure Grid ..." msgstr "//Konfigurera rutnät ..." #: src/mainwindow.c:5418 msgid "//Tracing Image ..." msgstr "" #: src/mainwindow.c:5421 msgid "//View Window" msgstr "//Visningsfönster" #: src/mainwindow.c:5423 msgid "//Horizontal Split" msgstr "" #: src/mainwindow.c:5425 msgid "//Focus View Window" msgstr "//Fokusera visningsfönster" #: src/mainwindow.c:5427 msgid "//Pan Window" msgstr "" #: src/mainwindow.c:5430 msgid "//Layers Window" msgstr "//Lagerfönster" #: src/mainwindow.c:5433 msgid "/_Image" msgstr "/_Bild" #: src/mainwindow.c:5436 msgid "//Convert To RGB" msgstr "//Konvertera till RGB" #: src/mainwindow.c:5438 msgid "//Convert To Indexed ..." msgstr "//Konvertera till indexerad ..." #: src/mainwindow.c:5441 msgid "//Scale Canvas ..." msgstr "" #: src/mainwindow.c:5443 msgid "//Resize Canvas ..." msgstr "" #: src/mainwindow.c:5445 msgid "//Crop" msgstr "//Beskär" #: src/mainwindow.c:5448 src/mainwindow.c:5517 msgid "//Flip Vertically" msgstr "//Vänd vertikalt" #: src/mainwindow.c:5449 src/mainwindow.c:5519 msgid "//Flip Horizontally" msgstr "//Vänd horisontellt" #: src/mainwindow.c:5452 src/mainwindow.c:5521 msgid "//Rotate Clockwise" msgstr "//Rotera medsols" #: src/mainwindow.c:5453 src/mainwindow.c:5523 msgid "//Rotate Anti-Clockwise" msgstr "//Rotera motsols" #: src/mainwindow.c:5454 msgid "//Free Rotate ..." msgstr "//Fri rotering ..." #: src/mainwindow.c:5455 msgid "//Skew ..." msgstr "" #: src/mainwindow.c:5458 msgid "//Segment ..." msgstr "" #: src/mainwindow.c:5462 msgid "//Script ..." msgstr "" #: src/mainwindow.c:5464 msgid "//Scripts" msgstr "" #: src/mainwindow.c:5491 msgid "//Information ..." msgstr "" #: src/mainwindow.c:5494 msgid "//Preferences ..." msgstr "//Inställningar ..." #: src/mainwindow.c:5497 msgid "/_Selection" msgstr "/_Markering" #: src/mainwindow.c:5499 msgid "//Select All" msgstr "//Markera allt" #: src/mainwindow.c:5501 msgid "//Select None (Esc)" msgstr "//Markera ingenting (Esc)" #: src/mainwindow.c:5503 msgid "//Lasso Selection" msgstr "//Markera med lasso" #: src/mainwindow.c:5505 msgid "//Lasso Selection Cut" msgstr "" #: src/mainwindow.c:5508 msgid "//Outline Selection" msgstr "//Konturmarkering" #: src/mainwindow.c:5510 msgid "//Fill Selection" msgstr "" #: src/mainwindow.c:5512 msgid "//Outline Ellipse" msgstr "" #: src/mainwindow.c:5514 msgid "//Fill Ellipse" msgstr "" #: src/mainwindow.c:5526 msgid "//Horizontal Ramp" msgstr "" #: src/mainwindow.c:5528 msgid "//Vertical Ramp" msgstr "" #: src/mainwindow.c:5531 msgid "//Alpha Blend A,B" msgstr "" #: src/mainwindow.c:5533 msgid "//Move Alpha to Mask" msgstr "//Flytta alfa till mask" #: src/mainwindow.c:5535 msgid "//Mask Colour A,B" msgstr "" #: src/mainwindow.c:5537 msgid "//Unmask Colour A,B" msgstr "" #: src/mainwindow.c:5539 msgid "//Mask All Colours" msgstr "//Maskera alla färger" #: src/mainwindow.c:5541 msgid "//Clear Mask" msgstr "//Töm mask" #: src/mainwindow.c:5544 msgid "/_Palette" msgstr "/_Palett" #: src/mainwindow.c:5548 src/mainwindow.c:5626 msgid "//Load ..." msgstr "//Läs in ..." #: src/mainwindow.c:5550 msgid "//Load Default" msgstr "//Läs in standard" #: src/mainwindow.c:5552 msgid "//Mask All" msgstr "//Maskera alla" #: src/mainwindow.c:5553 msgid "//Mask None" msgstr "//Maskera inget" #: src/mainwindow.c:5555 msgid "//Swap A & B" msgstr "//Växla A & B" #: src/mainwindow.c:5557 msgid "//Edit Colour A & B ..." msgstr "//Redigera färg A & B ..." #: src/mainwindow.c:5559 msgid "//Dither A" msgstr "" #: src/mainwindow.c:5561 msgid "//Palette Editor ..." msgstr "//Palettredigerare ..." #: src/mainwindow.c:5563 msgid "//Set Palette Size ..." msgstr "//Ställ in palettstorlek ..." #: src/mainwindow.c:5564 msgid "//Merge Duplicate Colours" msgstr "//SlÃ¥ samman dubbletta färger" #: src/mainwindow.c:5566 msgid "//Remove Unused Colours" msgstr "//Ta bort oanvända färger" #: src/mainwindow.c:5569 msgid "//Create Quantized ..." msgstr "//Skapa kvantiserad ..." #: src/mainwindow.c:5572 msgid "//Sort Colours ..." msgstr "//Sortera färger ..." #: src/mainwindow.c:5573 msgid "//Palette Shifter ..." msgstr "//Palettväxlare ..." #: src/mainwindow.c:5574 msgid "//Pick Gradient ..." msgstr "" #: src/mainwindow.c:5576 msgid "/Effe_cts" msgstr "/Effe_kter" #: src/mainwindow.c:5578 msgid "//Transform Colour ..." msgstr "//Transformera färg ..." #: src/mainwindow.c:5580 msgid "//Invert" msgstr "//Invertera" #: src/mainwindow.c:5582 msgid "//Greyscale" msgstr "//GrÃ¥skala" #: src/mainwindow.c:5584 msgid "//Greyscale (Gamma corrected)" msgstr "//GrÃ¥skala (Gamma-korrigerad)" #: src/mainwindow.c:5586 msgid "//Normalize" msgstr "" #: src/mainwindow.c:5587 src/mainwindow.c:5658 msgid "//Threshold ..." msgstr "//Tröskelvärde ..." #: src/mainwindow.c:5588 msgid "//Map ..." msgstr "" #: src/mainwindow.c:5590 msgid "//Isometric Transformation" msgstr "//Isometrisk transformering" #: src/mainwindow.c:5592 msgid "///Left Side Down" msgstr "///Vänster sida ner" #: src/mainwindow.c:5593 msgid "///Right Side Down" msgstr "///Höger sida ner" #: src/mainwindow.c:5594 msgid "///Top Side Right" msgstr "///Övre sidan Ã¥t höger" #: src/mainwindow.c:5595 msgid "///Bottom Side Right" msgstr "///Nedre sidan Ã¥t höger" #: src/mainwindow.c:5598 msgid "//Edge Detect ..." msgstr "" #: src/mainwindow.c:5600 msgid "//Difference of Gaussians ..." msgstr "" #: src/mainwindow.c:5602 msgid "//Sharpen ..." msgstr "//Gör skarp ..." #: src/mainwindow.c:5604 msgid "//Unsharp Mask ..." msgstr "" #: src/mainwindow.c:5606 msgid "//Soften ..." msgstr "" #: src/mainwindow.c:5608 msgid "//Gaussian Blur ..." msgstr "//Gaussisk oskärpa ..." #: src/mainwindow.c:5610 msgid "//Kuwahara-Nagao Blur ..." msgstr "//Kuwahara-Nagao-oskärpa ..." #: src/mainwindow.c:5612 msgid "//Emboss" msgstr "" #: src/mainwindow.c:5614 msgid "//Dilate" msgstr "" #: src/mainwindow.c:5616 msgid "//Erode" msgstr "" #: src/mainwindow.c:5619 msgid "//Solid Noise ..." msgstr "" #: src/mainwindow.c:5620 msgid "//Bacteria ..." msgstr "" #: src/mainwindow.c:5623 msgid "/Cha_nnels" msgstr "/Ka_naler" #: src/mainwindow.c:5625 msgid "//New ..." msgstr "//Ny ..." #: src/mainwindow.c:5628 msgid "//Delete ..." msgstr "//Ta bort ..." #: src/mainwindow.c:5632 msgid "//Edit Image" msgstr "//Redigera bild" #: src/mainwindow.c:5635 msgid "//Edit Alpha" msgstr "//Redigera alfa" #: src/mainwindow.c:5638 msgid "//Edit Selection" msgstr "//Redigera markering" #: src/mainwindow.c:5641 msgid "//Edit Mask" msgstr "//Redigera mask" #: src/mainwindow.c:5645 msgid "//Hide Image" msgstr "//Dölj bild" #: src/mainwindow.c:5648 msgid "//Disable Alpha" msgstr "//Inaktivera alfa" #: src/mainwindow.c:5651 msgid "//Disable Selection" msgstr "//Inaktivera markering" #: src/mainwindow.c:5654 msgid "//Disable Mask" msgstr "//Inaktivera mask" #: src/mainwindow.c:5657 msgid "//Couple RGBA Operations" msgstr "" #: src/mainwindow.c:5659 msgid "//Unassociate Alpha" msgstr "" #: src/mainwindow.c:5663 msgid "//View Alpha as an Overlay" msgstr "" #: src/mainwindow.c:5664 msgid "//Configure Overlays ..." msgstr "" #: src/mainwindow.c:5666 msgid "/_Layers" msgstr "/_Lager" #: src/mainwindow.c:5668 msgid "//New Layer" msgstr "//Nytt lager" #: src/mainwindow.c:5672 msgid "//Save Composite Image ..." msgstr "" #: src/mainwindow.c:5673 msgid "//Composite to New Layer" msgstr "" #: src/mainwindow.c:5674 msgid "//Remove All Layers" msgstr "//Ta bort alla lager" #: src/mainwindow.c:5676 msgid "//Configure Animation ..." msgstr "//Konfigurera animering ..." #: src/mainwindow.c:5677 msgid "//Preview Animation ..." msgstr "//Förhandsvisa animering ..." #: src/mainwindow.c:5678 msgid "//Set Key Frame ..." msgstr "" #: src/mainwindow.c:5679 msgid "//Remove All Key Frames ..." msgstr "" #: src/mainwindow.c:5681 msgid "/More..." msgstr "/Mer..." #: src/mainwindow.c:5683 msgid "/_Help" msgstr "/_Hjälp" #: src/mainwindow.c:5684 msgid "//Documentation" msgstr "//Dokumentation" #: src/mainwindow.c:5686 msgid "//About" msgstr "//Om" #: src/mainwindow.c:5689 msgid "//Keyboard Shortcuts ..." msgstr "" #: src/mainwindow.c:5690 msgid "//Rebind Shortcut Keycodes" msgstr "" #: src/memory.c:2800 msgid "Quantize Pass 1" msgstr "" #: src/memory.c:2854 msgid "Quantize Pass 2" msgstr "" #: src/memory.c:3073 src/memory.c:3458 msgid "Converting to Indexed Palette" msgstr "Konverterar till indexerad palett" #: src/memory.c:5135 src/otherwindow.c:540 msgid "Bacteria Effect" msgstr "Bakterie-effekt" #: src/memory.c:5170 msgid "Rotating" msgstr "Roterar" #: src/memory.c:5511 msgid "Free Rotation" msgstr "Fri rotering" #: src/memory.c:6096 msgid "Scaling Image" msgstr "Skalar bild" #: src/memory.c:7560 msgid "Counting Unique RGB Pixels" msgstr "Räknar unika RGB-bildpunkter" #: src/memory.c:7608 msgid "Applying Effect" msgstr "Tillämpar effekt" #: src/memory.c:8792 msgid "Kuwahara-Nagao Filter" msgstr "Kuwahara-Nagao-filter" #: src/memory.c:10456 src/otherwindow.c:2665 msgid "Skew" msgstr "Gör sned" #: src/memory.c:10630 msgid "Segmentation Pass 1" msgstr "" #: src/memory.c:10757 msgid "Segmentation Pass 2" msgstr "" #: src/memory.c:11019 src/otherwindow.c:3156 msgid "Solid Noise" msgstr "" #: src/mygtk.c:134 src/mygtk.c:163 msgid "Please Wait ..." msgstr "Vänta ..." #: src/mygtk.c:141 msgid "STOP" msgstr "STOP" #: src/mygtk.c:504 msgid "Disabled" msgstr "" #: src/mygtk.c:504 src/toolbar.c:301 msgid "Screen" msgstr "Skärm" #: src/mygtk.c:504 msgid "Window" msgstr "" #: src/mygtk.c:508 msgid "Input" msgstr "" #: src/mygtk.c:512 msgid "Device:" msgstr "" #: src/mygtk.c:514 msgid "Mode:" msgstr "" #: src/mygtk.c:519 msgid "Axes" msgstr "" #: src/mygtk.c:524 msgid "X:" msgstr "" #: src/mygtk.c:525 msgid "Y:" msgstr "" #: src/mygtk.c:526 msgid "Pressure:" msgstr "" #: src/mygtk.c:527 msgid "X tilt:" msgstr "" #: src/mygtk.c:528 msgid "Y tilt:" msgstr "" #: src/mygtk.c:529 msgid "Wheel:" msgstr "" #: src/mygtk.c:579 msgid "none" msgstr "" #: src/otherwindow.c:236 msgid "24 bit RGB" msgstr "24-bitars RGB" #: src/otherwindow.c:236 src/otherwindow.c:3179 msgid "Greyscale" msgstr "GrÃ¥skala" #: src/otherwindow.c:237 msgid "Indexed Palette" msgstr "Indexerad palett" #: src/otherwindow.c:237 msgid "From Clipboard" msgstr "FrÃ¥n urklipp" #: src/otherwindow.c:237 msgid "Grab Screenshot" msgstr "FÃ¥nga skärmbild" #: src/otherwindow.c:242 src/toolbar.c:542 msgid "New Image" msgstr "Ny bild" #: src/otherwindow.c:246 src/otherwindow.c:3164 msgid "Colours" msgstr "Färger" #: src/otherwindow.c:409 msgid "Pattern Chooser" msgstr "Mönsterväljare" #: src/otherwindow.c:497 msgid "Set Palette Size" msgstr "Ange palettstorlek" #: src/otherwindow.c:517 src/otherwindow.c:591 src/otherwindow.c:870 #: src/otherwindow.c:2538 src/otherwindow.c:2776 src/otherwindow.c:2939 #: src/prefs.c:338 src/prefs.c:538 msgid "Apply" msgstr "Verkställ" #: src/otherwindow.c:573 msgid "Luminance" msgstr "Luminans" #: src/otherwindow.c:573 src/otherwindow.c:814 msgid "Brightness" msgstr "Ljusstyrka" #: src/otherwindow.c:574 msgid "Distance to A" msgstr "AvstÃ¥nd till A" #: src/otherwindow.c:575 msgid "Projection to A->B" msgstr "Projektion till A->B" #: src/otherwindow.c:576 msgid "Frequency" msgstr "Frekvens" #: src/otherwindow.c:580 msgid "Sort Palette Colours" msgstr "Sortera palettfärger" #: src/otherwindow.c:582 msgid "Start Index" msgstr "Indexbörjan" #: src/otherwindow.c:583 msgid "End Index" msgstr "Indexslut" #: src/otherwindow.c:589 msgid "Reverse Order" msgstr "Omvänd ordning" #: src/otherwindow.c:805 msgid "Bitwise" msgstr "" #: src/otherwindow.c:805 msgid "Truncated" msgstr "" #: src/otherwindow.c:805 msgid "Rounded" msgstr "" #: src/otherwindow.c:809 src/toolbar.c:311 src/toolbar.c:558 msgid "Transform Colour" msgstr "Transformera färg" #: src/otherwindow.c:812 msgid "Gamma" msgstr "Gamma" #: src/otherwindow.c:816 msgid "Contrast" msgstr "Kontrast" #: src/otherwindow.c:822 src/otherwindow.c:1674 msgid "Posterize" msgstr "Posterisera" #: src/otherwindow.c:831 msgid "Show Detail" msgstr "Visa detalj" #: src/otherwindow.c:836 msgid "Posterize type" msgstr "" #: src/otherwindow.c:857 msgid "Auto-Preview" msgstr "Auto-förhandsvisning" #: src/otherwindow.c:869 msgid "Reset" msgstr "Ã…terställ" #: src/otherwindow.c:931 msgid "New geometry is the same as now - nothing to do." msgstr "Ny geometri är samma som nu - ingenting att göra." #: src/otherwindow.c:980 msgid "The operating system cannot allocate the memory for this operation." msgstr "Operativsystemet kan inte allokera minne för denna Ã¥tgärd." #: src/otherwindow.c:982 msgid "" "You have not allocated enough memory in the Preferences window for this " "operation." msgstr "" "Du har inte allokerat tillräckligt mycket minne i inställningsfönstret för " "denna Ã¥tgärd." #: src/otherwindow.c:993 src/otherwindow.c:2495 msgid "Mirror" msgstr "Spegla" #: src/otherwindow.c:993 src/otherwindow.c:994 msgid "Tile" msgstr "Ruta" #: src/otherwindow.c:993 msgid "Void" msgstr "" #: src/otherwindow.c:994 src/shifter.c:283 msgid "Clear" msgstr "Töm" #: src/otherwindow.c:994 msgid "Mirror tile" msgstr "Spegla Ruta" #: src/otherwindow.c:996 msgid "Nearest Neighbour" msgstr "Närmsta granne" #: src/otherwindow.c:997 msgid "Bilinear / Area Mapping" msgstr "Bilinjär / OmrÃ¥desmappning" #: src/otherwindow.c:998 msgid "Bicubic" msgstr "Bikubisk" #: src/otherwindow.c:999 msgid "Bicubic edged" msgstr "Bikubisk kantad" #: src/otherwindow.c:1000 msgid "Bicubic better" msgstr "Bättre Bikubisk" #: src/otherwindow.c:1001 msgid "Bicubic sharper" msgstr "Skarpare Bikubisk" #: src/otherwindow.c:1002 msgid "Blackman-Harris" msgstr "Blackman-Harris" #: src/otherwindow.c:1008 msgid "Scale Canvas" msgstr "Skala rityta" #: src/otherwindow.c:1009 msgid "Resize Canvas" msgstr "Ändra storlek pÃ¥ rityta" #: src/otherwindow.c:1012 msgid "Original " msgstr "" #: src/otherwindow.c:1013 msgid "New" msgstr "Ny" #: src/otherwindow.c:1014 msgid "Width " msgstr "Bredd " #: src/otherwindow.c:1018 msgid "Height " msgstr "Höjd " #: src/otherwindow.c:1023 src/otherwindow.c:2514 src/otherwindow.c:2672 #: src/toolbar.c:212 msgid "Offset" msgstr "" #: src/otherwindow.c:1026 src/otherwindow.c:1615 src/viewer.c:1209 msgid "Centre" msgstr "Center" #: src/otherwindow.c:1033 src/otherwindow.c:1052 msgid "Fix Aspect Ratio" msgstr "Fixa Bildformat" #: src/otherwindow.c:1039 src/otherwindow.c:2070 src/toolbar.c:312 msgid "Settings" msgstr "Inställningar" #: src/otherwindow.c:1046 msgid "Sharper image reduction" msgstr "Skarpare bildreduktion" #: src/otherwindow.c:1047 msgid "Boundary extension" msgstr "" #: src/otherwindow.c:1613 src/otherwindow.c:2302 msgid "HSV" msgstr "NMI" #: src/otherwindow.c:1614 msgid "Highlight" msgstr "" #: src/otherwindow.c:1615 msgid "Limit" msgstr "Gräns" #: src/otherwindow.c:1616 msgid "Sphere" msgstr "Sfär" #: src/otherwindow.c:1616 src/otherwindow.c:2670 msgid "Angle" msgstr "Vinkel" #: src/otherwindow.c:1616 msgid "Cube" msgstr "Kub" #: src/otherwindow.c:1617 msgid "Opaque" msgstr "Opak" #: src/otherwindow.c:1617 msgid "Border" msgstr "Ram" #: src/otherwindow.c:1618 msgid "Transparent" msgstr "Genomskinlig" #: src/otherwindow.c:1618 msgid "Tile " msgstr "Ruta " #: src/otherwindow.c:1618 msgid "Segment" msgstr "" #: src/otherwindow.c:1656 msgid "Scale" msgstr "Skala" #: src/otherwindow.c:1657 src/otherwindow.c:3059 msgid "From" msgstr "FrÃ¥n" #: src/otherwindow.c:1659 src/otherwindow.c:3061 msgid "To" msgstr "Till" #: src/otherwindow.c:1699 msgid "Range" msgstr "Intervall" #: src/otherwindow.c:1702 msgid "Inverse" msgstr "Invertera" #: src/otherwindow.c:1710 msgid "Smart grid" msgstr "Smart rutnät" #: src/otherwindow.c:1712 msgid "Tile grid" msgstr "Rutnät" #: src/otherwindow.c:1714 msgid "Minimum grid zoom" msgstr "Minimal rutnätszoom" #: src/otherwindow.c:1717 msgid "Tile width" msgstr "Bredd pÃ¥ ruta" #: src/otherwindow.c:1720 msgid "Tile height" msgstr "Höjd pÃ¥ ruta" #: src/otherwindow.c:1744 msgid "Palette Editor" msgstr "Palettredigerare" #: src/otherwindow.c:1763 msgid "Configure Overlays" msgstr "Konfigurera Överdrag" #: src/otherwindow.c:1782 msgid "Colour Editor" msgstr "Färgredigerare" #: src/otherwindow.c:1818 src/toolbar.c:430 msgid "Colour-Selective Mode" msgstr "Färg-Selektivt Läge" #: src/otherwindow.c:1843 msgid "Configure Grid" msgstr "Konfigurera rutnät" #: src/otherwindow.c:2045 msgid "Exact Conversion" msgstr "Exakt konvertering" #: src/otherwindow.c:2045 msgid "Use Current Palette" msgstr "Använd aktuell palett" #: src/otherwindow.c:2046 msgid "PNN Quantize (slow, better quality)" msgstr "PNN-kvantisering (lÃ¥ngsam, bättre kvalitet)" #: src/otherwindow.c:2047 msgid "Wu Quantize (fast)" msgstr "Wu-kvantisering (snabb)" #: src/otherwindow.c:2048 msgid "Max-Min Quantize (best for small palettes and dithering)" msgstr "Max-Min-kvantisering (bäst för mindre paletter och dithering)" #: src/otherwindow.c:2049 src/otherwindow.c:2495 src/otherwindow.c:2756 #: src/png.c:2794 src/prefs.c:377 msgid "None" msgstr "Ingen" #: src/otherwindow.c:2049 msgid "Floyd-Steinberg" msgstr "Floyd-Steinberg" #: src/otherwindow.c:2049 msgid "Stucki" msgstr "Stucki" #: src/otherwindow.c:2052 msgid "Floyd-Steinberg (quick)" msgstr "Floyd-Steinberg (snabb)" #: src/otherwindow.c:2052 msgid "Dithered (effect)" msgstr "Dithered (effekt)" #: src/otherwindow.c:2053 msgid "Scattered (effect)" msgstr "Skingra (effekt)" #: src/otherwindow.c:2054 msgid "Gamut" msgstr "Gamut" #: src/otherwindow.c:2054 msgid "Weakly" msgstr "Svagt" #: src/otherwindow.c:2054 msgid "Strongly" msgstr "Starkt" #: src/otherwindow.c:2055 msgid "Off" msgstr "Av" #: src/otherwindow.c:2055 msgid "Separate/Sum" msgstr "Separera/Summa" #: src/otherwindow.c:2055 msgid "Separate/Split" msgstr "Separera/Dela" #: src/otherwindow.c:2056 msgid "Length/Sum" msgstr "Längd/Summa" #: src/otherwindow.c:2056 msgid "Length/Split" msgstr "Längd/Dela" #: src/otherwindow.c:2057 msgid "Largest (Linf)" msgstr "Största (Linf)" #: src/otherwindow.c:2057 msgid "Sum (L1)" msgstr "Summa (L1)" #: src/otherwindow.c:2057 msgid "Euclidean (L2)" msgstr "Euklidisk (L2)" #: src/otherwindow.c:2061 msgid "Create Quantized" msgstr "" #: src/otherwindow.c:2062 msgid "Convert To Indexed" msgstr "Konvertera till indexerad" #: src/otherwindow.c:2065 msgid "Indexed Colours To Use" msgstr "Indexerade färger att använda" #: src/otherwindow.c:2078 msgid "Truncate palette" msgstr "Skär av pallett" #: src/otherwindow.c:2079 msgid "Diameter based weighting" msgstr "Diameterbaserad viktning" #: src/otherwindow.c:2084 msgid "Dither" msgstr "Dither" #: src/otherwindow.c:2087 src/otherwindow.c:2584 src/otherwindow.c:2928 msgid "Colour space" msgstr "Färgrymd" #: src/otherwindow.c:2088 src/otherwindow.c:2929 msgid "Difference measure" msgstr "" #: src/otherwindow.c:2089 msgid "Reduce colour bleed" msgstr "Reducera blödning av färg" #: src/otherwindow.c:2090 msgid "Serpentine scan" msgstr "" #: src/otherwindow.c:2092 msgid "Error propagation, %" msgstr "Felaktig spridning, %" #: src/otherwindow.c:2093 msgid "Selective error propagation" msgstr "Selektiv felaktig spridning" #: src/otherwindow.c:2097 msgid "Full error precision" msgstr "Full felprecision" #: src/otherwindow.c:2302 msgid "Backward HSV" msgstr "" #: src/otherwindow.c:2303 src/otherwindow.c:2326 msgid "Constant" msgstr "Konstant" #: src/otherwindow.c:2307 msgid "Edit Gradient" msgstr "Redigera gradient" #: src/otherwindow.c:2329 msgid "Points:" msgstr "Punkter:" #: src/otherwindow.c:2493 msgid "Linear" msgstr "Linjär" #: src/otherwindow.c:2493 src/otherwindow.c:2703 msgid "Bilinear" msgstr "Bilinjär" #: src/otherwindow.c:2493 msgid "Radial" msgstr "Radiell" #: src/otherwindow.c:2494 msgid "Square" msgstr "Fyrkantig" #: src/otherwindow.c:2494 msgid "Angular" msgstr "Vinkelformad" #: src/otherwindow.c:2494 msgid "Conical" msgstr "Konisk" #: src/otherwindow.c:2495 msgid "Level " msgstr "" #: src/otherwindow.c:2495 msgid "Repeat" msgstr "Upprepa" #: src/otherwindow.c:2496 msgid "A to B" msgstr "A till B" #: src/otherwindow.c:2496 msgid "A to B (RGB)" msgstr "A till B (RGB)" #: src/otherwindow.c:2497 msgid "A to B (sRGB)" msgstr "" #: src/otherwindow.c:2497 msgid "A to B (HSV)" msgstr "A till B (NMI)" #: src/otherwindow.c:2497 msgid "A to B (backward HSV)" msgstr "A till B (omvänd NMI)" #: src/otherwindow.c:2498 msgid "A only" msgstr "Endast A" #: src/otherwindow.c:2498 src/otherwindow.c:2500 msgid "Custom" msgstr "Anpassad" #: src/otherwindow.c:2499 msgid "Current to 0" msgstr "Aktuell till 0" #: src/otherwindow.c:2499 msgid "Current only" msgstr "Endast aktuell" #: src/otherwindow.c:2504 msgid "Configure Gradient" msgstr "Konfigurera gradient" #: src/otherwindow.c:2507 src/png.c:1001 msgid "Channel" msgstr "Kanal" #: src/otherwindow.c:2512 msgid "Length" msgstr "Längd" #: src/otherwindow.c:2513 msgid "Repeat length" msgstr "Repetera längd" #: src/otherwindow.c:2515 msgid "Gradient type" msgstr "Gradienttyp" #: src/otherwindow.c:2516 msgid "Extension type" msgstr "" #: src/otherwindow.c:2517 msgid "Distance type" msgstr "" #: src/otherwindow.c:2518 msgid "Preview opacity" msgstr "Förhandsvisa opacitet" #: src/otherwindow.c:2527 src/otherwindow.c:2533 src/toolbar.c:309 msgid "Reverse" msgstr "Omvänd" #: src/otherwindow.c:2528 src/otherwindow.c:2534 msgid "Edit Custom" msgstr "Redigera anpassad" #: src/otherwindow.c:2592 msgid "Pick Gradient" msgstr "" #: src/otherwindow.c:2668 msgid "Horizontal " msgstr "Horisontell " #: src/otherwindow.c:2674 msgid "At distance" msgstr "Vid avstÃ¥nd" #: src/otherwindow.c:2675 msgid "Vertical" msgstr "Vertikal" #: src/otherwindow.c:2756 msgid "Unchanged" msgstr "Oförändrad" #: src/otherwindow.c:2761 msgid "Tracing Image" msgstr "Skissa Bild" #: src/otherwindow.c:2763 src/toolbar.c:315 msgid "Source" msgstr "Källa" #: src/otherwindow.c:2768 msgid "Origin" msgstr "Ursprung" #: src/otherwindow.c:2771 msgid "Relative scale" msgstr "Relativ skala" #: src/otherwindow.c:2774 msgid "Display" msgstr "Bildskärm" #: src/otherwindow.c:2926 msgid "Segment Image" msgstr "" #: src/otherwindow.c:2931 src/toolbar.c:304 msgid "Threshold" msgstr "" #: src/otherwindow.c:2933 msgid "Level" msgstr "NivÃ¥" #: src/otherwindow.c:2934 msgid "Minimum size" msgstr "" #: src/otherwindow.c:3053 msgid "Max" msgstr "" #: src/otherwindow.c:3053 msgid "Min" msgstr "" #: src/otherwindow.c:3057 msgid "Threshold Image" msgstr "" #: src/otherwindow.c:3158 msgid "Seed" msgstr "" #: src/otherwindow.c:3160 msgid "X span" msgstr "" #: src/otherwindow.c:3161 msgid "Y span" msgstr "" #: src/otherwindow.c:3162 msgid "Octaves" msgstr "" #: src/png.c:620 #, c-format msgid "Saving %s image" msgstr "Sparar %s-bild" #: src/png.c:620 #, c-format msgid "Loading %s image" msgstr "Läser in %s-bild" #: src/png.c:998 msgid "Layer" msgstr "Lager" #: src/png.c:3577 msgid "Lossless" msgstr "" #: src/png.c:3577 msgid "Default" msgstr "" #: src/png.c:3577 msgid "Picture" msgstr "" #: src/png.c:3577 msgid "Photo" msgstr "" #: src/png.c:3578 msgid "Drawing" msgstr "" #: src/png.c:3578 msgid "Icon" msgstr "" #: src/png.c:8370 msgid "Applying colour profile" msgstr "" #: src/png.c:8792 #, c-format msgid "%d out of %d frames could not be saved as %s - saved as PNG instead" msgstr "" "%d ut av %d bildrutor kunde inte sparas som %s - sparades som PNG istället" #: src/png.c:8809 msgid "Explode frames" msgstr "" #: src/prefs.c:56 msgid "Default System Language" msgstr "StandardsprÃ¥k i systemet" #: src/prefs.c:57 msgid "Chinese (Simplified)" msgstr "Kinesiska (förenklad)" #: src/prefs.c:57 msgid "Chinese (Taiwanese)" msgstr "Kinesiska (Taiwan)" #: src/prefs.c:57 msgid "Czech" msgstr "Tjeckiska" #: src/prefs.c:58 msgid "Dutch" msgstr "Nederländska" #: src/prefs.c:58 msgid "English (UK)" msgstr "Engelska (UK)" #: src/prefs.c:58 msgid "French" msgstr "Franska" #: src/prefs.c:58 msgid "Galician" msgstr "Galiciska" #: src/prefs.c:58 msgid "German" msgstr "Tyska" #: src/prefs.c:59 msgid "Hungarian" msgstr "" #: src/prefs.c:59 msgid "Italian" msgstr "Italienska" #: src/prefs.c:59 msgid "Japanese" msgstr "Japanska" #: src/prefs.c:59 msgid "Kabyle" msgstr "" #: src/prefs.c:59 msgid "Polish" msgstr "Polska" #: src/prefs.c:60 msgid "Portuguese" msgstr "Portugisiska" #: src/prefs.c:60 msgid "Portuguese (Brazilian)" msgstr "Portugisiska (brasiliansk)" #: src/prefs.c:60 msgid "Russian" msgstr "Ryska" #: src/prefs.c:60 msgid "Slovak" msgstr "Slovakiska" #: src/prefs.c:61 msgid "Spanish" msgstr "Spanska" #: src/prefs.c:61 msgid "Swedish" msgstr "Svenska" #: src/prefs.c:61 msgid "Tagalog" msgstr "" #: src/prefs.c:61 msgid "Turkish" msgstr "Turkiska" #: src/prefs.c:81 msgid "Current Device" msgstr "Aktuell enhet" #: src/prefs.c:135 msgid "Pressure" msgstr "Tryck" #: src/prefs.c:149 msgid "Preferences" msgstr "Inställningar" #: src/prefs.c:163 msgid "Max threads (0 to autodetect)" msgstr "" #: src/prefs.c:164 msgid "Min kpixels per render thread" msgstr "" #: src/prefs.c:171 msgid "Max memory used for undo (MB)" msgstr "Max mängd minne för Ã¥ngra (MB)" #: src/prefs.c:172 msgid "Max undo levels" msgstr "Max Ã¥ngra-nivÃ¥er" #: src/prefs.c:173 msgid "Communal layer undo space (%)" msgstr "" #: src/prefs.c:175 msgid "Bayer master pattern" msgstr "" #: src/prefs.c:178 msgid "Use gamma correction by default" msgstr "Använd gammakorrigering som standard" #: src/prefs.c:179 msgid "Use gamma correction when painting" msgstr "" #: src/prefs.c:180 msgid "Separate patterns for A & B" msgstr "" #: src/prefs.c:183 msgid "Optimize alpha chequers" msgstr "" #: src/prefs.c:184 msgid "Disable view window transparencies" msgstr "Stäng av visningsfönstrets genomskinlighet" #: src/prefs.c:185 msgid "Enable overlays by layer" msgstr "" #: src/prefs.c:189 msgid "Language" msgstr "SprÃ¥k" #: src/prefs.c:191 msgid "" "Select preferred language translation\n" "\n" "You will need to restart mtPaint\n" "for this to take full effect" msgstr "" "Välj föredragen sprÃ¥köversättning\n" "\n" "Du kommer att behöver starta om\n" "mtPaint för att aktivera nytt sprÃ¥k" #: src/prefs.c:198 msgid "Interface" msgstr "Gränssnitt" #: src/prefs.c:200 msgid "Greyscale backdrop" msgstr "GrÃ¥skala bakgrund" #: src/prefs.c:201 msgid "Selection nudge pixels" msgstr "Knuffa pixlar i urval" #: src/prefs.c:202 msgid "Max Pan Window Size" msgstr "Max storlek för panoreringsfönstret" #: src/prefs.c:204 msgid "Display clipboard while pasting" msgstr "Visa urklipp vid inklistring" #: src/prefs.c:205 msgid "Mouse cursor = Tool" msgstr "Muspekare = Verktyg" #: src/prefs.c:206 msgid "Confirm Exit" msgstr "Bekräfta avslut" #: src/prefs.c:207 msgid "Q key quits mtPaint" msgstr "Q knappen avslutar mtPaint" #: src/prefs.c:208 msgid "Arrow keys scroll canvas" msgstr "" #: src/prefs.c:209 msgid "Changing tool commits paste" msgstr "Byta verktyg verkställer inklistring" #: src/prefs.c:210 msgid "Centre tool settings dialogs" msgstr "Centrera verktygsinställningsrutan" #: src/prefs.c:211 msgid "New image sets zoom to 100%" msgstr "Ny bild sätter zoom till 100%" #: src/prefs.c:212 msgid "Zoom on cursor position" msgstr "" #: src/prefs.c:214 msgid "Mouse Scroll Wheel = Zoom" msgstr "Musens Skrollhjul = Zoom" #: src/prefs.c:215 msgid "Use menu icons" msgstr "Använd menyikoner" #: src/prefs.c:220 msgid "Files" msgstr "Filer" #: src/prefs.c:223 msgid "XBM X hotspot" msgstr "" #: src/prefs.c:224 msgid "XBM Y hotspot" msgstr "" #: src/prefs.c:228 msgid "Recently Used Files" msgstr "Tidigare använda filer" #: src/prefs.c:229 msgid "Progress bar silence limit" msgstr "" #: src/prefs.c:232 msgid "Read 16-bit TGAs as 5:6:5 BGR" msgstr "Läs 16-bits TGA:er som 5:6:5 BGR" #: src/prefs.c:233 msgid "Write TGAs in bottom-up row order" msgstr "Skriv TGA:er rad för rad nedifrÃ¥n och upp" #: src/prefs.c:234 msgid "Undoable image loading" msgstr "" #: src/prefs.c:245 msgid "Compression (RGB)" msgstr "" #: src/prefs.c:246 msgid "Compression (indexed)" msgstr "" #: src/prefs.c:247 msgid "Compression (monochrome)" msgstr "" #: src/prefs.c:255 msgid "Enable predictor" msgstr "" #: src/prefs.c:262 msgid "Compression mode" msgstr "" #: src/prefs.c:271 msgid "Channel for Mask Plane" msgstr "" #: src/prefs.c:273 msgid "Ignore Transparent Colour" msgstr "" #: src/prefs.c:274 msgid "PackBits Compression" msgstr "" #: src/prefs.c:275 msgid "Write Indexed as Planar Bitmap (PBM)" msgstr "" #: src/prefs.c:280 msgid "Paths" msgstr "Sökvägar" #: src/prefs.c:281 msgid "Clipboard Files" msgstr "Urklippsfiler" #: src/prefs.c:281 msgid "Select Clipboard File" msgstr "Välj urklippsfil" #: src/prefs.c:283 msgid "HTML Browser Program" msgstr "HTML Läsarprogram" #: src/prefs.c:283 msgid "Select Browser Program" msgstr "Välj webbläsarprogram" #: src/prefs.c:285 msgid "Location of Handbook index" msgstr "Plats för Handbokens index" #: src/prefs.c:285 msgid "Select Handbook Index File" msgstr "Välj Hanbokens indexfil" #: src/prefs.c:287 msgid "Default Palette" msgstr "Standardpalett" #: src/prefs.c:287 msgid "Select Default Palette" msgstr "Välj standardpalett" #: src/prefs.c:289 msgid "Default Patterns" msgstr "Standardmönster" #: src/prefs.c:289 msgid "Select Default Patterns File" msgstr "Välj standardmönsterfil" #: src/prefs.c:292 msgid "Default CSS" msgstr "" #: src/prefs.c:292 msgid "Select Default CSS File" msgstr "" #: src/prefs.c:295 msgid "Default Theme" msgstr "" #: src/prefs.c:295 msgid "Select Default Theme File" msgstr "" #: src/prefs.c:300 msgid "Status Bar" msgstr "Statusrad" #: src/prefs.c:301 msgid "Canvas Geometry" msgstr "Geometri för ram" #: src/prefs.c:302 msgid "Cursor X,Y" msgstr "Pekare X,Y" #: src/prefs.c:303 msgid "Pixel [I] {RGB}" msgstr "" #: src/prefs.c:304 msgid "Selection Geometry" msgstr "Geometri för urval" #: src/prefs.c:305 msgid "Undo / Redo" msgstr "Ã…ngra / Gör om" #: src/prefs.c:308 msgid "Tablet" msgstr "Ritbord" #: src/prefs.c:309 msgid "Device Settings" msgstr "Enhetsinställningar" #: src/prefs.c:313 msgid "Configure Device" msgstr "Konfigurera enhet" #: src/prefs.c:319 msgid "Tool Variable" msgstr "Verktygsvariabel" #: src/prefs.c:322 src/toolbar.c:454 msgid "Flow" msgstr "Flöde" #: src/prefs.c:330 msgid "Test Area" msgstr "TestomrÃ¥de" #: src/prefs.c:373 msgid "Factor" msgstr "Faktor" #: src/prefs.c:459 msgid "This key is builtin" msgstr "" #: src/prefs.c:462 #, c-format msgid "" "This key is mapped to:\n" "\"%s\"" msgstr "" #: src/prefs.c:465 msgid "Remap" msgstr "" #: src/prefs.c:510 msgid "Keyboard Shortcuts" msgstr "" #: src/shifter.c:147 msgid "Frames" msgstr "Bildrutor" #: src/shifter.c:258 msgid "Palette Shifter" msgstr "Palettväxlare" #: src/shifter.c:263 msgid "Start" msgstr "Start" #: src/shifter.c:265 msgid "Finish" msgstr "Slut" #: src/shifter.c:284 msgid "Fix Palette" msgstr "Rätta till palett" #: src/spawn.c:651 msgid "Configure File Actions" msgstr "Konfigurera filÃ¥tgärder" #: src/spawn.c:657 src/spawn.c:663 msgid "Command" msgstr "Kommando" #: src/spawn.c:922 #, c-format msgid "Error %i reported when trying to run %s" msgstr "Fel %i rapporterat vid försök att köra %s" #: src/spawn.c:979 msgid "" "I am unable to find the documentation. Either you need to download the " "mtPaint Handbook from the web site and install it, or you need to set the " "correct location in the Preferences window." msgstr "" "Jag kunde inte hitta dokumentationen. Antingen sÃ¥ behöver du ladda ner " "mtPaint Handboken frÃ¥n hemsidan och installera den, eller sÃ¥ behöver du " "sätta den korrekta platsen i Inställningsfönstret." #: src/spawn.c:1018 msgid "" "There was a problem running the HTML browser. You need to set the correct " "program name in the Preferences window." msgstr "" "Det uppstod ett problem med att köra HTML-läsaren. Du behöver sätta korrekt " "programnamn i Inställningsfönstret." #: src/thread.c:361 msgid "Helper thread is not responding. Save your work and exit the program." msgstr "" #: src/toolbar.c:147 msgid "RGB Cube" msgstr "RGB Kub" #: src/toolbar.c:148 msgid "By image channel" msgstr "Av bildkanal" #: src/toolbar.c:149 msgid "Gradient-driven" msgstr "" #: src/toolbar.c:157 msgid "Fill settings" msgstr "Inställningar för fylla" #: src/toolbar.c:170 msgid "Respect opacity mode" msgstr "" #: src/toolbar.c:176 msgid "Smudge settings" msgstr "Inställningar för smeta" #: src/toolbar.c:215 msgid "Aligned" msgstr "" #: src/toolbar.c:222 msgid "Clone settings" msgstr "" #: src/toolbar.c:228 msgid "By selection channel" msgstr "" #: src/toolbar.c:234 msgid "Lasso settings" msgstr "" #: src/toolbar.c:252 msgid "Brush spacing" msgstr "" #: src/toolbar.c:299 src/toolbar.c:341 msgid "Normal" msgstr "" #: src/toolbar.c:300 msgid "Colour" msgstr "Färg" #: src/toolbar.c:300 msgid "Saturate More" msgstr "" #: src/toolbar.c:301 msgid "Multiply" msgstr "Multiplicera" #: src/toolbar.c:301 msgid "Divide" msgstr "Dividera" #: src/toolbar.c:301 msgid "Dodge" msgstr "Undvik" #: src/toolbar.c:302 msgid "Burn" msgstr "Bränn" #: src/toolbar.c:302 msgid "Hard Light" msgstr "HÃ¥rt ljus" #: src/toolbar.c:302 msgid "Soft Light" msgstr "Mjukt ljus" #: src/toolbar.c:302 msgid "Difference" msgstr "Skillnad" #: src/toolbar.c:303 msgid "Darken" msgstr "Mörkare" #: src/toolbar.c:303 msgid "Lighten" msgstr "Ljusare" #: src/toolbar.c:303 msgid "Grain Extract" msgstr "Grynextrahering" #: src/toolbar.c:304 msgid "Grain Merge" msgstr "Kornsammanfogning" #: src/toolbar.c:330 msgid "Blend mode" msgstr "Intoningsläge" #: src/toolbar.c:417 msgid "Continuous Mode" msgstr "Kontinuerligt Läge" #: src/toolbar.c:421 msgid "Opacity Mode" msgstr "Opacitetsläge" #: src/toolbar.c:424 msgid "Tint Mode" msgstr "Toningsläge" #: src/toolbar.c:427 msgid "Tint +-" msgstr "Tona +-" #: src/toolbar.c:434 msgid "Blend Mode" msgstr "Blandningsläge" #: src/toolbar.c:438 msgid "Disable All Masks" msgstr "Inaktivera alla masker" #: src/toolbar.c:441 msgid "Gradient Mode" msgstr "Gradientläge" #: src/toolbar.c:486 msgid "Settings Toolbar" msgstr "Inställningsverktygsrad" #: src/toolbar.c:546 msgid "Cut" msgstr "Klipp ut" #: src/toolbar.c:548 msgid "Copy" msgstr "Kopiera" #: src/toolbar.c:550 msgid "Paste" msgstr "Klistra in" #: src/toolbar.c:553 msgid "Undo" msgstr "Ã…ngra" #: src/toolbar.c:555 msgid "Redo" msgstr "Gör om" #: src/toolbar.c:559 src/viewer.c:328 msgid "Pan Window" msgstr "Panorera Fönster" #: src/toolbar.c:560 src/toolbar.c:640 msgid "More..." msgstr "" #: src/toolbar.c:574 msgid "Paint" msgstr "MÃ¥la" #: src/toolbar.c:580 msgid "Shuffle" msgstr "Blanda" #: src/toolbar.c:583 msgid "Flood Fill" msgstr "" #: src/toolbar.c:587 msgid "Straight Line" msgstr "Rak linje" #: src/toolbar.c:590 msgid "Smudge" msgstr "Smeta" #: src/toolbar.c:594 msgid "Clone" msgstr "Klona" #: src/toolbar.c:597 msgid "Make Selection" msgstr "Gör Urval" #: src/toolbar.c:600 msgid "Polygon Selection" msgstr "Polygonurval" #: src/toolbar.c:603 msgid "Place Gradient" msgstr "Placera gradient" #: src/toolbar.c:606 msgid "Lasso Selection" msgstr "Lasso-markering" #: src/toolbar.c:614 msgid "Ellipse Outline" msgstr "Oval Kontur" #: src/toolbar.c:617 msgid "Filled Ellipse" msgstr "Fylld Oval" #: src/toolbar.c:620 msgid "Outline Selection" msgstr "Konturmarkering" #: src/toolbar.c:623 msgid "Fill Selection" msgstr "Fyll Urval" #: src/toolbar.c:627 msgid "Flip Selection Vertically" msgstr "Vänd markering vertikalt" #: src/toolbar.c:630 msgid "Flip Selection Horizontally" msgstr "Vänd markering horisontellt" #: src/toolbar.c:633 msgid "Rotate Selection Clockwise" msgstr "Rotera markering medsols" #: src/toolbar.c:636 msgid "Rotate Selection Anti-Clockwise" msgstr "Rotera markering motsols" #: src/vcode.c:5201 msgid "Browse" msgstr "Bläddra" #: src/vcode.c:7886 msgid "New key ..." msgstr "" #: src/vcode.c:9909 #, c-format msgid "'%s' does not match any widget" msgstr "" #: src/vcode.c:9910 #, c-format msgid "'%s' value does not fit '%s' widget" msgstr "" #: src/viewer.c:115 msgid "About" msgstr "Om" #: src/viewer.c:1179 msgid "No font selected" msgstr "" #: src/viewer.c:1209 msgid "Left" msgstr "" #: src/viewer.c:1209 msgid "Right" msgstr "" #~ msgid "Create GIF frames" #~ msgstr "Skapa gifbildrutor" #~ msgid "" #~ "You are trying to save an XPM file with more than 4096 colours. Either " #~ "use another format or posterize the image to 4 bits, or otherwise reduce " #~ "the number of colours." #~ msgstr "" #~ "Du försöker att spara en XPM-fil med fler än 4096 färger. Använd antingen " #~ "ett annat format eller posterisera bilden till 4 bitar, annars minska " #~ "antalet färger." #~ msgid "Store Values" #~ msgstr "Lagra värden" #~ msgid "File: %s invalid - palette not updated" #~ msgstr "Fil: %s ogiltig - paletten inte uppdaterad" #~ msgid "Distance to A+B" #~ msgstr "AvstÃ¥nd till A+B" #~ msgid "Edit Frames" #~ msgstr "Redigera Bildrutor" mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/po/tl.po000066400000000000000000002355131471325446300215610ustar00rootroot00000000000000# Tagalog translation for mtpaint # Copyright (c) 2009 Rosetta Contributors and Canonical Ltd 2009 # This file is distributed under the same license as the mtpaint package. # FIRST AUTHOR , 2009. # msgid "" msgstr "" "Project-Id-Version: mtpaint\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-01-04 21:31+0200\n" "PO-Revision-Date: 2016-05-23 19:03+0000\n" "Last-Translator: yavinfour \n" "Language-Team: Tagalog \n" "Language: tl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Launchpad-Export-Date: 2020-04-05 23:36+0000\n" "X-Generator: Launchpad (build a296f04231dee355be5db73cc878b9e21689a253)\n" #: src/ani.c:647 msgid "Animation Preview" msgstr "Silipin ang Animation" #: src/ani.c:650 src/shifter.c:275 msgid "Play" msgstr "Paganahin" #: src/ani.c:654 msgid "Fix" msgstr "Ayusin" #: src/ani.c:655 src/ani.c:1005 src/font.c:1624 src/font.c:1643 #: src/shifter.c:286 src/viewer.c:97 msgid "Close" msgstr "Isara" #: src/ani.c:709 src/ani.c:812 src/ani.c:1022 src/ani.c:1028 src/canvas.c:356 #: src/canvas.c:708 src/canvas.c:989 src/canvas.c:1353 src/canvas.c:1383 #: src/canvas.c:1470 src/canvas.c:1545 src/canvas.c:1988 src/canvas.c:1994 #: src/canvas.c:2077 src/canvas.c:2217 src/canvas.c:2240 src/font.c:1352 #: src/fpick.c:636 src/fpick.c:754 src/layer.c:524 src/layer.c:815 #: src/layer.c:970 src/mainwindow.c:341 src/mainwindow.c:370 #: src/mainwindow.c:534 src/mainwindow.c:578 src/mainwindow.c:604 #: src/mainwindow.c:3797 src/mainwindow.c:4045 src/otherwindow.c:931 #: src/otherwindow.c:980 src/otherwindow.c:982 src/prefs.c:459 src/spawn.c:924 #: src/spawn.c:978 src/spawn.c:1017 src/thread.c:360 src/vcode.c:9912 #: src/viewer.c:1161 src/viewer.c:1179 msgid "Error" msgstr "Error" #: src/ani.c:709 msgid "Unable to create output directory" msgstr "Hindi makagawa ng output directory" #: src/ani.c:759 msgid "Creating Animation Frames" msgstr "Gumagawa na ng Animation Frames" #: src/ani.c:812 msgid "Unable to save image" msgstr "Hindi Mai-save ang Imahe" #: src/ani.c:840 src/canvas.c:1171 src/fpick.c:731 src/layer.c:311 #: src/layer.c:379 src/layer.c:826 src/layer.c:840 src/mainwindow.c:375 #: src/mainwindow.c:1026 src/png.c:8794 src/prefs.c:464 msgid "Warning" msgstr "Babala" #: src/ani.c:840 msgid "" "Do you really want to clear all of the position and cycle data for all of " "the layers?" msgstr "" "Gusto mo ba talagang burahin ang lahat ng datos para sa posisyon at cycle ng " "layers?" #: src/ani.c:841 src/fpick.c:731 src/layer.c:311 src/layer.c:842 #: src/mainwindow.c:375 msgid "No" msgstr "Hindi" #: src/ani.c:841 src/fpick.c:731 src/layer.c:311 src/layer.c:842 #: src/mainwindow.c:375 msgid "Yes" msgstr "Oo" #: src/ani.c:954 msgid "Set Key Frame" msgstr "Mag-set ng Key Frame" #: src/ani.c:961 msgid "Configure Animation" msgstr "Isaayos ang Animation" #: src/ani.c:964 msgid "Output Files" msgstr "Output Files" #: src/ani.c:967 msgid "Start frame" msgstr "Panimulang frame" #: src/ani.c:969 msgid "End frame" msgstr "Katapusang Frame" #: src/ani.c:971 src/shifter.c:267 msgid "Delay" msgstr "Pabagal" #: src/ani.c:973 msgid "Output path" msgstr "" #: src/ani.c:973 src/font.c:1637 src/spawn.c:664 msgid "Select Directory" msgstr "Piliin ang Directory" #: src/ani.c:976 msgid "File prefix" msgstr "" #: src/ani.c:978 src/canvas.c:2096 msgid "File Format" msgstr "Format ng File" #: src/ani.c:982 msgid "Positions" msgstr "Mga Posisyon" #: src/ani.c:997 msgid "Cycling" msgstr "Pag-ikot" #: src/ani.c:1006 msgid "Save" msgstr "I-save" #: src/ani.c:1007 src/font.c:1577 src/otherwindow.c:868 src/otherwindow.c:1615 #: src/otherwindow.c:1728 src/otherwindow.c:2938 src/otherwindow.c:3071 #: src/otherwindow.c:3170 msgid "Preview" msgstr "Tignan" #: src/ani.c:1008 src/shifter.c:285 msgid "Create Frames" msgstr "Gumawa ng Frames" #: src/ani.c:1022 msgid "You must have at least 2 layers to create an animation" msgstr "Dapat ay meron kang 2 layers kahit papaano para makabuo ng animation" #: src/ani.c:1028 msgid "You must save your layers file before creating an animation" msgstr "Dapay ma-save ang mga layers file mo bago bumuo ng animation" #: src/canvas.c:357 msgid "The image is too large to transform." msgstr "Masyadong malaki ang imahe para ma-transform." #: src/canvas.c:393 src/canvas.c:430 src/otherwindow.c:1613 #: src/otherwindow.c:2524 src/otherwindow.c:2583 src/otherwindow.c:3179 msgid "Gradient" msgstr "" #: src/canvas.c:393 src/otherwindow.c:840 src/otherwindow.c:842 #: src/otherwindow.c:2074 src/otherwindow.c:3180 msgid "Palette" msgstr "Palette" #: src/canvas.c:393 src/info.c:265 src/otherwindow.c:847 src/otherwindow.c:2757 #: src/otherwindow.c:3180 src/png.c:781 src/png.c:995 msgid "Clipboard" msgstr "Clipboard" #: src/canvas.c:394 src/cpick.c:831 src/toolbar.c:299 msgid "Value" msgstr "Halaga" #: src/canvas.c:394 src/cpick.c:811 src/otherwindow.c:575 src/otherwindow.c:859 #: src/otherwindow.c:3053 src/toolbar.c:318 msgid "Red" msgstr "Pula" #: src/canvas.c:394 src/cpick.c:815 src/otherwindow.c:575 src/otherwindow.c:860 #: src/otherwindow.c:3053 src/toolbar.c:319 msgid "Green" msgstr "Berde" #: src/canvas.c:394 src/cpick.c:819 src/otherwindow.c:575 src/otherwindow.c:861 #: src/otherwindow.c:3053 src/toolbar.c:320 msgid "Blue" msgstr "Asul" #: src/canvas.c:399 msgid "From " msgstr "" #: src/canvas.c:403 msgid "To " msgstr "" #: src/canvas.c:410 msgid "Map" msgstr "" #: src/canvas.c:429 msgid "MT" msgstr "" #: src/canvas.c:429 msgid "Sobel" msgstr "" #: src/canvas.c:429 msgid "Prewitt" msgstr "" #: src/canvas.c:429 msgid "Kirsch" msgstr "" #: src/canvas.c:430 msgid "Roberts" msgstr "" #: src/canvas.c:430 msgid "Laplace" msgstr "" #: src/canvas.c:430 msgid "Morphological" msgstr "" #: src/canvas.c:442 msgid "Edge Detect" msgstr "" #: src/canvas.c:464 msgid "Edge Sharpen" msgstr "Palinawin ang mga Singit" #: src/canvas.c:472 msgid "Edge Soften" msgstr "Palambutin ang Edge" #: src/canvas.c:521 msgid "Different X/Y" msgstr "Magkaibang X/Y" #: src/canvas.c:522 src/canvas.c:562 src/canvas.c:603 src/canvas.c:637 #: src/canvas.c:722 src/otherwindow.c:1037 src/otherwindow.c:2685 msgid "Gamma corrected" msgstr "Inayos ng Gama" #: src/canvas.c:530 src/memory.c:8219 msgid "Gaussian Blur" msgstr "Blur na Gaussian" #: src/canvas.c:558 msgid "Radius" msgstr "Radius" #: src/canvas.c:559 msgid "Amount" msgstr "Dami" #: src/canvas.c:560 msgid "Threshold " msgstr "" #: src/canvas.c:570 src/memory.c:8360 msgid "Unsharp Mask" msgstr "" #: src/canvas.c:599 msgid "Outer radius" msgstr "Panlabas na Radius" #: src/canvas.c:600 msgid "Inner radius" msgstr "Panloob na Radius" #: src/canvas.c:602 src/info.c:280 msgid "Normalize" msgstr "Gawing normal" #: src/canvas.c:611 src/memory.c:8512 msgid "Difference of Gaussians" msgstr "Pagkakaiba ng mga Gaussians" #: src/canvas.c:636 msgid "Protect details" msgstr "" #: src/canvas.c:645 msgid "Kuwahara-Nagao Blur" msgstr "" #: src/canvas.c:709 msgid "The image is too large for this rotation." msgstr "Masyadong malaki ang imahe para sa pag-ikot na ito" #: src/canvas.c:723 msgid "Smooth" msgstr "Malambot" #: src/canvas.c:732 msgid "Free Rotate" msgstr "Ikutin" #: src/canvas.c:989 src/viewer.c:1161 msgid "Not enough memory to create clipboard" msgstr "Hindi sapat ang memory para makabuo ng clipboard" #: src/canvas.c:1172 msgid "" "You have not allocated enough memory in the Preferences window to undo this " "action." msgstr "" #: src/canvas.c:1353 msgid "Invalid palette file" msgstr "Maling palette file" #: src/canvas.c:1383 msgid "Invalid channel file." msgstr "Maling channel file" #: src/canvas.c:1401 msgid "Raw frames" msgstr "" #: src/canvas.c:1401 msgid "Composited frames" msgstr "" #: src/canvas.c:1402 msgid "Composited frames with nonzero delay" msgstr "" #: src/canvas.c:1406 msgid "Load Frames" msgstr "" #: src/canvas.c:1409 msgid "Load into Layers" msgstr "Ikarga sa mga Layers" #: src/canvas.c:1415 msgid "Load First Frame" msgstr "" #: src/canvas.c:1416 msgid "Explode Frames" msgstr "" #: src/canvas.c:1418 msgid "View Animation" msgstr "Ipakita ang Animasyon" #: src/canvas.c:1434 #, c-format msgid "This is an animated %s file." msgstr "Ito ay isang gumagalaw na %s file." #: src/canvas.c:1435 #, c-format msgid "This is a multipage %s file." msgstr "" #: src/canvas.c:1459 #, c-format msgid "File is too big, must be <= to width=%i height=%i" msgstr "Masyadong malaki ang file, dapat ay <= %i na haba at %i na taas" #: src/canvas.c:1461 msgid "Unable to explode frames" msgstr "" #: src/canvas.c:1463 msgid "Unable to load file" msgstr "Hindi maikarga ang file" #: src/canvas.c:1465 msgid "" "The file import library had to terminate due to a problem with the file " "(possibly corrupt image data or a truncated file). I have managed to load " "some data as the header seemed fine, but I would suggest you save this image " "to a new file to ensure this does not happen again." msgstr "" #: src/canvas.c:1467 msgid "The animation is too long to load all of it into layers." msgstr "" "Masyadong malaki ang animation para iload ang kabuuan nito sa mga layers" #: src/canvas.c:1469 msgid "Could not explode all the frames in the animation." msgstr "" #: src/canvas.c:1481 src/font.c:1556 src/fpick.c:937 src/otherwindow.c:2765 #: src/prefs.c:321 src/toolbar.c:451 msgid "Size" msgstr "Sukat" #: src/canvas.c:1484 src/otherwindow.c:244 msgid "Width" msgstr "Lapad" #: src/canvas.c:1485 src/otherwindow.c:245 msgid "Height" msgstr "Taas" #: src/canvas.c:1489 src/channels.c:253 src/channels.c:317 src/fpick.c:666 #: src/fpick.c:957 src/mainwindow.c:3990 src/otherwindow.c:255 #: src/otherwindow.c:517 src/otherwindow.c:591 src/otherwindow.c:867 #: src/otherwindow.c:1058 src/otherwindow.c:1727 src/otherwindow.c:2101 #: src/otherwindow.c:2336 src/otherwindow.c:2538 src/otherwindow.c:2691 #: src/otherwindow.c:2776 src/otherwindow.c:2937 src/otherwindow.c:3070 #: src/otherwindow.c:3169 src/prefs.c:338 src/prefs.c:464 src/prefs.c:538 #: src/spawn.c:666 src/viewer.c:1258 msgid "Cancel" msgstr "Huwag Ituloy" #: src/canvas.c:1490 src/channels.c:253 src/channels.c:317 src/fpick.c:956 #: src/info.c:297 src/mainwindow.c:3992 src/mygtk.c:233 src/mygtk.c:535 #: src/otherwindow.c:591 src/otherwindow.c:871 src/otherwindow.c:1058 #: src/otherwindow.c:1729 src/otherwindow.c:2101 src/otherwindow.c:2336 #: src/otherwindow.c:2538 src/otherwindow.c:2691 src/otherwindow.c:2776 #: src/otherwindow.c:3072 src/otherwindow.c:3171 src/prefs.c:338 #: src/prefs.c:538 src/spawn.c:666 msgid "OK" msgstr "OK" #: src/canvas.c:1504 #, c-format msgid "This is a scalable %s file." msgstr "" #: src/canvas.c:1545 msgid "Cannot open file" msgstr "Hindi mabuksan ang file" #: src/canvas.c:1546 msgid "Unsupported file format" msgstr "Hindi suportadong file format" #: src/canvas.c:1673 #, c-format msgid "File: %s already exists. Do you want to overwrite it?" msgstr "Meron nang file na: %s gusto mo ba siyang mapalitan?" #: src/canvas.c:1674 msgid "File Found" msgstr "Nakita ang file" #: src/canvas.c:1674 src/mainwindow.c:1095 msgid "NO" msgstr "HINDI" #: src/canvas.c:1674 src/mainwindow.c:1095 msgid "YES" msgstr "OO" #: src/canvas.c:1988 msgid "Unable to export undo images" msgstr "Hindi mai-export ang mga undo image" #: src/canvas.c:1994 msgid "Unable to export ASCII file" msgstr "Hindi mai-export ang ASCII file" #: src/canvas.c:2076 src/layer.c:814 src/mainwindow.c:529 #, c-format msgid "Unable to save file: %s" msgstr "Hindi mai-save ang file: %s" #: src/canvas.c:2101 src/prefs.c:222 msgid "Transparency index" msgstr "Index sa transparency" #: src/canvas.c:2103 msgid "TIFF Compression" msgstr "" #: src/canvas.c:2105 src/prefs.c:225 msgid "JPEG Save Quality (100=High)" msgstr "Save Quality para sa JPEG (100=mataas)" #: src/canvas.c:2107 msgid "ZIP Compression (0=None)" msgstr "" #: src/canvas.c:2108 src/prefs.c:227 msgid "PNG Compression (0=None)" msgstr "Kompresiyon ng PNG (0=Kung Wala)" #: src/canvas.c:2111 src/prefs.c:249 msgid "LZMA2 Compression (0=None)" msgstr "" #: src/canvas.c:2113 src/prefs.c:252 msgid "ZSTD Compression Level" msgstr "" #: src/canvas.c:2115 src/prefs.c:231 msgid "TGA RLE Compression" msgstr "Kompresiyon ng TGA RLE" #: src/canvas.c:2117 msgid "LBM PackBits Compression" msgstr "" #: src/canvas.c:2118 src/prefs.c:226 msgid "JPEG2000 Compression (0=Lossless)" msgstr "Kompresiyon ng JPEG2000 (0=Lossless)" #: src/canvas.c:2120 msgid "WebP Compression" msgstr "" #: src/canvas.c:2122 msgid "WebP Save Quality (100=High)" msgstr "" #: src/canvas.c:2123 src/prefs.c:263 msgid "V8 Save Quality (100=High)" msgstr "" #: src/canvas.c:2125 src/prefs.c:264 msgid "V8L Compression (0=None)" msgstr "" #: src/canvas.c:2127 msgid "Hotspot at X =" msgstr "Hotspot sa X =" #: src/canvas.c:2129 msgid "Y =" msgstr "Y =" #: src/canvas.c:2133 msgid "Animation delay" msgstr "Delay sa Animation" #: src/canvas.c:2136 src/otherwindow.c:253 msgid "Undoable" msgstr "Hindi Maa-undo" #: src/canvas.c:2138 src/prefs.c:236 msgid "Apply colour profile" msgstr "" #: src/canvas.c:2176 src/toolbar.c:543 msgid "Load Image File" msgstr "Ikarga ang Image File" #: src/canvas.c:2191 src/toolbar.c:544 msgid "Save Image File" msgstr "I-save ang Image File" #: src/canvas.c:2196 msgid "Load Palette File" msgstr "Ikarga ng Palette File" #: src/canvas.c:2202 msgid "Save Palette File" msgstr "I-save ang Palette File" #: src/canvas.c:2207 msgid "Export Undo Images" msgstr "I-export" #: src/canvas.c:2212 msgid "Export Undo Images (reversed)" msgstr "I-export ang mga Undo Image (nakabaligtad)" #: src/canvas.c:2217 msgid "You must have 16 or fewer palette colours to export ASCII art." msgstr "" "Dapat 16 o mas kakaunti pa dito ang bilang ng mga kulay mo sa palette para " "maiexort ito bilang ASCII art." #: src/canvas.c:2220 msgid "Export ASCII Art" msgstr "I-export ang ASCII Art" #: src/canvas.c:2224 msgid "Save Layer Files" msgstr "I-save ang mga Layer Files" #: src/canvas.c:2234 msgid "Choose frames directory" msgstr "Pumili ng frames directory" #: src/canvas.c:2240 msgid "You must save at least one frame to create an animated GIF." msgstr "" "Dapat ay meron kang kahit isang frame para makagawa ng GIF na animated " "(gumagalaw)." #: src/canvas.c:2243 msgid "Export GIF animation" msgstr "I-export ang GIF animation" #: src/canvas.c:2247 msgid "Load Channel" msgstr "Ikarga ang Tsanel" #: src/canvas.c:2255 msgid "Save Channel" msgstr "I-save ang Tsanel" #: src/canvas.c:2260 msgid "Save Composite Image" msgstr "I-save ang Composite na Imahe" #: src/channels.c:243 msgid "Create Channel" msgstr "Gumawa ng Tsanel" #: src/channels.c:244 msgid "Channel Type" msgstr "Uri ng Tsanel" #: src/channels.c:247 msgid "Initial Channel State" msgstr "" #: src/channels.c:251 msgid "Inverted" msgstr "Binaligtad" #: src/channels.c:265 msgid "Cleared" msgstr "Nilinis" #: src/channels.c:266 msgid "Set" msgstr "Itakda" #: src/channels.c:267 msgid "Set colour A radius B" msgstr "Itakda ang kulay A radius B" #: src/channels.c:268 msgid "Set blend A to B" msgstr "Itakta ang blend A hanggang B" #: src/channels.c:269 msgid "Image Red" msgstr "Pulang Imahe" #: src/channels.c:270 msgid "Image Green" msgstr "Berdeng Imahe" #: src/channels.c:271 msgid "Image Blue" msgstr "Asul na Imahe" #: src/channels.c:273 src/channels.c:313 src/mainwindow.c:67 #: src/otherwindow.c:1679 msgid "Alpha" msgstr "Alpa" #: src/channels.c:274 src/channels.c:314 src/mainwindow.c:67 #: src/otherwindow.c:1683 msgid "Selection" msgstr "Seleksyon" #: src/channels.c:275 src/channels.c:315 src/mainwindow.c:67 #: src/otherwindow.c:1687 msgid "Mask" msgstr "Maskara" #: src/channels.c:312 msgid "Delete Channels" msgstr "Burahin ang mga Tsanel" #: src/channels.c:367 msgid "Threshold Channel" msgstr "" #: src/cpick.c:823 src/otherwindow.c:573 src/otherwindow.c:820 #: src/toolbar.c:299 msgid "Hue" msgstr "Hue" #: src/cpick.c:827 src/otherwindow.c:573 src/otherwindow.c:818 #: src/toolbar.c:299 msgid "Saturation" msgstr "Tinkad" #: src/cpick.c:835 msgid "Hex" msgstr "" #: src/cpick.c:840 src/layer.c:1109 src/otherwindow.c:2530 src/prefs.c:323 #: src/toolbar.c:457 msgid "Opacity" msgstr "" #: src/font.c:982 msgid "Creating Font Index" msgstr "Gumagawa ng Font Index" #: src/font.c:1353 msgid "You must select at least one directory to search for fonts." msgstr "" "Dapat ay pumili ka ng kahit isang directory mara makahanap ng mga font." #: src/font.c:1529 src/font.c:1624 src/toolbar.c:609 src/viewer.c:1213 #: src/viewer.c:1258 msgid "Paste Text" msgstr "Idikit ang Teksto" #: src/font.c:1533 src/font.c:1572 src/png.c:3578 msgid "Text" msgstr "Teksto" #: src/font.c:1540 msgid "Font" msgstr "Font" #: src/font.c:1548 msgid "Style" msgstr "Istilo" #: src/font.c:1566 msgid "Filename" msgstr "Pangalan ng file" #: src/font.c:1567 msgid "Face" msgstr "Harap" #: src/font.c:1587 src/viewer.c:1222 msgid "Antialias" msgstr "" #: src/font.c:1590 src/viewer.c:1224 msgid "Invert" msgstr "Baliktarin" #: src/font.c:1593 src/viewer.c:1226 msgid "Background colour =" msgstr "Kulay ng Likuran =" #: src/font.c:1601 src/viewer.c:1233 msgid "DPI =" msgstr "" #: src/font.c:1610 msgid "Oblique" msgstr "Tabinge" #: src/font.c:1612 src/viewer.c:1244 msgid "Angle of rotation =" msgstr "Anggulo ng pag-ikot" #: src/font.c:1617 src/viewer.c:1248 msgid "Align" msgstr "" #: src/font.c:1620 src/viewer.c:1253 msgid "Spacing" msgstr "" #: src/font.c:1629 msgid "Font Directories" msgstr "Directory ng Font" #: src/font.c:1634 src/spawn.c:664 msgid "Directory" msgstr "Directory" #: src/font.c:1637 msgid "New Directory" msgstr "Bagong directory" #: src/font.c:1644 src/prefs.c:532 msgid "Add" msgstr "Magdagdag" #: src/font.c:1645 src/prefs.c:533 msgid "Remove" msgstr "Alisin" #: src/font.c:1646 msgid "Create Index" msgstr "Gumawa ng Index" #: src/font.c:1660 src/viewer.c:1267 msgid "Enter Text Here" msgstr "Ilagay ang Teksto Dito" #: src/fpick.c:635 #, c-format msgid "Could not access directory %s" msgstr "Hindi mapasok ang direktori na %s" #: src/fpick.c:668 src/fpick.c:698 msgid "Delete" msgstr "Alisin" #: src/fpick.c:669 src/fpick.c:698 msgid "Rename" msgstr "Palitan ng pangalan" #: src/fpick.c:672 src/otherwindow.c:255 src/otherwindow.c:1666 msgid "Create" msgstr "Lumikha" #: src/fpick.c:699 msgid "Enter the new filename" msgstr "Ilagay ang bagong pangalan ng file" #: src/fpick.c:704 msgid "Create Directory" msgstr "Gumawa ng Direktori" #: src/fpick.c:705 msgid "Enter the name of the new directory" msgstr "" #: src/fpick.c:729 #, c-format msgid "Do you really want to delete \"%s\" ?" msgstr "Gusto mo ba talagang burahin ang \"%s\" ?" #: src/fpick.c:735 msgid "Unable to delete" msgstr "Hindi mabura" #: src/fpick.c:741 msgid "Unable to rename" msgstr "Hindi mabago ang pangalan" #: src/fpick.c:750 msgid "Unable to create directory" msgstr "Hindi makagawa ng directory" #: src/fpick.c:924 msgid "Up" msgstr "Umakyat" #: src/fpick.c:925 msgid "Home" msgstr "Tahanan" #: src/fpick.c:926 msgid "Create New Directory" msgstr "Gumawa ng bagong directory" #: src/fpick.c:927 msgid "Show Hidden Files" msgstr "Ipakita ang mga nakatagong Files" #: src/fpick.c:929 msgid "Case Insensitive Sort" msgstr "" #: src/fpick.c:936 msgid "Name" msgstr "Pangalan" #: src/fpick.c:938 msgid "Type" msgstr "Tipo" #: src/fpick.c:939 msgid "Modified" msgstr "Huling nabago" #: src/help.c:25 src/prefs.c:160 msgid "General" msgstr "Pangkalahatan" #: src/help.c:26 msgid "Keyboard shortcuts" msgstr "Shortcut sa kibord" #: src/help.c:27 msgid "Mouse shortcuts" msgstr "Shortcut sa Mouse" #: src/help.c:28 msgid "Credits" msgstr "Mga Pagkilala" #: src/help.c:32 msgid "mtPaint 3.51 - Copyright (C) 2004-2021 The Authors\n" msgstr "" #: src/help.c:33 msgid "See 'Credits' section for a list of the authors.\n" msgstr "" #: src/help.c:34 msgid "" "mtPaint 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.\n" msgstr "" "Ang mtPaint ay isang libreng software; pwede mo siyang ipakalat at/o kaya " "baguhin ayon sa mga tuntunin ng GNU General Public License na inilimbag ng " "Free Software Foundation; either version 3 of the License, or (at your " "option) any later version.\n" #: src/help.c:35 msgid "" "mtPaint 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.\n" msgstr "" #: src/help.c:36 msgid "" "mtPaint is a simple GTK+1/2/3 painting program designed for creating icons " "and pixel based artwork. It can edit indexed palette or 24 bit RGB images " "and offers basic painting and palette manipulation tools. It also has " "several other more powerful features such as channels, layers and animation. " "Due to its simplicity and lack of dependencies it runs well on GNU/Linux, " "Windows and older PC hardware.\n" msgstr "" #: src/help.c:37 msgid "" "There is full documentation of mtPaint's features contained in a handbook. " "If you don't already have this, you can download it from the mtPaint " "website.\n" msgstr "" "Merong kumpetong dokyumentasyon ng lahat ng pwedeng magawa ng mtPaint at ito " "ay nasa handbook. Kung wala ka pa nito, pwede mo siyang ma-download mula sa " "websayt ng mtPaint\n" #: src/help.c:38 msgid "" "If you like mtPaint and you want to keep up to date with new releases, or " "you want to give some feedback, then the mailing lists may be of interest to " "you:\n" msgstr "" #: src/help.c:39 msgid "http://sourceforge.net/mail/?group_id=155874" msgstr "http://sourceforge.net/mail/?group_id=155874" #: src/help.c:42 msgid " Ctrl-N Create new image" msgstr " Ctrl-N Gumawa ng bagong imahe" #: src/help.c:43 msgid " Ctrl-O Open Image" msgstr " Ctrl-O Magbukas ng Image" #: src/help.c:44 msgid " Ctrl-S Save Image" msgstr " Ctrl-S I-Save ang Imahe" #: src/help.c:45 msgid " Ctrl-Shift-S Save layers file" msgstr "" #: src/help.c:46 msgid " Ctrl-Q Quit program\n" msgstr " Ctrl-Q Umalis sa Program\n" #: src/help.c:47 msgid " Ctrl-A Select whole image" msgstr " Ctrl-A I-select ang buong imahe" #: src/help.c:48 msgid " Escape Select nothing, cancel paste box" msgstr "" #: src/help.c:49 msgid " J Lasso selection\n" msgstr "" #: src/help.c:50 msgid " Ctrl-C Copy selection to clipboard" msgstr " Ctrl-C Kopyahin ang seleksyon patungo sa clipboard" #: src/help.c:51 msgid "" " Ctrl-X Copy selection to clipboard, and then paint current " "pattern to selection area" msgstr "" #: src/help.c:52 msgid " Ctrl-V Paste clipboard to centre of current view" msgstr "" #: src/help.c:53 msgid " Ctrl-K Paste clipboard to location it was copied from" msgstr "" #: src/help.c:54 msgid " Ctrl-Shift-V Paste clipboard to new layer" msgstr "" #: src/help.c:55 msgid " Enter/Return Commit paste to canvas" msgstr "" #: src/help.c:56 msgid " Shift+Enter/Return Commit paste and swap canvas into the clipboard\n" msgstr "" #: src/help.c:57 msgid " Arrow keys Paint Mode - Move the mouse pointer" msgstr "" #: src/help.c:58 msgid "" " Arrow keys Selection Mode - Nudge selection box or paste box by one " "pixel" msgstr "" #: src/help.c:59 msgid "" " Shift+Arrow keys Nudge mouse pointer, selection box or paste box by x " "pixels - x is defined by the Preferences window" msgstr "" #: src/help.c:60 msgid " Ctrl+Arrows Move layer or resize selection box" msgstr "" #: src/help.c:61 msgid " Ctrl+Shift+Arrows Move layer or resize selection box by x pixels\n" msgstr "" #: src/help.c:62 msgid " Enter/Return Paint Mode - Simulate left click" msgstr "" #: src/help.c:63 msgid " Backspace Paint Mode - Simulate right click\n" msgstr "" #: src/help.c:64 msgid "" " [ or ] Change colour A to the next or previous palette item" msgstr "" #: src/help.c:65 msgid "" " Shift+[ or ] Change colour B to the next or previous palette item\n" msgstr "" #: src/help.c:66 msgid " Delete Crop image to selection" msgstr "" #: src/help.c:67 msgid "" " Insert Transform colours - i.e. Brightness, Contrast, " "Saturation, Posterize, Gamma" msgstr "" #: src/help.c:68 msgid " Ctrl-G Greyscale the image" msgstr "" #: src/help.c:69 msgid " Shift-Ctrl-G Greyscale the image (Gamma corrected)" msgstr "" #: src/help.c:70 msgid " Ctrl+M Mirror the image" msgstr "" #: src/help.c:71 msgid " Shift-Ctrl-I Invert the image\n" msgstr "" #: src/help.c:72 msgid "" " Ctrl-T Draw a rectangle around the selection area with the " "current fill" msgstr "" #: src/help.c:73 msgid " Ctrl-Shift-T Fill in the selection area with the current fill" msgstr "" #: src/help.c:74 msgid " Ctrl-L Draw an ellipse spanning the selection area" msgstr "" #: src/help.c:75 msgid " Ctrl-Shift-L Draw a filled ellipse spanning the selection area\n" msgstr "" #: src/help.c:76 msgid " Ctrl-E Edit the RGB values for colours A & B" msgstr "" #: src/help.c:77 msgid " Ctrl-W Edit all palette colours\n" msgstr "" #: src/help.c:78 msgid " Ctrl-P Preferences" msgstr "" #: src/help.c:79 msgid " Ctrl-I Information\n" msgstr "" #: src/help.c:80 msgid " Ctrl-Z Undo last action" msgstr "" #: src/help.c:81 msgid " Ctrl-R Redo an undone action\n" msgstr "" #: src/help.c:82 msgid " Shift-T Text Tool (GTK+)" msgstr "" #: src/help.c:83 msgid " T Text Tool (FreeType)\n" msgstr "" #: src/help.c:84 msgid " V View Window" msgstr "" #: src/help.c:85 msgid " L Layers Window\n" msgstr "" #: src/help.c:86 msgid " Ctrl-H Toggle Hide Image mode" msgstr "" #: src/help.c:87 msgid " B Toggle Snap to Tile Grid mode\n" msgstr "" #: src/help.c:88 msgid " X Swap Colours A & B" msgstr "" #: src/help.c:89 msgid " E Choose Colour\n" msgstr "" #: src/help.c:90 msgid "" " A Draw open arrow head when using the line tool (size set " "by flow setting)" msgstr "" #: src/help.c:91 msgid "" " S Draw closed arrow head when using the line tool (size " "set by flow setting)\n" msgstr "" #: src/help.c:92 msgid " D Line Tool" msgstr "" #: src/help.c:93 msgid " F Flood Fill Tool\n" msgstr "" #: src/help.c:94 msgid " +,= Main edit window - Zoom in" msgstr "" #: src/help.c:95 msgid " - Main edit window - Zoom out" msgstr "" #: src/help.c:96 msgid " Shift +,= View window - Zoom in" msgstr "" #: src/help.c:97 msgid " Shift - View window - Zoom out\n" msgstr "" #: src/help.c:98 #, c-format msgid " 1 10% zoom" msgstr "" #: src/help.c:99 #, c-format msgid " 2 25% zoom" msgstr "" #: src/help.c:100 #, c-format msgid " 3 50% zoom" msgstr "" #: src/help.c:101 #, c-format msgid " 4 100% zoom" msgstr "" #: src/help.c:102 #, c-format msgid " 5 400% zoom" msgstr "" #: src/help.c:103 #, c-format msgid " 6 800% zoom" msgstr "" #: src/help.c:104 #, c-format msgid " 7 1200% zoom" msgstr "" #: src/help.c:105 #, c-format msgid " 8 1600% zoom" msgstr "" #: src/help.c:106 #, c-format msgid " 9 2000% zoom\n" msgstr "" #: src/help.c:107 msgid " Shift + 1 Edit image channel" msgstr "" #: src/help.c:108 msgid " Shift + 2 Edit alpha channel" msgstr "" #: src/help.c:109 msgid " Shift + 3 Edit selection channel" msgstr "" #: src/help.c:110 msgid " Shift + 4 Edit mask channel\n" msgstr "" #: src/help.c:111 msgid " F1 Help" msgstr " F1 Tulong" #: src/help.c:112 msgid " F2 Choose Pattern" msgstr "" #: src/help.c:113 msgid " F3 Choose Brush" msgstr "" #: src/help.c:114 msgid " F4 Paint Tool" msgstr "" #: src/help.c:115 msgid " F5 Toggle Main Toolbar" msgstr "" #: src/help.c:116 msgid " F6 Toggle Tools Toolbar" msgstr "" #: src/help.c:117 msgid " F7 Toggle Settings Toolbar" msgstr "" #: src/help.c:118 msgid " F8 Toggle Palette" msgstr "" #: src/help.c:119 msgid " F9 Selection Tool" msgstr "" #: src/help.c:120 msgid " F12 Toggle Dock Area\n" msgstr "" #: src/help.c:121 msgid " Ctrl + F1 - F12 Save current clipboard to file 1-12" msgstr "" #: src/help.c:122 msgid " Shift + F1 - F12 Load clipboard from file 1-12\n" msgstr "" #: src/help.c:123 msgid "" " Ctrl + 1, 2, ... , 0 Set opacity to 10%, 20%, ... , 100% (main or keypad " "numbers)" msgstr "" #: src/help.c:124 msgid " Ctrl + + or = Increase opacity by 1" msgstr "" #: src/help.c:125 msgid " Ctrl + - Decrease opacity by 1\n" msgstr "" #: src/help.c:126 msgid "" " Home Show or hide main window menu/toolbar/status bar/palette" msgstr "" #: src/help.c:127 msgid " Page Up Scale Image" msgstr "" #: src/help.c:128 msgid " Page Down Resize Image canvas" msgstr "" #: src/help.c:129 msgid " End Pan Window" msgstr "" #: src/help.c:132 msgid " Left button Paint to canvas using the current tool" msgstr "" #: src/help.c:133 msgid "" " Middle button Selects the point which will be the centre of the " "image after the next zoom" msgstr "" #: src/help.c:134 msgid "" " Right button Commit paste to canvas / Stop drawing current line / " "Cancel selection\n" msgstr "" #: src/help.c:135 msgid "" " Scroll Wheel In GTK+2/3 the user can have the scroll wheel zoom in " "or out via the Preferences window\n" msgstr "" #: src/help.c:136 msgid " Ctrl+Left button Choose colour A from under mouse pointer" msgstr "" #: src/help.c:137 msgid " Ctrl+Left button Clone tool - Select source" msgstr "" #: src/help.c:138 msgid "" " Ctrl+Middle button Create colour A/B and pattern based on the RGB colour " "in A (RGB images only)" msgstr "" #: src/help.c:139 msgid " Ctrl+Right button Choose colour B from under mouse pointer" msgstr "" #: src/help.c:140 msgid "" " Ctrl+Right button Polygon tool - Delete last point / Delete nearest " "point" msgstr "" #: src/help.c:141 msgid " Ctrl+Scroll Wheel Scroll the main edit window left or right\n" msgstr "" #: src/help.c:142 msgid "" " Ctrl+Double click Set colour A or B to average colour under brush " "square or selection marquee (RGB only)\n" msgstr "" #: src/help.c:143 msgid "" " Shift+Right button Selects the point which will be the centre of the " "image after the next zoom\n" "\n" msgstr "" #: src/help.c:144 msgid "You can fixate the X/Y co-ordinates while moving the mouse:\n" msgstr "" #: src/help.c:145 msgid " Shift Constrain mouse movements to vertical line" msgstr "" #: src/help.c:146 msgid " Shift+Ctrl Constrain mouse movements to horizontal line" msgstr "" #: src/help.c:149 msgid "mtPaint is maintained by Dmitry Groshev.\n" msgstr "" #: src/help.c:150 msgid "wjaguar@users.sourceforge.net" msgstr "wjaguar@users.sourceforge.net" #: src/help.c:151 msgid "http://mtpaint.sourceforge.net/\n" msgstr "http://mtpaint.sourceforge.net/\n" #: src/help.c:152 msgid "" "The following people (in alphabetical order) have contributed directly to " "the project, and are therefore worthy of gracious thanks for their " "generosity and hard work:\n" "\n" msgstr "" #: src/help.c:153 msgid "Authors\n" msgstr "Mga May-Akda\n" #: src/help.c:154 msgid "" "Dmitry Groshev - Contributing developer for version 2.30. Lead developer and " "maintainer from version 3.00 to the present." msgstr "" #: src/help.c:155 msgid "" "Mark Tyler - Original author and maintainer up to version 3.00, occasional " "contributor thereafter." msgstr "" "Mark Tyler - Orihinal na awtor at tagapamahala hanggang sa version 3.00, " "kasalukuyang kontributor pa rin." #: src/help.c:156 msgid "" "Xiaolin Wu - Wrote the Wu quantizing method - see wu.c for more " "information.\n" "\n" msgstr "" #: src/help.c:157 msgid "" "General Contributions (Feedback and Ideas for improvements unless otherwise " "stated)\n" msgstr "" #: src/help.c:158 msgid "Abdulla Al Muhairi - Website redesign April 2005" msgstr "" #: src/help.c:159 msgid "Alan Horkan" msgstr "Alan Horkan" #: src/help.c:160 msgid "Alexandre Prokoudine" msgstr "Alexandre Prokoudine" #: src/help.c:161 msgid "Antonio Andrea Bianco" msgstr "Antonio Andrea Bianco" #: src/help.c:162 msgid "Charlie Ledocq" msgstr "" #: src/help.c:163 msgid "Dennis Lee" msgstr "Dennis Lee" #: src/help.c:164 msgid "Donald White" msgstr "" #: src/help.c:165 msgid "Ed Jason" msgstr "Ed Jason" #: src/help.c:166 msgid "" "Eddie Kohler - Created Gifsicle which is needed for the creation and viewing " "of animated GIF files http://www.lcdf.org/gifsicle/" msgstr "" "Eddie Kohler - Ang gumawa ng Gifsicle na kailangan para makabuo at " "makatingin ng mga animated GIF files http://www.lcdf.org/gifsicle/" #: src/help.c:167 msgid "" "Guadalinex Team (Junta de Andalucia) - man page, Launchpad/Rosetta " "registration" msgstr "" "Guadalinex Team (Junta de Andalucia) - man page, Launchpad/Rosetta " "registration" #: src/help.c:168 msgid "Lou Afonso" msgstr "Lou Afonso" #: src/help.c:169 msgid "Magnus Hjorth" msgstr "Magnus Hjorth" #: src/help.c:170 msgid "Martin Zelaia" msgstr "Martin Zelaia" #: src/help.c:171 msgid "Pasi Kallinen" msgstr "" #: src/help.c:172 msgid "Pavel Ruzicka" msgstr "" #: src/help.c:173 msgid "Puppy Linux (Barry Kauler)" msgstr "Puppy Linux (Barry Kauler)" #: src/help.c:174 msgid "Victor Copovi" msgstr "" #: src/help.c:175 msgid "Vlastimil Krejcir" msgstr "Vlastimil Krejcir" #: src/help.c:176 msgid "" "William Kern\n" "\n" msgstr "" "William Kern\n" "\n" #: src/help.c:177 msgid "Translations\n" msgstr "Mga Pag-sasalin ng Wika\n" #: src/help.c:178 msgid "Brazilian Portuguese - Paulo Trevizan, Valter Nazianzeno" msgstr "Brazilian Portuguese - Paulo Trevizan, Valter Nazianzeno" #: src/help.c:179 msgid "Czech - Pavel Ruzicka, Martin Petricek, Roman Hornik, Pavel Fric" msgstr "" #: src/help.c:180 msgid "Dutch - Hans Strijards, Pjotr" msgstr "" #: src/help.c:181 msgid "" "French - Nicolas Velin, Pascal Billard, Sylvain Cresto, Johan Serre, " "Philippe Etienne, Victor Copovi" msgstr "" #: src/help.c:182 msgid "Galician - Miguel Anxo Bouzada" msgstr "Galician - Miguel Anxo Bouzada" #: src/help.c:183 msgid "German - Oliver Frommel, B. Clausius, Ulrich Ringel, Simon Brixel" msgstr "Aleman - Oliver Frommel, B. Clausius, Ulrich Ringel, Simon Brixel" #: src/help.c:184 msgid "Hungarian - Ur Balazs" msgstr "" #: src/help.c:185 msgid "Italian - Angelo Gemmi" msgstr "" #: src/help.c:186 msgid "Japanese - Norihiro YONEDA" msgstr "Hapon - Norihiro YONEDA" #: src/help.c:187 msgid "Kabyle - Yacine Bouklif" msgstr "" #: src/help.c:188 msgid "Polish - Bartosz Kaszubowski, LucaS" msgstr "Polish - Bartosz Kaszubowski, LucaS" #: src/help.c:189 msgid "Portuguese - Israel G. Lugo, Tiago Silva" msgstr "Portuges - Israel G. Lugo, Tiago Silva" #: src/help.c:190 msgid "Russian - Sergey Irupin, Dmitry Groshev" msgstr "Ruso - Sergey Irupin, Dmitry Groshev" #: src/help.c:191 msgid "Simplified Chinese - Cecc" msgstr "" #: src/help.c:192 msgid "Slovak - Jozef Riha" msgstr "Slovak - Jozef Riha" #: src/help.c:193 msgid "" "Spanish - Guadalinex Team (Junta de Andalucia), Antonio Sanchez Leon, Miguel " "Anxo Bouzada, Francisco Jose Rey, Adolfo Jayme" msgstr "" #: src/help.c:194 msgid "Swedish - Daniel Nylander, Daniel Eriksson" msgstr "" #: src/help.c:195 msgid "Tagalog - Anjelo delCarmen" msgstr "" #: src/help.c:196 msgid "Taiwanese Chinese - Wei-Lun Chao" msgstr "Taiwanese Chinese - Wei-Lun Chao" #: src/help.c:197 msgid "Turkish - Muhammet Kara, Tutku Dalmaz" msgstr "Turko - Muhammet Kara, Tutku Dalmaz" #: src/info.c:258 msgid "Information" msgstr "Impormasyon" #: src/info.c:260 msgid "Memory" msgstr "Memory" #: src/info.c:261 msgid "Total memory for main + undo images" msgstr "Kabuuang memory para sa main + mga undo na imahe" #: src/info.c:263 msgid "Undo / Redo / Max levels used" msgstr "" #: src/info.c:265 msgid "Unused" msgstr "Hindi nagamit" #: src/info.c:269 msgid "Unique RGB pixels" msgstr "Magkaibang RGB pixels" #: src/info.c:272 src/layer.c:121 msgid "Layers" msgstr "Mga Layer" #: src/info.c:273 msgid "Total layer memory usage" msgstr "" #: src/info.c:277 msgid "Colour Histogram" msgstr "Histogram sa Kulay" #: src/info.c:289 src/otherwindow.c:1614 msgid "Index" msgstr "Index" #: src/info.c:290 msgid "Canvas pixels" msgstr "" #: src/info.c:328 #, c-format msgid "Clipboard = %i x %i" msgstr "Clipboard = %i x %i" #: src/info.c:328 #, c-format msgid "Clipboard = %i x %i x RGB" msgstr "Clipboard = %i x %i x RGB" #: src/info.c:377 msgid "Orphans" msgstr "Mga Ampon" #: src/info.c:383 #, c-format msgid "Colour index totals - %i of %i used" msgstr "Kabuuang index ng kulay - %i ng %i ang nagagamit" #: src/inifile.c:966 msgid "" "Could not find home directory. Using current directory as home directory." msgstr "" #: src/layer.c:63 msgid "Background" msgstr "Likuran" #: src/layer.c:122 src/mainwindow.c:5931 msgid "(Modified)" msgstr "(Binago)" #: src/layer.c:123 src/mainwindow.c:5932 msgid "Untitled" msgstr "Walang Pamagat" #: src/layer.c:308 #, c-format msgid "Do you really want to delete layer %i (%s) ?" msgstr "Gusto mo bang murahin ang layer na %i (%s) ?" #: src/layer.c:380 msgid "" "One or more of the layers contains changes that have not been saved. Do you " "really want to lose these changes?" msgstr "" #: src/layer.c:381 src/mainwindow.c:1028 msgid "Cancel Operation" msgstr "Kanselahin ang operasyon." #: src/layer.c:381 src/mainwindow.c:1028 msgid "Lose Changes" msgstr "" #: src/layer.c:523 #, c-format msgid "%d layers failed to load" msgstr "" #: src/layer.c:826 msgid "" "One or more of the image layers has not been saved. You must save each " "image individually before saving the layers text file in order to load this " "composite image in the future." msgstr "" #: src/layer.c:841 msgid "Do you really want to delete all of the layers?" msgstr "Gusto mo ba talagang burahin ang lahat ng mga leyer?" #: src/layer.c:970 msgid "You cannot add any more layers." msgstr "Hindi ka na pwedeng magdadag pa ng mga layer" #: src/layer.c:1083 src/otherwindow.c:241 msgid "New Layer" msgstr "Bagong Layer" #: src/layer.c:1085 msgid "Raise" msgstr "" #: src/layer.c:1087 msgid "Lower" msgstr "" #: src/layer.c:1089 msgid "Duplicate Layer" msgstr "" #: src/layer.c:1091 msgid "Centralise Layer" msgstr "" #: src/layer.c:1093 msgid "Delete Layer" msgstr "" #: src/layer.c:1095 msgid "Close Layers Window" msgstr "" #: src/layer.c:1101 msgid "Layer Name" msgstr "Pangalan ng Layer" #: src/layer.c:1104 src/toolbar.c:209 msgid "Position" msgstr "Posisyon" #: src/layer.c:1112 msgid "Transparent Colour" msgstr "" #: src/layer.c:1117 msgid "Show all layers in main window" msgstr "Ipakita lahat ng mga layer sa main window" #: src/mainwindow.c:67 src/otherwindow.c:844 src/otherwindow.c:2756 #: src/toolbar.c:342 msgid "Image" msgstr "Imahe" #: src/mainwindow.c:69 src/mainwindow.c:489 src/otherwindow.c:1613 #: src/otherwindow.c:2302 msgid "RGB" msgstr "RGB" #: src/mainwindow.c:69 src/otherwindow.c:1613 src/otherwindow.c:2302 msgid "sRGB" msgstr "" #: src/mainwindow.c:342 msgid "There were no unused colours to remove!" msgstr "" #: src/mainwindow.c:371 msgid "The palette does not contain 2 colours that have identical RGB values" msgstr "" #: src/mainwindow.c:374 #, c-format msgid "" "The palette contains %i colours that have identical RGB values. Do you " "really want to merge them into one index and realign the canvas?" msgstr "" #: src/mainwindow.c:492 msgid "indexed" msgstr "naka-index" #: src/mainwindow.c:498 #, c-format msgid "" "You are trying to save an %s image to an %s file which is not possible. I " "would suggest you save with a PNG extension." msgstr "" #: src/mainwindow.c:500 #, c-format msgid "" "You are trying to save an %s file with a palette of more than %d colours. " "Either use another format or reduce the palette to %d colours." msgstr "" #: src/mainwindow.c:578 msgid "Unable to load clipboard" msgstr "Hindi mai-karga ang clipboard" #: src/mainwindow.c:604 msgid "Unable to save clipboard" msgstr "Hindi mai-save ang clipboard" #: src/mainwindow.c:775 msgid "Zoom in" msgstr "" #: src/mainwindow.c:777 msgid "Zoom out" msgstr "" #: src/mainwindow.c:779 #, c-format msgid "10% zoom" msgstr "" #: src/mainwindow.c:781 #, c-format msgid "25% zoom" msgstr "" #: src/mainwindow.c:783 #, c-format msgid "50% zoom" msgstr "" #: src/mainwindow.c:785 #, c-format msgid "100% zoom" msgstr "" #: src/mainwindow.c:787 #, c-format msgid "400% zoom" msgstr "" #: src/mainwindow.c:789 #, c-format msgid "600% zoom" msgstr "" #: src/mainwindow.c:791 #, c-format msgid "800% zoom" msgstr "" #: src/mainwindow.c:793 #, c-format msgid "1000% zoom" msgstr "" #: src/mainwindow.c:795 #, c-format msgid "1200% zoom" msgstr "" #: src/mainwindow.c:797 #, c-format msgid "1600% zoom" msgstr "" #: src/mainwindow.c:799 #, c-format msgid "2000% zoom" msgstr "" #: src/mainwindow.c:801 #, c-format msgid "4000% zoom" msgstr "" #: src/mainwindow.c:803 #, c-format msgid "8000% zoom" msgstr "" #: src/mainwindow.c:805 #, c-format msgid "10% opacity" msgstr "" #: src/mainwindow.c:807 #, c-format msgid "20% opacity" msgstr "" #: src/mainwindow.c:809 #, c-format msgid "30% opacity" msgstr "" #: src/mainwindow.c:811 #, c-format msgid "40% opacity" msgstr "" #: src/mainwindow.c:813 #, c-format msgid "50% opacity" msgstr "" #: src/mainwindow.c:815 #, c-format msgid "60% opacity" msgstr "" #: src/mainwindow.c:817 #, c-format msgid "70% opacity" msgstr "" #: src/mainwindow.c:819 #, c-format msgid "80% opacity" msgstr "" #: src/mainwindow.c:821 #, c-format msgid "90% opacity" msgstr "" #: src/mainwindow.c:823 #, c-format msgid "100% opacity" msgstr "" #: src/mainwindow.c:825 msgid "Increase opacity" msgstr "" #: src/mainwindow.c:827 msgid "Decrease opacity" msgstr "" #: src/mainwindow.c:829 msgid "Draw open arrow head" msgstr "" #: src/mainwindow.c:831 msgid "Draw closed arrow head" msgstr "" #: src/mainwindow.c:833 msgid "Previous colour A" msgstr "" #: src/mainwindow.c:835 msgid "Next colour A" msgstr "" #: src/mainwindow.c:837 msgid "Previous colour B" msgstr "" #: src/mainwindow.c:839 msgid "Next colour B" msgstr "" #: src/mainwindow.c:841 msgid "Previous pattern" msgstr "" #: src/mainwindow.c:843 msgid "Next pattern" msgstr "" #: src/mainwindow.c:845 msgid "Larger brush" msgstr "" #: src/mainwindow.c:847 msgid "Smaller brush" msgstr "" #: src/mainwindow.c:849 msgid "View window - Zoom in" msgstr "" #: src/mainwindow.c:851 msgid "View window - Zoom out" msgstr "" #: src/mainwindow.c:1027 msgid "" "This canvas/palette contains changes that have not been saved. Do you " "really want to lose these changes?" msgstr "" "Ang kanbas/paleyt na ito ay may mga nabago at hindi pa nai-sasave. Gusto mo " "bang bali-walain ang mga nabago?" #: src/mainwindow.c:1094 msgid "Do you really want to quit?" msgstr "Gusto mo ba talagang umalis?" #: src/mainwindow.c:3754 msgid "Empty string or broken quoting" msgstr "" #: src/mainwindow.c:3755 msgid "Script must begin with a command" msgstr "" #: src/mainwindow.c:3756 msgid "Script nesting limit exceeded" msgstr "" #: src/mainwindow.c:3765 #, c-format msgid "'%s' does not match any item" msgstr "" #: src/mainwindow.c:3767 #, c-format msgid "'%s' matches a non-scriptable item" msgstr "" #: src/mainwindow.c:3769 #, c-format msgid "'%s' matches a disabled item" msgstr "" #: src/mainwindow.c:3788 #, c-format msgid "'%s' value does not fit item" msgstr "" #: src/mainwindow.c:3969 msgid "Script" msgstr "" #: src/mainwindow.c:3982 src/spawn.c:656 src/spawn.c:662 msgid "Action" msgstr "Aksyon" #: src/mainwindow.c:3991 src/spawn.c:666 msgid "Execute" msgstr "Isagawa" #: src/mainwindow.c:4045 msgid "Unable to load script" msgstr "" #: src/mainwindow.c:5182 msgid "/_File" msgstr "" #: src/mainwindow.c:5184 msgid "//New" msgstr "" #: src/mainwindow.c:5186 msgid "//Open ..." msgstr "" #: src/mainwindow.c:5188 src/mainwindow.c:5669 msgid "//Save" msgstr "" #: src/mainwindow.c:5190 src/mainwindow.c:5549 src/mainwindow.c:5627 #: src/mainwindow.c:5671 msgid "//Save As ..." msgstr "" #: src/mainwindow.c:5192 msgid "//Export Undo Images ..." msgstr "" #: src/mainwindow.c:5194 msgid "//Export Undo Images (reversed) ..." msgstr "" #: src/mainwindow.c:5196 msgid "//Export ASCII Art ..." msgstr "" #: src/mainwindow.c:5198 msgid "//Export Animated GIF ..." msgstr "" #: src/mainwindow.c:5201 msgid "//Actions" msgstr "" #: src/mainwindow.c:5235 src/mainwindow.c:5488 msgid "///Configure" msgstr "" #: src/mainwindow.c:5290 msgid "//Quit" msgstr "" #: src/mainwindow.c:5293 msgid "/_Edit" msgstr "" #: src/mainwindow.c:5295 msgid "//Undo" msgstr "" #: src/mainwindow.c:5297 msgid "//Redo" msgstr "" #: src/mainwindow.c:5300 msgid "//Cut" msgstr "//Putulin" #: src/mainwindow.c:5302 msgid "//Copy" msgstr "//Kopyahin" #: src/mainwindow.c:5304 msgid "//Copy To Palette" msgstr "" #: src/mainwindow.c:5306 msgid "//Paste To Centre" msgstr "//Idikit sa Gitna" #: src/mainwindow.c:5308 msgid "//Paste To New Layer" msgstr "//Idikit sa Bagong Layer" #: src/mainwindow.c:5310 msgid "//Paste" msgstr "//Idikit" #: src/mainwindow.c:5312 msgid "//Paste Text" msgstr "//Idikit ang Teksto" #: src/mainwindow.c:5318 msgid "//Paste Text (FreeType)" msgstr "" #: src/mainwindow.c:5321 msgid "//Paste Palette" msgstr "" #: src/mainwindow.c:5323 msgid "//Load Clipboard" msgstr "//Ikarga ang Clipbord" #: src/mainwindow.c:5350 msgid "//Save Clipboard" msgstr "//I-save ang Clipboard" #: src/mainwindow.c:5377 msgid "//Import Clipboard from System" msgstr "" #: src/mainwindow.c:5378 msgid "//Export Clipboard to System" msgstr "" #: src/mainwindow.c:5381 msgid "//Choose Pattern ..." msgstr "" #: src/mainwindow.c:5383 msgid "//Choose Brush ..." msgstr "//Pumili ng Brush ..." #: src/mainwindow.c:5385 msgid "//Choose Colour ..." msgstr "" #: src/mainwindow.c:5392 msgid "/_View" msgstr "/_Tignan" #: src/mainwindow.c:5394 msgid "//Show Main Toolbar" msgstr "//Ipakita ang Main Toolbar" #: src/mainwindow.c:5396 msgid "//Show Tools Toolbar" msgstr "//Ipakita ang Tools Toolbar" #: src/mainwindow.c:5399 msgid "//Show Settings Toolbar" msgstr "//Ipakita ang Settings Toolbar" #: src/mainwindow.c:5402 msgid "//Show Dock" msgstr "" #: src/mainwindow.c:5404 msgid "//Show Palette" msgstr "//Ipakita ang Palette" #: src/mainwindow.c:5406 msgid "//Show Status Bar" msgstr "//Ipakita ang Istatus Bar" #: src/mainwindow.c:5409 msgid "//Toggle Image View" msgstr "" #: src/mainwindow.c:5413 msgid "//Centralize Image" msgstr "//Igitna ang Imahe" #: src/mainwindow.c:5414 msgid "//Show Zoom Grid" msgstr "" #: src/mainwindow.c:5415 msgid "//Snap To Tile Grid" msgstr "" #: src/mainwindow.c:5417 msgid "//Configure Grid ..." msgstr "" #: src/mainwindow.c:5418 msgid "//Tracing Image ..." msgstr "" #: src/mainwindow.c:5421 msgid "//View Window" msgstr "" #: src/mainwindow.c:5423 msgid "//Horizontal Split" msgstr "//Pahalang na hati" #: src/mainwindow.c:5425 msgid "//Focus View Window" msgstr "//Ipokus ang View Window" #: src/mainwindow.c:5427 msgid "//Pan Window" msgstr "" #: src/mainwindow.c:5430 msgid "//Layers Window" msgstr "" #: src/mainwindow.c:5433 msgid "/_Image" msgstr "" #: src/mainwindow.c:5436 msgid "//Convert To RGB" msgstr "" #: src/mainwindow.c:5438 msgid "//Convert To Indexed ..." msgstr "" #: src/mainwindow.c:5441 msgid "//Scale Canvas ..." msgstr "" #: src/mainwindow.c:5443 msgid "//Resize Canvas ..." msgstr "" #: src/mainwindow.c:5445 msgid "//Crop" msgstr "" #: src/mainwindow.c:5448 src/mainwindow.c:5517 msgid "//Flip Vertically" msgstr "" #: src/mainwindow.c:5449 src/mainwindow.c:5519 msgid "//Flip Horizontally" msgstr "" #: src/mainwindow.c:5452 src/mainwindow.c:5521 msgid "//Rotate Clockwise" msgstr "" #: src/mainwindow.c:5453 src/mainwindow.c:5523 msgid "//Rotate Anti-Clockwise" msgstr "" #: src/mainwindow.c:5454 msgid "//Free Rotate ..." msgstr "" #: src/mainwindow.c:5455 msgid "//Skew ..." msgstr "" #: src/mainwindow.c:5458 msgid "//Segment ..." msgstr "" #: src/mainwindow.c:5462 msgid "//Script ..." msgstr "" #: src/mainwindow.c:5464 msgid "//Scripts" msgstr "" #: src/mainwindow.c:5491 msgid "//Information ..." msgstr "" #: src/mainwindow.c:5494 msgid "//Preferences ..." msgstr "" #: src/mainwindow.c:5497 msgid "/_Selection" msgstr "" #: src/mainwindow.c:5499 msgid "//Select All" msgstr "" #: src/mainwindow.c:5501 msgid "//Select None (Esc)" msgstr "" #: src/mainwindow.c:5503 msgid "//Lasso Selection" msgstr "" #: src/mainwindow.c:5505 msgid "//Lasso Selection Cut" msgstr "" #: src/mainwindow.c:5508 msgid "//Outline Selection" msgstr "" #: src/mainwindow.c:5510 msgid "//Fill Selection" msgstr "" #: src/mainwindow.c:5512 msgid "//Outline Ellipse" msgstr "" #: src/mainwindow.c:5514 msgid "//Fill Ellipse" msgstr "" #: src/mainwindow.c:5526 msgid "//Horizontal Ramp" msgstr "" #: src/mainwindow.c:5528 msgid "//Vertical Ramp" msgstr "" #: src/mainwindow.c:5531 msgid "//Alpha Blend A,B" msgstr "" #: src/mainwindow.c:5533 msgid "//Move Alpha to Mask" msgstr "" #: src/mainwindow.c:5535 msgid "//Mask Colour A,B" msgstr "" #: src/mainwindow.c:5537 msgid "//Unmask Colour A,B" msgstr "" #: src/mainwindow.c:5539 msgid "//Mask All Colours" msgstr "" #: src/mainwindow.c:5541 msgid "//Clear Mask" msgstr "" #: src/mainwindow.c:5544 msgid "/_Palette" msgstr "" #: src/mainwindow.c:5548 src/mainwindow.c:5626 msgid "//Load ..." msgstr "" #: src/mainwindow.c:5550 msgid "//Load Default" msgstr "" #: src/mainwindow.c:5552 msgid "//Mask All" msgstr "" #: src/mainwindow.c:5553 msgid "//Mask None" msgstr "" #: src/mainwindow.c:5555 msgid "//Swap A & B" msgstr "" #: src/mainwindow.c:5557 msgid "//Edit Colour A & B ..." msgstr "" #: src/mainwindow.c:5559 msgid "//Dither A" msgstr "" #: src/mainwindow.c:5561 msgid "//Palette Editor ..." msgstr "" #: src/mainwindow.c:5563 msgid "//Set Palette Size ..." msgstr "" #: src/mainwindow.c:5564 msgid "//Merge Duplicate Colours" msgstr "" #: src/mainwindow.c:5566 msgid "//Remove Unused Colours" msgstr "" #: src/mainwindow.c:5569 msgid "//Create Quantized ..." msgstr "" #: src/mainwindow.c:5572 msgid "//Sort Colours ..." msgstr "" #: src/mainwindow.c:5573 msgid "//Palette Shifter ..." msgstr "" #: src/mainwindow.c:5574 msgid "//Pick Gradient ..." msgstr "" #: src/mainwindow.c:5576 msgid "/Effe_cts" msgstr "" #: src/mainwindow.c:5578 msgid "//Transform Colour ..." msgstr "" #: src/mainwindow.c:5580 msgid "//Invert" msgstr "" #: src/mainwindow.c:5582 msgid "//Greyscale" msgstr "" #: src/mainwindow.c:5584 msgid "//Greyscale (Gamma corrected)" msgstr "" #: src/mainwindow.c:5586 msgid "//Normalize" msgstr "" #: src/mainwindow.c:5587 src/mainwindow.c:5658 msgid "//Threshold ..." msgstr "" #: src/mainwindow.c:5588 msgid "//Map ..." msgstr "" #: src/mainwindow.c:5590 msgid "//Isometric Transformation" msgstr "" #: src/mainwindow.c:5592 msgid "///Left Side Down" msgstr "" #: src/mainwindow.c:5593 msgid "///Right Side Down" msgstr "" #: src/mainwindow.c:5594 msgid "///Top Side Right" msgstr "" #: src/mainwindow.c:5595 msgid "///Bottom Side Right" msgstr "" #: src/mainwindow.c:5598 msgid "//Edge Detect ..." msgstr "" #: src/mainwindow.c:5600 msgid "//Difference of Gaussians ..." msgstr "" #: src/mainwindow.c:5602 msgid "//Sharpen ..." msgstr "" #: src/mainwindow.c:5604 msgid "//Unsharp Mask ..." msgstr "" #: src/mainwindow.c:5606 msgid "//Soften ..." msgstr "" #: src/mainwindow.c:5608 msgid "//Gaussian Blur ..." msgstr "" #: src/mainwindow.c:5610 msgid "//Kuwahara-Nagao Blur ..." msgstr "" #: src/mainwindow.c:5612 msgid "//Emboss" msgstr "" #: src/mainwindow.c:5614 msgid "//Dilate" msgstr "" #: src/mainwindow.c:5616 msgid "//Erode" msgstr "" #: src/mainwindow.c:5619 msgid "//Solid Noise ..." msgstr "" #: src/mainwindow.c:5620 msgid "//Bacteria ..." msgstr "" #: src/mainwindow.c:5623 msgid "/Cha_nnels" msgstr "" #: src/mainwindow.c:5625 msgid "//New ..." msgstr "" #: src/mainwindow.c:5628 msgid "//Delete ..." msgstr "" #: src/mainwindow.c:5632 msgid "//Edit Image" msgstr "" #: src/mainwindow.c:5635 msgid "//Edit Alpha" msgstr "" #: src/mainwindow.c:5638 msgid "//Edit Selection" msgstr "" #: src/mainwindow.c:5641 msgid "//Edit Mask" msgstr "" #: src/mainwindow.c:5645 msgid "//Hide Image" msgstr "" #: src/mainwindow.c:5648 msgid "//Disable Alpha" msgstr "" #: src/mainwindow.c:5651 msgid "//Disable Selection" msgstr "" #: src/mainwindow.c:5654 msgid "//Disable Mask" msgstr "" #: src/mainwindow.c:5657 msgid "//Couple RGBA Operations" msgstr "" #: src/mainwindow.c:5659 msgid "//Unassociate Alpha" msgstr "" #: src/mainwindow.c:5663 msgid "//View Alpha as an Overlay" msgstr "" #: src/mainwindow.c:5664 msgid "//Configure Overlays ..." msgstr "" #: src/mainwindow.c:5666 msgid "/_Layers" msgstr "" #: src/mainwindow.c:5668 msgid "//New Layer" msgstr "" #: src/mainwindow.c:5672 msgid "//Save Composite Image ..." msgstr "" #: src/mainwindow.c:5673 msgid "//Composite to New Layer" msgstr "" #: src/mainwindow.c:5674 msgid "//Remove All Layers" msgstr "" #: src/mainwindow.c:5676 msgid "//Configure Animation ..." msgstr "" #: src/mainwindow.c:5677 msgid "//Preview Animation ..." msgstr "" #: src/mainwindow.c:5678 msgid "//Set Key Frame ..." msgstr "" #: src/mainwindow.c:5679 msgid "//Remove All Key Frames ..." msgstr "" #: src/mainwindow.c:5681 msgid "/More..." msgstr "" #: src/mainwindow.c:5683 msgid "/_Help" msgstr "" #: src/mainwindow.c:5684 msgid "//Documentation" msgstr "" #: src/mainwindow.c:5686 msgid "//About" msgstr "" #: src/mainwindow.c:5689 msgid "//Keyboard Shortcuts ..." msgstr "" #: src/mainwindow.c:5690 msgid "//Rebind Shortcut Keycodes" msgstr "" #: src/memory.c:2800 msgid "Quantize Pass 1" msgstr "" #: src/memory.c:2854 msgid "Quantize Pass 2" msgstr "" #: src/memory.c:3073 src/memory.c:3458 msgid "Converting to Indexed Palette" msgstr "" #: src/memory.c:5135 src/otherwindow.c:540 msgid "Bacteria Effect" msgstr "Epektong Mala-Bakterya" #: src/memory.c:5170 msgid "Rotating" msgstr "Iniikot" #: src/memory.c:5511 msgid "Free Rotation" msgstr "Libreng Pag-iikot" #: src/memory.c:6096 msgid "Scaling Image" msgstr "" #: src/memory.c:7560 msgid "Counting Unique RGB Pixels" msgstr "" #: src/memory.c:7608 msgid "Applying Effect" msgstr "Ginagawa ang Effect" #: src/memory.c:8792 msgid "Kuwahara-Nagao Filter" msgstr "" #: src/memory.c:10456 src/otherwindow.c:2665 msgid "Skew" msgstr "" #: src/memory.c:10630 msgid "Segmentation Pass 1" msgstr "" #: src/memory.c:10757 msgid "Segmentation Pass 2" msgstr "" #: src/memory.c:11019 src/otherwindow.c:3156 msgid "Solid Noise" msgstr "" #: src/mygtk.c:134 src/mygtk.c:163 msgid "Please Wait ..." msgstr "Maghintay lang po ..." #: src/mygtk.c:141 msgid "STOP" msgstr "ITIGIL" #: src/mygtk.c:504 msgid "Disabled" msgstr "" #: src/mygtk.c:504 src/toolbar.c:301 msgid "Screen" msgstr "Screen" #: src/mygtk.c:504 msgid "Window" msgstr "" #: src/mygtk.c:508 msgid "Input" msgstr "" #: src/mygtk.c:512 msgid "Device:" msgstr "" #: src/mygtk.c:514 msgid "Mode:" msgstr "" #: src/mygtk.c:519 msgid "Axes" msgstr "" #: src/mygtk.c:524 msgid "X:" msgstr "" #: src/mygtk.c:525 msgid "Y:" msgstr "" #: src/mygtk.c:526 msgid "Pressure:" msgstr "" #: src/mygtk.c:527 msgid "X tilt:" msgstr "" #: src/mygtk.c:528 msgid "Y tilt:" msgstr "" #: src/mygtk.c:529 msgid "Wheel:" msgstr "" #: src/mygtk.c:579 msgid "none" msgstr "" #: src/otherwindow.c:236 msgid "24 bit RGB" msgstr "24 bit na RGB" #: src/otherwindow.c:236 src/otherwindow.c:3179 msgid "Greyscale" msgstr "Greyscale" #: src/otherwindow.c:237 msgid "Indexed Palette" msgstr "" #: src/otherwindow.c:237 msgid "From Clipboard" msgstr "Mula sa Klipbord" #: src/otherwindow.c:237 msgid "Grab Screenshot" msgstr "Dumukot ng Iskrinshat" #: src/otherwindow.c:242 src/toolbar.c:542 msgid "New Image" msgstr "Bagong Imahe" #: src/otherwindow.c:246 src/otherwindow.c:3164 msgid "Colours" msgstr "Mga Kulay" #: src/otherwindow.c:409 msgid "Pattern Chooser" msgstr "" #: src/otherwindow.c:497 msgid "Set Palette Size" msgstr "" #: src/otherwindow.c:517 src/otherwindow.c:591 src/otherwindow.c:870 #: src/otherwindow.c:2538 src/otherwindow.c:2776 src/otherwindow.c:2939 #: src/prefs.c:338 src/prefs.c:538 msgid "Apply" msgstr "I-apply" #: src/otherwindow.c:573 msgid "Luminance" msgstr "Pagka-liwanag" #: src/otherwindow.c:573 src/otherwindow.c:814 msgid "Brightness" msgstr "Pagka-liwanag" #: src/otherwindow.c:574 msgid "Distance to A" msgstr "Layo patungo sa A" #: src/otherwindow.c:575 msgid "Projection to A->B" msgstr "" #: src/otherwindow.c:576 msgid "Frequency" msgstr "Frequency" #: src/otherwindow.c:580 msgid "Sort Palette Colours" msgstr "" #: src/otherwindow.c:582 msgid "Start Index" msgstr "Simulan ang Indes" #: src/otherwindow.c:583 msgid "End Index" msgstr "Tapusin ang Index" #: src/otherwindow.c:589 msgid "Reverse Order" msgstr "" #: src/otherwindow.c:805 msgid "Bitwise" msgstr "" #: src/otherwindow.c:805 msgid "Truncated" msgstr "" #: src/otherwindow.c:805 msgid "Rounded" msgstr "" #: src/otherwindow.c:809 src/toolbar.c:311 src/toolbar.c:558 msgid "Transform Colour" msgstr "" #: src/otherwindow.c:812 msgid "Gamma" msgstr "Gama" #: src/otherwindow.c:816 msgid "Contrast" msgstr "" #: src/otherwindow.c:822 src/otherwindow.c:1674 msgid "Posterize" msgstr "Posterize" #: src/otherwindow.c:831 msgid "Show Detail" msgstr "Ipakita ang Detalye" #: src/otherwindow.c:836 msgid "Posterize type" msgstr "" #: src/otherwindow.c:857 msgid "Auto-Preview" msgstr "" #: src/otherwindow.c:869 msgid "Reset" msgstr "Ibalik sa Dati" #: src/otherwindow.c:931 msgid "New geometry is the same as now - nothing to do." msgstr "" #: src/otherwindow.c:980 msgid "The operating system cannot allocate the memory for this operation." msgstr "" #: src/otherwindow.c:982 msgid "" "You have not allocated enough memory in the Preferences window for this " "operation." msgstr "" #: src/otherwindow.c:993 src/otherwindow.c:2495 msgid "Mirror" msgstr "Salamin" #: src/otherwindow.c:993 src/otherwindow.c:994 msgid "Tile" msgstr "" #: src/otherwindow.c:993 msgid "Void" msgstr "" #: src/otherwindow.c:994 src/shifter.c:283 msgid "Clear" msgstr "Burahin" #: src/otherwindow.c:994 msgid "Mirror tile" msgstr "" #: src/otherwindow.c:996 msgid "Nearest Neighbour" msgstr "Pinakamalapit na Kapitbahay" #: src/otherwindow.c:997 msgid "Bilinear / Area Mapping" msgstr "" #: src/otherwindow.c:998 msgid "Bicubic" msgstr "" #: src/otherwindow.c:999 msgid "Bicubic edged" msgstr "" #: src/otherwindow.c:1000 msgid "Bicubic better" msgstr "" #: src/otherwindow.c:1001 msgid "Bicubic sharper" msgstr "" #: src/otherwindow.c:1002 msgid "Blackman-Harris" msgstr "" #: src/otherwindow.c:1008 msgid "Scale Canvas" msgstr "" #: src/otherwindow.c:1009 msgid "Resize Canvas" msgstr "Ibahin ang Size ng Kanbas" #: src/otherwindow.c:1012 msgid "Original " msgstr "Orihinal " #: src/otherwindow.c:1013 msgid "New" msgstr "Panibago" #: src/otherwindow.c:1014 msgid "Width " msgstr "Lapad " #: src/otherwindow.c:1018 msgid "Height " msgstr "Taas " #: src/otherwindow.c:1023 src/otherwindow.c:2514 src/otherwindow.c:2672 #: src/toolbar.c:212 msgid "Offset" msgstr "" #: src/otherwindow.c:1026 src/otherwindow.c:1615 src/viewer.c:1209 msgid "Centre" msgstr "Gitna" #: src/otherwindow.c:1033 src/otherwindow.c:1052 msgid "Fix Aspect Ratio" msgstr "" #: src/otherwindow.c:1039 src/otherwindow.c:2070 src/toolbar.c:312 msgid "Settings" msgstr "Mga Kaayusan" #: src/otherwindow.c:1046 msgid "Sharper image reduction" msgstr "" #: src/otherwindow.c:1047 msgid "Boundary extension" msgstr "" #: src/otherwindow.c:1613 src/otherwindow.c:2302 msgid "HSV" msgstr "HSV" #: src/otherwindow.c:1614 msgid "Highlight" msgstr "" #: src/otherwindow.c:1615 msgid "Limit" msgstr "Hangganan" #: src/otherwindow.c:1616 msgid "Sphere" msgstr "Bola" #: src/otherwindow.c:1616 src/otherwindow.c:2670 msgid "Angle" msgstr "Anggulo" #: src/otherwindow.c:1616 msgid "Cube" msgstr "" #: src/otherwindow.c:1617 msgid "Opaque" msgstr "" #: src/otherwindow.c:1617 msgid "Border" msgstr "Gilid" #: src/otherwindow.c:1618 msgid "Transparent" msgstr "Transparent" #: src/otherwindow.c:1618 msgid "Tile " msgstr "" #: src/otherwindow.c:1618 msgid "Segment" msgstr "" #: src/otherwindow.c:1656 msgid "Scale" msgstr "Baguhin ang Laki" #: src/otherwindow.c:1657 src/otherwindow.c:3059 msgid "From" msgstr "Mula sa" #: src/otherwindow.c:1659 src/otherwindow.c:3061 msgid "To" msgstr "Hanggang" #: src/otherwindow.c:1699 msgid "Range" msgstr "" #: src/otherwindow.c:1702 msgid "Inverse" msgstr "" #: src/otherwindow.c:1710 msgid "Smart grid" msgstr "Matalinong grid" #: src/otherwindow.c:1712 msgid "Tile grid" msgstr "" #: src/otherwindow.c:1714 msgid "Minimum grid zoom" msgstr "" #: src/otherwindow.c:1717 msgid "Tile width" msgstr "Lapad ng Tile" #: src/otherwindow.c:1720 msgid "Tile height" msgstr "Taas ng Tile" #: src/otherwindow.c:1744 msgid "Palette Editor" msgstr "Editor ng Palette" #: src/otherwindow.c:1763 msgid "Configure Overlays" msgstr "" #: src/otherwindow.c:1782 msgid "Colour Editor" msgstr "Editor ng Kulay" #: src/otherwindow.c:1818 src/toolbar.c:430 msgid "Colour-Selective Mode" msgstr "" #: src/otherwindow.c:1843 msgid "Configure Grid" msgstr "" #: src/otherwindow.c:2045 msgid "Exact Conversion" msgstr "Saktong Konbersyon" #: src/otherwindow.c:2045 msgid "Use Current Palette" msgstr "" #: src/otherwindow.c:2046 msgid "PNN Quantize (slow, better quality)" msgstr "" #: src/otherwindow.c:2047 msgid "Wu Quantize (fast)" msgstr "" #: src/otherwindow.c:2048 msgid "Max-Min Quantize (best for small palettes and dithering)" msgstr "" #: src/otherwindow.c:2049 src/otherwindow.c:2495 src/otherwindow.c:2756 #: src/png.c:2794 src/prefs.c:377 msgid "None" msgstr "Wala" #: src/otherwindow.c:2049 msgid "Floyd-Steinberg" msgstr "Floyd-Steinberg" #: src/otherwindow.c:2049 msgid "Stucki" msgstr "Stucki" #: src/otherwindow.c:2052 msgid "Floyd-Steinberg (quick)" msgstr "Floyd-Steinberg (madalian)" #: src/otherwindow.c:2052 msgid "Dithered (effect)" msgstr "Dithered (effect)" #: src/otherwindow.c:2053 msgid "Scattered (effect)" msgstr "Pakalat (effect)" #: src/otherwindow.c:2054 msgid "Gamut" msgstr "Gamut" #: src/otherwindow.c:2054 msgid "Weakly" msgstr "" #: src/otherwindow.c:2054 msgid "Strongly" msgstr "" #: src/otherwindow.c:2055 msgid "Off" msgstr "Off" #: src/otherwindow.c:2055 msgid "Separate/Sum" msgstr "" #: src/otherwindow.c:2055 msgid "Separate/Split" msgstr "" #: src/otherwindow.c:2056 msgid "Length/Sum" msgstr "" #: src/otherwindow.c:2056 msgid "Length/Split" msgstr "" #: src/otherwindow.c:2057 msgid "Largest (Linf)" msgstr "Pinakamalaki (Linf)" #: src/otherwindow.c:2057 msgid "Sum (L1)" msgstr "Kabuuan (L1)" #: src/otherwindow.c:2057 msgid "Euclidean (L2)" msgstr "" #: src/otherwindow.c:2061 msgid "Create Quantized" msgstr "" #: src/otherwindow.c:2062 msgid "Convert To Indexed" msgstr "" #: src/otherwindow.c:2065 msgid "Indexed Colours To Use" msgstr "" #: src/otherwindow.c:2078 msgid "Truncate palette" msgstr "Putulin ang paleyt" #: src/otherwindow.c:2079 msgid "Diameter based weighting" msgstr "" #: src/otherwindow.c:2084 msgid "Dither" msgstr "" #: src/otherwindow.c:2087 src/otherwindow.c:2584 src/otherwindow.c:2928 msgid "Colour space" msgstr "" #: src/otherwindow.c:2088 src/otherwindow.c:2929 msgid "Difference measure" msgstr "" #: src/otherwindow.c:2089 msgid "Reduce colour bleed" msgstr "" #: src/otherwindow.c:2090 msgid "Serpentine scan" msgstr "" #: src/otherwindow.c:2092 msgid "Error propagation, %" msgstr "" #: src/otherwindow.c:2093 msgid "Selective error propagation" msgstr "" #: src/otherwindow.c:2097 msgid "Full error precision" msgstr "" #: src/otherwindow.c:2302 msgid "Backward HSV" msgstr "" #: src/otherwindow.c:2303 src/otherwindow.c:2326 msgid "Constant" msgstr "" #: src/otherwindow.c:2307 msgid "Edit Gradient" msgstr "" #: src/otherwindow.c:2329 msgid "Points:" msgstr "" #: src/otherwindow.c:2493 msgid "Linear" msgstr "" #: src/otherwindow.c:2493 src/otherwindow.c:2703 msgid "Bilinear" msgstr "" #: src/otherwindow.c:2493 msgid "Radial" msgstr "" #: src/otherwindow.c:2494 msgid "Square" msgstr "Parisukat" #: src/otherwindow.c:2494 msgid "Angular" msgstr "" #: src/otherwindow.c:2494 msgid "Conical" msgstr "" #: src/otherwindow.c:2495 msgid "Level " msgstr "" #: src/otherwindow.c:2495 msgid "Repeat" msgstr "" #: src/otherwindow.c:2496 msgid "A to B" msgstr "Mula A hanggang B" #: src/otherwindow.c:2496 msgid "A to B (RGB)" msgstr "Mula A hanggang B (RGB)" #: src/otherwindow.c:2497 msgid "A to B (sRGB)" msgstr "" #: src/otherwindow.c:2497 msgid "A to B (HSV)" msgstr "Mula A hanggang B (HSV)" #: src/otherwindow.c:2497 msgid "A to B (backward HSV)" msgstr "Mula A hanggang B (pabaligtad na HSV)" #: src/otherwindow.c:2498 msgid "A only" msgstr "A lang" #: src/otherwindow.c:2498 src/otherwindow.c:2500 msgid "Custom" msgstr "" #: src/otherwindow.c:2499 msgid "Current to 0" msgstr "" #: src/otherwindow.c:2499 msgid "Current only" msgstr "" #: src/otherwindow.c:2504 msgid "Configure Gradient" msgstr "" #: src/otherwindow.c:2507 src/png.c:1001 msgid "Channel" msgstr "" #: src/otherwindow.c:2512 msgid "Length" msgstr "Haba" #: src/otherwindow.c:2513 msgid "Repeat length" msgstr "Ulitin ang haba" #: src/otherwindow.c:2515 msgid "Gradient type" msgstr "" #: src/otherwindow.c:2516 msgid "Extension type" msgstr "" #: src/otherwindow.c:2517 msgid "Distance type" msgstr "" #: src/otherwindow.c:2518 msgid "Preview opacity" msgstr "" #: src/otherwindow.c:2527 src/otherwindow.c:2533 src/toolbar.c:309 msgid "Reverse" msgstr "" #: src/otherwindow.c:2528 src/otherwindow.c:2534 msgid "Edit Custom" msgstr "" #: src/otherwindow.c:2592 msgid "Pick Gradient" msgstr "" #: src/otherwindow.c:2668 msgid "Horizontal " msgstr "Pahalang " #: src/otherwindow.c:2674 msgid "At distance" msgstr "" #: src/otherwindow.c:2675 msgid "Vertical" msgstr "Patindig" #: src/otherwindow.c:2756 msgid "Unchanged" msgstr "Hindi nagbago" #: src/otherwindow.c:2761 msgid "Tracing Image" msgstr "" #: src/otherwindow.c:2763 src/toolbar.c:315 msgid "Source" msgstr "Pinanggalingan" #: src/otherwindow.c:2768 msgid "Origin" msgstr "Pinagmulan" #: src/otherwindow.c:2771 msgid "Relative scale" msgstr "" #: src/otherwindow.c:2774 msgid "Display" msgstr "Display" #: src/otherwindow.c:2926 msgid "Segment Image" msgstr "" #: src/otherwindow.c:2931 src/toolbar.c:304 msgid "Threshold" msgstr "" #: src/otherwindow.c:2933 msgid "Level" msgstr "" #: src/otherwindow.c:2934 msgid "Minimum size" msgstr "" #: src/otherwindow.c:3053 msgid "Max" msgstr "" #: src/otherwindow.c:3053 msgid "Min" msgstr "" #: src/otherwindow.c:3057 msgid "Threshold Image" msgstr "" #: src/otherwindow.c:3158 msgid "Seed" msgstr "" #: src/otherwindow.c:3160 msgid "X span" msgstr "" #: src/otherwindow.c:3161 msgid "Y span" msgstr "" #: src/otherwindow.c:3162 msgid "Octaves" msgstr "" #: src/png.c:620 #, c-format msgid "Saving %s image" msgstr "Sinasave na ang imaheng %s" #: src/png.c:620 #, c-format msgid "Loading %s image" msgstr "Kinakarga na ang imaheng %s" #: src/png.c:998 msgid "Layer" msgstr "Leyer" #: src/png.c:3577 msgid "Lossless" msgstr "" #: src/png.c:3577 msgid "Default" msgstr "" #: src/png.c:3577 msgid "Picture" msgstr "" #: src/png.c:3577 msgid "Photo" msgstr "" #: src/png.c:3578 msgid "Drawing" msgstr "" #: src/png.c:3578 msgid "Icon" msgstr "" #: src/png.c:8370 msgid "Applying colour profile" msgstr "" #: src/png.c:8792 #, c-format msgid "%d out of %d frames could not be saved as %s - saved as PNG instead" msgstr "" #: src/png.c:8809 msgid "Explode frames" msgstr "" #: src/prefs.c:56 msgid "Default System Language" msgstr "" #: src/prefs.c:57 msgid "Chinese (Simplified)" msgstr "Intsik (Simple)" #: src/prefs.c:57 msgid "Chinese (Taiwanese)" msgstr "Intsik (Taiwanese)" #: src/prefs.c:57 msgid "Czech" msgstr "Czech" #: src/prefs.c:58 msgid "Dutch" msgstr "Dutch" #: src/prefs.c:58 msgid "English (UK)" msgstr "Ingles (UK)" #: src/prefs.c:58 msgid "French" msgstr "Pranses" #: src/prefs.c:58 msgid "Galician" msgstr "Galisyiano" #: src/prefs.c:58 msgid "German" msgstr "Aleman" #: src/prefs.c:59 msgid "Hungarian" msgstr "" #: src/prefs.c:59 msgid "Italian" msgstr "" #: src/prefs.c:59 msgid "Japanese" msgstr "Hapones" #: src/prefs.c:59 msgid "Kabyle" msgstr "" #: src/prefs.c:59 msgid "Polish" msgstr "Polish" #: src/prefs.c:60 msgid "Portuguese" msgstr "Portuges" #: src/prefs.c:60 msgid "Portuguese (Brazilian)" msgstr "Portuges (Pam-Brazil)" #: src/prefs.c:60 msgid "Russian" msgstr "Ruso" #: src/prefs.c:60 msgid "Slovak" msgstr "Islovak" #: src/prefs.c:61 msgid "Spanish" msgstr "Kastila" #: src/prefs.c:61 msgid "Swedish" msgstr "" #: src/prefs.c:61 msgid "Tagalog" msgstr "" #: src/prefs.c:61 msgid "Turkish" msgstr "Turko" #: src/prefs.c:81 msgid "Current Device" msgstr "" #: src/prefs.c:135 msgid "Pressure" msgstr "Presyur" #: src/prefs.c:149 msgid "Preferences" msgstr "Mga kagustuhan" #: src/prefs.c:163 msgid "Max threads (0 to autodetect)" msgstr "" #: src/prefs.c:164 msgid "Min kpixels per render thread" msgstr "" #: src/prefs.c:171 msgid "Max memory used for undo (MB)" msgstr "" #: src/prefs.c:172 msgid "Max undo levels" msgstr "" #: src/prefs.c:173 msgid "Communal layer undo space (%)" msgstr "" #: src/prefs.c:175 msgid "Bayer master pattern" msgstr "" #: src/prefs.c:178 msgid "Use gamma correction by default" msgstr "" #: src/prefs.c:179 msgid "Use gamma correction when painting" msgstr "" #: src/prefs.c:180 msgid "Separate patterns for A & B" msgstr "" #: src/prefs.c:183 msgid "Optimize alpha chequers" msgstr "" #: src/prefs.c:184 msgid "Disable view window transparencies" msgstr "" #: src/prefs.c:185 msgid "Enable overlays by layer" msgstr "" #: src/prefs.c:189 msgid "Language" msgstr "Wika/Lenguahe" #: src/prefs.c:191 msgid "" "Select preferred language translation\n" "\n" "You will need to restart mtPaint\n" "for this to take full effect" msgstr "" "Pumili ng gustong lenguahe\n" "\n" "Dapat i-restart mo ang mtPaint\n" "para gumana ito" #: src/prefs.c:198 msgid "Interface" msgstr "Interpeys" #: src/prefs.c:200 msgid "Greyscale backdrop" msgstr "Greyscale na bakdrop" #: src/prefs.c:201 msgid "Selection nudge pixels" msgstr "" #: src/prefs.c:202 msgid "Max Pan Window Size" msgstr "" #: src/prefs.c:204 msgid "Display clipboard while pasting" msgstr "Ipakita ang klipbord habang nagdidikit" #: src/prefs.c:205 msgid "Mouse cursor = Tool" msgstr "" #: src/prefs.c:206 msgid "Confirm Exit" msgstr "" #: src/prefs.c:207 msgid "Q key quits mtPaint" msgstr "" #: src/prefs.c:208 msgid "Arrow keys scroll canvas" msgstr "" #: src/prefs.c:209 msgid "Changing tool commits paste" msgstr "" #: src/prefs.c:210 msgid "Centre tool settings dialogs" msgstr "" #: src/prefs.c:211 msgid "New image sets zoom to 100%" msgstr "" #: src/prefs.c:212 msgid "Zoom on cursor position" msgstr "" #: src/prefs.c:214 msgid "Mouse Scroll Wheel = Zoom" msgstr "" #: src/prefs.c:215 msgid "Use menu icons" msgstr "Gumamit ng menu icons" #: src/prefs.c:220 msgid "Files" msgstr "Mga Files" #: src/prefs.c:223 msgid "XBM X hotspot" msgstr "XBM X na hotspot" #: src/prefs.c:224 msgid "XBM Y hotspot" msgstr "XBM Y na hotspot" #: src/prefs.c:228 msgid "Recently Used Files" msgstr "Mga Files na Kasalukuyang Ginamit" #: src/prefs.c:229 msgid "Progress bar silence limit" msgstr "" #: src/prefs.c:232 msgid "Read 16-bit TGAs as 5:6:5 BGR" msgstr "" #: src/prefs.c:233 msgid "Write TGAs in bottom-up row order" msgstr "" #: src/prefs.c:234 msgid "Undoable image loading" msgstr "" #: src/prefs.c:245 msgid "Compression (RGB)" msgstr "" #: src/prefs.c:246 msgid "Compression (indexed)" msgstr "" #: src/prefs.c:247 msgid "Compression (monochrome)" msgstr "" #: src/prefs.c:255 msgid "Enable predictor" msgstr "" #: src/prefs.c:262 msgid "Compression mode" msgstr "" #: src/prefs.c:271 msgid "Channel for Mask Plane" msgstr "" #: src/prefs.c:273 msgid "Ignore Transparent Colour" msgstr "" #: src/prefs.c:274 msgid "PackBits Compression" msgstr "" #: src/prefs.c:275 msgid "Write Indexed as Planar Bitmap (PBM)" msgstr "" #: src/prefs.c:280 msgid "Paths" msgstr "" #: src/prefs.c:281 msgid "Clipboard Files" msgstr "" #: src/prefs.c:281 msgid "Select Clipboard File" msgstr "" #: src/prefs.c:283 msgid "HTML Browser Program" msgstr "Browser Program sa HTML" #: src/prefs.c:283 msgid "Select Browser Program" msgstr "Pumili ng Browser Program" #: src/prefs.c:285 msgid "Location of Handbook index" msgstr "Lokasyon ng Handbook index" #: src/prefs.c:285 msgid "Select Handbook Index File" msgstr "Pumili ng Handbook Index File" #: src/prefs.c:287 msgid "Default Palette" msgstr "" #: src/prefs.c:287 msgid "Select Default Palette" msgstr "" #: src/prefs.c:289 msgid "Default Patterns" msgstr "" #: src/prefs.c:289 msgid "Select Default Patterns File" msgstr "" #: src/prefs.c:292 msgid "Default CSS" msgstr "" #: src/prefs.c:292 msgid "Select Default CSS File" msgstr "" #: src/prefs.c:295 msgid "Default Theme" msgstr "" #: src/prefs.c:295 msgid "Select Default Theme File" msgstr "" #: src/prefs.c:300 msgid "Status Bar" msgstr "Istatus Bar" #: src/prefs.c:301 msgid "Canvas Geometry" msgstr "Geometry ng Kanbas" #: src/prefs.c:302 msgid "Cursor X,Y" msgstr "Cursor X,Y" #: src/prefs.c:303 msgid "Pixel [I] {RGB}" msgstr "Pixel [I] {RGB}" #: src/prefs.c:304 msgid "Selection Geometry" msgstr "Selection Geometry" #: src/prefs.c:305 msgid "Undo / Redo" msgstr "" #: src/prefs.c:308 msgid "Tablet" msgstr "Tabletas" #: src/prefs.c:309 msgid "Device Settings" msgstr "Device Settings" #: src/prefs.c:313 msgid "Configure Device" msgstr "" #: src/prefs.c:319 msgid "Tool Variable" msgstr "" #: src/prefs.c:322 src/toolbar.c:454 msgid "Flow" msgstr "Daloy" #: src/prefs.c:330 msgid "Test Area" msgstr "Test Area" #: src/prefs.c:373 msgid "Factor" msgstr "Paktor" #: src/prefs.c:459 msgid "This key is builtin" msgstr "" #: src/prefs.c:462 #, c-format msgid "" "This key is mapped to:\n" "\"%s\"" msgstr "" #: src/prefs.c:465 msgid "Remap" msgstr "" #: src/prefs.c:510 msgid "Keyboard Shortcuts" msgstr "" #: src/shifter.c:147 msgid "Frames" msgstr "Mga Preym" #: src/shifter.c:258 msgid "Palette Shifter" msgstr "" #: src/shifter.c:263 msgid "Start" msgstr "Simulan" #: src/shifter.c:265 msgid "Finish" msgstr "Wakas" #: src/shifter.c:284 msgid "Fix Palette" msgstr "" #: src/spawn.c:651 msgid "Configure File Actions" msgstr "" #: src/spawn.c:657 src/spawn.c:663 msgid "Command" msgstr "Command" #: src/spawn.c:922 #, c-format msgid "Error %i reported when trying to run %s" msgstr "" #: src/spawn.c:979 msgid "" "I am unable to find the documentation. Either you need to download the " "mtPaint Handbook from the web site and install it, or you need to set the " "correct location in the Preferences window." msgstr "" #: src/spawn.c:1018 msgid "" "There was a problem running the HTML browser. You need to set the correct " "program name in the Preferences window." msgstr "" #: src/thread.c:361 msgid "Helper thread is not responding. Save your work and exit the program." msgstr "" #: src/toolbar.c:147 msgid "RGB Cube" msgstr "" #: src/toolbar.c:148 msgid "By image channel" msgstr "" #: src/toolbar.c:149 msgid "Gradient-driven" msgstr "" #: src/toolbar.c:157 msgid "Fill settings" msgstr "" #: src/toolbar.c:170 msgid "Respect opacity mode" msgstr "" #: src/toolbar.c:176 msgid "Smudge settings" msgstr "" #: src/toolbar.c:215 msgid "Aligned" msgstr "" #: src/toolbar.c:222 msgid "Clone settings" msgstr "" #: src/toolbar.c:228 msgid "By selection channel" msgstr "" #: src/toolbar.c:234 msgid "Lasso settings" msgstr "" #: src/toolbar.c:252 msgid "Brush spacing" msgstr "" #: src/toolbar.c:299 src/toolbar.c:341 msgid "Normal" msgstr "Normal" #: src/toolbar.c:300 msgid "Colour" msgstr "Kulay" #: src/toolbar.c:300 msgid "Saturate More" msgstr "" #: src/toolbar.c:301 msgid "Multiply" msgstr "Multiply" #: src/toolbar.c:301 msgid "Divide" msgstr "Hatiin" #: src/toolbar.c:301 msgid "Dodge" msgstr "" #: src/toolbar.c:302 msgid "Burn" msgstr "Sungin" #: src/toolbar.c:302 msgid "Hard Light" msgstr "Malakas na Ilaw" #: src/toolbar.c:302 msgid "Soft Light" msgstr "Mahinang Ilaw" #: src/toolbar.c:302 msgid "Difference" msgstr "Pagkakaiba" #: src/toolbar.c:303 msgid "Darken" msgstr "Padilimin" #: src/toolbar.c:303 msgid "Lighten" msgstr "" #: src/toolbar.c:303 msgid "Grain Extract" msgstr "" #: src/toolbar.c:304 msgid "Grain Merge" msgstr "" #: src/toolbar.c:330 msgid "Blend mode" msgstr "" #: src/toolbar.c:417 msgid "Continuous Mode" msgstr "" #: src/toolbar.c:421 msgid "Opacity Mode" msgstr "" #: src/toolbar.c:424 msgid "Tint Mode" msgstr "" #: src/toolbar.c:427 msgid "Tint +-" msgstr "" #: src/toolbar.c:434 msgid "Blend Mode" msgstr "" #: src/toolbar.c:438 msgid "Disable All Masks" msgstr "" #: src/toolbar.c:441 msgid "Gradient Mode" msgstr "" #: src/toolbar.c:486 msgid "Settings Toolbar" msgstr "" #: src/toolbar.c:546 msgid "Cut" msgstr "Putulin" #: src/toolbar.c:548 msgid "Copy" msgstr "Kopyahin" #: src/toolbar.c:550 msgid "Paste" msgstr "Idikit" #: src/toolbar.c:553 msgid "Undo" msgstr "Ibalik" #: src/toolbar.c:555 msgid "Redo" msgstr "Gawin muli" #: src/toolbar.c:559 src/viewer.c:328 msgid "Pan Window" msgstr "" #: src/toolbar.c:560 src/toolbar.c:640 msgid "More..." msgstr "Iba pa..." #: src/toolbar.c:574 msgid "Paint" msgstr "I-pinta" #: src/toolbar.c:580 msgid "Shuffle" msgstr "Balasahin" #: src/toolbar.c:583 msgid "Flood Fill" msgstr "" #: src/toolbar.c:587 msgid "Straight Line" msgstr "Deretsong linya" #: src/toolbar.c:590 msgid "Smudge" msgstr "Punasan" #: src/toolbar.c:594 msgid "Clone" msgstr "Gayahin" #: src/toolbar.c:597 msgid "Make Selection" msgstr "Bumuo ng Seleksyon" #: src/toolbar.c:600 msgid "Polygon Selection" msgstr "Polygon na Seleksyon" #: src/toolbar.c:603 msgid "Place Gradient" msgstr "Ilagay ang Gradient" #: src/toolbar.c:606 msgid "Lasso Selection" msgstr "Seleksyong Lasso" #: src/toolbar.c:614 msgid "Ellipse Outline" msgstr "Ellipse na Outliine" #: src/toolbar.c:617 msgid "Filled Ellipse" msgstr "Ellipse na may Laman" #: src/toolbar.c:620 msgid "Outline Selection" msgstr "Selekyiong Outline" #: src/toolbar.c:623 msgid "Fill Selection" msgstr "" #: src/toolbar.c:627 msgid "Flip Selection Vertically" msgstr "Baligtarin ang Seleksyon ng Patayo" #: src/toolbar.c:630 msgid "Flip Selection Horizontally" msgstr "Baligtarin ang Seleksyon ng Palihis" #: src/toolbar.c:633 msgid "Rotate Selection Clockwise" msgstr "Iikot ang Seleksyon ng Pa-clockwise" #: src/toolbar.c:636 msgid "Rotate Selection Anti-Clockwise" msgstr "Iikot ang Seleksyon ng Pa-counterclockwise" #: src/vcode.c:5201 msgid "Browse" msgstr "Magtingin-tingin" #: src/vcode.c:7886 msgid "New key ..." msgstr "" #: src/vcode.c:9909 #, c-format msgid "'%s' does not match any widget" msgstr "" #: src/vcode.c:9910 #, c-format msgid "'%s' value does not fit '%s' widget" msgstr "" #: src/viewer.c:115 msgid "About" msgstr "Tungkol dito" #: src/viewer.c:1179 msgid "No font selected" msgstr "" #: src/viewer.c:1209 msgid "Left" msgstr "" #: src/viewer.c:1209 msgid "Right" msgstr "" #~ msgid "Create GIF frames" #~ msgstr "Gumawa ng GIF frames" #~ msgid "Distance to A+B" #~ msgstr "Layo patungo sa A+B" mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/po/tr.po000066400000000000000000002360011471325446300215600ustar00rootroot00000000000000# Turkish translation for mtpaint # Copyright (c) (c) 2006 Canonical Ltd, and Rosetta Contributors 2006 # This file is distributed under the same license as the mtpaint package. # FIRST AUTHOR , 2006. # msgid "" msgstr "" "Project-Id-Version: mtpaint\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-01-04 21:31+0200\n" "PO-Revision-Date: 2008-06-19 21:36+0000\n" "Last-Translator: Tutku Dalmaz \n" "Language-Team: Turkish \n" "Language: tr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Launchpad-Export-Date: 2009-01-18 12:36+0000\n" "X-Generator: Launchpad (build Unknown)\n" #: src/ani.c:647 msgid "Animation Preview" msgstr "Animasyon Önizleme" #: src/ani.c:650 src/shifter.c:275 msgid "Play" msgstr "Yürüt" #: src/ani.c:654 msgid "Fix" msgstr "Onar" #: src/ani.c:655 src/ani.c:1005 src/font.c:1624 src/font.c:1643 #: src/shifter.c:286 src/viewer.c:97 msgid "Close" msgstr "Kapat" #: src/ani.c:709 src/ani.c:812 src/ani.c:1022 src/ani.c:1028 src/canvas.c:356 #: src/canvas.c:708 src/canvas.c:989 src/canvas.c:1353 src/canvas.c:1383 #: src/canvas.c:1470 src/canvas.c:1545 src/canvas.c:1988 src/canvas.c:1994 #: src/canvas.c:2077 src/canvas.c:2217 src/canvas.c:2240 src/font.c:1352 #: src/fpick.c:636 src/fpick.c:754 src/layer.c:524 src/layer.c:815 #: src/layer.c:970 src/mainwindow.c:341 src/mainwindow.c:370 #: src/mainwindow.c:534 src/mainwindow.c:578 src/mainwindow.c:604 #: src/mainwindow.c:3797 src/mainwindow.c:4045 src/otherwindow.c:931 #: src/otherwindow.c:980 src/otherwindow.c:982 src/prefs.c:459 src/spawn.c:924 #: src/spawn.c:978 src/spawn.c:1017 src/thread.c:360 src/vcode.c:9912 #: src/viewer.c:1161 src/viewer.c:1179 msgid "Error" msgstr "Hata" #: src/ani.c:709 msgid "Unable to create output directory" msgstr "Çıktı dizini oluÅŸturulamıyor" #: src/ani.c:759 msgid "Creating Animation Frames" msgstr "Animasyon Çerçeveleri OluÅŸturuluyor" #: src/ani.c:812 msgid "Unable to save image" msgstr "Resim kaydedilemedi" #: src/ani.c:840 src/canvas.c:1171 src/fpick.c:731 src/layer.c:311 #: src/layer.c:379 src/layer.c:826 src/layer.c:840 src/mainwindow.c:375 #: src/mainwindow.c:1026 src/png.c:8794 src/prefs.c:464 msgid "Warning" msgstr "Uyarı" #: src/ani.c:840 msgid "" "Do you really want to clear all of the position and cycle data for all of " "the layers?" msgstr "" "Tüm katmanlara ait konumları ve çevrim verilerini gerçekten temizlemek " "istiyor musunuz?" #: src/ani.c:841 src/fpick.c:731 src/layer.c:311 src/layer.c:842 #: src/mainwindow.c:375 msgid "No" msgstr "Hayır" #: src/ani.c:841 src/fpick.c:731 src/layer.c:311 src/layer.c:842 #: src/mainwindow.c:375 msgid "Yes" msgstr "Evet" #: src/ani.c:954 msgid "Set Key Frame" msgstr "" #: src/ani.c:961 msgid "Configure Animation" msgstr "Animasyonu Yapıladır" #: src/ani.c:964 msgid "Output Files" msgstr "Çıktı Dosyaları" #: src/ani.c:967 msgid "Start frame" msgstr "" #: src/ani.c:969 msgid "End frame" msgstr "" #: src/ani.c:971 src/shifter.c:267 msgid "Delay" msgstr "Gecikme" #: src/ani.c:973 msgid "Output path" msgstr "Çıktı dizini" #: src/ani.c:973 src/font.c:1637 src/spawn.c:664 msgid "Select Directory" msgstr "" #: src/ani.c:976 msgid "File prefix" msgstr "Dosya öneki" #: src/ani.c:978 src/canvas.c:2096 msgid "File Format" msgstr "Dosya Biçimi" #: src/ani.c:982 msgid "Positions" msgstr "Konumlar" #: src/ani.c:997 msgid "Cycling" msgstr "Çevrim" #: src/ani.c:1006 msgid "Save" msgstr "Kaydet" #: src/ani.c:1007 src/font.c:1577 src/otherwindow.c:868 src/otherwindow.c:1615 #: src/otherwindow.c:1728 src/otherwindow.c:2938 src/otherwindow.c:3071 #: src/otherwindow.c:3170 msgid "Preview" msgstr "Ön İzleme" #: src/ani.c:1008 src/shifter.c:285 msgid "Create Frames" msgstr "Çerçeveleri OluÅŸtur" #: src/ani.c:1022 msgid "You must have at least 2 layers to create an animation" msgstr "Bir animasyon oluÅŸturmak için en az 2 katman gerekir." #: src/ani.c:1028 msgid "You must save your layers file before creating an animation" msgstr "Animasyon yaratmadan önce tüm katman dosyalarınızı kaydetmelisiniz" #: src/canvas.c:357 msgid "The image is too large to transform." msgstr "Resim dönüştürmek için çok büyük." #: src/canvas.c:393 src/canvas.c:430 src/otherwindow.c:1613 #: src/otherwindow.c:2524 src/otherwindow.c:2583 src/otherwindow.c:3179 msgid "Gradient" msgstr "" #: src/canvas.c:393 src/otherwindow.c:840 src/otherwindow.c:842 #: src/otherwindow.c:2074 src/otherwindow.c:3180 msgid "Palette" msgstr "Palet" #: src/canvas.c:393 src/info.c:265 src/otherwindow.c:847 src/otherwindow.c:2757 #: src/otherwindow.c:3180 src/png.c:781 src/png.c:995 msgid "Clipboard" msgstr "Pano" #: src/canvas.c:394 src/cpick.c:831 src/toolbar.c:299 msgid "Value" msgstr "" #: src/canvas.c:394 src/cpick.c:811 src/otherwindow.c:575 src/otherwindow.c:859 #: src/otherwindow.c:3053 src/toolbar.c:318 msgid "Red" msgstr "Kırmızı" #: src/canvas.c:394 src/cpick.c:815 src/otherwindow.c:575 src/otherwindow.c:860 #: src/otherwindow.c:3053 src/toolbar.c:319 msgid "Green" msgstr "YeÅŸil" #: src/canvas.c:394 src/cpick.c:819 src/otherwindow.c:575 src/otherwindow.c:861 #: src/otherwindow.c:3053 src/toolbar.c:320 msgid "Blue" msgstr "Mavi" #: src/canvas.c:399 msgid "From " msgstr "" #: src/canvas.c:403 msgid "To " msgstr "" #: src/canvas.c:410 msgid "Map" msgstr "" #: src/canvas.c:429 msgid "MT" msgstr "" #: src/canvas.c:429 msgid "Sobel" msgstr "" #: src/canvas.c:429 msgid "Prewitt" msgstr "" #: src/canvas.c:429 msgid "Kirsch" msgstr "" #: src/canvas.c:430 msgid "Roberts" msgstr "" #: src/canvas.c:430 msgid "Laplace" msgstr "" #: src/canvas.c:430 msgid "Morphological" msgstr "" #: src/canvas.c:442 msgid "Edge Detect" msgstr "" #: src/canvas.c:464 msgid "Edge Sharpen" msgstr "" #: src/canvas.c:472 msgid "Edge Soften" msgstr "" #: src/canvas.c:521 msgid "Different X/Y" msgstr "" #: src/canvas.c:522 src/canvas.c:562 src/canvas.c:603 src/canvas.c:637 #: src/canvas.c:722 src/otherwindow.c:1037 src/otherwindow.c:2685 msgid "Gamma corrected" msgstr "" #: src/canvas.c:530 src/memory.c:8219 msgid "Gaussian Blur" msgstr "Gauss BulanıklaÅŸtırması" #: src/canvas.c:558 msgid "Radius" msgstr "Yarıçap" #: src/canvas.c:559 msgid "Amount" msgstr "Miktar" #: src/canvas.c:560 msgid "Threshold " msgstr "" #: src/canvas.c:570 src/memory.c:8360 msgid "Unsharp Mask" msgstr "" #: src/canvas.c:599 msgid "Outer radius" msgstr "" #: src/canvas.c:600 msgid "Inner radius" msgstr "" #: src/canvas.c:602 src/info.c:280 msgid "Normalize" msgstr "NormalleÅŸtir" #: src/canvas.c:611 src/memory.c:8512 msgid "Difference of Gaussians" msgstr "" #: src/canvas.c:636 msgid "Protect details" msgstr "" #: src/canvas.c:645 msgid "Kuwahara-Nagao Blur" msgstr "" #: src/canvas.c:709 msgid "The image is too large for this rotation." msgstr "Resim bu çevrim için çok büyük" #: src/canvas.c:723 msgid "Smooth" msgstr "Pürüzsüz" #: src/canvas.c:732 msgid "Free Rotate" msgstr "" #: src/canvas.c:989 src/viewer.c:1161 msgid "Not enough memory to create clipboard" msgstr "Pano yaratmak için yeterli bellek yok" #: src/canvas.c:1172 msgid "" "You have not allocated enough memory in the Preferences window to undo this " "action." msgstr "" #: src/canvas.c:1353 msgid "Invalid palette file" msgstr "" #: src/canvas.c:1383 msgid "Invalid channel file." msgstr "Geçersiz kanal dosyası." #: src/canvas.c:1401 msgid "Raw frames" msgstr "" #: src/canvas.c:1401 msgid "Composited frames" msgstr "" #: src/canvas.c:1402 msgid "Composited frames with nonzero delay" msgstr "" #: src/canvas.c:1406 msgid "Load Frames" msgstr "" #: src/canvas.c:1409 msgid "Load into Layers" msgstr "" #: src/canvas.c:1415 msgid "Load First Frame" msgstr "" #: src/canvas.c:1416 msgid "Explode Frames" msgstr "" #: src/canvas.c:1418 msgid "View Animation" msgstr "Animasyonu Göster" #: src/canvas.c:1434 #, c-format msgid "This is an animated %s file." msgstr "Bu bir animasyonlu %s dosyasıdır." #: src/canvas.c:1435 #, c-format msgid "This is a multipage %s file." msgstr "" #: src/canvas.c:1459 #, c-format msgid "File is too big, must be <= to width=%i height=%i" msgstr "" #: src/canvas.c:1461 msgid "Unable to explode frames" msgstr "" #: src/canvas.c:1463 msgid "Unable to load file" msgstr "Dosya yüklenemedi" #: src/canvas.c:1465 msgid "" "The file import library had to terminate due to a problem with the file " "(possibly corrupt image data or a truncated file). I have managed to load " "some data as the header seemed fine, but I would suggest you save this image " "to a new file to ensure this does not happen again." msgstr "" #: src/canvas.c:1467 msgid "The animation is too long to load all of it into layers." msgstr "" #: src/canvas.c:1469 msgid "Could not explode all the frames in the animation." msgstr "" #: src/canvas.c:1481 src/font.c:1556 src/fpick.c:937 src/otherwindow.c:2765 #: src/prefs.c:321 src/toolbar.c:451 msgid "Size" msgstr "Boyut" #: src/canvas.c:1484 src/otherwindow.c:244 msgid "Width" msgstr "GeniÅŸlik" #: src/canvas.c:1485 src/otherwindow.c:245 msgid "Height" msgstr "Yükseklik" #: src/canvas.c:1489 src/channels.c:253 src/channels.c:317 src/fpick.c:666 #: src/fpick.c:957 src/mainwindow.c:3990 src/otherwindow.c:255 #: src/otherwindow.c:517 src/otherwindow.c:591 src/otherwindow.c:867 #: src/otherwindow.c:1058 src/otherwindow.c:1727 src/otherwindow.c:2101 #: src/otherwindow.c:2336 src/otherwindow.c:2538 src/otherwindow.c:2691 #: src/otherwindow.c:2776 src/otherwindow.c:2937 src/otherwindow.c:3070 #: src/otherwindow.c:3169 src/prefs.c:338 src/prefs.c:464 src/prefs.c:538 #: src/spawn.c:666 src/viewer.c:1258 msgid "Cancel" msgstr "İptal" #: src/canvas.c:1490 src/channels.c:253 src/channels.c:317 src/fpick.c:956 #: src/info.c:297 src/mainwindow.c:3992 src/mygtk.c:233 src/mygtk.c:535 #: src/otherwindow.c:591 src/otherwindow.c:871 src/otherwindow.c:1058 #: src/otherwindow.c:1729 src/otherwindow.c:2101 src/otherwindow.c:2336 #: src/otherwindow.c:2538 src/otherwindow.c:2691 src/otherwindow.c:2776 #: src/otherwindow.c:3072 src/otherwindow.c:3171 src/prefs.c:338 #: src/prefs.c:538 src/spawn.c:666 msgid "OK" msgstr "TAMAM" #: src/canvas.c:1504 #, c-format msgid "This is a scalable %s file." msgstr "" #: src/canvas.c:1545 msgid "Cannot open file" msgstr "Dosya açılamıyor" #: src/canvas.c:1546 msgid "Unsupported file format" msgstr "Desteklenmeyen dosya biçimi" #: src/canvas.c:1673 #, c-format msgid "File: %s already exists. Do you want to overwrite it?" msgstr "%s zaten var. Üzerine yazmak ister misiniz?" #: src/canvas.c:1674 msgid "File Found" msgstr "Dosya Bulundu" #: src/canvas.c:1674 src/mainwindow.c:1095 msgid "NO" msgstr "HAYIR" #: src/canvas.c:1674 src/mainwindow.c:1095 msgid "YES" msgstr "EVET" #: src/canvas.c:1988 msgid "Unable to export undo images" msgstr "" #: src/canvas.c:1994 msgid "Unable to export ASCII file" msgstr "ASCII dosyası dışa aktarılamıyor" #: src/canvas.c:2076 src/layer.c:814 src/mainwindow.c:529 #, c-format msgid "Unable to save file: %s" msgstr "Dosya kaydedilemedi: %s" #: src/canvas.c:2101 src/prefs.c:222 msgid "Transparency index" msgstr "Åžeffalık Dizini" #: src/canvas.c:2103 msgid "TIFF Compression" msgstr "" #: src/canvas.c:2105 src/prefs.c:225 msgid "JPEG Save Quality (100=High)" msgstr "" #: src/canvas.c:2107 msgid "ZIP Compression (0=None)" msgstr "" #: src/canvas.c:2108 src/prefs.c:227 msgid "PNG Compression (0=None)" msgstr "" #: src/canvas.c:2111 src/prefs.c:249 msgid "LZMA2 Compression (0=None)" msgstr "" #: src/canvas.c:2113 src/prefs.c:252 msgid "ZSTD Compression Level" msgstr "" #: src/canvas.c:2115 src/prefs.c:231 msgid "TGA RLE Compression" msgstr "" #: src/canvas.c:2117 msgid "LBM PackBits Compression" msgstr "" #: src/canvas.c:2118 src/prefs.c:226 msgid "JPEG2000 Compression (0=Lossless)" msgstr "" #: src/canvas.c:2120 msgid "WebP Compression" msgstr "" #: src/canvas.c:2122 msgid "WebP Save Quality (100=High)" msgstr "" #: src/canvas.c:2123 src/prefs.c:263 msgid "V8 Save Quality (100=High)" msgstr "" #: src/canvas.c:2125 src/prefs.c:264 msgid "V8L Compression (0=None)" msgstr "" #: src/canvas.c:2127 msgid "Hotspot at X =" msgstr "" #: src/canvas.c:2129 msgid "Y =" msgstr "Y =" #: src/canvas.c:2133 msgid "Animation delay" msgstr "Animasyon gecikmesi" #: src/canvas.c:2136 src/otherwindow.c:253 msgid "Undoable" msgstr "" #: src/canvas.c:2138 src/prefs.c:236 msgid "Apply colour profile" msgstr "" #: src/canvas.c:2176 src/toolbar.c:543 msgid "Load Image File" msgstr "Resim Dosyası Yükle" #: src/canvas.c:2191 src/toolbar.c:544 msgid "Save Image File" msgstr "Resim Dosyasını Kaydet" #: src/canvas.c:2196 msgid "Load Palette File" msgstr "Palet Dosyası Yükle" #: src/canvas.c:2202 msgid "Save Palette File" msgstr "Palet Dosyasını Kaydet" #: src/canvas.c:2207 msgid "Export Undo Images" msgstr "" #: src/canvas.c:2212 msgid "Export Undo Images (reversed)" msgstr "" #: src/canvas.c:2217 msgid "You must have 16 or fewer palette colours to export ASCII art." msgstr "" "ASCII resmini içe aktarmak için 16 ya da daha az renk paletine gerek " "duyuluyor." #: src/canvas.c:2220 msgid "Export ASCII Art" msgstr "" #: src/canvas.c:2224 msgid "Save Layer Files" msgstr "Katman Dosyalarını Kaydet" #: src/canvas.c:2234 msgid "Choose frames directory" msgstr "" #: src/canvas.c:2240 msgid "You must save at least one frame to create an animated GIF." msgstr "GIF animasyonu oluÅŸturmak için en az bir çerçeveye gerek duyuluyor." #: src/canvas.c:2243 msgid "Export GIF animation" msgstr "GIF animasyonunu dışa aktar" #: src/canvas.c:2247 msgid "Load Channel" msgstr "Kanal Yükle" #: src/canvas.c:2255 msgid "Save Channel" msgstr "Kanalı Kaydet" #: src/canvas.c:2260 msgid "Save Composite Image" msgstr "" #: src/channels.c:243 msgid "Create Channel" msgstr "Kanal OluÅŸtur" #: src/channels.c:244 msgid "Channel Type" msgstr "Kanal Tipi" #: src/channels.c:247 msgid "Initial Channel State" msgstr "" #: src/channels.c:251 msgid "Inverted" msgstr "" #: src/channels.c:265 msgid "Cleared" msgstr "Temizlendi" #: src/channels.c:266 msgid "Set" msgstr "Ayarla" #: src/channels.c:267 msgid "Set colour A radius B" msgstr "" #: src/channels.c:268 msgid "Set blend A to B" msgstr "" #: src/channels.c:269 msgid "Image Red" msgstr "" #: src/channels.c:270 msgid "Image Green" msgstr "" #: src/channels.c:271 msgid "Image Blue" msgstr "" #: src/channels.c:273 src/channels.c:313 src/mainwindow.c:67 #: src/otherwindow.c:1679 msgid "Alpha" msgstr "Alfa" #: src/channels.c:274 src/channels.c:314 src/mainwindow.c:67 #: src/otherwindow.c:1683 msgid "Selection" msgstr "Seçim" #: src/channels.c:275 src/channels.c:315 src/mainwindow.c:67 #: src/otherwindow.c:1687 msgid "Mask" msgstr "Maske" #: src/channels.c:312 msgid "Delete Channels" msgstr "Kanalları Sil" #: src/channels.c:367 msgid "Threshold Channel" msgstr "" #: src/cpick.c:823 src/otherwindow.c:573 src/otherwindow.c:820 #: src/toolbar.c:299 msgid "Hue" msgstr "" #: src/cpick.c:827 src/otherwindow.c:573 src/otherwindow.c:818 #: src/toolbar.c:299 msgid "Saturation" msgstr "Doygunluk" #: src/cpick.c:835 msgid "Hex" msgstr "" #: src/cpick.c:840 src/layer.c:1109 src/otherwindow.c:2530 src/prefs.c:323 #: src/toolbar.c:457 msgid "Opacity" msgstr "Donukluk" #: src/font.c:982 msgid "Creating Font Index" msgstr "" #: src/font.c:1353 msgid "You must select at least one directory to search for fonts." msgstr "" #: src/font.c:1529 src/font.c:1624 src/toolbar.c:609 src/viewer.c:1213 #: src/viewer.c:1258 msgid "Paste Text" msgstr "Metni Yapıştır" #: src/font.c:1533 src/font.c:1572 src/png.c:3578 msgid "Text" msgstr "" #: src/font.c:1540 msgid "Font" msgstr "" #: src/font.c:1548 msgid "Style" msgstr "" #: src/font.c:1566 msgid "Filename" msgstr "" #: src/font.c:1567 msgid "Face" msgstr "" #: src/font.c:1587 src/viewer.c:1222 msgid "Antialias" msgstr "" #: src/font.c:1590 src/viewer.c:1224 msgid "Invert" msgstr "" #: src/font.c:1593 src/viewer.c:1226 msgid "Background colour =" msgstr "ArkaPlan rengi=" #: src/font.c:1601 src/viewer.c:1233 msgid "DPI =" msgstr "" #: src/font.c:1610 msgid "Oblique" msgstr "" #: src/font.c:1612 src/viewer.c:1244 msgid "Angle of rotation =" msgstr "Çevirme açısı=" #: src/font.c:1617 src/viewer.c:1248 msgid "Align" msgstr "" #: src/font.c:1620 src/viewer.c:1253 msgid "Spacing" msgstr "" #: src/font.c:1629 msgid "Font Directories" msgstr "" #: src/font.c:1634 src/spawn.c:664 msgid "Directory" msgstr "" #: src/font.c:1637 msgid "New Directory" msgstr "" #: src/font.c:1644 src/prefs.c:532 msgid "Add" msgstr "" #: src/font.c:1645 src/prefs.c:533 msgid "Remove" msgstr "" #: src/font.c:1646 msgid "Create Index" msgstr "" #: src/font.c:1660 src/viewer.c:1267 msgid "Enter Text Here" msgstr "Metni Buraya Girin" #: src/fpick.c:635 #, c-format msgid "Could not access directory %s" msgstr "" #: src/fpick.c:668 src/fpick.c:698 msgid "Delete" msgstr "" #: src/fpick.c:669 src/fpick.c:698 msgid "Rename" msgstr "" #: src/fpick.c:672 src/otherwindow.c:255 src/otherwindow.c:1666 msgid "Create" msgstr "Yarat" #: src/fpick.c:699 msgid "Enter the new filename" msgstr "" #: src/fpick.c:704 msgid "Create Directory" msgstr "" #: src/fpick.c:705 msgid "Enter the name of the new directory" msgstr "" #: src/fpick.c:729 #, c-format msgid "Do you really want to delete \"%s\" ?" msgstr "" #: src/fpick.c:735 msgid "Unable to delete" msgstr "" #: src/fpick.c:741 msgid "Unable to rename" msgstr "" #: src/fpick.c:750 msgid "Unable to create directory" msgstr "" #: src/fpick.c:924 msgid "Up" msgstr "" #: src/fpick.c:925 msgid "Home" msgstr "" #: src/fpick.c:926 msgid "Create New Directory" msgstr "" #: src/fpick.c:927 msgid "Show Hidden Files" msgstr "" #: src/fpick.c:929 msgid "Case Insensitive Sort" msgstr "" #: src/fpick.c:936 msgid "Name" msgstr "" #: src/fpick.c:938 msgid "Type" msgstr "" #: src/fpick.c:939 msgid "Modified" msgstr "" #: src/help.c:25 src/prefs.c:160 msgid "General" msgstr "Genel" #: src/help.c:26 msgid "Keyboard shortcuts" msgstr "Klavye Kısayolları" #: src/help.c:27 msgid "Mouse shortcuts" msgstr "Fare kısayolları" #: src/help.c:28 msgid "Credits" msgstr "Katkıda Bulunanlar" #: src/help.c:32 msgid "mtPaint 3.51 - Copyright (C) 2004-2021 The Authors\n" msgstr "" #: src/help.c:33 msgid "See 'Credits' section for a list of the authors.\n" msgstr "" #: src/help.c:34 msgid "" "mtPaint 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.\n" msgstr "" #: src/help.c:35 msgid "" "mtPaint 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.\n" msgstr "" #: src/help.c:36 msgid "" "mtPaint is a simple GTK+1/2/3 painting program designed for creating icons " "and pixel based artwork. It can edit indexed palette or 24 bit RGB images " "and offers basic painting and palette manipulation tools. It also has " "several other more powerful features such as channels, layers and animation. " "Due to its simplicity and lack of dependencies it runs well on GNU/Linux, " "Windows and older PC hardware.\n" msgstr "" #: src/help.c:37 msgid "" "There is full documentation of mtPaint's features contained in a handbook. " "If you don't already have this, you can download it from the mtPaint " "website.\n" msgstr "" #: src/help.c:38 msgid "" "If you like mtPaint and you want to keep up to date with new releases, or " "you want to give some feedback, then the mailing lists may be of interest to " "you:\n" msgstr "" #: src/help.c:39 msgid "http://sourceforge.net/mail/?group_id=155874" msgstr "" #: src/help.c:42 msgid " Ctrl-N Create new image" msgstr "" #: src/help.c:43 msgid " Ctrl-O Open Image" msgstr "" #: src/help.c:44 msgid " Ctrl-S Save Image" msgstr "" #: src/help.c:45 msgid " Ctrl-Shift-S Save layers file" msgstr "" #: src/help.c:46 msgid " Ctrl-Q Quit program\n" msgstr "" #: src/help.c:47 msgid " Ctrl-A Select whole image" msgstr "" #: src/help.c:48 msgid " Escape Select nothing, cancel paste box" msgstr "" #: src/help.c:49 msgid " J Lasso selection\n" msgstr "" #: src/help.c:50 msgid " Ctrl-C Copy selection to clipboard" msgstr "" #: src/help.c:51 msgid "" " Ctrl-X Copy selection to clipboard, and then paint current " "pattern to selection area" msgstr "" #: src/help.c:52 msgid " Ctrl-V Paste clipboard to centre of current view" msgstr "" #: src/help.c:53 msgid " Ctrl-K Paste clipboard to location it was copied from" msgstr "" #: src/help.c:54 msgid " Ctrl-Shift-V Paste clipboard to new layer" msgstr "" #: src/help.c:55 msgid " Enter/Return Commit paste to canvas" msgstr "" #: src/help.c:56 msgid " Shift+Enter/Return Commit paste and swap canvas into the clipboard\n" msgstr "" #: src/help.c:57 msgid " Arrow keys Paint Mode - Move the mouse pointer" msgstr "" #: src/help.c:58 msgid "" " Arrow keys Selection Mode - Nudge selection box or paste box by one " "pixel" msgstr "" #: src/help.c:59 msgid "" " Shift+Arrow keys Nudge mouse pointer, selection box or paste box by x " "pixels - x is defined by the Preferences window" msgstr "" #: src/help.c:60 msgid " Ctrl+Arrows Move layer or resize selection box" msgstr "" #: src/help.c:61 msgid " Ctrl+Shift+Arrows Move layer or resize selection box by x pixels\n" msgstr "" #: src/help.c:62 msgid " Enter/Return Paint Mode - Simulate left click" msgstr "" #: src/help.c:63 msgid " Backspace Paint Mode - Simulate right click\n" msgstr "" #: src/help.c:64 msgid "" " [ or ] Change colour A to the next or previous palette item" msgstr "" #: src/help.c:65 msgid "" " Shift+[ or ] Change colour B to the next or previous palette item\n" msgstr "" #: src/help.c:66 msgid " Delete Crop image to selection" msgstr "" #: src/help.c:67 msgid "" " Insert Transform colours - i.e. Brightness, Contrast, " "Saturation, Posterize, Gamma" msgstr "" #: src/help.c:68 msgid " Ctrl-G Greyscale the image" msgstr "" #: src/help.c:69 msgid " Shift-Ctrl-G Greyscale the image (Gamma corrected)" msgstr "" #: src/help.c:70 msgid " Ctrl+M Mirror the image" msgstr "" #: src/help.c:71 msgid " Shift-Ctrl-I Invert the image\n" msgstr "" #: src/help.c:72 msgid "" " Ctrl-T Draw a rectangle around the selection area with the " "current fill" msgstr "" #: src/help.c:73 msgid " Ctrl-Shift-T Fill in the selection area with the current fill" msgstr "" #: src/help.c:74 msgid " Ctrl-L Draw an ellipse spanning the selection area" msgstr "" #: src/help.c:75 msgid " Ctrl-Shift-L Draw a filled ellipse spanning the selection area\n" msgstr "" #: src/help.c:76 msgid " Ctrl-E Edit the RGB values for colours A & B" msgstr "" #: src/help.c:77 msgid " Ctrl-W Edit all palette colours\n" msgstr "" #: src/help.c:78 msgid " Ctrl-P Preferences" msgstr "" #: src/help.c:79 msgid " Ctrl-I Information\n" msgstr "" #: src/help.c:80 msgid " Ctrl-Z Undo last action" msgstr "" #: src/help.c:81 msgid " Ctrl-R Redo an undone action\n" msgstr "" #: src/help.c:82 msgid " Shift-T Text Tool (GTK+)" msgstr "" #: src/help.c:83 msgid " T Text Tool (FreeType)\n" msgstr "" #: src/help.c:84 msgid " V View Window" msgstr "" #: src/help.c:85 msgid " L Layers Window\n" msgstr "" #: src/help.c:86 msgid " Ctrl-H Toggle Hide Image mode" msgstr "" #: src/help.c:87 msgid " B Toggle Snap to Tile Grid mode\n" msgstr "" #: src/help.c:88 msgid " X Swap Colours A & B" msgstr "" #: src/help.c:89 msgid " E Choose Colour\n" msgstr "" #: src/help.c:90 msgid "" " A Draw open arrow head when using the line tool (size set " "by flow setting)" msgstr "" #: src/help.c:91 msgid "" " S Draw closed arrow head when using the line tool (size " "set by flow setting)\n" msgstr "" #: src/help.c:92 msgid " D Line Tool" msgstr "" #: src/help.c:93 msgid " F Flood Fill Tool\n" msgstr "" #: src/help.c:94 msgid " +,= Main edit window - Zoom in" msgstr "" #: src/help.c:95 msgid " - Main edit window - Zoom out" msgstr "" #: src/help.c:96 msgid " Shift +,= View window - Zoom in" msgstr "" #: src/help.c:97 msgid " Shift - View window - Zoom out\n" msgstr "" #: src/help.c:98 #, c-format msgid " 1 10% zoom" msgstr "" #: src/help.c:99 #, c-format msgid " 2 25% zoom" msgstr "" #: src/help.c:100 #, c-format msgid " 3 50% zoom" msgstr "" #: src/help.c:101 #, c-format msgid " 4 100% zoom" msgstr "" #: src/help.c:102 #, c-format msgid " 5 400% zoom" msgstr "" #: src/help.c:103 #, c-format msgid " 6 800% zoom" msgstr "" #: src/help.c:104 #, c-format msgid " 7 1200% zoom" msgstr "" #: src/help.c:105 #, c-format msgid " 8 1600% zoom" msgstr "" #: src/help.c:106 #, c-format msgid " 9 2000% zoom\n" msgstr "" #: src/help.c:107 msgid " Shift + 1 Edit image channel" msgstr "" #: src/help.c:108 msgid " Shift + 2 Edit alpha channel" msgstr "" #: src/help.c:109 msgid " Shift + 3 Edit selection channel" msgstr "" #: src/help.c:110 msgid " Shift + 4 Edit mask channel\n" msgstr "" #: src/help.c:111 msgid " F1 Help" msgstr "" #: src/help.c:112 msgid " F2 Choose Pattern" msgstr "" #: src/help.c:113 msgid " F3 Choose Brush" msgstr "" #: src/help.c:114 msgid " F4 Paint Tool" msgstr "" #: src/help.c:115 msgid " F5 Toggle Main Toolbar" msgstr "" #: src/help.c:116 msgid " F6 Toggle Tools Toolbar" msgstr "" #: src/help.c:117 msgid " F7 Toggle Settings Toolbar" msgstr "" #: src/help.c:118 msgid " F8 Toggle Palette" msgstr "" #: src/help.c:119 msgid " F9 Selection Tool" msgstr "" #: src/help.c:120 msgid " F12 Toggle Dock Area\n" msgstr "" #: src/help.c:121 msgid " Ctrl + F1 - F12 Save current clipboard to file 1-12" msgstr "" #: src/help.c:122 msgid " Shift + F1 - F12 Load clipboard from file 1-12\n" msgstr "" #: src/help.c:123 msgid "" " Ctrl + 1, 2, ... , 0 Set opacity to 10%, 20%, ... , 100% (main or keypad " "numbers)" msgstr "" #: src/help.c:124 msgid " Ctrl + + or = Increase opacity by 1" msgstr "" #: src/help.c:125 msgid " Ctrl + - Decrease opacity by 1\n" msgstr "" #: src/help.c:126 msgid "" " Home Show or hide main window menu/toolbar/status bar/palette" msgstr "" #: src/help.c:127 msgid " Page Up Scale Image" msgstr "" #: src/help.c:128 msgid " Page Down Resize Image canvas" msgstr "" #: src/help.c:129 msgid " End Pan Window" msgstr "" #: src/help.c:132 msgid " Left button Paint to canvas using the current tool" msgstr "" #: src/help.c:133 msgid "" " Middle button Selects the point which will be the centre of the " "image after the next zoom" msgstr "" #: src/help.c:134 msgid "" " Right button Commit paste to canvas / Stop drawing current line / " "Cancel selection\n" msgstr "" #: src/help.c:135 msgid "" " Scroll Wheel In GTK+2/3 the user can have the scroll wheel zoom in " "or out via the Preferences window\n" msgstr "" #: src/help.c:136 msgid " Ctrl+Left button Choose colour A from under mouse pointer" msgstr "" #: src/help.c:137 msgid " Ctrl+Left button Clone tool - Select source" msgstr "" #: src/help.c:138 msgid "" " Ctrl+Middle button Create colour A/B and pattern based on the RGB colour " "in A (RGB images only)" msgstr "" #: src/help.c:139 msgid " Ctrl+Right button Choose colour B from under mouse pointer" msgstr "" #: src/help.c:140 msgid "" " Ctrl+Right button Polygon tool - Delete last point / Delete nearest " "point" msgstr "" #: src/help.c:141 msgid " Ctrl+Scroll Wheel Scroll the main edit window left or right\n" msgstr "" #: src/help.c:142 msgid "" " Ctrl+Double click Set colour A or B to average colour under brush " "square or selection marquee (RGB only)\n" msgstr "" #: src/help.c:143 msgid "" " Shift+Right button Selects the point which will be the centre of the " "image after the next zoom\n" "\n" msgstr "" #: src/help.c:144 msgid "You can fixate the X/Y co-ordinates while moving the mouse:\n" msgstr "" #: src/help.c:145 msgid " Shift Constrain mouse movements to vertical line" msgstr "" #: src/help.c:146 msgid " Shift+Ctrl Constrain mouse movements to horizontal line" msgstr "" #: src/help.c:149 msgid "mtPaint is maintained by Dmitry Groshev.\n" msgstr "" #: src/help.c:150 msgid "wjaguar@users.sourceforge.net" msgstr "" #: src/help.c:151 msgid "http://mtpaint.sourceforge.net/\n" msgstr "" #: src/help.c:152 msgid "" "The following people (in alphabetical order) have contributed directly to " "the project, and are therefore worthy of gracious thanks for their " "generosity and hard work:\n" "\n" msgstr "" #: src/help.c:153 msgid "Authors\n" msgstr "" #: src/help.c:154 msgid "" "Dmitry Groshev - Contributing developer for version 2.30. Lead developer and " "maintainer from version 3.00 to the present." msgstr "" #: src/help.c:155 msgid "" "Mark Tyler - Original author and maintainer up to version 3.00, occasional " "contributor thereafter." msgstr "" #: src/help.c:156 msgid "" "Xiaolin Wu - Wrote the Wu quantizing method - see wu.c for more " "information.\n" "\n" msgstr "" #: src/help.c:157 msgid "" "General Contributions (Feedback and Ideas for improvements unless otherwise " "stated)\n" msgstr "" #: src/help.c:158 msgid "Abdulla Al Muhairi - Website redesign April 2005" msgstr "" #: src/help.c:159 msgid "Alan Horkan" msgstr "" #: src/help.c:160 msgid "Alexandre Prokoudine" msgstr "" #: src/help.c:161 msgid "Antonio Andrea Bianco" msgstr "" #: src/help.c:162 msgid "Charlie Ledocq" msgstr "" #: src/help.c:163 msgid "Dennis Lee" msgstr "" #: src/help.c:164 msgid "Donald White" msgstr "" #: src/help.c:165 msgid "Ed Jason" msgstr "" #: src/help.c:166 msgid "" "Eddie Kohler - Created Gifsicle which is needed for the creation and viewing " "of animated GIF files http://www.lcdf.org/gifsicle/" msgstr "" #: src/help.c:167 msgid "" "Guadalinex Team (Junta de Andalucia) - man page, Launchpad/Rosetta " "registration" msgstr "" #: src/help.c:168 msgid "Lou Afonso" msgstr "" #: src/help.c:169 msgid "Magnus Hjorth" msgstr "" #: src/help.c:170 msgid "Martin Zelaia" msgstr "" #: src/help.c:171 msgid "Pasi Kallinen" msgstr "" #: src/help.c:172 msgid "Pavel Ruzicka" msgstr "" #: src/help.c:173 msgid "Puppy Linux (Barry Kauler)" msgstr "" #: src/help.c:174 msgid "Victor Copovi" msgstr "" #: src/help.c:175 msgid "Vlastimil Krejcir" msgstr "" #: src/help.c:176 msgid "" "William Kern\n" "\n" msgstr "" #: src/help.c:177 msgid "Translations\n" msgstr "" #: src/help.c:178 msgid "Brazilian Portuguese - Paulo Trevizan, Valter Nazianzeno" msgstr "" #: src/help.c:179 msgid "Czech - Pavel Ruzicka, Martin Petricek, Roman Hornik, Pavel Fric" msgstr "" #: src/help.c:180 msgid "Dutch - Hans Strijards, Pjotr" msgstr "" #: src/help.c:181 msgid "" "French - Nicolas Velin, Pascal Billard, Sylvain Cresto, Johan Serre, " "Philippe Etienne, Victor Copovi" msgstr "" #: src/help.c:182 msgid "Galician - Miguel Anxo Bouzada" msgstr "" #: src/help.c:183 msgid "German - Oliver Frommel, B. Clausius, Ulrich Ringel, Simon Brixel" msgstr "" #: src/help.c:184 msgid "Hungarian - Ur Balazs" msgstr "" #: src/help.c:185 msgid "Italian - Angelo Gemmi" msgstr "" #: src/help.c:186 msgid "Japanese - Norihiro YONEDA" msgstr "" #: src/help.c:187 msgid "Kabyle - Yacine Bouklif" msgstr "" #: src/help.c:188 msgid "Polish - Bartosz Kaszubowski, LucaS" msgstr "" #: src/help.c:189 msgid "Portuguese - Israel G. Lugo, Tiago Silva" msgstr "" #: src/help.c:190 msgid "Russian - Sergey Irupin, Dmitry Groshev" msgstr "" #: src/help.c:191 msgid "Simplified Chinese - Cecc" msgstr "" #: src/help.c:192 msgid "Slovak - Jozef Riha" msgstr "" #: src/help.c:193 msgid "" "Spanish - Guadalinex Team (Junta de Andalucia), Antonio Sanchez Leon, Miguel " "Anxo Bouzada, Francisco Jose Rey, Adolfo Jayme" msgstr "" #: src/help.c:194 msgid "Swedish - Daniel Nylander, Daniel Eriksson" msgstr "" #: src/help.c:195 msgid "Tagalog - Anjelo delCarmen" msgstr "" #: src/help.c:196 msgid "Taiwanese Chinese - Wei-Lun Chao" msgstr "" #: src/help.c:197 msgid "Turkish - Muhammet Kara, Tutku Dalmaz" msgstr "" #: src/info.c:258 msgid "Information" msgstr "Bilgi" #: src/info.c:260 msgid "Memory" msgstr "Bellek" #: src/info.c:261 msgid "Total memory for main + undo images" msgstr "" #: src/info.c:263 msgid "Undo / Redo / Max levels used" msgstr "" #: src/info.c:265 msgid "Unused" msgstr "Kullanılmamış" #: src/info.c:269 msgid "Unique RGB pixels" msgstr "" #: src/info.c:272 src/layer.c:121 msgid "Layers" msgstr "Katmanlar" #: src/info.c:273 msgid "Total layer memory usage" msgstr "Toplam katman bellek kullanımı" #: src/info.c:277 msgid "Colour Histogram" msgstr "" #: src/info.c:289 src/otherwindow.c:1614 msgid "Index" msgstr "Dizin" #: src/info.c:290 msgid "Canvas pixels" msgstr "" #: src/info.c:328 #, c-format msgid "Clipboard = %i x %i" msgstr "Pano= %i x %i" #: src/info.c:328 #, c-format msgid "Clipboard = %i x %i x RGB" msgstr "Pano = %i x %i x RGB" #: src/info.c:377 msgid "Orphans" msgstr "" #: src/info.c:383 #, c-format msgid "Colour index totals - %i of %i used" msgstr "" #: src/inifile.c:966 msgid "" "Could not find home directory. Using current directory as home directory." msgstr "Ev dizini bulunamıyor. Åžuanki dizin ev dizini olarak kullanılıyor." #: src/layer.c:63 msgid "Background" msgstr "Arkaplan" #: src/layer.c:122 src/mainwindow.c:5931 msgid "(Modified)" msgstr "(DeÄŸiÅŸtirildi)" #: src/layer.c:123 src/mainwindow.c:5932 msgid "Untitled" msgstr "Adsız" #: src/layer.c:308 #, c-format msgid "Do you really want to delete layer %i (%s) ?" msgstr "Katmanı %i(%s) gerçekten silmek istiyor musunuz?" #: src/layer.c:380 msgid "" "One or more of the layers contains changes that have not been saved. Do you " "really want to lose these changes?" msgstr "" "Bir veya daha fazla katmanın içerdiÄŸi deÄŸiÅŸiklikler kaydedilmemiÅŸ. Bu " "deÄŸiÅŸiklikleri kaybetmek istiyor musunuz?" #: src/layer.c:381 src/mainwindow.c:1028 msgid "Cancel Operation" msgstr "Çalışmayı İptal Et" #: src/layer.c:381 src/mainwindow.c:1028 msgid "Lose Changes" msgstr "DeÄŸiÅŸiklikleri Kaybet" #: src/layer.c:523 #, c-format msgid "%d layers failed to load" msgstr "%d katmanının yüklenmesi baÅŸarısız oldu" #: src/layer.c:826 msgid "" "One or more of the image layers has not been saved. You must save each " "image individually before saving the layers text file in order to load this " "composite image in the future." msgstr "" #: src/layer.c:841 msgid "Do you really want to delete all of the layers?" msgstr "Tüm katmanları silmek istiyor musunuz?" #: src/layer.c:970 msgid "You cannot add any more layers." msgstr "Daha fazla katman ekleyemezsiniz" #: src/layer.c:1083 src/otherwindow.c:241 msgid "New Layer" msgstr "Yeni Katman" #: src/layer.c:1085 msgid "Raise" msgstr "Yükselt" #: src/layer.c:1087 msgid "Lower" msgstr "" #: src/layer.c:1089 msgid "Duplicate Layer" msgstr "Kamanı ÇoÄŸalt" #: src/layer.c:1091 msgid "Centralise Layer" msgstr "" #: src/layer.c:1093 msgid "Delete Layer" msgstr "Katmanı Sil" #: src/layer.c:1095 msgid "Close Layers Window" msgstr "Katmanlar Penceresini Kapat" #: src/layer.c:1101 msgid "Layer Name" msgstr "Katman Adı" #: src/layer.c:1104 src/toolbar.c:209 msgid "Position" msgstr "Konum" #: src/layer.c:1112 msgid "Transparent Colour" msgstr "Åžeffaf Renk" #: src/layer.c:1117 msgid "Show all layers in main window" msgstr "Tüm katmanları ana pencerede göster" #: src/mainwindow.c:67 src/otherwindow.c:844 src/otherwindow.c:2756 #: src/toolbar.c:342 msgid "Image" msgstr "Resim" #: src/mainwindow.c:69 src/mainwindow.c:489 src/otherwindow.c:1613 #: src/otherwindow.c:2302 msgid "RGB" msgstr "" #: src/mainwindow.c:69 src/otherwindow.c:1613 src/otherwindow.c:2302 msgid "sRGB" msgstr "" #: src/mainwindow.c:342 msgid "There were no unused colours to remove!" msgstr "Kaldırılacak kullanılmayan renk yok!" #: src/mainwindow.c:371 msgid "The palette does not contain 2 colours that have identical RGB values" msgstr "" #: src/mainwindow.c:374 #, c-format msgid "" "The palette contains %i colours that have identical RGB values. Do you " "really want to merge them into one index and realign the canvas?" msgstr "" #: src/mainwindow.c:492 msgid "indexed" msgstr "" #: src/mainwindow.c:498 #, c-format msgid "" "You are trying to save an %s image to an %s file which is not possible. I " "would suggest you save with a PNG extension." msgstr "" #: src/mainwindow.c:500 #, c-format msgid "" "You are trying to save an %s file with a palette of more than %d colours. " "Either use another format or reduce the palette to %d colours." msgstr "" #: src/mainwindow.c:578 msgid "Unable to load clipboard" msgstr "Pano yüklenemiyor" #: src/mainwindow.c:604 msgid "Unable to save clipboard" msgstr "Pano kaydedilemiyor" #: src/mainwindow.c:775 msgid "Zoom in" msgstr "" #: src/mainwindow.c:777 msgid "Zoom out" msgstr "" #: src/mainwindow.c:779 #, c-format msgid "10% zoom" msgstr "" #: src/mainwindow.c:781 #, c-format msgid "25% zoom" msgstr "" #: src/mainwindow.c:783 #, c-format msgid "50% zoom" msgstr "" #: src/mainwindow.c:785 #, c-format msgid "100% zoom" msgstr "" #: src/mainwindow.c:787 #, c-format msgid "400% zoom" msgstr "" #: src/mainwindow.c:789 #, c-format msgid "600% zoom" msgstr "" #: src/mainwindow.c:791 #, c-format msgid "800% zoom" msgstr "" #: src/mainwindow.c:793 #, c-format msgid "1000% zoom" msgstr "" #: src/mainwindow.c:795 #, c-format msgid "1200% zoom" msgstr "" #: src/mainwindow.c:797 #, c-format msgid "1600% zoom" msgstr "" #: src/mainwindow.c:799 #, c-format msgid "2000% zoom" msgstr "" #: src/mainwindow.c:801 #, c-format msgid "4000% zoom" msgstr "" #: src/mainwindow.c:803 #, c-format msgid "8000% zoom" msgstr "" #: src/mainwindow.c:805 #, c-format msgid "10% opacity" msgstr "" #: src/mainwindow.c:807 #, c-format msgid "20% opacity" msgstr "" #: src/mainwindow.c:809 #, c-format msgid "30% opacity" msgstr "" #: src/mainwindow.c:811 #, c-format msgid "40% opacity" msgstr "" #: src/mainwindow.c:813 #, c-format msgid "50% opacity" msgstr "" #: src/mainwindow.c:815 #, c-format msgid "60% opacity" msgstr "" #: src/mainwindow.c:817 #, c-format msgid "70% opacity" msgstr "" #: src/mainwindow.c:819 #, c-format msgid "80% opacity" msgstr "" #: src/mainwindow.c:821 #, c-format msgid "90% opacity" msgstr "" #: src/mainwindow.c:823 #, c-format msgid "100% opacity" msgstr "" #: src/mainwindow.c:825 msgid "Increase opacity" msgstr "" #: src/mainwindow.c:827 msgid "Decrease opacity" msgstr "" #: src/mainwindow.c:829 msgid "Draw open arrow head" msgstr "" #: src/mainwindow.c:831 msgid "Draw closed arrow head" msgstr "" #: src/mainwindow.c:833 msgid "Previous colour A" msgstr "" #: src/mainwindow.c:835 msgid "Next colour A" msgstr "" #: src/mainwindow.c:837 msgid "Previous colour B" msgstr "" #: src/mainwindow.c:839 msgid "Next colour B" msgstr "" #: src/mainwindow.c:841 msgid "Previous pattern" msgstr "" #: src/mainwindow.c:843 msgid "Next pattern" msgstr "" #: src/mainwindow.c:845 msgid "Larger brush" msgstr "" #: src/mainwindow.c:847 msgid "Smaller brush" msgstr "" #: src/mainwindow.c:849 msgid "View window - Zoom in" msgstr "" #: src/mainwindow.c:851 msgid "View window - Zoom out" msgstr "" #: src/mainwindow.c:1027 msgid "" "This canvas/palette contains changes that have not been saved. Do you " "really want to lose these changes?" msgstr "" "Bu tuval/palet kaydedilmemiÅŸ deÄŸiÅŸiklikler içeriyor. Bu deÄŸiÅŸiklikleri " "kaybetmek iÅŸtiyor musunuz?" #: src/mainwindow.c:1094 msgid "Do you really want to quit?" msgstr "Gerçekten çıkmak istiyor musunuz?" #: src/mainwindow.c:3754 msgid "Empty string or broken quoting" msgstr "" #: src/mainwindow.c:3755 msgid "Script must begin with a command" msgstr "" #: src/mainwindow.c:3756 msgid "Script nesting limit exceeded" msgstr "" #: src/mainwindow.c:3765 #, c-format msgid "'%s' does not match any item" msgstr "" #: src/mainwindow.c:3767 #, c-format msgid "'%s' matches a non-scriptable item" msgstr "" #: src/mainwindow.c:3769 #, c-format msgid "'%s' matches a disabled item" msgstr "" #: src/mainwindow.c:3788 #, c-format msgid "'%s' value does not fit item" msgstr "" #: src/mainwindow.c:3969 msgid "Script" msgstr "" #: src/mainwindow.c:3982 src/spawn.c:656 src/spawn.c:662 msgid "Action" msgstr "" #: src/mainwindow.c:3991 src/spawn.c:666 msgid "Execute" msgstr "" #: src/mainwindow.c:4045 msgid "Unable to load script" msgstr "" #: src/mainwindow.c:5182 msgid "/_File" msgstr "/_Dosya" #: src/mainwindow.c:5184 msgid "//New" msgstr "//Yeni" #: src/mainwindow.c:5186 msgid "//Open ..." msgstr "//Aç ..." #: src/mainwindow.c:5188 src/mainwindow.c:5669 msgid "//Save" msgstr "//Kaydet" #: src/mainwindow.c:5190 src/mainwindow.c:5549 src/mainwindow.c:5627 #: src/mainwindow.c:5671 msgid "//Save As ..." msgstr "//Farklı Kaydet ..." #: src/mainwindow.c:5192 msgid "//Export Undo Images ..." msgstr "" #: src/mainwindow.c:5194 msgid "//Export Undo Images (reversed) ..." msgstr "" #: src/mainwindow.c:5196 msgid "//Export ASCII Art ..." msgstr "" #: src/mainwindow.c:5198 msgid "//Export Animated GIF ..." msgstr "" #: src/mainwindow.c:5201 msgid "//Actions" msgstr "" #: src/mainwindow.c:5235 src/mainwindow.c:5488 msgid "///Configure" msgstr "" #: src/mainwindow.c:5290 msgid "//Quit" msgstr "//Çıkış" #: src/mainwindow.c:5293 msgid "/_Edit" msgstr "/_Düzenle" #: src/mainwindow.c:5295 msgid "//Undo" msgstr "//Geri al" #: src/mainwindow.c:5297 msgid "//Redo" msgstr "//Yinele" #: src/mainwindow.c:5300 msgid "//Cut" msgstr "//Kes" #: src/mainwindow.c:5302 msgid "//Copy" msgstr "//Kopyala" #: src/mainwindow.c:5304 msgid "//Copy To Palette" msgstr "" #: src/mainwindow.c:5306 msgid "//Paste To Centre" msgstr "//Merkeze Yapıştır" #: src/mainwindow.c:5308 msgid "//Paste To New Layer" msgstr "//Yeni Katmana Yapıştır" #: src/mainwindow.c:5310 msgid "//Paste" msgstr "//Yapıştır" #: src/mainwindow.c:5312 msgid "//Paste Text" msgstr "//Metni Yapıştır" #: src/mainwindow.c:5318 msgid "//Paste Text (FreeType)" msgstr "" #: src/mainwindow.c:5321 msgid "//Paste Palette" msgstr "" #: src/mainwindow.c:5323 msgid "//Load Clipboard" msgstr "//Panoyu Yükle" #: src/mainwindow.c:5350 msgid "//Save Clipboard" msgstr "//Panoyu Kaydet" #: src/mainwindow.c:5377 msgid "//Import Clipboard from System" msgstr "" #: src/mainwindow.c:5378 msgid "//Export Clipboard to System" msgstr "" #: src/mainwindow.c:5381 msgid "//Choose Pattern ..." msgstr "" #: src/mainwindow.c:5383 msgid "//Choose Brush ..." msgstr "//Fırça Seç ..." #: src/mainwindow.c:5385 msgid "//Choose Colour ..." msgstr "" #: src/mainwindow.c:5392 msgid "/_View" msgstr "/_Görünüm" #: src/mainwindow.c:5394 msgid "//Show Main Toolbar" msgstr "" #: src/mainwindow.c:5396 msgid "//Show Tools Toolbar" msgstr "" #: src/mainwindow.c:5399 msgid "//Show Settings Toolbar" msgstr "" #: src/mainwindow.c:5402 msgid "//Show Dock" msgstr "" #: src/mainwindow.c:5404 msgid "//Show Palette" msgstr "" #: src/mainwindow.c:5406 msgid "//Show Status Bar" msgstr "" #: src/mainwindow.c:5409 msgid "//Toggle Image View" msgstr "" #: src/mainwindow.c:5413 msgid "//Centralize Image" msgstr "" #: src/mainwindow.c:5414 msgid "//Show Zoom Grid" msgstr "" #: src/mainwindow.c:5415 msgid "//Snap To Tile Grid" msgstr "" #: src/mainwindow.c:5417 msgid "//Configure Grid ..." msgstr "" #: src/mainwindow.c:5418 msgid "//Tracing Image ..." msgstr "" #: src/mainwindow.c:5421 msgid "//View Window" msgstr "" #: src/mainwindow.c:5423 msgid "//Horizontal Split" msgstr "" #: src/mainwindow.c:5425 msgid "//Focus View Window" msgstr "" #: src/mainwindow.c:5427 msgid "//Pan Window" msgstr "" #: src/mainwindow.c:5430 msgid "//Layers Window" msgstr "" #: src/mainwindow.c:5433 msgid "/_Image" msgstr "/_Resim" #: src/mainwindow.c:5436 msgid "//Convert To RGB" msgstr "" #: src/mainwindow.c:5438 msgid "//Convert To Indexed ..." msgstr "" #: src/mainwindow.c:5441 msgid "//Scale Canvas ..." msgstr "//Tuvali Ölçekle ..." #: src/mainwindow.c:5443 msgid "//Resize Canvas ..." msgstr "//Tuvali Yeniden Boyutlandır ..." #: src/mainwindow.c:5445 msgid "//Crop" msgstr "//Kırp" #: src/mainwindow.c:5448 src/mainwindow.c:5517 msgid "//Flip Vertically" msgstr "" #: src/mainwindow.c:5449 src/mainwindow.c:5519 msgid "//Flip Horizontally" msgstr "" #: src/mainwindow.c:5452 src/mainwindow.c:5521 msgid "//Rotate Clockwise" msgstr "//Saat Yönünde Döndür" #: src/mainwindow.c:5453 src/mainwindow.c:5523 msgid "//Rotate Anti-Clockwise" msgstr "//Saat Yönünün Tersine Döndür" #: src/mainwindow.c:5454 msgid "//Free Rotate ..." msgstr "" #: src/mainwindow.c:5455 msgid "//Skew ..." msgstr "" #: src/mainwindow.c:5458 msgid "//Segment ..." msgstr "" #: src/mainwindow.c:5462 msgid "//Script ..." msgstr "" #: src/mainwindow.c:5464 msgid "//Scripts" msgstr "" #: src/mainwindow.c:5491 msgid "//Information ..." msgstr "//Bilgi ..." #: src/mainwindow.c:5494 msgid "//Preferences ..." msgstr "" #: src/mainwindow.c:5497 msgid "/_Selection" msgstr "/_Seçim" #: src/mainwindow.c:5499 msgid "//Select All" msgstr "//Tümünü Seç" #: src/mainwindow.c:5501 msgid "//Select None (Esc)" msgstr "" #: src/mainwindow.c:5503 msgid "//Lasso Selection" msgstr "" #: src/mainwindow.c:5505 msgid "//Lasso Selection Cut" msgstr "" #: src/mainwindow.c:5508 msgid "//Outline Selection" msgstr "" #: src/mainwindow.c:5510 msgid "//Fill Selection" msgstr "//Seçimi Doldur" #: src/mainwindow.c:5512 msgid "//Outline Ellipse" msgstr "" #: src/mainwindow.c:5514 msgid "//Fill Ellipse" msgstr "//İçi Dolu Elips" #: src/mainwindow.c:5526 msgid "//Horizontal Ramp" msgstr "" #: src/mainwindow.c:5528 msgid "//Vertical Ramp" msgstr "" #: src/mainwindow.c:5531 msgid "//Alpha Blend A,B" msgstr "" #: src/mainwindow.c:5533 msgid "//Move Alpha to Mask" msgstr "" #: src/mainwindow.c:5535 msgid "//Mask Colour A,B" msgstr "" #: src/mainwindow.c:5537 msgid "//Unmask Colour A,B" msgstr "" #: src/mainwindow.c:5539 msgid "//Mask All Colours" msgstr "" #: src/mainwindow.c:5541 msgid "//Clear Mask" msgstr "" #: src/mainwindow.c:5544 msgid "/_Palette" msgstr "/_Palet" #: src/mainwindow.c:5548 src/mainwindow.c:5626 msgid "//Load ..." msgstr "//Yükle ..." #: src/mainwindow.c:5550 msgid "//Load Default" msgstr "//Varsayılanı Yükle" #: src/mainwindow.c:5552 msgid "//Mask All" msgstr "" #: src/mainwindow.c:5553 msgid "//Mask None" msgstr "" #: src/mainwindow.c:5555 msgid "//Swap A & B" msgstr "" #: src/mainwindow.c:5557 msgid "//Edit Colour A & B ..." msgstr "//Renk Düzenle A & B ..." #: src/mainwindow.c:5559 msgid "//Dither A" msgstr "" #: src/mainwindow.c:5561 msgid "//Palette Editor ..." msgstr "" #: src/mainwindow.c:5563 msgid "//Set Palette Size ..." msgstr "//Palet Boyutunu Ayarla ..." #: src/mainwindow.c:5564 msgid "//Merge Duplicate Colours" msgstr "//Çoklu Renkleri BirleÅŸtir" #: src/mainwindow.c:5566 msgid "//Remove Unused Colours" msgstr "//Kullanılmayan Renkleri Kaldır" #: src/mainwindow.c:5569 msgid "//Create Quantized ..." msgstr "" #: src/mainwindow.c:5572 msgid "//Sort Colours ..." msgstr "//Renkleri Sırala ..." #: src/mainwindow.c:5573 msgid "//Palette Shifter ..." msgstr "" #: src/mainwindow.c:5574 msgid "//Pick Gradient ..." msgstr "" #: src/mainwindow.c:5576 msgid "/Effe_cts" msgstr "/Efektler" #: src/mainwindow.c:5578 msgid "//Transform Colour ..." msgstr "" #: src/mainwindow.c:5580 msgid "//Invert" msgstr "" #: src/mainwindow.c:5582 msgid "//Greyscale" msgstr "" #: src/mainwindow.c:5584 msgid "//Greyscale (Gamma corrected)" msgstr "" #: src/mainwindow.c:5586 msgid "//Normalize" msgstr "" #: src/mainwindow.c:5587 src/mainwindow.c:5658 msgid "//Threshold ..." msgstr "" #: src/mainwindow.c:5588 msgid "//Map ..." msgstr "" #: src/mainwindow.c:5590 msgid "//Isometric Transformation" msgstr "" #: src/mainwindow.c:5592 msgid "///Left Side Down" msgstr "" #: src/mainwindow.c:5593 msgid "///Right Side Down" msgstr "" #: src/mainwindow.c:5594 msgid "///Top Side Right" msgstr "" #: src/mainwindow.c:5595 msgid "///Bottom Side Right" msgstr "" #: src/mainwindow.c:5598 msgid "//Edge Detect ..." msgstr "" #: src/mainwindow.c:5600 msgid "//Difference of Gaussians ..." msgstr "" #: src/mainwindow.c:5602 msgid "//Sharpen ..." msgstr "" #: src/mainwindow.c:5604 msgid "//Unsharp Mask ..." msgstr "" #: src/mainwindow.c:5606 msgid "//Soften ..." msgstr "" #: src/mainwindow.c:5608 msgid "//Gaussian Blur ..." msgstr "" #: src/mainwindow.c:5610 msgid "//Kuwahara-Nagao Blur ..." msgstr "" #: src/mainwindow.c:5612 msgid "//Emboss" msgstr "" #: src/mainwindow.c:5614 msgid "//Dilate" msgstr "" #: src/mainwindow.c:5616 msgid "//Erode" msgstr "" #: src/mainwindow.c:5619 msgid "//Solid Noise ..." msgstr "" #: src/mainwindow.c:5620 msgid "//Bacteria ..." msgstr "" #: src/mainwindow.c:5623 msgid "/Cha_nnels" msgstr "/Ka_nallar" #: src/mainwindow.c:5625 msgid "//New ..." msgstr "//Yeni ..." #: src/mainwindow.c:5628 msgid "//Delete ..." msgstr "//Sil ..." #: src/mainwindow.c:5632 msgid "//Edit Image" msgstr "//Resmi Düzenle" #: src/mainwindow.c:5635 msgid "//Edit Alpha" msgstr "" #: src/mainwindow.c:5638 msgid "//Edit Selection" msgstr "//Seçimi Düzenle" #: src/mainwindow.c:5641 msgid "//Edit Mask" msgstr "//Maskeyi Düzenle" #: src/mainwindow.c:5645 msgid "//Hide Image" msgstr "//Resmi Gizle" #: src/mainwindow.c:5648 msgid "//Disable Alpha" msgstr "//Alfayı Etkisiz Kıl" #: src/mainwindow.c:5651 msgid "//Disable Selection" msgstr "//Seçimi Etkisiz Kıl" #: src/mainwindow.c:5654 msgid "//Disable Mask" msgstr "//Maskeyi Etkisiz Kıl" #: src/mainwindow.c:5657 msgid "//Couple RGBA Operations" msgstr "" #: src/mainwindow.c:5659 msgid "//Unassociate Alpha" msgstr "" #: src/mainwindow.c:5663 msgid "//View Alpha as an Overlay" msgstr "" #: src/mainwindow.c:5664 msgid "//Configure Overlays ..." msgstr "" #: src/mainwindow.c:5666 msgid "/_Layers" msgstr "/Katmanlar" #: src/mainwindow.c:5668 msgid "//New Layer" msgstr "" #: src/mainwindow.c:5672 msgid "//Save Composite Image ..." msgstr "" #: src/mainwindow.c:5673 msgid "//Composite to New Layer" msgstr "" #: src/mainwindow.c:5674 msgid "//Remove All Layers" msgstr "" #: src/mainwindow.c:5676 msgid "//Configure Animation ..." msgstr "//Animasyonu Yapılandır ..." #: src/mainwindow.c:5677 msgid "//Preview Animation ..." msgstr "//Animasyonu Önizle ..." #: src/mainwindow.c:5678 msgid "//Set Key Frame ..." msgstr "" #: src/mainwindow.c:5679 msgid "//Remove All Key Frames ..." msgstr "" #: src/mainwindow.c:5681 msgid "/More..." msgstr "" #: src/mainwindow.c:5683 msgid "/_Help" msgstr "/_Yardım" #: src/mainwindow.c:5684 msgid "//Documentation" msgstr "" #: src/mainwindow.c:5686 msgid "//About" msgstr "//Hakkında" #: src/mainwindow.c:5689 msgid "//Keyboard Shortcuts ..." msgstr "" #: src/mainwindow.c:5690 msgid "//Rebind Shortcut Keycodes" msgstr "" #: src/memory.c:2800 msgid "Quantize Pass 1" msgstr "" #: src/memory.c:2854 msgid "Quantize Pass 2" msgstr "" #: src/memory.c:3073 src/memory.c:3458 msgid "Converting to Indexed Palette" msgstr "" #: src/memory.c:5135 src/otherwindow.c:540 msgid "Bacteria Effect" msgstr "" #: src/memory.c:5170 msgid "Rotating" msgstr "Dördürme" #: src/memory.c:5511 msgid "Free Rotation" msgstr "" #: src/memory.c:6096 msgid "Scaling Image" msgstr "Resmi Boyutlandırma" #: src/memory.c:7560 msgid "Counting Unique RGB Pixels" msgstr "" #: src/memory.c:7608 msgid "Applying Effect" msgstr "" #: src/memory.c:8792 msgid "Kuwahara-Nagao Filter" msgstr "" #: src/memory.c:10456 src/otherwindow.c:2665 msgid "Skew" msgstr "" #: src/memory.c:10630 msgid "Segmentation Pass 1" msgstr "" #: src/memory.c:10757 msgid "Segmentation Pass 2" msgstr "" #: src/memory.c:11019 src/otherwindow.c:3156 msgid "Solid Noise" msgstr "" #: src/mygtk.c:134 src/mygtk.c:163 msgid "Please Wait ..." msgstr "Lütfen Bekleyiniz ..." #: src/mygtk.c:141 msgid "STOP" msgstr "DUR" #: src/mygtk.c:504 msgid "Disabled" msgstr "" #: src/mygtk.c:504 src/toolbar.c:301 msgid "Screen" msgstr "" #: src/mygtk.c:504 msgid "Window" msgstr "" #: src/mygtk.c:508 msgid "Input" msgstr "" #: src/mygtk.c:512 msgid "Device:" msgstr "" #: src/mygtk.c:514 msgid "Mode:" msgstr "" #: src/mygtk.c:519 msgid "Axes" msgstr "" #: src/mygtk.c:524 msgid "X:" msgstr "" #: src/mygtk.c:525 msgid "Y:" msgstr "" #: src/mygtk.c:526 msgid "Pressure:" msgstr "" #: src/mygtk.c:527 msgid "X tilt:" msgstr "" #: src/mygtk.c:528 msgid "Y tilt:" msgstr "" #: src/mygtk.c:529 msgid "Wheel:" msgstr "" #: src/mygtk.c:579 msgid "none" msgstr "" #: src/otherwindow.c:236 msgid "24 bit RGB" msgstr "24 bit RGB" #: src/otherwindow.c:236 src/otherwindow.c:3179 msgid "Greyscale" msgstr "Gri tonlama" #: src/otherwindow.c:237 msgid "Indexed Palette" msgstr "İndisli Palet" #: src/otherwindow.c:237 msgid "From Clipboard" msgstr "" #: src/otherwindow.c:237 msgid "Grab Screenshot" msgstr "" #: src/otherwindow.c:242 src/toolbar.c:542 msgid "New Image" msgstr "Yeni Resim" #: src/otherwindow.c:246 src/otherwindow.c:3164 msgid "Colours" msgstr "Renkler" #: src/otherwindow.c:409 msgid "Pattern Chooser" msgstr "Desen Seçici" #: src/otherwindow.c:497 msgid "Set Palette Size" msgstr "Palet Boyutunu Ayarla" #: src/otherwindow.c:517 src/otherwindow.c:591 src/otherwindow.c:870 #: src/otherwindow.c:2538 src/otherwindow.c:2776 src/otherwindow.c:2939 #: src/prefs.c:338 src/prefs.c:538 msgid "Apply" msgstr "Uygula" #: src/otherwindow.c:573 msgid "Luminance" msgstr "" #: src/otherwindow.c:573 src/otherwindow.c:814 msgid "Brightness" msgstr "Parlaklık" #: src/otherwindow.c:574 msgid "Distance to A" msgstr "A'ya uzaklık" #: src/otherwindow.c:575 msgid "Projection to A->B" msgstr "" #: src/otherwindow.c:576 msgid "Frequency" msgstr "Sıklık" #: src/otherwindow.c:580 msgid "Sort Palette Colours" msgstr "Palet Renklerini Sırala" #: src/otherwindow.c:582 msgid "Start Index" msgstr "Dizini BaÅŸlat" #: src/otherwindow.c:583 msgid "End Index" msgstr "Dizini Sonlandır" #: src/otherwindow.c:589 msgid "Reverse Order" msgstr "" #: src/otherwindow.c:805 msgid "Bitwise" msgstr "" #: src/otherwindow.c:805 msgid "Truncated" msgstr "" #: src/otherwindow.c:805 msgid "Rounded" msgstr "" #: src/otherwindow.c:809 src/toolbar.c:311 src/toolbar.c:558 msgid "Transform Colour" msgstr "" #: src/otherwindow.c:812 msgid "Gamma" msgstr "" #: src/otherwindow.c:816 msgid "Contrast" msgstr "Parlaklık" #: src/otherwindow.c:822 src/otherwindow.c:1674 msgid "Posterize" msgstr "" #: src/otherwindow.c:831 msgid "Show Detail" msgstr "Ayrıntı Göster" #: src/otherwindow.c:836 msgid "Posterize type" msgstr "" #: src/otherwindow.c:857 msgid "Auto-Preview" msgstr "Otomatik-Ön İzleme" #: src/otherwindow.c:869 msgid "Reset" msgstr "Sıfırla" #: src/otherwindow.c:931 msgid "New geometry is the same as now - nothing to do." msgstr "" #: src/otherwindow.c:980 msgid "The operating system cannot allocate the memory for this operation." msgstr "İşletim sistemi bu çalışma için belleÄŸi paylaÅŸtıramadı." #: src/otherwindow.c:982 msgid "" "You have not allocated enough memory in the Preferences window for this " "operation." msgstr "" "Bu çalışma için Tercihler penceresine yeteri kadar bellek " "paylaÅŸtırmamışsınız." #: src/otherwindow.c:993 src/otherwindow.c:2495 msgid "Mirror" msgstr "" #: src/otherwindow.c:993 src/otherwindow.c:994 msgid "Tile" msgstr "Döşe" #: src/otherwindow.c:993 msgid "Void" msgstr "" #: src/otherwindow.c:994 src/shifter.c:283 msgid "Clear" msgstr "Temizle" #: src/otherwindow.c:994 msgid "Mirror tile" msgstr "" #: src/otherwindow.c:996 msgid "Nearest Neighbour" msgstr "" #: src/otherwindow.c:997 msgid "Bilinear / Area Mapping" msgstr "" #: src/otherwindow.c:998 msgid "Bicubic" msgstr "" #: src/otherwindow.c:999 msgid "Bicubic edged" msgstr "" #: src/otherwindow.c:1000 msgid "Bicubic better" msgstr "" #: src/otherwindow.c:1001 msgid "Bicubic sharper" msgstr "" #: src/otherwindow.c:1002 msgid "Blackman-Harris" msgstr "" #: src/otherwindow.c:1008 msgid "Scale Canvas" msgstr "Tuvali Ölçeklendir" #: src/otherwindow.c:1009 msgid "Resize Canvas" msgstr "Tuvali Yeniden Boyutlandır" #: src/otherwindow.c:1012 msgid "Original " msgstr "Özgün " #: src/otherwindow.c:1013 msgid "New" msgstr "Yeni" #: src/otherwindow.c:1014 msgid "Width " msgstr "GeniÅŸlik " #: src/otherwindow.c:1018 msgid "Height " msgstr "Yükseklik " #: src/otherwindow.c:1023 src/otherwindow.c:2514 src/otherwindow.c:2672 #: src/toolbar.c:212 msgid "Offset" msgstr "BaÅŸlangıç Noktası" #: src/otherwindow.c:1026 src/otherwindow.c:1615 src/viewer.c:1209 msgid "Centre" msgstr "Merkez" #: src/otherwindow.c:1033 src/otherwindow.c:1052 msgid "Fix Aspect Ratio" msgstr "" #: src/otherwindow.c:1039 src/otherwindow.c:2070 src/toolbar.c:312 msgid "Settings" msgstr "Ayarlar" #: src/otherwindow.c:1046 msgid "Sharper image reduction" msgstr "" #: src/otherwindow.c:1047 msgid "Boundary extension" msgstr "" #: src/otherwindow.c:1613 src/otherwindow.c:2302 msgid "HSV" msgstr "" #: src/otherwindow.c:1614 msgid "Highlight" msgstr "" #: src/otherwindow.c:1615 msgid "Limit" msgstr "Sınır" #: src/otherwindow.c:1616 msgid "Sphere" msgstr "Küre" #: src/otherwindow.c:1616 src/otherwindow.c:2670 msgid "Angle" msgstr "Açı" #: src/otherwindow.c:1616 msgid "Cube" msgstr "Küp" #: src/otherwindow.c:1617 msgid "Opaque" msgstr "" #: src/otherwindow.c:1617 msgid "Border" msgstr "" #: src/otherwindow.c:1618 msgid "Transparent" msgstr "" #: src/otherwindow.c:1618 msgid "Tile " msgstr "" #: src/otherwindow.c:1618 msgid "Segment" msgstr "" #: src/otherwindow.c:1656 msgid "Scale" msgstr "Ölçeklendirme" #: src/otherwindow.c:1657 src/otherwindow.c:3059 msgid "From" msgstr "BaÅŸlangıç" #: src/otherwindow.c:1659 src/otherwindow.c:3061 msgid "To" msgstr "" #: src/otherwindow.c:1699 msgid "Range" msgstr "" #: src/otherwindow.c:1702 msgid "Inverse" msgstr "" #: src/otherwindow.c:1710 msgid "Smart grid" msgstr "" #: src/otherwindow.c:1712 msgid "Tile grid" msgstr "" #: src/otherwindow.c:1714 msgid "Minimum grid zoom" msgstr "En az ızgara yakınlaÅŸtırması" #: src/otherwindow.c:1717 msgid "Tile width" msgstr "" #: src/otherwindow.c:1720 msgid "Tile height" msgstr "" #: src/otherwindow.c:1744 msgid "Palette Editor" msgstr "Palet Düzenleyici" #: src/otherwindow.c:1763 msgid "Configure Overlays" msgstr "" #: src/otherwindow.c:1782 msgid "Colour Editor" msgstr "Renk Editörü" #: src/otherwindow.c:1818 src/toolbar.c:430 msgid "Colour-Selective Mode" msgstr "" #: src/otherwindow.c:1843 msgid "Configure Grid" msgstr "" #: src/otherwindow.c:2045 msgid "Exact Conversion" msgstr "" #: src/otherwindow.c:2045 msgid "Use Current Palette" msgstr "Åžuanki Paleti Kullan" #: src/otherwindow.c:2046 msgid "PNN Quantize (slow, better quality)" msgstr "" #: src/otherwindow.c:2047 msgid "Wu Quantize (fast)" msgstr "" #: src/otherwindow.c:2048 msgid "Max-Min Quantize (best for small palettes and dithering)" msgstr "" #: src/otherwindow.c:2049 src/otherwindow.c:2495 src/otherwindow.c:2756 #: src/png.c:2794 src/prefs.c:377 msgid "None" msgstr "" #: src/otherwindow.c:2049 msgid "Floyd-Steinberg" msgstr "" #: src/otherwindow.c:2049 msgid "Stucki" msgstr "" #: src/otherwindow.c:2052 msgid "Floyd-Steinberg (quick)" msgstr "" #: src/otherwindow.c:2052 msgid "Dithered (effect)" msgstr "" #: src/otherwindow.c:2053 msgid "Scattered (effect)" msgstr "" #: src/otherwindow.c:2054 msgid "Gamut" msgstr "" #: src/otherwindow.c:2054 msgid "Weakly" msgstr "Zayıfca" #: src/otherwindow.c:2054 msgid "Strongly" msgstr "" #: src/otherwindow.c:2055 msgid "Off" msgstr "" #: src/otherwindow.c:2055 msgid "Separate/Sum" msgstr "" #: src/otherwindow.c:2055 msgid "Separate/Split" msgstr "" #: src/otherwindow.c:2056 msgid "Length/Sum" msgstr "" #: src/otherwindow.c:2056 msgid "Length/Split" msgstr "" #: src/otherwindow.c:2057 msgid "Largest (Linf)" msgstr "" #: src/otherwindow.c:2057 msgid "Sum (L1)" msgstr "" #: src/otherwindow.c:2057 msgid "Euclidean (L2)" msgstr "" #: src/otherwindow.c:2061 msgid "Create Quantized" msgstr "" #: src/otherwindow.c:2062 msgid "Convert To Indexed" msgstr "" #: src/otherwindow.c:2065 msgid "Indexed Colours To Use" msgstr "" #: src/otherwindow.c:2078 msgid "Truncate palette" msgstr "" #: src/otherwindow.c:2079 msgid "Diameter based weighting" msgstr "" #: src/otherwindow.c:2084 msgid "Dither" msgstr "" #: src/otherwindow.c:2087 src/otherwindow.c:2584 src/otherwindow.c:2928 msgid "Colour space" msgstr "" #: src/otherwindow.c:2088 src/otherwindow.c:2929 msgid "Difference measure" msgstr "" #: src/otherwindow.c:2089 msgid "Reduce colour bleed" msgstr "" #: src/otherwindow.c:2090 msgid "Serpentine scan" msgstr "" #: src/otherwindow.c:2092 msgid "Error propagation, %" msgstr "" #: src/otherwindow.c:2093 msgid "Selective error propagation" msgstr "" #: src/otherwindow.c:2097 msgid "Full error precision" msgstr "" #: src/otherwindow.c:2302 msgid "Backward HSV" msgstr "" #: src/otherwindow.c:2303 src/otherwindow.c:2326 msgid "Constant" msgstr "Sabit" #: src/otherwindow.c:2307 msgid "Edit Gradient" msgstr "" #: src/otherwindow.c:2329 msgid "Points:" msgstr "Nokta" #: src/otherwindow.c:2493 msgid "Linear" msgstr "Çizgisel" #: src/otherwindow.c:2493 src/otherwindow.c:2703 msgid "Bilinear" msgstr "İkili doÄŸrusal" #: src/otherwindow.c:2493 msgid "Radial" msgstr "" #: src/otherwindow.c:2494 msgid "Square" msgstr "" #: src/otherwindow.c:2494 msgid "Angular" msgstr "" #: src/otherwindow.c:2494 msgid "Conical" msgstr "" #: src/otherwindow.c:2495 msgid "Level " msgstr "" #: src/otherwindow.c:2495 msgid "Repeat" msgstr "Yinele" #: src/otherwindow.c:2496 msgid "A to B" msgstr "A'dan B'ye" #: src/otherwindow.c:2496 msgid "A to B (RGB)" msgstr "" #: src/otherwindow.c:2497 msgid "A to B (sRGB)" msgstr "" #: src/otherwindow.c:2497 msgid "A to B (HSV)" msgstr "" #: src/otherwindow.c:2497 msgid "A to B (backward HSV)" msgstr "" #: src/otherwindow.c:2498 msgid "A only" msgstr "Sadece A" #: src/otherwindow.c:2498 src/otherwindow.c:2500 msgid "Custom" msgstr "Özel tanımlı" #: src/otherwindow.c:2499 msgid "Current to 0" msgstr "" #: src/otherwindow.c:2499 msgid "Current only" msgstr "" #: src/otherwindow.c:2504 msgid "Configure Gradient" msgstr "" #: src/otherwindow.c:2507 src/png.c:1001 msgid "Channel" msgstr "Kanal" #: src/otherwindow.c:2512 msgid "Length" msgstr "Uzunluk" #: src/otherwindow.c:2513 msgid "Repeat length" msgstr "Tekrar uzunluÄŸu" #: src/otherwindow.c:2515 msgid "Gradient type" msgstr "" #: src/otherwindow.c:2516 msgid "Extension type" msgstr "" #: src/otherwindow.c:2517 msgid "Distance type" msgstr "" #: src/otherwindow.c:2518 msgid "Preview opacity" msgstr "" #: src/otherwindow.c:2527 src/otherwindow.c:2533 src/toolbar.c:309 msgid "Reverse" msgstr "" #: src/otherwindow.c:2528 src/otherwindow.c:2534 msgid "Edit Custom" msgstr "" #: src/otherwindow.c:2592 msgid "Pick Gradient" msgstr "" #: src/otherwindow.c:2668 msgid "Horizontal " msgstr "" #: src/otherwindow.c:2674 msgid "At distance" msgstr "" #: src/otherwindow.c:2675 msgid "Vertical" msgstr "" #: src/otherwindow.c:2756 msgid "Unchanged" msgstr "" #: src/otherwindow.c:2761 msgid "Tracing Image" msgstr "" #: src/otherwindow.c:2763 src/toolbar.c:315 msgid "Source" msgstr "" #: src/otherwindow.c:2768 msgid "Origin" msgstr "" #: src/otherwindow.c:2771 msgid "Relative scale" msgstr "" #: src/otherwindow.c:2774 msgid "Display" msgstr "" #: src/otherwindow.c:2926 msgid "Segment Image" msgstr "" #: src/otherwindow.c:2931 src/toolbar.c:304 msgid "Threshold" msgstr "" #: src/otherwindow.c:2933 msgid "Level" msgstr "Seviye" #: src/otherwindow.c:2934 msgid "Minimum size" msgstr "" #: src/otherwindow.c:3053 msgid "Max" msgstr "" #: src/otherwindow.c:3053 msgid "Min" msgstr "" #: src/otherwindow.c:3057 msgid "Threshold Image" msgstr "" #: src/otherwindow.c:3158 msgid "Seed" msgstr "" #: src/otherwindow.c:3160 msgid "X span" msgstr "" #: src/otherwindow.c:3161 msgid "Y span" msgstr "" #: src/otherwindow.c:3162 msgid "Octaves" msgstr "" #: src/png.c:620 #, c-format msgid "Saving %s image" msgstr "" #: src/png.c:620 #, c-format msgid "Loading %s image" msgstr "" #: src/png.c:998 msgid "Layer" msgstr "Katman" #: src/png.c:3577 msgid "Lossless" msgstr "" #: src/png.c:3577 msgid "Default" msgstr "" #: src/png.c:3577 msgid "Picture" msgstr "" #: src/png.c:3577 msgid "Photo" msgstr "" #: src/png.c:3578 msgid "Drawing" msgstr "" #: src/png.c:3578 msgid "Icon" msgstr "" #: src/png.c:8370 msgid "Applying colour profile" msgstr "" #: src/png.c:8792 #, c-format msgid "%d out of %d frames could not be saved as %s - saved as PNG instead" msgstr "" #: src/png.c:8809 msgid "Explode frames" msgstr "" #: src/prefs.c:56 msgid "Default System Language" msgstr "Varsayılan Sistem Dili" #: src/prefs.c:57 msgid "Chinese (Simplified)" msgstr "" #: src/prefs.c:57 msgid "Chinese (Taiwanese)" msgstr "" #: src/prefs.c:57 msgid "Czech" msgstr "Çekçe" #: src/prefs.c:58 msgid "Dutch" msgstr "" #: src/prefs.c:58 msgid "English (UK)" msgstr "İngilizce (UK)" #: src/prefs.c:58 msgid "French" msgstr "Fransızca" #: src/prefs.c:58 msgid "Galician" msgstr "" #: src/prefs.c:58 msgid "German" msgstr "Almanca" #: src/prefs.c:59 msgid "Hungarian" msgstr "" #: src/prefs.c:59 msgid "Italian" msgstr "" #: src/prefs.c:59 msgid "Japanese" msgstr "" #: src/prefs.c:59 msgid "Kabyle" msgstr "" #: src/prefs.c:59 msgid "Polish" msgstr "Polonya dili" #: src/prefs.c:60 msgid "Portuguese" msgstr "Portekizce" #: src/prefs.c:60 msgid "Portuguese (Brazilian)" msgstr "Portekizce (Brezilya)" #: src/prefs.c:60 msgid "Russian" msgstr "" #: src/prefs.c:60 msgid "Slovak" msgstr "Slovakça" #: src/prefs.c:61 msgid "Spanish" msgstr "İspanyolca" #: src/prefs.c:61 msgid "Swedish" msgstr "" #: src/prefs.c:61 msgid "Tagalog" msgstr "" #: src/prefs.c:61 msgid "Turkish" msgstr "Türkçe" #: src/prefs.c:81 msgid "Current Device" msgstr "Åžuanli Aygıt" #: src/prefs.c:135 msgid "Pressure" msgstr "Basınç" #: src/prefs.c:149 msgid "Preferences" msgstr "Tercihler" #: src/prefs.c:163 msgid "Max threads (0 to autodetect)" msgstr "" #: src/prefs.c:164 msgid "Min kpixels per render thread" msgstr "" #: src/prefs.c:171 msgid "Max memory used for undo (MB)" msgstr "" #: src/prefs.c:172 msgid "Max undo levels" msgstr "" #: src/prefs.c:173 msgid "Communal layer undo space (%)" msgstr "" #: src/prefs.c:175 msgid "Bayer master pattern" msgstr "" #: src/prefs.c:178 msgid "Use gamma correction by default" msgstr "" #: src/prefs.c:179 msgid "Use gamma correction when painting" msgstr "" #: src/prefs.c:180 msgid "Separate patterns for A & B" msgstr "" #: src/prefs.c:183 msgid "Optimize alpha chequers" msgstr "" #: src/prefs.c:184 msgid "Disable view window transparencies" msgstr "" #: src/prefs.c:185 msgid "Enable overlays by layer" msgstr "" #: src/prefs.c:189 msgid "Language" msgstr "Dil" #: src/prefs.c:191 msgid "" "Select preferred language translation\n" "\n" "You will need to restart mtPaint\n" "for this to take full effect" msgstr "" "Tercih ettiÄŸiniz dil çevirisini seçin\n" "\n" "mtPaint'i yeniden baÅŸlatmanız gerekir\n" "tam etkisini göstermesi için" #: src/prefs.c:198 msgid "Interface" msgstr "" #: src/prefs.c:200 msgid "Greyscale backdrop" msgstr "" #: src/prefs.c:201 msgid "Selection nudge pixels" msgstr "" #: src/prefs.c:202 msgid "Max Pan Window Size" msgstr "" #: src/prefs.c:204 msgid "Display clipboard while pasting" msgstr "Yapıştırma boyunca panoyu göster" #: src/prefs.c:205 msgid "Mouse cursor = Tool" msgstr "Fare imleci = Araç" #: src/prefs.c:206 msgid "Confirm Exit" msgstr "Çıkışı Onayla" #: src/prefs.c:207 msgid "Q key quits mtPaint" msgstr "Q tuÅŸu mtPaint'i sonlandırır" #: src/prefs.c:208 msgid "Arrow keys scroll canvas" msgstr "" #: src/prefs.c:209 msgid "Changing tool commits paste" msgstr "" #: src/prefs.c:210 msgid "Centre tool settings dialogs" msgstr "" #: src/prefs.c:211 msgid "New image sets zoom to 100%" msgstr "" #: src/prefs.c:212 msgid "Zoom on cursor position" msgstr "" #: src/prefs.c:214 msgid "Mouse Scroll Wheel = Zoom" msgstr "" #: src/prefs.c:215 msgid "Use menu icons" msgstr "" #: src/prefs.c:220 msgid "Files" msgstr "Dosyalar" #: src/prefs.c:223 msgid "XBM X hotspot" msgstr "" #: src/prefs.c:224 msgid "XBM Y hotspot" msgstr "" #: src/prefs.c:228 msgid "Recently Used Files" msgstr "Son kullanılan Dosyalar" #: src/prefs.c:229 msgid "Progress bar silence limit" msgstr "" #: src/prefs.c:232 msgid "Read 16-bit TGAs as 5:6:5 BGR" msgstr "" #: src/prefs.c:233 msgid "Write TGAs in bottom-up row order" msgstr "" #: src/prefs.c:234 msgid "Undoable image loading" msgstr "" #: src/prefs.c:245 msgid "Compression (RGB)" msgstr "" #: src/prefs.c:246 msgid "Compression (indexed)" msgstr "" #: src/prefs.c:247 msgid "Compression (monochrome)" msgstr "" #: src/prefs.c:255 msgid "Enable predictor" msgstr "" #: src/prefs.c:262 msgid "Compression mode" msgstr "" #: src/prefs.c:271 msgid "Channel for Mask Plane" msgstr "" #: src/prefs.c:273 msgid "Ignore Transparent Colour" msgstr "" #: src/prefs.c:274 msgid "PackBits Compression" msgstr "" #: src/prefs.c:275 msgid "Write Indexed as Planar Bitmap (PBM)" msgstr "" #: src/prefs.c:280 msgid "Paths" msgstr "" #: src/prefs.c:281 msgid "Clipboard Files" msgstr "Pano Dosyaları" #: src/prefs.c:281 msgid "Select Clipboard File" msgstr "Pano Dosyasını Seçin" #: src/prefs.c:283 msgid "HTML Browser Program" msgstr "HTML Tarayıcı Programı" #: src/prefs.c:283 msgid "Select Browser Program" msgstr "Tarayıcı Programı Seç" #: src/prefs.c:285 msgid "Location of Handbook index" msgstr "Elkitabı Dizini konumu" #: src/prefs.c:285 msgid "Select Handbook Index File" msgstr "Elkitabı Dizin Dosyası Seç" #: src/prefs.c:287 msgid "Default Palette" msgstr "" #: src/prefs.c:287 msgid "Select Default Palette" msgstr "" #: src/prefs.c:289 msgid "Default Patterns" msgstr "" #: src/prefs.c:289 msgid "Select Default Patterns File" msgstr "" #: src/prefs.c:292 msgid "Default CSS" msgstr "" #: src/prefs.c:292 msgid "Select Default CSS File" msgstr "" #: src/prefs.c:295 msgid "Default Theme" msgstr "" #: src/prefs.c:295 msgid "Select Default Theme File" msgstr "" #: src/prefs.c:300 msgid "Status Bar" msgstr "Durum ÇubuÄŸu" #: src/prefs.c:301 msgid "Canvas Geometry" msgstr "Tuval Geometrisi" #: src/prefs.c:302 msgid "Cursor X,Y" msgstr "İmleç X,Y" #: src/prefs.c:303 msgid "Pixel [I] {RGB}" msgstr "" #: src/prefs.c:304 msgid "Selection Geometry" msgstr "" #: src/prefs.c:305 msgid "Undo / Redo" msgstr "Geri al / Yinele" #: src/prefs.c:308 msgid "Tablet" msgstr "Tablet" #: src/prefs.c:309 msgid "Device Settings" msgstr "Aygıt Ayarları" #: src/prefs.c:313 msgid "Configure Device" msgstr "Aygıtı Ayarla" #: src/prefs.c:319 msgid "Tool Variable" msgstr "Araç DeÄŸiÅŸkeni" #: src/prefs.c:322 src/toolbar.c:454 msgid "Flow" msgstr "Akış" #: src/prefs.c:330 msgid "Test Area" msgstr "Test Alanı" #: src/prefs.c:373 msgid "Factor" msgstr "Etken" #: src/prefs.c:459 msgid "This key is builtin" msgstr "" #: src/prefs.c:462 #, c-format msgid "" "This key is mapped to:\n" "\"%s\"" msgstr "" #: src/prefs.c:465 msgid "Remap" msgstr "" #: src/prefs.c:510 msgid "Keyboard Shortcuts" msgstr "" #: src/shifter.c:147 msgid "Frames" msgstr "Çerçeveler" #: src/shifter.c:258 msgid "Palette Shifter" msgstr "" #: src/shifter.c:263 msgid "Start" msgstr "BaÅŸlat" #: src/shifter.c:265 msgid "Finish" msgstr "Bitir" #: src/shifter.c:284 msgid "Fix Palette" msgstr "" #: src/spawn.c:651 msgid "Configure File Actions" msgstr "" #: src/spawn.c:657 src/spawn.c:663 msgid "Command" msgstr "" #: src/spawn.c:922 #, c-format msgid "Error %i reported when trying to run %s" msgstr "" #: src/spawn.c:979 msgid "" "I am unable to find the documentation. Either you need to download the " "mtPaint Handbook from the web site and install it, or you need to set the " "correct location in the Preferences window." msgstr "" #: src/spawn.c:1018 msgid "" "There was a problem running the HTML browser. You need to set the correct " "program name in the Preferences window." msgstr "" "HTML taracıyısını çalıştırmada problem var. Tercihler penceresinde doÄŸru " "program adını ayarlamaya ihtiyaç var." #: src/thread.c:361 msgid "Helper thread is not responding. Save your work and exit the program." msgstr "" #: src/toolbar.c:147 msgid "RGB Cube" msgstr "" #: src/toolbar.c:148 msgid "By image channel" msgstr "Resim kanalı tarafından" #: src/toolbar.c:149 msgid "Gradient-driven" msgstr "" #: src/toolbar.c:157 msgid "Fill settings" msgstr "Doldurma ayarları" #: src/toolbar.c:170 msgid "Respect opacity mode" msgstr "" #: src/toolbar.c:176 msgid "Smudge settings" msgstr "" #: src/toolbar.c:215 msgid "Aligned" msgstr "" #: src/toolbar.c:222 msgid "Clone settings" msgstr "" #: src/toolbar.c:228 msgid "By selection channel" msgstr "" #: src/toolbar.c:234 msgid "Lasso settings" msgstr "" #: src/toolbar.c:252 msgid "Brush spacing" msgstr "" #: src/toolbar.c:299 src/toolbar.c:341 msgid "Normal" msgstr "" #: src/toolbar.c:300 msgid "Colour" msgstr "" #: src/toolbar.c:300 msgid "Saturate More" msgstr "" #: src/toolbar.c:301 msgid "Multiply" msgstr "" #: src/toolbar.c:301 msgid "Divide" msgstr "" #: src/toolbar.c:301 msgid "Dodge" msgstr "" #: src/toolbar.c:302 msgid "Burn" msgstr "" #: src/toolbar.c:302 msgid "Hard Light" msgstr "" #: src/toolbar.c:302 msgid "Soft Light" msgstr "" #: src/toolbar.c:302 msgid "Difference" msgstr "" #: src/toolbar.c:303 msgid "Darken" msgstr "" #: src/toolbar.c:303 msgid "Lighten" msgstr "" #: src/toolbar.c:303 msgid "Grain Extract" msgstr "" #: src/toolbar.c:304 msgid "Grain Merge" msgstr "" #: src/toolbar.c:330 msgid "Blend mode" msgstr "" #: src/toolbar.c:417 msgid "Continuous Mode" msgstr "" #: src/toolbar.c:421 msgid "Opacity Mode" msgstr "" #: src/toolbar.c:424 msgid "Tint Mode" msgstr "" #: src/toolbar.c:427 msgid "Tint +-" msgstr "" #: src/toolbar.c:434 msgid "Blend Mode" msgstr "" #: src/toolbar.c:438 msgid "Disable All Masks" msgstr "Tüm Maskeleri Etkisiz Kıl" #: src/toolbar.c:441 msgid "Gradient Mode" msgstr "" #: src/toolbar.c:486 msgid "Settings Toolbar" msgstr "Ayar Araç ÇubuÄŸu" #: src/toolbar.c:546 msgid "Cut" msgstr "Kes" #: src/toolbar.c:548 msgid "Copy" msgstr "Kopyala" #: src/toolbar.c:550 msgid "Paste" msgstr "Yapıştır" #: src/toolbar.c:553 msgid "Undo" msgstr "Geri Al" #: src/toolbar.c:555 msgid "Redo" msgstr "Yinele" #: src/toolbar.c:559 src/viewer.c:328 msgid "Pan Window" msgstr "" #: src/toolbar.c:560 src/toolbar.c:640 msgid "More..." msgstr "" #: src/toolbar.c:574 msgid "Paint" msgstr "Boya" #: src/toolbar.c:580 msgid "Shuffle" msgstr "Karışık" #: src/toolbar.c:583 msgid "Flood Fill" msgstr "Su Dolgusu" #: src/toolbar.c:587 msgid "Straight Line" msgstr "Düz Çizgi" #: src/toolbar.c:590 msgid "Smudge" msgstr "Lekeleme" #: src/toolbar.c:594 msgid "Clone" msgstr "Kopyala" #: src/toolbar.c:597 msgid "Make Selection" msgstr "Seçim Yap" #: src/toolbar.c:600 msgid "Polygon Selection" msgstr "Çokgen Seçimi" #: src/toolbar.c:603 msgid "Place Gradient" msgstr "" #: src/toolbar.c:606 msgid "Lasso Selection" msgstr "" #: src/toolbar.c:614 msgid "Ellipse Outline" msgstr "" #: src/toolbar.c:617 msgid "Filled Ellipse" msgstr "İçi Dolu Elips" #: src/toolbar.c:620 msgid "Outline Selection" msgstr "Dış Çeper Seçimi" #: src/toolbar.c:623 msgid "Fill Selection" msgstr "Seçimi Doldur" #: src/toolbar.c:627 msgid "Flip Selection Vertically" msgstr "Seçimi Dikey Olarak Döndür" #: src/toolbar.c:630 msgid "Flip Selection Horizontally" msgstr "" #: src/toolbar.c:633 msgid "Rotate Selection Clockwise" msgstr "Seçimi Saat Yönünde Çevir" #: src/toolbar.c:636 msgid "Rotate Selection Anti-Clockwise" msgstr "Seçimi Saat Yönünün Tersine Çevir" #: src/vcode.c:5201 msgid "Browse" msgstr "Göz At" #: src/vcode.c:7886 msgid "New key ..." msgstr "" #: src/vcode.c:9909 #, c-format msgid "'%s' does not match any widget" msgstr "" #: src/vcode.c:9910 #, c-format msgid "'%s' value does not fit '%s' widget" msgstr "" #: src/viewer.c:115 msgid "About" msgstr "Hakkında" #: src/viewer.c:1179 msgid "No font selected" msgstr "" #: src/viewer.c:1209 msgid "Left" msgstr "" #: src/viewer.c:1209 msgid "Right" msgstr "" #~ msgid "Create GIF frames" #~ msgstr "GIF çerçeveleri oluÅŸtur" #~ msgid "File: %s invalid - palette not updated" #~ msgstr "%s dosyası geçersiz- palet güncellenmedi" #~ msgid "Distance to A+B" #~ msgstr "A+B'ye uzaklık" #~ msgid "Edit Frames" #~ msgstr "Çerçeveleri Düzenle" #~ msgid "The palette does not contain enough colours to do a merge" #~ msgstr "Palet, birleÅŸtirmek için yeterli renkleri içermiyor." #~ msgid "/View/Command Line Window" #~ msgstr "/Görünüm/Komut Satırı Penceresi" #~ msgid "Zoom" #~ msgstr "YakınlaÅŸtır" #~ msgid "Not enough memory to rotate image" #~ msgstr "Resmi çevirecek için yeterli bellek yok" #~ msgid "Not enough memory to rotate clipboard" #~ msgstr "Panoyu çevirmek için yeterli bellek yok." #~ msgid "patterns_user.c could not be opened in current directory" #~ msgstr "patterns_user.c ÅŸuanki dizinde açılamadı" #~ msgid "Done" #~ msgstr "Bitti" #~ msgid "patterns_user.c created in current directory" #~ msgstr "patterns_user.c ÅŸuanki dizinde yaratıldı" #~ msgid "/File/Actions/sep2" #~ msgstr "/Dosya/Actions/sep2" #~ msgid "/Edit/Create Patterns" #~ msgstr "/Düzenle/Create Patterns" #~ msgid "/Image/Convert To Indexed" #~ msgstr "/Resim/Convert To Indexed" #~ msgid "/Palette/Create Quantized (DL1)" #~ msgstr "/Palet/Create Quantized (DL1)" #~ msgid "/Palette/Create Quantized (DL3)" #~ msgstr "/Palet/Create Quantized (DL3)" #~ msgid "/Palette/Create Quantized (Wu)" #~ msgstr "/Palet/Create Quantized (Wu)" #~ msgid "/File/%i" #~ msgstr "/Dosya/%i" #~ msgid "/File/Actions/%i" #~ msgstr "/Dosya/Actions/%i" #~ msgid "Loading PNG image" #~ msgstr "PNG resmi yükleniyor" #~ msgid "Loading clipboard image" #~ msgstr "Pano resmi yükleniyor" #~ msgid "Saving PNG image" #~ msgstr "PNG resmi kaydediliyor" #~ msgid "Saving Clipboard image" #~ msgstr "Pano resmi kaydediliyor" #~ msgid "Saving Layer image" #~ msgstr "Katman resmi kaydediliyor" #~ msgid "Loading GIF image" #~ msgstr "GIF resmi yükleniyor" #~ msgid "Saving GIF image" #~ msgstr "GIF resmi kaydediliyor" #~ msgid "Loading JPEG image" #~ msgstr "JPEG resmi yükleniyor" #~ msgid "Saving JPEG image" #~ msgstr "JPEG resmi kaydediliyor" #~ msgid "Loading TIFF image" #~ msgstr "TIFF resmi yükleniyor" #~ msgid "Saving TIFF image" #~ msgstr "TIFF resmi kaydediliyor" #~ msgid "Loading BMP image" #~ msgstr "BMP resmi yükleniyor" #~ msgid "Saving BMP image" #~ msgstr "BMP resmi kaydediliyor" #~ msgid "Loading XPM image" #~ msgstr "XPM resmi yükleniyor" #~ msgid "Saving XPM image" #~ msgstr "XPM resmi kaydediliyor" #~ msgid "Loading XBM image" #~ msgstr "XBM resmi yükleniyor" #~ msgid "Saving XBM image" #~ msgstr "XBM resmi kaydediliyor" #~ msgid "Loading LSS16 image" #~ msgstr "LSS16 resmi yükleniyor" #~ msgid "Saving LSS16 image" #~ msgstr "LSS16 resmi kaydediliyor" mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/po/zh_CN.po000066400000000000000000002623751471325446300221510ustar00rootroot00000000000000# Simplified Chinese translation for mtpaint # This file is distributed under the same license as the mtpaint package. # Cecc , 2008. # msgid "" msgstr "" "Project-Id-Version: mtpaint 3.51\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-01-04 21:31+0200\n" "PO-Revision-Date: 2011-10-02 04:53+0000\n" "Last-Translator: Cecc \n" "Language-Team: Chinese (simplified) \n" "Language: zh_CN\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Launchpad-Export-Date: 2011-10-02 05:04+0000\n" "X-Generator: Launchpad (build 14071)\n" "X-Rosetta-Version: 0.1\n" #: src/ani.c:647 msgid "Animation Preview" msgstr "动画预览" #: src/ani.c:650 src/shifter.c:275 msgid "Play" msgstr "播放" #: src/ani.c:654 msgid "Fix" msgstr "ä¿®å¤" #: src/ani.c:655 src/ani.c:1005 src/font.c:1624 src/font.c:1643 #: src/shifter.c:286 src/viewer.c:97 msgid "Close" msgstr "关闭" #: src/ani.c:709 src/ani.c:812 src/ani.c:1022 src/ani.c:1028 src/canvas.c:356 #: src/canvas.c:708 src/canvas.c:989 src/canvas.c:1353 src/canvas.c:1383 #: src/canvas.c:1470 src/canvas.c:1545 src/canvas.c:1988 src/canvas.c:1994 #: src/canvas.c:2077 src/canvas.c:2217 src/canvas.c:2240 src/font.c:1352 #: src/fpick.c:636 src/fpick.c:754 src/layer.c:524 src/layer.c:815 #: src/layer.c:970 src/mainwindow.c:341 src/mainwindow.c:370 #: src/mainwindow.c:534 src/mainwindow.c:578 src/mainwindow.c:604 #: src/mainwindow.c:3797 src/mainwindow.c:4045 src/otherwindow.c:931 #: src/otherwindow.c:980 src/otherwindow.c:982 src/prefs.c:459 src/spawn.c:924 #: src/spawn.c:978 src/spawn.c:1017 src/thread.c:360 src/vcode.c:9912 #: src/viewer.c:1161 src/viewer.c:1179 msgid "Error" msgstr "错误" #: src/ani.c:709 msgid "Unable to create output directory" msgstr "无法建立输出目录" #: src/ani.c:759 msgid "Creating Animation Frames" msgstr "建立动画帧" #: src/ani.c:812 msgid "Unable to save image" msgstr "无法ä¿å­˜å›¾åƒ" #: src/ani.c:840 src/canvas.c:1171 src/fpick.c:731 src/layer.c:311 #: src/layer.c:379 src/layer.c:826 src/layer.c:840 src/mainwindow.c:375 #: src/mainwindow.c:1026 src/png.c:8794 src/prefs.c:464 msgid "Warning" msgstr "警告" #: src/ani.c:840 msgid "" "Do you really want to clear all of the position and cycle data for all of " "the layers?" msgstr "æ‚¨çœŸè¦æ¸…除所有图层上的全部ä½ç½®å’Œå¾ªçŽ¯æ•°æ®å—?" #: src/ani.c:841 src/fpick.c:731 src/layer.c:311 src/layer.c:842 #: src/mainwindow.c:375 msgid "No" msgstr "å¦" #: src/ani.c:841 src/fpick.c:731 src/layer.c:311 src/layer.c:842 #: src/mainwindow.c:375 msgid "Yes" msgstr "是" #: src/ani.c:954 msgid "Set Key Frame" msgstr "设置关键帧" #: src/ani.c:961 msgid "Configure Animation" msgstr "é…置动画" #: src/ani.c:964 msgid "Output Files" msgstr "输出文件" #: src/ani.c:967 msgid "Start frame" msgstr "起始帧" #: src/ani.c:969 msgid "End frame" msgstr "结æŸå¸§" #: src/ani.c:971 src/shifter.c:267 msgid "Delay" msgstr "延迟" #: src/ani.c:973 msgid "Output path" msgstr "输出路径" #: src/ani.c:973 src/font.c:1637 src/spawn.c:664 msgid "Select Directory" msgstr "选择目录" #: src/ani.c:976 msgid "File prefix" msgstr "文件å‰ç¼€" #: src/ani.c:978 src/canvas.c:2096 msgid "File Format" msgstr "文件格å¼" #: src/ani.c:982 msgid "Positions" msgstr "ä½ç½®" #: src/ani.c:997 msgid "Cycling" msgstr "循环中" #: src/ani.c:1006 msgid "Save" msgstr "ä¿å­˜" #: src/ani.c:1007 src/font.c:1577 src/otherwindow.c:868 src/otherwindow.c:1615 #: src/otherwindow.c:1728 src/otherwindow.c:2938 src/otherwindow.c:3071 #: src/otherwindow.c:3170 msgid "Preview" msgstr "预览" #: src/ani.c:1008 src/shifter.c:285 msgid "Create Frames" msgstr "创建帧" #: src/ani.c:1022 msgid "You must have at least 2 layers to create an animation" msgstr "您必须至少有2层图层以建立动画" #: src/ani.c:1028 msgid "You must save your layers file before creating an animation" msgstr "您必须在建立动画之å‰ä¿å­˜æ‚¨çš„图层文件" #: src/canvas.c:357 msgid "The image is too large to transform." msgstr "图åƒå¤ªå¤§æ— æ³•转æ¢ã€‚" #: src/canvas.c:393 src/canvas.c:430 src/otherwindow.c:1613 #: src/otherwindow.c:2524 src/otherwindow.c:2583 src/otherwindow.c:3179 msgid "Gradient" msgstr "æ¸å˜" #: src/canvas.c:393 src/otherwindow.c:840 src/otherwindow.c:842 #: src/otherwindow.c:2074 src/otherwindow.c:3180 msgid "Palette" msgstr "调色æ¿" #: src/canvas.c:393 src/info.c:265 src/otherwindow.c:847 src/otherwindow.c:2757 #: src/otherwindow.c:3180 src/png.c:781 src/png.c:995 msgid "Clipboard" msgstr "剪贴æ¿" #: src/canvas.c:394 src/cpick.c:831 src/toolbar.c:299 msgid "Value" msgstr "数值" #: src/canvas.c:394 src/cpick.c:811 src/otherwindow.c:575 src/otherwindow.c:859 #: src/otherwindow.c:3053 src/toolbar.c:318 msgid "Red" msgstr "红色" #: src/canvas.c:394 src/cpick.c:815 src/otherwindow.c:575 src/otherwindow.c:860 #: src/otherwindow.c:3053 src/toolbar.c:319 msgid "Green" msgstr "绿色" #: src/canvas.c:394 src/cpick.c:819 src/otherwindow.c:575 src/otherwindow.c:861 #: src/otherwindow.c:3053 src/toolbar.c:320 msgid "Blue" msgstr "è“色" #: src/canvas.c:399 msgid "From " msgstr "" #: src/canvas.c:403 msgid "To " msgstr "" #: src/canvas.c:410 msgid "Map" msgstr "" #: src/canvas.c:429 msgid "MT" msgstr "MT" #: src/canvas.c:429 msgid "Sobel" msgstr "ç´¢è´å°”" #: src/canvas.c:429 msgid "Prewitt" msgstr "" #: src/canvas.c:429 msgid "Kirsch" msgstr "" #: src/canvas.c:430 msgid "Roberts" msgstr "" #: src/canvas.c:430 msgid "Laplace" msgstr "拉普拉斯" #: src/canvas.c:430 msgid "Morphological" msgstr "å½¢æ€å­¦" #: src/canvas.c:442 msgid "Edge Detect" msgstr "边缘检测" #: src/canvas.c:464 msgid "Edge Sharpen" msgstr "边缘é”化" #: src/canvas.c:472 msgid "Edge Soften" msgstr "边缘柔化" #: src/canvas.c:521 msgid "Different X/Y" msgstr "差异化 X/Y" #: src/canvas.c:522 src/canvas.c:562 src/canvas.c:603 src/canvas.c:637 #: src/canvas.c:722 src/otherwindow.c:1037 src/otherwindow.c:2685 msgid "Gamma corrected" msgstr "伽马修正" #: src/canvas.c:530 src/memory.c:8219 msgid "Gaussian Blur" msgstr "高斯模糊" #: src/canvas.c:558 msgid "Radius" msgstr "åŠå¾„" #: src/canvas.c:559 msgid "Amount" msgstr "æ•°é‡" #: src/canvas.c:560 msgid "Threshold " msgstr "阈值 " #: src/canvas.c:570 src/memory.c:8360 msgid "Unsharp Mask" msgstr "é’化é®ç½©" #: src/canvas.c:599 msgid "Outer radius" msgstr "外åŠå¾„" #: src/canvas.c:600 msgid "Inner radius" msgstr "内åŠå¾„" #: src/canvas.c:602 src/info.c:280 msgid "Normalize" msgstr "标准化" #: src/canvas.c:611 src/memory.c:8512 msgid "Difference of Gaussians" msgstr "高斯差异" #: src/canvas.c:636 msgid "Protect details" msgstr "" #: src/canvas.c:645 msgid "Kuwahara-Nagao Blur" msgstr "Kuwahara-Nagao 模糊" #: src/canvas.c:709 msgid "The image is too large for this rotation." msgstr "此旋转所用图åƒå¤ªå¤§ã€‚" #: src/canvas.c:723 msgid "Smooth" msgstr "平滑" #: src/canvas.c:732 msgid "Free Rotate" msgstr "自由旋转" #: src/canvas.c:989 src/viewer.c:1161 msgid "Not enough memory to create clipboard" msgstr "没有足够的内存æ¥åˆ›å»ºå‰ªè´´æ¿" #: src/canvas.c:1172 msgid "" "You have not allocated enough memory in the Preferences window to undo this " "action." msgstr "" #: src/canvas.c:1353 msgid "Invalid palette file" msgstr "" #: src/canvas.c:1383 msgid "Invalid channel file." msgstr "æ— æ•ˆçš„é€šé“æ–‡ä»¶ã€‚" #: src/canvas.c:1401 msgid "Raw frames" msgstr "" #: src/canvas.c:1401 msgid "Composited frames" msgstr "" #: src/canvas.c:1402 msgid "Composited frames with nonzero delay" msgstr "" #: src/canvas.c:1406 msgid "Load Frames" msgstr "" #: src/canvas.c:1409 msgid "Load into Layers" msgstr "" #: src/canvas.c:1415 msgid "Load First Frame" msgstr "" #: src/canvas.c:1416 msgid "Explode Frames" msgstr "" #: src/canvas.c:1418 msgid "View Animation" msgstr "查看动画" #: src/canvas.c:1434 #, c-format msgid "This is an animated %s file." msgstr "这是一个%s动画文件。" #: src/canvas.c:1435 #, c-format msgid "This is a multipage %s file." msgstr "" #: src/canvas.c:1459 #, c-format msgid "File is too big, must be <= to width=%i height=%i" msgstr "文件太大,宽度必须å°äºŽ %i,高度必须å°äºŽ %i" #: src/canvas.c:1461 msgid "Unable to explode frames" msgstr "" #: src/canvas.c:1463 msgid "Unable to load file" msgstr "无法导入文件" #: src/canvas.c:1465 msgid "" "The file import library had to terminate due to a problem with the file " "(possibly corrupt image data or a truncated file). I have managed to load " "some data as the header seemed fine, but I would suggest you save this image " "to a new file to ensure this does not happen again." msgstr "" "文件导入函å¼åº“因文件问题终止(å¯èƒ½æ˜¯å›¾åƒæ•°æ®æŸå或文件被缩短)。 文件头似乎正" "常,我å¯ä»¥è½½å…¥ä¸€äº›æ•°æ®ï¼Œä¸è¿‡æˆ‘建议您ä¿å­˜æ­¤å›¾åƒåˆ°æ–°æ–‡ä»¶ 以确ä¿è¿™æ ·çš„事情ä¸å†å‘" "生。" #: src/canvas.c:1467 msgid "The animation is too long to load all of it into layers." msgstr "" #: src/canvas.c:1469 msgid "Could not explode all the frames in the animation." msgstr "" #: src/canvas.c:1481 src/font.c:1556 src/fpick.c:937 src/otherwindow.c:2765 #: src/prefs.c:321 src/toolbar.c:451 msgid "Size" msgstr "大å°" #: src/canvas.c:1484 src/otherwindow.c:244 msgid "Width" msgstr "宽度" #: src/canvas.c:1485 src/otherwindow.c:245 msgid "Height" msgstr "高度" #: src/canvas.c:1489 src/channels.c:253 src/channels.c:317 src/fpick.c:666 #: src/fpick.c:957 src/mainwindow.c:3990 src/otherwindow.c:255 #: src/otherwindow.c:517 src/otherwindow.c:591 src/otherwindow.c:867 #: src/otherwindow.c:1058 src/otherwindow.c:1727 src/otherwindow.c:2101 #: src/otherwindow.c:2336 src/otherwindow.c:2538 src/otherwindow.c:2691 #: src/otherwindow.c:2776 src/otherwindow.c:2937 src/otherwindow.c:3070 #: src/otherwindow.c:3169 src/prefs.c:338 src/prefs.c:464 src/prefs.c:538 #: src/spawn.c:666 src/viewer.c:1258 msgid "Cancel" msgstr "å–æ¶ˆ" #: src/canvas.c:1490 src/channels.c:253 src/channels.c:317 src/fpick.c:956 #: src/info.c:297 src/mainwindow.c:3992 src/mygtk.c:233 src/mygtk.c:535 #: src/otherwindow.c:591 src/otherwindow.c:871 src/otherwindow.c:1058 #: src/otherwindow.c:1729 src/otherwindow.c:2101 src/otherwindow.c:2336 #: src/otherwindow.c:2538 src/otherwindow.c:2691 src/otherwindow.c:2776 #: src/otherwindow.c:3072 src/otherwindow.c:3171 src/prefs.c:338 #: src/prefs.c:538 src/spawn.c:666 msgid "OK" msgstr "确定" #: src/canvas.c:1504 #, c-format msgid "This is a scalable %s file." msgstr "" #: src/canvas.c:1545 msgid "Cannot open file" msgstr "无法打开文件" #: src/canvas.c:1546 msgid "Unsupported file format" msgstr "䏿”¯æŒçš„æ–‡ä»¶æ ¼å¼" #: src/canvas.c:1673 #, c-format msgid "File: %s already exists. Do you want to overwrite it?" msgstr "文件:%s å·²ç»å­˜åœ¨ã€‚æ‚¨è¦æ”¹å†™å®ƒå—?" #: src/canvas.c:1674 msgid "File Found" msgstr "找到文件" #: src/canvas.c:1674 src/mainwindow.c:1095 msgid "NO" msgstr "å¦" #: src/canvas.c:1674 src/mainwindow.c:1095 msgid "YES" msgstr "是" #: src/canvas.c:1988 msgid "Unable to export undo images" msgstr "ä¸èƒ½å¯¼å‡ºè¿˜åŽŸå›¾åƒ" #: src/canvas.c:1994 msgid "Unable to export ASCII file" msgstr "无法导出 ASCII 文件" #: src/canvas.c:2076 src/layer.c:814 src/mainwindow.c:529 #, c-format msgid "Unable to save file: %s" msgstr "无法ä¿å­˜æ–‡ä»¶ï¼š%s" #: src/canvas.c:2101 src/prefs.c:222 msgid "Transparency index" msgstr "逿˜Žç´¢å¼•" #: src/canvas.c:2103 msgid "TIFF Compression" msgstr "" #: src/canvas.c:2105 src/prefs.c:225 msgid "JPEG Save Quality (100=High)" msgstr "JPEG ä¿å­˜è´¨é‡(100 = 高)" #: src/canvas.c:2107 msgid "ZIP Compression (0=None)" msgstr "" #: src/canvas.c:2108 src/prefs.c:227 msgid "PNG Compression (0=None)" msgstr "PNG 压缩 (0 = æ— )" #: src/canvas.c:2111 src/prefs.c:249 msgid "LZMA2 Compression (0=None)" msgstr "" #: src/canvas.c:2113 src/prefs.c:252 msgid "ZSTD Compression Level" msgstr "" #: src/canvas.c:2115 src/prefs.c:231 msgid "TGA RLE Compression" msgstr "TGA RLE 压缩" #: src/canvas.c:2117 msgid "LBM PackBits Compression" msgstr "" #: src/canvas.c:2118 src/prefs.c:226 msgid "JPEG2000 Compression (0=Lossless)" msgstr "JPEG2000 压缩 (0 = æ— æŸ)" #: src/canvas.c:2120 msgid "WebP Compression" msgstr "" #: src/canvas.c:2122 msgid "WebP Save Quality (100=High)" msgstr "" #: src/canvas.c:2123 src/prefs.c:263 msgid "V8 Save Quality (100=High)" msgstr "" #: src/canvas.c:2125 src/prefs.c:264 msgid "V8L Compression (0=None)" msgstr "" #: src/canvas.c:2127 msgid "Hotspot at X =" msgstr "热点ä½äºŽ X =" #: src/canvas.c:2129 msgid "Y =" msgstr "Y =" #: src/canvas.c:2133 msgid "Animation delay" msgstr "动画延迟" #: src/canvas.c:2136 src/otherwindow.c:253 msgid "Undoable" msgstr "å¯é€†çš„" #: src/canvas.c:2138 src/prefs.c:236 msgid "Apply colour profile" msgstr "" #: src/canvas.c:2176 src/toolbar.c:543 msgid "Load Image File" msgstr "è½½å…¥å›¾åƒæ–‡ä»¶" #: src/canvas.c:2191 src/toolbar.c:544 msgid "Save Image File" msgstr "ä¿å­˜å›¾åƒæ–‡ä»¶" #: src/canvas.c:2196 msgid "Load Palette File" msgstr "è½½å…¥è°ƒè‰²æ¿æ–‡ä»¶" #: src/canvas.c:2202 msgid "Save Palette File" msgstr "ä¿å­˜è°ƒè‰²æ¿æ–‡ä»¶" #: src/canvas.c:2207 msgid "Export Undo Images" msgstr "导出还原图åƒ" #: src/canvas.c:2212 msgid "Export Undo Images (reversed)" msgstr "å¯¼å‡ºè¿˜åŽŸå›¾åƒ (åå‘)" #: src/canvas.c:2217 msgid "You must have 16 or fewer palette colours to export ASCII art." msgstr "您必须使用 16 或更少的调色æ¿é¢œè‰²æ¥å¯¼å‡º ASCII 图案。" #: src/canvas.c:2220 msgid "Export ASCII Art" msgstr "导出 ASCII 图案" #: src/canvas.c:2224 msgid "Save Layer Files" msgstr "ä¿å­˜å›¾å±‚文件" #: src/canvas.c:2234 msgid "Choose frames directory" msgstr "选å–帧目录" #: src/canvas.c:2240 msgid "You must save at least one frame to create an animated GIF." msgstr "您必须ä¿å­˜è‡³å°‘一个帧以建立 GIF 动画。" #: src/canvas.c:2243 msgid "Export GIF animation" msgstr "导出 GIF 动画" #: src/canvas.c:2247 msgid "Load Channel" msgstr "载入通é“" #: src/canvas.c:2255 msgid "Save Channel" msgstr "ä¿å­˜é€šé“" #: src/canvas.c:2260 msgid "Save Composite Image" msgstr "ä¿å­˜åˆæˆå›¾åƒ" #: src/channels.c:243 msgid "Create Channel" msgstr "建立通é“" #: src/channels.c:244 msgid "Channel Type" msgstr "通é“类型" #: src/channels.c:247 msgid "Initial Channel State" msgstr "åˆå§‹é€šé“状æ€" #: src/channels.c:251 msgid "Inverted" msgstr "åå‘" #: src/channels.c:265 msgid "Cleared" msgstr "已清除" #: src/channels.c:266 msgid "Set" msgstr "设置" #: src/channels.c:267 msgid "Set colour A radius B" msgstr "设置颜色 A åŠå¾„ B" #: src/channels.c:268 msgid "Set blend A to B" msgstr "设置混色 A 到 B" #: src/channels.c:269 msgid "Image Red" msgstr "红色图åƒ" #: src/channels.c:270 msgid "Image Green" msgstr "绿色图åƒ" #: src/channels.c:271 msgid "Image Blue" msgstr "è“色图åƒ" #: src/channels.c:273 src/channels.c:313 src/mainwindow.c:67 #: src/otherwindow.c:1679 msgid "Alpha" msgstr "逿˜Žæ•ˆæžœ" #: src/channels.c:274 src/channels.c:314 src/mainwindow.c:67 #: src/otherwindow.c:1683 msgid "Selection" msgstr "选择" #: src/channels.c:275 src/channels.c:315 src/mainwindow.c:67 #: src/otherwindow.c:1687 msgid "Mask" msgstr "é®ç½©" #: src/channels.c:312 msgid "Delete Channels" msgstr "删除通é“" #: src/channels.c:367 msgid "Threshold Channel" msgstr "临界通é“" #: src/cpick.c:823 src/otherwindow.c:573 src/otherwindow.c:820 #: src/toolbar.c:299 msgid "Hue" msgstr "色调" #: src/cpick.c:827 src/otherwindow.c:573 src/otherwindow.c:818 #: src/toolbar.c:299 msgid "Saturation" msgstr "饱和度" #: src/cpick.c:835 msgid "Hex" msgstr "å六进制" #: src/cpick.c:840 src/layer.c:1109 src/otherwindow.c:2530 src/prefs.c:323 #: src/toolbar.c:457 msgid "Opacity" msgstr "ä¸é€æ˜Ž" #: src/font.c:982 msgid "Creating Font Index" msgstr "创建字体索引" #: src/font.c:1353 msgid "You must select at least one directory to search for fonts." msgstr "您必须为æœç´¢å­—体选择一个目录。" #: src/font.c:1529 src/font.c:1624 src/toolbar.c:609 src/viewer.c:1213 #: src/viewer.c:1258 msgid "Paste Text" msgstr "粘贴文本" #: src/font.c:1533 src/font.c:1572 src/png.c:3578 msgid "Text" msgstr "文本" #: src/font.c:1540 msgid "Font" msgstr "字体" #: src/font.c:1548 msgid "Style" msgstr "风格" #: src/font.c:1566 msgid "Filename" msgstr "文件å" #: src/font.c:1567 msgid "Face" msgstr "字体å" #: src/font.c:1587 src/viewer.c:1222 msgid "Antialias" msgstr "抗锯齿" #: src/font.c:1590 src/viewer.c:1224 msgid "Invert" msgstr "åå‘" #: src/font.c:1593 src/viewer.c:1226 msgid "Background colour =" msgstr "背景颜色 =" #: src/font.c:1601 src/viewer.c:1233 msgid "DPI =" msgstr "" #: src/font.c:1610 msgid "Oblique" msgstr "斜体" #: src/font.c:1612 src/viewer.c:1244 msgid "Angle of rotation =" msgstr "旋转角度=" #: src/font.c:1617 src/viewer.c:1248 msgid "Align" msgstr "" #: src/font.c:1620 src/viewer.c:1253 msgid "Spacing" msgstr "" #: src/font.c:1629 msgid "Font Directories" msgstr "字体目录" #: src/font.c:1634 src/spawn.c:664 msgid "Directory" msgstr "目录" #: src/font.c:1637 msgid "New Directory" msgstr "新建目录" #: src/font.c:1644 src/prefs.c:532 msgid "Add" msgstr "添加" #: src/font.c:1645 src/prefs.c:533 msgid "Remove" msgstr "移除" #: src/font.c:1646 msgid "Create Index" msgstr "创建索引" #: src/font.c:1660 src/viewer.c:1267 msgid "Enter Text Here" msgstr "在此输入文字" #: src/fpick.c:635 #, c-format msgid "Could not access directory %s" msgstr "无法访问目录 %s" #: src/fpick.c:668 src/fpick.c:698 msgid "Delete" msgstr "删除" #: src/fpick.c:669 src/fpick.c:698 msgid "Rename" msgstr "é‡å‘½å" #: src/fpick.c:672 src/otherwindow.c:255 src/otherwindow.c:1666 msgid "Create" msgstr "创建" #: src/fpick.c:699 msgid "Enter the new filename" msgstr "输入新文件å" #: src/fpick.c:704 msgid "Create Directory" msgstr "创建目录" #: src/fpick.c:705 msgid "Enter the name of the new directory" msgstr "输入新目录å" #: src/fpick.c:729 #, c-format msgid "Do you really want to delete \"%s\" ?" msgstr "您确定è¦åˆ é™¤ \"%s\" ?" #: src/fpick.c:735 msgid "Unable to delete" msgstr "无法删除" #: src/fpick.c:741 msgid "Unable to rename" msgstr "无法é‡å‘½å" #: src/fpick.c:750 msgid "Unable to create directory" msgstr "无法创建目录" #: src/fpick.c:924 msgid "Up" msgstr "å‘上" #: src/fpick.c:925 msgid "Home" msgstr "主目录" #: src/fpick.c:926 msgid "Create New Directory" msgstr "新建目录" #: src/fpick.c:927 msgid "Show Hidden Files" msgstr "显示éšè—文件" #: src/fpick.c:929 msgid "Case Insensitive Sort" msgstr "ä¸åŒºåˆ†å¤§å°å†™æŽ’åº" #: src/fpick.c:936 msgid "Name" msgstr "åç§°" #: src/fpick.c:938 msgid "Type" msgstr "类型" #: src/fpick.c:939 msgid "Modified" msgstr "修改日期" #: src/help.c:25 src/prefs.c:160 msgid "General" msgstr "常规" #: src/help.c:26 msgid "Keyboard shortcuts" msgstr "键盘快æ·é”®" #: src/help.c:27 msgid "Mouse shortcuts" msgstr "鼠标快æ·é”®" #: src/help.c:28 msgid "Credits" msgstr "致谢" #: src/help.c:32 msgid "mtPaint 3.51 - Copyright (C) 2004-2021 The Authors\n" msgstr "mtPaint 3.51 - ç‰ˆæƒ (C) 2004-2021 作者群\n" #: src/help.c:33 msgid "See 'Credits' section for a list of the authors.\n" msgstr "作者列表请查看「致谢ã€éƒ¨åˆ†ã€‚\n" #: src/help.c:34 msgid "" "mtPaint 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.\n" msgstr "" "mtPaint为自由软件;基于自由软件基金会å‘布的GNU通用公共许å¯ï¼Œæ‚¨å¯ä»¥å†æ¬¡æ•£å¸ƒå®ƒ" "å’Œ/或修改它;å¯ä¾ç‰ˆæœ¬3的授æƒï¼Œæˆ–是(便‚¨çš„选择)任何之åŽçš„版本。\n" #: src/help.c:35 msgid "" "mtPaint 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.\n" msgstr "" "mtPaint 是希望它会有用而å‘行的,但是ä¸åšä»»ä½•ä¿è¯ï¼›ä¹Ÿä¸æš—示任何的适销性或特定" "目的的åˆç”¨æ€§ã€‚å‚看 GNU é€šç”¨å…¬å…±è®¸å¯æ¥èŽ·å¾—æ›´å¤šç»†èŠ‚ã€‚\n" #: src/help.c:36 msgid "" "mtPaint is a simple GTK+1/2/3 painting program designed for creating icons " "and pixel based artwork. It can edit indexed palette or 24 bit RGB images " "and offers basic painting and palette manipulation tools. It also has " "several other more powerful features such as channels, layers and animation. " "Due to its simplicity and lack of dependencies it runs well on GNU/Linux, " "Windows and older PC hardware.\n" msgstr "" "mtPaint 是一个简å•çš„ GTK+1/2/3 绘画程åºï¼Œä¸“为创建图标和åƒç´ å›¾è€Œè®¾è®¡ã€‚它å¯ä»¥ç¼–" "è¾‘ç´¢å¼•è¿‡çš„è°ƒè‰²æ¿æˆ– 24 ä½ RGB 图åƒï¼Œæä¾›åŸºæœ¬çš„绘画和调色æ¿å¤„ç†å·¥å…·ã€‚它还有其他" "几个更强大的特å¾ä¾‹å¦‚通é“ï¼Œå›¾å±‚å’ŒåŠ¨ç”»ç­‰ã€‚ç”±äºŽå®ƒçš„ç®€å•æ˜“用和较少的ä¾èµ–性,它在 " "GNU/Linux,Windows和较旧的 PC 硬件上è¿è¡Œè‰¯å¥½ã€‚\n" #: src/help.c:37 msgid "" "There is full documentation of mtPaint's features contained in a handbook. " "If you don't already have this, you can download it from the mtPaint " "website.\n" msgstr "" "有关 mtPaint 特性的完整文档包å«åœ¨æ‰‹å†Œä¹‹ä¸­ã€‚如果您尚未得到它,您å¯ä»¥ä»Ž " "mtPaint 网站下载。\n" #: src/help.c:38 msgid "" "If you like mtPaint and you want to keep up to date with new releases, or " "you want to give some feedback, then the mailing lists may be of interest to " "you:\n" msgstr "" "如果您喜欢 mtPaint 并想使用最新版本,或是您想æä¾›ä¸€äº›å馈信æ¯ï¼Œé‚£ä¹ˆæ‚¨ä¹Ÿè®¸ä¼šå¯¹" "邮件列表感兴趣:\n" #: src/help.c:39 msgid "http://sourceforge.net/mail/?group_id=155874" msgstr "" #: src/help.c:42 msgid " Ctrl-N Create new image" msgstr " Ctrl-N 新建图åƒ" #: src/help.c:43 msgid " Ctrl-O Open Image" msgstr " Ctrl-O 打开图åƒ" #: src/help.c:44 msgid " Ctrl-S Save Image" msgstr " Ctrl-S ä¿å­˜å›¾åƒ" #: src/help.c:45 msgid " Ctrl-Shift-S Save layers file" msgstr "" #: src/help.c:46 msgid " Ctrl-Q Quit program\n" msgstr " Ctrl-Q 退出\n" #: src/help.c:47 msgid " Ctrl-A Select whole image" msgstr " Ctrl-A 选择整个图åƒ" #: src/help.c:48 msgid " Escape Select nothing, cancel paste box" msgstr " Esc å–æ¶ˆé€‰æ‹©ï¼Œå–消粘贴框" #: src/help.c:49 msgid " J Lasso selection\n" msgstr "" #: src/help.c:50 msgid " Ctrl-C Copy selection to clipboard" msgstr " Ctrl-C å¤åˆ¶é€‰æ‹©åŒºå¯¹è±¡åˆ°å‰ªè´´æ¿" #: src/help.c:51 msgid "" " Ctrl-X Copy selection to clipboard, and then paint current " "pattern to selection area" msgstr " Ctrl-X å¤åˆ¶é€‰æ‹©åŒºå¯¹è±¡åˆ°å‰ªè´´æ¿å¹¶ç»˜åˆ¶å½“å‰å›¾æ¡ˆåˆ°æ‰€é€‰åŒºåŸŸ" #: src/help.c:52 msgid " Ctrl-V Paste clipboard to centre of current view" msgstr " Ctrl-V 粘贴剪贴æ¿åˆ°å½“å‰è§†å›¾ä¸­å¿ƒ" #: src/help.c:53 msgid " Ctrl-K Paste clipboard to location it was copied from" msgstr " Ctrl-K 粘贴剪贴æ¿åˆ°å®ƒçš„æ¥æºä½ç½®" #: src/help.c:54 msgid " Ctrl-Shift-V Paste clipboard to new layer" msgstr "" #: src/help.c:55 msgid " Enter/Return Commit paste to canvas" msgstr " 回车键 粘贴到画布" #: src/help.c:56 msgid " Shift+Enter/Return Commit paste and swap canvas into the clipboard\n" msgstr "" #: src/help.c:57 msgid " Arrow keys Paint Mode - Move the mouse pointer" msgstr " æ–¹å‘é”® ç»˜ç”»æ¨¡å¼ - 移动鼠标指针" #: src/help.c:58 msgid "" " Arrow keys Selection Mode - Nudge selection box or paste box by one " "pixel" msgstr " æ–¹å‘é”® é€‰æ‹©æ¨¡å¼ - 以一个åƒç´ æŒªåŠ¨é€‰æ‹©æ¡†æˆ–ç²˜è´´æ¡†" #: src/help.c:59 msgid "" " Shift+Arrow keys Nudge mouse pointer, selection box or paste box by x " "pixels - x is defined by the Preferences window" msgstr "" " Shift+æ–¹å‘é”® 以 x 个åƒç´ æŒªåŠ¨é¼ æ ‡æŒ‡é’ˆï¼Œé€‰æ‹©æ¡†æˆ–ç²˜è´´æ¡† - x 由首选项窗å£" "定义" #: src/help.c:60 msgid " Ctrl+Arrows Move layer or resize selection box" msgstr " Ctrl+æ–¹å‘é”® 移动图层或调整选择框大å°" #: src/help.c:61 msgid " Ctrl+Shift+Arrows Move layer or resize selection box by x pixels\n" msgstr "" #: src/help.c:62 msgid " Enter/Return Paint Mode - Simulate left click" msgstr "" #: src/help.c:63 msgid " Backspace Paint Mode - Simulate right click\n" msgstr "" #: src/help.c:64 msgid "" " [ or ] Change colour A to the next or previous palette item" msgstr " [ 或 ] 把颜色 A 改为下一个或å‰ä¸€ä¸ªè°ƒè‰²æ¿é¡¹ç›®" #: src/help.c:65 msgid "" " Shift+[ or ] Change colour B to the next or previous palette item\n" msgstr " Shift+[ 或 ] 把颜色 B 改为下一个或å‰ä¸€ä¸ªè°ƒè‰²æ¿é¡¹ç›®\n" #: src/help.c:66 msgid " Delete Crop image to selection" msgstr " Delete è£åˆ‡å›¾åƒåˆ°é€‰æ‹©åŒºåŸŸ" #: src/help.c:67 msgid "" " Insert Transform colours - i.e. Brightness, Contrast, " "Saturation, Posterize, Gamma" msgstr " Insert å˜æ¢é¢œè‰² - 例如亮度,对比度,饱和度,海报化,伽马" #: src/help.c:68 msgid " Ctrl-G Greyscale the image" msgstr " Ctrl-G 图åƒç°åº¦å¤„ç†" #: src/help.c:69 msgid " Shift-Ctrl-G Greyscale the image (Gamma corrected)" msgstr " Shift-Ctrl-G 图åƒç°åº¦å¤„ç†ï¼ˆä¼½çŽ›ä¿®æ­£ï¼‰" #: src/help.c:70 msgid " Ctrl+M Mirror the image" msgstr "" #: src/help.c:71 msgid " Shift-Ctrl-I Invert the image\n" msgstr "" #: src/help.c:72 msgid "" " Ctrl-T Draw a rectangle around the selection area with the " "current fill" msgstr " Ctrl-T 用当å‰å¡«å……在选择区域绘制一个矩形" #: src/help.c:73 msgid " Ctrl-Shift-T Fill in the selection area with the current fill" msgstr " Ctrl-Shift-T 用当å‰å¡«å……填满选择区域" #: src/help.c:74 msgid " Ctrl-L Draw an ellipse spanning the selection area" msgstr " Ctrl-L 绘制一个椭圆跨越选择区域" #: src/help.c:75 msgid " Ctrl-Shift-L Draw a filled ellipse spanning the selection area\n" msgstr " Ctrl-Shift-L 绘制一个填充椭圆跨越选择区域\n" #: src/help.c:76 msgid " Ctrl-E Edit the RGB values for colours A & B" msgstr " Ctrl-E 编辑颜色 A å’Œ B çš„ RGB 值" #: src/help.c:77 msgid " Ctrl-W Edit all palette colours\n" msgstr " Ctrl-W 编辑所有调色æ¿é¢œè‰²\n" #: src/help.c:78 msgid " Ctrl-P Preferences" msgstr " Ctrl-P 首选项" #: src/help.c:79 msgid " Ctrl-I Information\n" msgstr " Ctrl-I ä¿¡æ¯\n" #: src/help.c:80 msgid " Ctrl-Z Undo last action" msgstr " Ctrl-Z 撤销上次æ“作" #: src/help.c:81 msgid " Ctrl-R Redo an undone action\n" msgstr " Ctrl-R æ¢å¤ä¸Šä¸€æ¬¡æ“作\n" #: src/help.c:82 msgid " Shift-T Text Tool (GTK+)" msgstr "" #: src/help.c:83 msgid " T Text Tool (FreeType)\n" msgstr "" #: src/help.c:84 msgid " V View Window" msgstr " V 查看窗å£" #: src/help.c:85 msgid " L Layers Window\n" msgstr " L 图层窗å£\n" #: src/help.c:86 msgid " Ctrl-H Toggle Hide Image mode" msgstr "" #: src/help.c:87 msgid " B Toggle Snap to Tile Grid mode\n" msgstr "" #: src/help.c:88 msgid " X Swap Colours A & B" msgstr "" #: src/help.c:89 msgid " E Choose Colour\n" msgstr "" #: src/help.c:90 msgid "" " A Draw open arrow head when using the line tool (size set " "by flow setting)" msgstr " A 使用直线工具时绘制开放箭头(大å°ç”±æµé‡è®¾ç½®è§„定)" #: src/help.c:91 msgid "" " S Draw closed arrow head when using the line tool (size " "set by flow setting)\n" msgstr " S 使用直线工具时绘制å°é—­ç®­å¤´ï¼ˆå¤§å°ç”±æµé‡è®¾ç½®è§„定)\n" #: src/help.c:92 msgid " D Line Tool" msgstr "" #: src/help.c:93 msgid " F Flood Fill Tool\n" msgstr "" #: src/help.c:94 msgid " +,= Main edit window - Zoom in" msgstr " +,= ä¸»ç¼–è¾‘çª—å£ - 放大" #: src/help.c:95 msgid " - Main edit window - Zoom out" msgstr " - ä¸»ç¼–è¾‘çª—å£ - 缩å°" #: src/help.c:96 msgid " Shift +,= View window - Zoom in" msgstr " Shift +,= æŸ¥çœ‹çª—å£ - 放大" #: src/help.c:97 msgid " Shift - View window - Zoom out\n" msgstr " Shift - æŸ¥çœ‹çª—å£ - 缩å°\n" #: src/help.c:98 #, c-format msgid " 1 10% zoom" msgstr "" #: src/help.c:99 #, c-format msgid " 2 25% zoom" msgstr "" #: src/help.c:100 #, c-format msgid " 3 50% zoom" msgstr "" #: src/help.c:101 #, c-format msgid " 4 100% zoom" msgstr "" #: src/help.c:102 #, c-format msgid " 5 400% zoom" msgstr "" #: src/help.c:103 #, c-format msgid " 6 800% zoom" msgstr "" #: src/help.c:104 #, c-format msgid " 7 1200% zoom" msgstr "" #: src/help.c:105 #, c-format msgid " 8 1600% zoom" msgstr "" #: src/help.c:106 #, c-format msgid " 9 2000% zoom\n" msgstr "" #: src/help.c:107 msgid " Shift + 1 Edit image channel" msgstr " Shift + 1 编辑图åƒé€šé“" #: src/help.c:108 msgid " Shift + 2 Edit alpha channel" msgstr " Shift + 2 ç¼–è¾‘é€æ˜Žé€šé“" #: src/help.c:109 msgid " Shift + 3 Edit selection channel" msgstr " Shift + 3 编辑选定的通é“" #: src/help.c:110 msgid " Shift + 4 Edit mask channel\n" msgstr " Shift + 4 编辑蒙版通é“\n" #: src/help.c:111 msgid " F1 Help" msgstr " F1 帮助" #: src/help.c:112 msgid " F2 Choose Pattern" msgstr " F2 选择样å¼" #: src/help.c:113 msgid " F3 Choose Brush" msgstr " F3 选择画笔" #: src/help.c:114 msgid " F4 Paint Tool" msgstr " F4 绘画工具" #: src/help.c:115 msgid " F5 Toggle Main Toolbar" msgstr " F5 切æ¢ä¸»å·¥å…·æ " #: src/help.c:116 msgid " F6 Toggle Tools Toolbar" msgstr " F6 切æ¢å·¥å…·å·¥å…·æ " #: src/help.c:117 msgid " F7 Toggle Settings Toolbar" msgstr " F7 切æ¢è®¾ç½®å·¥å…·æ " #: src/help.c:118 msgid " F8 Toggle Palette" msgstr " F8 切æ¢è°ƒè‰²æ¿" #: src/help.c:119 msgid " F9 Selection Tool" msgstr " F9 选å–工具" #: src/help.c:120 msgid " F12 Toggle Dock Area\n" msgstr " F12 切æ¢åœé åŒº\n" #: src/help.c:121 msgid " Ctrl + F1 - F12 Save current clipboard to file 1-12" msgstr " Ctrl + F1 - F12 ä¿å­˜å½“å‰å‰ªè´´æ¿åˆ°æ–‡ä»¶ 1-12" #: src/help.c:122 msgid " Shift + F1 - F12 Load clipboard from file 1-12\n" msgstr " Shift + F1 - F12 从文件 1-12 载入剪贴æ¿\n" #: src/help.c:123 msgid "" " Ctrl + 1, 2, ... , 0 Set opacity to 10%, 20%, ... , 100% (main or keypad " "numbers)" msgstr "" " Ctrl + 1, 2, ... , 0 设置ä¸é€æ˜Žåº¦ä¸º10%, 20%, ... , 100%(主键盘或å°é”®ç›˜æ•°å­—" "键)" #: src/help.c:124 msgid " Ctrl + + or = Increase opacity by 1" msgstr " Ctrl + + 或 = 增加ä¸é€æ˜Žåº¦ 1" #: src/help.c:125 msgid " Ctrl + - Decrease opacity by 1\n" msgstr " Ctrl + - å‡å°‘ä¸é€æ˜Žåº¦ 1\n" #: src/help.c:126 msgid "" " Home Show or hide main window menu/toolbar/status bar/palette" msgstr " Home 显示或éšè—主窗å£èœå•/工具æ /çŠ¶æ€æ /调色æ¿" #: src/help.c:127 msgid " Page Up Scale Image" msgstr " Page Up 缩放图åƒ" #: src/help.c:128 msgid " Page Down Resize Image canvas" msgstr " Page Down 调整图åƒç”»å¸ƒå¤§å°" #: src/help.c:129 msgid " End Pan Window" msgstr " End 全景窗å£" #: src/help.c:132 msgid " Left button Paint to canvas using the current tool" msgstr " 左键 使用当å‰å·¥å…·ç»˜åˆ¶åˆ°ç”»å¸ƒ" #: src/help.c:133 msgid "" " Middle button Selects the point which will be the centre of the " "image after the next zoom" msgstr " 中键 选å–下次缩放åŽä½œä¸ºå›¾åƒä¸­å¿ƒçš„点" #: src/help.c:134 msgid "" " Right button Commit paste to canvas / Stop drawing current line / " "Cancel selection\n" msgstr " å³é”® 粘贴到画布/åœæ­¢ç”»å½“å‰çš„直线/å–æ¶ˆé€‰æ‹©\n" #: src/help.c:135 msgid "" " Scroll Wheel In GTK+2/3 the user can have the scroll wheel zoom in " "or out via the Preferences window\n" msgstr "" " 转动滚轮 在 GTK+2/3 上使用者å¯é€šè¿‡é¦–选项窗å£è®¾ç½®ä½¿ç”¨é¼ æ ‡æ»šè½®" "进行缩放\n" #: src/help.c:136 msgid " Ctrl+Left button Choose colour A from under mouse pointer" msgstr " Ctrl+左键 从鼠标指针下选择颜色 A" #: src/help.c:137 msgid " Ctrl+Left button Clone tool - Select source" msgstr "" #: src/help.c:138 msgid "" " Ctrl+Middle button Create colour A/B and pattern based on the RGB colour " "in A (RGB images only)" msgstr "" " Ctrl+中键 创建颜色 A/B 和基于 A 中 RGB 颜色的图案(仅 RGB 图" "åƒï¼‰" #: src/help.c:139 msgid " Ctrl+Right button Choose colour B from under mouse pointer" msgstr " Ctrl+å³é”® 从鼠标指针下选择颜色 B" #: src/help.c:140 msgid "" " Ctrl+Right button Polygon tool - Delete last point / Delete nearest " "point" msgstr "" #: src/help.c:141 msgid " Ctrl+Scroll Wheel Scroll the main edit window left or right\n" msgstr " Ctrl+滚轮 å‘左或å‘å³ç§»åŠ¨ä¸»ç¼–è¾‘çª—å£\n" #: src/help.c:142 msgid "" " Ctrl+Double click Set colour A or B to average colour under brush " "square or selection marquee (RGB only)\n" msgstr "" " Ctrl+åŒå‡» 设置颜色 A 或 B ä¸ºç¬”åˆ·æ–¹æ ¼æˆ–é€‰å–æ¡†ä¸‹çš„å¹³å‡è‰²ï¼ˆä»…" "RGB)\n" #: src/help.c:143 msgid "" " Shift+Right button Selects the point which will be the centre of the " "image after the next zoom\n" "\n" msgstr "" " Shift+å³é”® 选å–下次缩放åŽä½œä¸ºå›¾åƒä¸­å¿ƒçš„点\n" "\n" #: src/help.c:144 msgid "You can fixate the X/Y co-ordinates while moving the mouse:\n" msgstr "您å¯åœ¨ç§»åŠ¨é¼ æ ‡çš„åŒæ—¶é”定 X/Y åæ ‡ï¼š\n" #: src/help.c:145 msgid " Shift Constrain mouse movements to vertical line" msgstr " Shift 强迫鼠标移动为垂直线" #: src/help.c:146 msgid " Shift+Ctrl Constrain mouse movements to horizontal line" msgstr " Shift+Ctrl 强迫鼠标移动为水平线" #: src/help.c:149 msgid "mtPaint is maintained by Dmitry Groshev.\n" msgstr "mtPaint ç”± Dmitry Groshev 维护。\n" #: src/help.c:150 msgid "wjaguar@users.sourceforge.net" msgstr "" #: src/help.c:151 msgid "http://mtpaint.sourceforge.net/\n" msgstr "" #: src/help.c:152 msgid "" "The following people (in alphabetical order) have contributed directly to " "the project, and are therefore worthy of gracious thanks for their " "generosity and hard work:\n" "\n" msgstr "" "ä¸‹åˆ—äººå£«ï¼ˆä»¥å­—æ¯æŽ’åºï¼‰å¯¹æœ¬é¡¹ç›®æœ‰ç›´æŽ¥è´¡çŒ®ï¼Œå¯¹ä»–们的慷慨和辛勤工作表示衷心感" "谢:\n" "\n" #: src/help.c:153 msgid "Authors\n" msgstr "作者群\n" #: src/help.c:154 msgid "" "Dmitry Groshev - Contributing developer for version 2.30. Lead developer and " "maintainer from version 3.00 to the present." msgstr "" "Dmitry Groshev - version 2.30 贡献开å‘者。从 version 3.00 到现在的主导开å‘者" "和维护者。" #: src/help.c:155 msgid "" "Mark Tyler - Original author and maintainer up to version 3.00, occasional " "contributor thereafter." msgstr "Mark Tyler - 原作者和直到 version 3.00 的维护者,其åŽçš„å¶å°”贡献者。" #: src/help.c:156 msgid "" "Xiaolin Wu - Wrote the Wu quantizing method - see wu.c for more " "information.\n" "\n" msgstr "" "Xiaolin Wu - Wu é‡åŒ–方法的作者,请看 wu.c ä»¥èŽ·å–æ›´å¤šä¿¡æ¯ã€‚\n" "\n" #: src/help.c:157 msgid "" "General Contributions (Feedback and Ideas for improvements unless otherwise " "stated)\n" msgstr "一般贡献者(å馈和改进æ„è§ï¼Œé™¤å¦æœ‰è¯´æ˜Žå¤–)\n" #: src/help.c:158 msgid "Abdulla Al Muhairi - Website redesign April 2005" msgstr "Abdulla Al Muhairi - 网站é‡è®¾è®¡ 2005å¹´4月" #: src/help.c:159 msgid "Alan Horkan" msgstr "" #: src/help.c:160 msgid "Alexandre Prokoudine" msgstr "" #: src/help.c:161 msgid "Antonio Andrea Bianco" msgstr "" #: src/help.c:162 msgid "Charlie Ledocq" msgstr "" #: src/help.c:163 msgid "Dennis Lee" msgstr "" #: src/help.c:164 msgid "Donald White" msgstr "" #: src/help.c:165 msgid "Ed Jason" msgstr "" #: src/help.c:166 msgid "" "Eddie Kohler - Created Gifsicle which is needed for the creation and viewing " "of animated GIF files http://www.lcdf.org/gifsicle/" msgstr "" "Eddie Kohler - 用于建立和查看 GIF 动画文件的 Gifsicle 的作者 http://www.lcdf." "org/gifsicle/" #: src/help.c:167 msgid "" "Guadalinex Team (Junta de Andalucia) - man page, Launchpad/Rosetta " "registration" msgstr "" "Guadalinex 团队(Junta de Andalucia)- å‚考指å—,Launchpad/Rosetta 注册" #: src/help.c:168 msgid "Lou Afonso" msgstr "Lou Afonso" #: src/help.c:169 msgid "Magnus Hjorth" msgstr "" #: src/help.c:170 msgid "Martin Zelaia" msgstr "" #: src/help.c:171 msgid "Pasi Kallinen" msgstr "" #: src/help.c:172 msgid "Pavel Ruzicka" msgstr "" #: src/help.c:173 msgid "Puppy Linux (Barry Kauler)" msgstr "" #: src/help.c:174 msgid "Victor Copovi" msgstr "" #: src/help.c:175 msgid "Vlastimil Krejcir" msgstr "" #: src/help.c:176 msgid "" "William Kern\n" "\n" msgstr "" #: src/help.c:177 msgid "Translations\n" msgstr "翻译\n" #: src/help.c:178 msgid "Brazilian Portuguese - Paulo Trevizan, Valter Nazianzeno" msgstr "巴西葡è„牙语 - Paulo Trevizan, Valter Nazianzeno" #: src/help.c:179 msgid "Czech - Pavel Ruzicka, Martin Petricek, Roman Hornik, Pavel Fric" msgstr "æ·å…‹è¯­ - Pavel Ruzicka, Martin Petricek, Roman Hornik, Pavel Fric" #: src/help.c:180 msgid "Dutch - Hans Strijards, Pjotr" msgstr "è·å…°è¯­ - Hans Strijards, Pjotr" #: src/help.c:181 msgid "" "French - Nicolas Velin, Pascal Billard, Sylvain Cresto, Johan Serre, " "Philippe Etienne, Victor Copovi" msgstr "" "法语 - Nicolas Velin, Pascal Billard, Sylvain Cresto, Johan Serre, Philippe " "Etienne" #: src/help.c:182 msgid "Galician - Miguel Anxo Bouzada" msgstr "加利西亚语 - Miguel Anxo Bouzada" #: src/help.c:183 msgid "German - Oliver Frommel, B. Clausius, Ulrich Ringel, Simon Brixel" msgstr "德语 - Oliver Frommel, B. Clausius, Ulrich Ringel, Simon Brixel" #: src/help.c:184 msgid "Hungarian - Ur Balazs" msgstr "" #: src/help.c:185 msgid "Italian - Angelo Gemmi" msgstr "æ„大利语 - Angelo Gemmi" #: src/help.c:186 msgid "Japanese - Norihiro YONEDA" msgstr "日语 - Norihiro YONEDA" #: src/help.c:187 msgid "Kabyle - Yacine Bouklif" msgstr "" #: src/help.c:188 msgid "Polish - Bartosz Kaszubowski, LucaS" msgstr "波兰语 - Bartosz Kaszubowski, LucaS" #: src/help.c:189 msgid "Portuguese - Israel G. Lugo, Tiago Silva" msgstr "è‘¡è„牙语 - Israel G. Lugo, Tiago Silva" #: src/help.c:190 msgid "Russian - Sergey Irupin, Dmitry Groshev" msgstr "俄语 - Sergey Irupin, Dmitry Groshev" #: src/help.c:191 msgid "Simplified Chinese - Cecc" msgstr "简体中文 - Cecc" #: src/help.c:192 msgid "Slovak - Jozef Riha" msgstr "斯洛ä¼å…‹è¯­ - Jozef Riha" #: src/help.c:193 msgid "" "Spanish - Guadalinex Team (Junta de Andalucia), Antonio Sanchez Leon, Miguel " "Anxo Bouzada, Francisco Jose Rey, Adolfo Jayme" msgstr "" "西ç­ç‰™è¯­ - Guadalinex Team (Junta de Andalucia), Antonio Sanchez Leon, " "Miguel Anxo Bouzada, Francisco Jose Rey, Adolfo Jayme" #: src/help.c:194 msgid "Swedish - Daniel Nylander, Daniel Eriksson" msgstr "瑞典语 - Daniel Nylander, Daniel Eriksson" #: src/help.c:195 msgid "Tagalog - Anjelo delCarmen" msgstr "" #: src/help.c:196 msgid "Taiwanese Chinese - Wei-Lun Chao" msgstr "ç¹ä½“中文 - Wei-Lun Chao" #: src/help.c:197 msgid "Turkish - Muhammet Kara, Tutku Dalmaz" msgstr "土耳其语 - Muhammet Kara, Tutku Dalmaz" #: src/info.c:258 msgid "Information" msgstr "ä¿¡æ¯" #: src/info.c:260 msgid "Memory" msgstr "内存" #: src/info.c:261 msgid "Total memory for main + undo images" msgstr "用于主文件 + 还原图åƒçš„全部内存" #: src/info.c:263 msgid "Undo / Redo / Max levels used" msgstr "撤销/é‡åš/最大撤销次数" #: src/info.c:265 msgid "Unused" msgstr "未使用的" #: src/info.c:269 msgid "Unique RGB pixels" msgstr "独特 RGB åƒç´ æ•°" #: src/info.c:272 src/layer.c:121 msgid "Layers" msgstr "图层" #: src/info.c:273 msgid "Total layer memory usage" msgstr "图层内存总计" #: src/info.c:277 msgid "Colour Histogram" msgstr "颜色柱状图" #: src/info.c:289 src/otherwindow.c:1614 msgid "Index" msgstr "索引" #: src/info.c:290 msgid "Canvas pixels" msgstr "画布åƒç´ " #: src/info.c:328 #, c-format msgid "Clipboard = %i x %i" msgstr "å‰ªè´´æ¿ = %i x %i" #: src/info.c:328 #, c-format msgid "Clipboard = %i x %i x RGB" msgstr "å‰ªè´´æ¿ = %i x %i x RGB" #: src/info.c:377 msgid "Orphans" msgstr "段è½å‰åˆ†é¡µ" #: src/info.c:383 #, c-format msgid "Colour index totals - %i of %i used" msgstr "颜色索引总计 - %i 在 %i 中已使用" #: src/inifile.c:966 msgid "" "Could not find home directory. Using current directory as home directory." msgstr "无法找到主目录。使用当å‰ç›®å½•作为主目录。" #: src/layer.c:63 msgid "Background" msgstr "背景" #: src/layer.c:122 src/mainwindow.c:5931 msgid "(Modified)" msgstr "(已修改)" #: src/layer.c:123 src/mainwindow.c:5932 msgid "Untitled" msgstr "无标题" #: src/layer.c:308 #, c-format msgid "Do you really want to delete layer %i (%s) ?" msgstr "您真的è¦åˆ é™¤å›¾å±‚ %i (%s) å—?" #: src/layer.c:380 msgid "" "One or more of the layers contains changes that have not been saved. Do you " "really want to lose these changes?" msgstr "ä¸€ä¸ªæˆ–æ›´å¤šçš„å›¾å±‚åŒ…å«æœªä¿å­˜çš„修改,您确定放弃这些修改å—?" #: src/layer.c:381 src/mainwindow.c:1028 msgid "Cancel Operation" msgstr "å–æ¶ˆæ“作" #: src/layer.c:381 src/mainwindow.c:1028 msgid "Lose Changes" msgstr "放弃修改" #: src/layer.c:523 #, c-format msgid "%d layers failed to load" msgstr "%d 层无法æˆåŠŸåŠ è½½" #: src/layer.c:826 msgid "" "One or more of the image layers has not been saved. You must save each " "image individually before saving the layers text file in order to load this " "composite image in the future." msgstr "" "一个或多个图层未ä¿å­˜ã€‚您必须在ä¿å­˜å›¾å±‚文本文件之å‰å•独地ä¿å­˜æ¯ä¸ªå›¾åƒï¼Œ 以便åŽ" "é¢è½½å…¥è¿™ä¸ªåˆæˆå›¾åƒã€‚" #: src/layer.c:841 msgid "Do you really want to delete all of the layers?" msgstr "您真的è¦åˆ é™¤å…¨éƒ¨çš„图层å—?" #: src/layer.c:970 msgid "You cannot add any more layers." msgstr "您ä¸å¯ä»¥å†æ·»åŠ æ›´å¤šå›¾å±‚ã€‚" #: src/layer.c:1083 src/otherwindow.c:241 msgid "New Layer" msgstr "新建图层" #: src/layer.c:1085 msgid "Raise" msgstr "æå‡" #: src/layer.c:1087 msgid "Lower" msgstr "é™ä½Ž" #: src/layer.c:1089 msgid "Duplicate Layer" msgstr "å¤åˆ¶å›¾å±‚" #: src/layer.c:1091 msgid "Centralise Layer" msgstr "图层居中" #: src/layer.c:1093 msgid "Delete Layer" msgstr "删除图层" #: src/layer.c:1095 msgid "Close Layers Window" msgstr "关闭图层窗å£" #: src/layer.c:1101 msgid "Layer Name" msgstr "图层åç§°" #: src/layer.c:1104 src/toolbar.c:209 msgid "Position" msgstr "ä½ç½®" #: src/layer.c:1112 msgid "Transparent Colour" msgstr "逿˜Žè‰²" #: src/layer.c:1117 msgid "Show all layers in main window" msgstr "在主窗å£ä¸­æ˜¾ç¤ºå…¨éƒ¨å›¾å±‚" #: src/mainwindow.c:67 src/otherwindow.c:844 src/otherwindow.c:2756 #: src/toolbar.c:342 msgid "Image" msgstr "图åƒ" #: src/mainwindow.c:69 src/mainwindow.c:489 src/otherwindow.c:1613 #: src/otherwindow.c:2302 msgid "RGB" msgstr "" #: src/mainwindow.c:69 src/otherwindow.c:1613 src/otherwindow.c:2302 msgid "sRGB" msgstr "" #: src/mainwindow.c:342 msgid "There were no unused colours to remove!" msgstr "没有未使用的颜色å¯ç§»é™¤ï¼" #: src/mainwindow.c:371 msgid "The palette does not contain 2 colours that have identical RGB values" msgstr "调色æ¿ä¸åŒ…å« RGB 值相åŒçš„两ç§é¢œè‰²" #: src/mainwindow.c:374 #, c-format msgid "" "The palette contains %i colours that have identical RGB values. Do you " "really want to merge them into one index and realign the canvas?" msgstr "" "调色æ¿åŒ…å«%iç§ RGB 值相åŒçš„颜色。您真的è¦å°†å®ƒä»¬åˆå¹¶åˆ°ä¸€ä¸ªç´¢å¼•并䏔釿–°å¯¹é½ç”»å¸ƒ" "å—?" #: src/mainwindow.c:492 msgid "indexed" msgstr "已索引" #: src/mainwindow.c:498 #, c-format msgid "" "You are trying to save an %s image to an %s file which is not possible. I " "would suggest you save with a PNG extension." msgstr "" "您正试图将图åƒ%sä¿å­˜åˆ°æ–‡ä»¶%s,这是无法实现的。我建议您将其ä¿å­˜ä¸º PNG æ ¼å¼æ–‡" "件。" #: src/mainwindow.c:500 #, c-format msgid "" "You are trying to save an %s file with a palette of more than %d colours. " "Either use another format or reduce the palette to %d colours." msgstr "" "您正试图ä¿å­˜çš„æ–‡ä»¶%s所用调色æ¿çš„颜色数多于%dç§ã€‚请使用å¦ä¸€ç§æ ¼å¼æˆ–将调色æ¿é¢œ" "色数å‡å°‘为%dç§ã€‚" #: src/mainwindow.c:578 msgid "Unable to load clipboard" msgstr "无法载入剪贴æ¿" #: src/mainwindow.c:604 msgid "Unable to save clipboard" msgstr "无法ä¿å­˜å‰ªè´´æ¿" #: src/mainwindow.c:775 msgid "Zoom in" msgstr "" #: src/mainwindow.c:777 msgid "Zoom out" msgstr "" #: src/mainwindow.c:779 #, c-format msgid "10% zoom" msgstr "" #: src/mainwindow.c:781 #, c-format msgid "25% zoom" msgstr "" #: src/mainwindow.c:783 #, c-format msgid "50% zoom" msgstr "" #: src/mainwindow.c:785 #, c-format msgid "100% zoom" msgstr "" #: src/mainwindow.c:787 #, c-format msgid "400% zoom" msgstr "" #: src/mainwindow.c:789 #, c-format msgid "600% zoom" msgstr "" #: src/mainwindow.c:791 #, c-format msgid "800% zoom" msgstr "" #: src/mainwindow.c:793 #, c-format msgid "1000% zoom" msgstr "" #: src/mainwindow.c:795 #, c-format msgid "1200% zoom" msgstr "" #: src/mainwindow.c:797 #, c-format msgid "1600% zoom" msgstr "" #: src/mainwindow.c:799 #, c-format msgid "2000% zoom" msgstr "" #: src/mainwindow.c:801 #, c-format msgid "4000% zoom" msgstr "" #: src/mainwindow.c:803 #, c-format msgid "8000% zoom" msgstr "" #: src/mainwindow.c:805 #, c-format msgid "10% opacity" msgstr "" #: src/mainwindow.c:807 #, c-format msgid "20% opacity" msgstr "" #: src/mainwindow.c:809 #, c-format msgid "30% opacity" msgstr "" #: src/mainwindow.c:811 #, c-format msgid "40% opacity" msgstr "" #: src/mainwindow.c:813 #, c-format msgid "50% opacity" msgstr "" #: src/mainwindow.c:815 #, c-format msgid "60% opacity" msgstr "" #: src/mainwindow.c:817 #, c-format msgid "70% opacity" msgstr "" #: src/mainwindow.c:819 #, c-format msgid "80% opacity" msgstr "" #: src/mainwindow.c:821 #, c-format msgid "90% opacity" msgstr "" #: src/mainwindow.c:823 #, c-format msgid "100% opacity" msgstr "" #: src/mainwindow.c:825 msgid "Increase opacity" msgstr "" #: src/mainwindow.c:827 msgid "Decrease opacity" msgstr "" #: src/mainwindow.c:829 msgid "Draw open arrow head" msgstr "" #: src/mainwindow.c:831 msgid "Draw closed arrow head" msgstr "" #: src/mainwindow.c:833 msgid "Previous colour A" msgstr "" #: src/mainwindow.c:835 msgid "Next colour A" msgstr "" #: src/mainwindow.c:837 msgid "Previous colour B" msgstr "" #: src/mainwindow.c:839 msgid "Next colour B" msgstr "" #: src/mainwindow.c:841 msgid "Previous pattern" msgstr "" #: src/mainwindow.c:843 msgid "Next pattern" msgstr "" #: src/mainwindow.c:845 msgid "Larger brush" msgstr "" #: src/mainwindow.c:847 msgid "Smaller brush" msgstr "" #: src/mainwindow.c:849 msgid "View window - Zoom in" msgstr "" #: src/mainwindow.c:851 msgid "View window - Zoom out" msgstr "" #: src/mainwindow.c:1027 msgid "" "This canvas/palette contains changes that have not been saved. Do you " "really want to lose these changes?" msgstr "此画布/调色æ¿åŒ…嫿œªä¿å­˜çš„修改。您确定放弃这些修改å—?" #: src/mainwindow.c:1094 msgid "Do you really want to quit?" msgstr "您确定è¦é€€å‡ºå—?" #: src/mainwindow.c:3754 msgid "Empty string or broken quoting" msgstr "" #: src/mainwindow.c:3755 msgid "Script must begin with a command" msgstr "" #: src/mainwindow.c:3756 msgid "Script nesting limit exceeded" msgstr "" #: src/mainwindow.c:3765 #, c-format msgid "'%s' does not match any item" msgstr "" #: src/mainwindow.c:3767 #, c-format msgid "'%s' matches a non-scriptable item" msgstr "" #: src/mainwindow.c:3769 #, c-format msgid "'%s' matches a disabled item" msgstr "" #: src/mainwindow.c:3788 #, c-format msgid "'%s' value does not fit item" msgstr "" #: src/mainwindow.c:3969 msgid "Script" msgstr "" #: src/mainwindow.c:3982 src/spawn.c:656 src/spawn.c:662 msgid "Action" msgstr "动作" #: src/mainwindow.c:3991 src/spawn.c:666 msgid "Execute" msgstr "è¿è¡Œ" #: src/mainwindow.c:4045 msgid "Unable to load script" msgstr "" #: src/mainwindow.c:5182 msgid "/_File" msgstr "/文件(_F)" #: src/mainwindow.c:5184 msgid "//New" msgstr "//新建" #: src/mainwindow.c:5186 msgid "//Open ..." msgstr "//打开…" #: src/mainwindow.c:5188 src/mainwindow.c:5669 msgid "//Save" msgstr "//ä¿å­˜" #: src/mainwindow.c:5190 src/mainwindow.c:5549 src/mainwindow.c:5627 #: src/mainwindow.c:5671 msgid "//Save As ..." msgstr "//å¦å­˜ä¸ºâ€¦" #: src/mainwindow.c:5192 msgid "//Export Undo Images ..." msgstr "//导出还原图åƒâ€¦" #: src/mainwindow.c:5194 msgid "//Export Undo Images (reversed) ..." msgstr "//导出还原图åƒï¼ˆåå‘)…" #: src/mainwindow.c:5196 msgid "//Export ASCII Art ..." msgstr "//导出 ASCII 图案…" #: src/mainwindow.c:5198 msgid "//Export Animated GIF ..." msgstr "//导出 GIF 动画…" #: src/mainwindow.c:5201 msgid "//Actions" msgstr "//动作" #: src/mainwindow.c:5235 src/mainwindow.c:5488 msgid "///Configure" msgstr "///é…ç½®" #: src/mainwindow.c:5290 msgid "//Quit" msgstr "//退出" #: src/mainwindow.c:5293 msgid "/_Edit" msgstr "/编辑(_E)" #: src/mainwindow.c:5295 msgid "//Undo" msgstr "//撤消" #: src/mainwindow.c:5297 msgid "//Redo" msgstr "//é‡åš" #: src/mainwindow.c:5300 msgid "//Cut" msgstr "//剪切" #: src/mainwindow.c:5302 msgid "//Copy" msgstr "//å¤åˆ¶" #: src/mainwindow.c:5304 msgid "//Copy To Palette" msgstr "//å¤åˆ¶åˆ°è°ƒè‰²æ¿" #: src/mainwindow.c:5306 msgid "//Paste To Centre" msgstr "//粘贴到中心" #: src/mainwindow.c:5308 msgid "//Paste To New Layer" msgstr "//粘贴到新图层" #: src/mainwindow.c:5310 msgid "//Paste" msgstr "//粘贴" #: src/mainwindow.c:5312 msgid "//Paste Text" msgstr "//粘贴文本" #: src/mainwindow.c:5318 msgid "//Paste Text (FreeType)" msgstr "//粘贴文本 (FreeType)" #: src/mainwindow.c:5321 msgid "//Paste Palette" msgstr "//粘贴调色æ¿" #: src/mainwindow.c:5323 msgid "//Load Clipboard" msgstr "//载入剪贴æ¿" #: src/mainwindow.c:5350 msgid "//Save Clipboard" msgstr "//ä¿å­˜å‰ªè´´æ¿" #: src/mainwindow.c:5377 msgid "//Import Clipboard from System" msgstr "//从系统导入剪贴æ¿" #: src/mainwindow.c:5378 msgid "//Export Clipboard to System" msgstr "//导出剪贴æ¿åˆ°ç³»ç»Ÿ" #: src/mainwindow.c:5381 msgid "//Choose Pattern ..." msgstr "//选å–图案…" #: src/mainwindow.c:5383 msgid "//Choose Brush ..." msgstr "//选å–笔刷…" #: src/mainwindow.c:5385 msgid "//Choose Colour ..." msgstr "" #: src/mainwindow.c:5392 msgid "/_View" msgstr "/查看(_V)" #: src/mainwindow.c:5394 msgid "//Show Main Toolbar" msgstr "//显示主工具æ " #: src/mainwindow.c:5396 msgid "//Show Tools Toolbar" msgstr "//显示工具工具æ " #: src/mainwindow.c:5399 msgid "//Show Settings Toolbar" msgstr "//显示设置工具æ " #: src/mainwindow.c:5402 msgid "//Show Dock" msgstr "//显示åœé " #: src/mainwindow.c:5404 msgid "//Show Palette" msgstr "//显示调色æ¿" #: src/mainwindow.c:5406 msgid "//Show Status Bar" msgstr "//æ˜¾ç¤ºçŠ¶æ€æ " #: src/mainwindow.c:5409 msgid "//Toggle Image View" msgstr "//切æ¢ä¸ºå›¾åƒæŸ¥çœ‹" #: src/mainwindow.c:5413 msgid "//Centralize Image" msgstr "//图åƒå±…中" #: src/mainwindow.c:5414 msgid "//Show Zoom Grid" msgstr "//显示缩放格线" #: src/mainwindow.c:5415 msgid "//Snap To Tile Grid" msgstr "" #: src/mainwindow.c:5417 msgid "//Configure Grid ..." msgstr "//é…置网格…" #: src/mainwindow.c:5418 msgid "//Tracing Image ..." msgstr "//ææ‘¹å›¾åƒâ€¦" #: src/mainwindow.c:5421 msgid "//View Window" msgstr "//查看窗å£" #: src/mainwindow.c:5423 msgid "//Horizontal Split" msgstr "//水平分隔" #: src/mainwindow.c:5425 msgid "//Focus View Window" msgstr "//åŒæ­¥æŸ¥çœ‹çª—å£" #: src/mainwindow.c:5427 msgid "//Pan Window" msgstr "//全景窗å£" #: src/mainwindow.c:5430 msgid "//Layers Window" msgstr "//图层窗å£" #: src/mainwindow.c:5433 msgid "/_Image" msgstr "/图åƒ(_I)" #: src/mainwindow.c:5436 msgid "//Convert To RGB" msgstr "//转æ¢åˆ° RGB" #: src/mainwindow.c:5438 msgid "//Convert To Indexed ..." msgstr "//转æ¢åˆ°ç´¢å¼•值…" #: src/mainwindow.c:5441 msgid "//Scale Canvas ..." msgstr "//伸缩画布…" #: src/mainwindow.c:5443 msgid "//Resize Canvas ..." msgstr "//调整画布大å°â€¦" #: src/mainwindow.c:5445 msgid "//Crop" msgstr "//è£åˆ‡" #: src/mainwindow.c:5448 src/mainwindow.c:5517 msgid "//Flip Vertically" msgstr "//垂直翻转" #: src/mainwindow.c:5449 src/mainwindow.c:5519 msgid "//Flip Horizontally" msgstr "//水平翻转" #: src/mainwindow.c:5452 src/mainwindow.c:5521 msgid "//Rotate Clockwise" msgstr "//顺时针旋转" #: src/mainwindow.c:5453 src/mainwindow.c:5523 msgid "//Rotate Anti-Clockwise" msgstr "//逆时针旋转" #: src/mainwindow.c:5454 msgid "//Free Rotate ..." msgstr "//自由旋转…" #: src/mainwindow.c:5455 msgid "//Skew ..." msgstr "//倾斜…" #: src/mainwindow.c:5458 msgid "//Segment ..." msgstr "" #: src/mainwindow.c:5462 msgid "//Script ..." msgstr "" #: src/mainwindow.c:5464 msgid "//Scripts" msgstr "" #: src/mainwindow.c:5491 msgid "//Information ..." msgstr "//ä¿¡æ¯â€¦" #: src/mainwindow.c:5494 msgid "//Preferences ..." msgstr "//首选项…" #: src/mainwindow.c:5497 msgid "/_Selection" msgstr "/选择(_S)" #: src/mainwindow.c:5499 msgid "//Select All" msgstr "//全选" #: src/mainwindow.c:5501 msgid "//Select None (Esc)" msgstr "//全部ä¸é€‰(Esc)" #: src/mainwindow.c:5503 msgid "//Lasso Selection" msgstr "//套索选择" #: src/mainwindow.c:5505 msgid "//Lasso Selection Cut" msgstr "//剪切套索选择区" #: src/mainwindow.c:5508 msgid "//Outline Selection" msgstr "//æè¾¹é€‰æ‹©" #: src/mainwindow.c:5510 msgid "//Fill Selection" msgstr "//填充选择" #: src/mainwindow.c:5512 msgid "//Outline Ellipse" msgstr "//æè¾¹æ¤­åœ†" #: src/mainwindow.c:5514 msgid "//Fill Ellipse" msgstr "//填充椭圆" #: src/mainwindow.c:5526 msgid "//Horizontal Ramp" msgstr "//æ°´å¹³æ¸å˜" #: src/mainwindow.c:5528 msgid "//Vertical Ramp" msgstr "//垂直æ¸å˜" #: src/mainwindow.c:5531 msgid "//Alpha Blend A,B" msgstr "//逿˜Žæ··è‰² A,B" #: src/mainwindow.c:5533 msgid "//Move Alpha to Mask" msgstr "//ç§»åŠ¨é€æ˜Žåˆ°é®ç½©" #: src/mainwindow.c:5535 msgid "//Mask Colour A,B" msgstr "//é®ç½©é¢œè‰² A,B" #: src/mainwindow.c:5537 msgid "//Unmask Colour A,B" msgstr "//å–æ¶ˆé®ç½©é¢œè‰² A,B" #: src/mainwindow.c:5539 msgid "//Mask All Colours" msgstr "//é®ç½©æ‰€æœ‰é¢œè‰²" #: src/mainwindow.c:5541 msgid "//Clear Mask" msgstr "//清除é®ç½©" #: src/mainwindow.c:5544 msgid "/_Palette" msgstr "/调色æ¿(_P)" #: src/mainwindow.c:5548 src/mainwindow.c:5626 msgid "//Load ..." msgstr "//载入…" #: src/mainwindow.c:5550 msgid "//Load Default" msgstr "//载入默认调色æ¿" #: src/mainwindow.c:5552 msgid "//Mask All" msgstr "//全部é®ç½©" #: src/mainwindow.c:5553 msgid "//Mask None" msgstr "//æ— é®ç½©" #: src/mainwindow.c:5555 msgid "//Swap A & B" msgstr "//äº¤æ¢ A å’Œ B" #: src/mainwindow.c:5557 msgid "//Edit Colour A & B ..." msgstr "//编辑 A å’Œ B 的颜色…" #: src/mainwindow.c:5559 msgid "//Dither A" msgstr "//抖动 A" #: src/mainwindow.c:5561 msgid "//Palette Editor ..." msgstr "//调色æ¿ç¼–辑器…" #: src/mainwindow.c:5563 msgid "//Set Palette Size ..." msgstr "//设置调色æ¿å¤§å°â€¦" #: src/mainwindow.c:5564 msgid "//Merge Duplicate Colours" msgstr "//åˆå¹¶é‡å¤çš„颜色" #: src/mainwindow.c:5566 msgid "//Remove Unused Colours" msgstr "//移除未使用的颜色" #: src/mainwindow.c:5569 msgid "//Create Quantized ..." msgstr "//建立é‡åŒ–…" #: src/mainwindow.c:5572 msgid "//Sort Colours ..." msgstr "//颜色排åºâ€¦" #: src/mainwindow.c:5573 msgid "//Palette Shifter ..." msgstr "//调色æ¿å˜æ¢â€¦" #: src/mainwindow.c:5574 msgid "//Pick Gradient ..." msgstr "" #: src/mainwindow.c:5576 msgid "/Effe_cts" msgstr "/效果(_C)" #: src/mainwindow.c:5578 msgid "//Transform Colour ..." msgstr "//å˜æ¢é¢œè‰²â€¦" #: src/mainwindow.c:5580 msgid "//Invert" msgstr "//åå‘" #: src/mainwindow.c:5582 msgid "//Greyscale" msgstr "//ç°é˜¶" #: src/mainwindow.c:5584 msgid "//Greyscale (Gamma corrected)" msgstr "//ç°åº¦å¤„ç†ï¼ˆä¼½çŽ›ä¿®æ­£ï¼‰" #: src/mainwindow.c:5586 msgid "//Normalize" msgstr "" #: src/mainwindow.c:5587 src/mainwindow.c:5658 msgid "//Threshold ..." msgstr "//阈值…" #: src/mainwindow.c:5588 msgid "//Map ..." msgstr "" #: src/mainwindow.c:5590 msgid "//Isometric Transformation" msgstr "//ç­‰é‡å˜æ¢" #: src/mainwindow.c:5592 msgid "///Left Side Down" msgstr "///左侧å‘下" #: src/mainwindow.c:5593 msgid "///Right Side Down" msgstr "///å³ä¾§å‘下" #: src/mainwindow.c:5594 msgid "///Top Side Right" msgstr "///顶端å‘å³" #: src/mainwindow.c:5595 msgid "///Bottom Side Right" msgstr "///底侧å‘å³" #: src/mainwindow.c:5598 msgid "//Edge Detect ..." msgstr "//边缘检测…" #: src/mainwindow.c:5600 msgid "//Difference of Gaussians ..." msgstr "//高斯差异…" #: src/mainwindow.c:5602 msgid "//Sharpen ..." msgstr "//é”化…" #: src/mainwindow.c:5604 msgid "//Unsharp Mask ..." msgstr "//é’化é®ç½©â€¦" #: src/mainwindow.c:5606 msgid "//Soften ..." msgstr "//柔化…" #: src/mainwindow.c:5608 msgid "//Gaussian Blur ..." msgstr "//高斯模糊…" #: src/mainwindow.c:5610 msgid "//Kuwahara-Nagao Blur ..." msgstr "//Kuwahara-Nagao 模糊…" #: src/mainwindow.c:5612 msgid "//Emboss" msgstr "//浮雕" #: src/mainwindow.c:5614 msgid "//Dilate" msgstr "//膨胀" #: src/mainwindow.c:5616 msgid "//Erode" msgstr "//è…蚀" #: src/mainwindow.c:5619 msgid "//Solid Noise ..." msgstr "" #: src/mainwindow.c:5620 msgid "//Bacteria ..." msgstr "//èŒåŒ–…" #: src/mainwindow.c:5623 msgid "/Cha_nnels" msgstr "/通é“(_N)" #: src/mainwindow.c:5625 msgid "//New ..." msgstr "//新建…" #: src/mainwindow.c:5628 msgid "//Delete ..." msgstr "//删除…" #: src/mainwindow.c:5632 msgid "//Edit Image" msgstr "//编辑图åƒ" #: src/mainwindow.c:5635 msgid "//Edit Alpha" msgstr "//ç¼–è¾‘é€æ˜Ž" #: src/mainwindow.c:5638 msgid "//Edit Selection" msgstr "//编辑选择" #: src/mainwindow.c:5641 msgid "//Edit Mask" msgstr "//编辑é®ç½©" #: src/mainwindow.c:5645 msgid "//Hide Image" msgstr "//éšè—图åƒ" #: src/mainwindow.c:5648 msgid "//Disable Alpha" msgstr "//åœç”¨é€æ˜Ž" #: src/mainwindow.c:5651 msgid "//Disable Selection" msgstr "//åœç”¨é€‰æ‹©" #: src/mainwindow.c:5654 msgid "//Disable Mask" msgstr "//åœç”¨é®ç½©" #: src/mainwindow.c:5657 msgid "//Couple RGBA Operations" msgstr "//ç»“åˆ RGBA æ“作" #: src/mainwindow.c:5659 msgid "//Unassociate Alpha" msgstr "//解除关è”逿˜Ž" #: src/mainwindow.c:5663 msgid "//View Alpha as an Overlay" msgstr "//将逿˜Žä½œä¸ºå¤–罩查看" #: src/mainwindow.c:5664 msgid "//Configure Overlays ..." msgstr "//é…置外罩…" #: src/mainwindow.c:5666 msgid "/_Layers" msgstr "/图层(_L)" #: src/mainwindow.c:5668 msgid "//New Layer" msgstr "//新建图层" #: src/mainwindow.c:5672 msgid "//Save Composite Image ..." msgstr "//ä¿å­˜åˆæˆå›¾åƒâ€¦" #: src/mainwindow.c:5673 msgid "//Composite to New Layer" msgstr "//åˆå¹¶åˆ°æ–°å›¾å±‚" #: src/mainwindow.c:5674 msgid "//Remove All Layers" msgstr "//移除所有图层" #: src/mainwindow.c:5676 msgid "//Configure Animation ..." msgstr "//é…置动画…" #: src/mainwindow.c:5677 msgid "//Preview Animation ..." msgstr "//预览动画…" #: src/mainwindow.c:5678 msgid "//Set Key Frame ..." msgstr "//设置关键帧…" #: src/mainwindow.c:5679 msgid "//Remove All Key Frames ..." msgstr "//移除所有关键帧…" #: src/mainwindow.c:5681 msgid "/More..." msgstr "/更多…" #: src/mainwindow.c:5683 msgid "/_Help" msgstr "/帮助(_H)" #: src/mainwindow.c:5684 msgid "//Documentation" msgstr "//文件" #: src/mainwindow.c:5686 msgid "//About" msgstr "//关于" #: src/mainwindow.c:5689 msgid "//Keyboard Shortcuts ..." msgstr "" #: src/mainwindow.c:5690 msgid "//Rebind Shortcut Keycodes" msgstr "//釿–°ç»‘定快æ·é”®" #: src/memory.c:2800 msgid "Quantize Pass 1" msgstr "" #: src/memory.c:2854 msgid "Quantize Pass 2" msgstr "" #: src/memory.c:3073 src/memory.c:3458 msgid "Converting to Indexed Palette" msgstr "转æ¢åˆ°ç´¢å¼•过的调色æ¿" #: src/memory.c:5135 src/otherwindow.c:540 msgid "Bacteria Effect" msgstr "èŒåŒ–效果" #: src/memory.c:5170 msgid "Rotating" msgstr "旋转" #: src/memory.c:5511 msgid "Free Rotation" msgstr "自由旋转" #: src/memory.c:6096 msgid "Scaling Image" msgstr "伸缩图åƒ" #: src/memory.c:7560 msgid "Counting Unique RGB Pixels" msgstr "计算唯一 RGB åƒç´ " #: src/memory.c:7608 msgid "Applying Effect" msgstr "应用效果" #: src/memory.c:8792 msgid "Kuwahara-Nagao Filter" msgstr "Kuwahara-Nagao 过滤" #: src/memory.c:10456 src/otherwindow.c:2665 msgid "Skew" msgstr "倾斜" #: src/memory.c:10630 msgid "Segmentation Pass 1" msgstr "" #: src/memory.c:10757 msgid "Segmentation Pass 2" msgstr "" #: src/memory.c:11019 src/otherwindow.c:3156 msgid "Solid Noise" msgstr "" #: src/mygtk.c:134 src/mygtk.c:163 msgid "Please Wait ..." msgstr "请ç¨ç­‰â€¦" #: src/mygtk.c:141 msgid "STOP" msgstr "åœæ­¢" #: src/mygtk.c:504 msgid "Disabled" msgstr "" #: src/mygtk.c:504 src/toolbar.c:301 msgid "Screen" msgstr "滤色" #: src/mygtk.c:504 msgid "Window" msgstr "" #: src/mygtk.c:508 msgid "Input" msgstr "" #: src/mygtk.c:512 msgid "Device:" msgstr "" #: src/mygtk.c:514 msgid "Mode:" msgstr "" #: src/mygtk.c:519 msgid "Axes" msgstr "" #: src/mygtk.c:524 msgid "X:" msgstr "" #: src/mygtk.c:525 msgid "Y:" msgstr "" #: src/mygtk.c:526 msgid "Pressure:" msgstr "" #: src/mygtk.c:527 msgid "X tilt:" msgstr "" #: src/mygtk.c:528 msgid "Y tilt:" msgstr "" #: src/mygtk.c:529 msgid "Wheel:" msgstr "" #: src/mygtk.c:579 msgid "none" msgstr "" #: src/otherwindow.c:236 msgid "24 bit RGB" msgstr "24 ä½ RGB" #: src/otherwindow.c:236 src/otherwindow.c:3179 msgid "Greyscale" msgstr "ç°åº¦" #: src/otherwindow.c:237 msgid "Indexed Palette" msgstr "索引过的调色æ¿" #: src/otherwindow.c:237 msgid "From Clipboard" msgstr "从剪贴æ¿" #: src/otherwindow.c:237 msgid "Grab Screenshot" msgstr "抓å–å±å¹•å¿«ç…§" #: src/otherwindow.c:242 src/toolbar.c:542 msgid "New Image" msgstr "新建图åƒ" #: src/otherwindow.c:246 src/otherwindow.c:3164 msgid "Colours" msgstr "颜色" #: src/otherwindow.c:409 msgid "Pattern Chooser" msgstr "图案选择器" #: src/otherwindow.c:497 msgid "Set Palette Size" msgstr "设置调色æ¿å¤§å°" #: src/otherwindow.c:517 src/otherwindow.c:591 src/otherwindow.c:870 #: src/otherwindow.c:2538 src/otherwindow.c:2776 src/otherwindow.c:2939 #: src/prefs.c:338 src/prefs.c:538 msgid "Apply" msgstr "应用" #: src/otherwindow.c:573 msgid "Luminance" msgstr "亮度" #: src/otherwindow.c:573 src/otherwindow.c:814 msgid "Brightness" msgstr "亮度" #: src/otherwindow.c:574 msgid "Distance to A" msgstr "到 A çš„è·ç¦»" #: src/otherwindow.c:575 msgid "Projection to A->B" msgstr "A->B 投影" #: src/otherwindow.c:576 msgid "Frequency" msgstr "频率" #: src/otherwindow.c:580 msgid "Sort Palette Colours" msgstr "调色æ¿é¢œè‰²æŽ’åº" #: src/otherwindow.c:582 msgid "Start Index" msgstr "开始索引" #: src/otherwindow.c:583 msgid "End Index" msgstr "结æŸç´¢å¼•" #: src/otherwindow.c:589 msgid "Reverse Order" msgstr "å呿ޒåº" #: src/otherwindow.c:805 msgid "Bitwise" msgstr "" #: src/otherwindow.c:805 msgid "Truncated" msgstr "" #: src/otherwindow.c:805 msgid "Rounded" msgstr "" #: src/otherwindow.c:809 src/toolbar.c:311 src/toolbar.c:558 msgid "Transform Colour" msgstr "å˜æ¢é¢œè‰²" #: src/otherwindow.c:812 msgid "Gamma" msgstr "伽玛" #: src/otherwindow.c:816 msgid "Contrast" msgstr "对比" #: src/otherwindow.c:822 src/otherwindow.c:1674 msgid "Posterize" msgstr "色调分离" #: src/otherwindow.c:831 msgid "Show Detail" msgstr "显示明细" #: src/otherwindow.c:836 msgid "Posterize type" msgstr "" #: src/otherwindow.c:857 msgid "Auto-Preview" msgstr "自动预览" #: src/otherwindow.c:869 msgid "Reset" msgstr "é‡ç½®" #: src/otherwindow.c:931 msgid "New geometry is the same as now - nothing to do." msgstr "æ–°åæ ‡ä½ç½®ä¸ŽçŽ°åœ¨ç›¸åŒ - æ— å˜åŒ–。" #: src/otherwindow.c:980 msgid "The operating system cannot allocate the memory for this operation." msgstr "æ“作系统无法为此æ“作分é…内存。" #: src/otherwindow.c:982 msgid "" "You have not allocated enough memory in the Preferences window for this " "operation." msgstr "您未在首选项窗å£ä¸­ä¸ºæ­¤é¡¹æ“作分é…足够的内存。" #: src/otherwindow.c:993 src/otherwindow.c:2495 msgid "Mirror" msgstr "镜åƒ" #: src/otherwindow.c:993 src/otherwindow.c:994 msgid "Tile" msgstr "平铺效果" #: src/otherwindow.c:993 msgid "Void" msgstr "" #: src/otherwindow.c:994 src/shifter.c:283 msgid "Clear" msgstr "清除" #: src/otherwindow.c:994 msgid "Mirror tile" msgstr "镜åƒå¹³é“ºæ•ˆæžœ" #: src/otherwindow.c:996 msgid "Nearest Neighbour" msgstr "最近的邻居" #: src/otherwindow.c:997 msgid "Bilinear / Area Mapping" msgstr "åŒçº¿æ€§/区域映射" #: src/otherwindow.c:998 msgid "Bicubic" msgstr "åŒç«‹ä½“" #: src/otherwindow.c:999 msgid "Bicubic edged" msgstr "åŒç«‹ä½“边缘化" #: src/otherwindow.c:1000 msgid "Bicubic better" msgstr "åŒç«‹ä½“优化" #: src/otherwindow.c:1001 msgid "Bicubic sharper" msgstr "åŒç«‹ä½“é”化" #: src/otherwindow.c:1002 msgid "Blackman-Harris" msgstr "Blackman-Harris" #: src/otherwindow.c:1008 msgid "Scale Canvas" msgstr "伸缩画布" #: src/otherwindow.c:1009 msgid "Resize Canvas" msgstr "调整画布大å°" #: src/otherwindow.c:1012 msgid "Original " msgstr "原值 " #: src/otherwindow.c:1013 msgid "New" msgstr "新值" #: src/otherwindow.c:1014 msgid "Width " msgstr "宽 " #: src/otherwindow.c:1018 msgid "Height " msgstr "高 " #: src/otherwindow.c:1023 src/otherwindow.c:2514 src/otherwindow.c:2672 #: src/toolbar.c:212 msgid "Offset" msgstr "åç§»" #: src/otherwindow.c:1026 src/otherwindow.c:1615 src/viewer.c:1209 msgid "Centre" msgstr "居中" #: src/otherwindow.c:1033 src/otherwindow.c:1052 msgid "Fix Aspect Ratio" msgstr "ä¿®å¤é«˜å®½æ¯”" #: src/otherwindow.c:1039 src/otherwindow.c:2070 src/toolbar.c:312 msgid "Settings" msgstr "é…ç½®" #: src/otherwindow.c:1046 msgid "Sharper image reduction" msgstr "é”化缩å°å›¾åƒ" #: src/otherwindow.c:1047 msgid "Boundary extension" msgstr "" #: src/otherwindow.c:1613 src/otherwindow.c:2302 msgid "HSV" msgstr "" #: src/otherwindow.c:1614 msgid "Highlight" msgstr "" #: src/otherwindow.c:1615 msgid "Limit" msgstr "é™åˆ¶" #: src/otherwindow.c:1616 msgid "Sphere" msgstr "çƒä½“" #: src/otherwindow.c:1616 src/otherwindow.c:2670 msgid "Angle" msgstr "角度" #: src/otherwindow.c:1616 msgid "Cube" msgstr "立方体" #: src/otherwindow.c:1617 msgid "Opaque" msgstr "ä¸é€æ˜Ž" #: src/otherwindow.c:1617 msgid "Border" msgstr "分界" #: src/otherwindow.c:1618 msgid "Transparent" msgstr "逿˜Ž" #: src/otherwindow.c:1618 msgid "Tile " msgstr "平铺 " #: src/otherwindow.c:1618 msgid "Segment" msgstr "" #: src/otherwindow.c:1656 msgid "Scale" msgstr "缩放" #: src/otherwindow.c:1657 src/otherwindow.c:3059 msgid "From" msgstr "从" #: src/otherwindow.c:1659 src/otherwindow.c:3061 msgid "To" msgstr "到" #: src/otherwindow.c:1699 msgid "Range" msgstr "范围" #: src/otherwindow.c:1702 msgid "Inverse" msgstr "åå‘" #: src/otherwindow.c:1710 msgid "Smart grid" msgstr "智能网格" #: src/otherwindow.c:1712 msgid "Tile grid" msgstr "平铺网格" #: src/otherwindow.c:1714 msgid "Minimum grid zoom" msgstr "æœ€å°æ ¼çº¿ç¼©æ”¾" #: src/otherwindow.c:1717 msgid "Tile width" msgstr "平铺宽" #: src/otherwindow.c:1720 msgid "Tile height" msgstr "平铺高" #: src/otherwindow.c:1744 msgid "Palette Editor" msgstr "调色æ¿ç¼–辑器" #: src/otherwindow.c:1763 msgid "Configure Overlays" msgstr "é…置外罩" #: src/otherwindow.c:1782 msgid "Colour Editor" msgstr "颜色编辑器" #: src/otherwindow.c:1818 src/toolbar.c:430 msgid "Colour-Selective Mode" msgstr "颜色选择模å¼" #: src/otherwindow.c:1843 msgid "Configure Grid" msgstr "é…置网格" #: src/otherwindow.c:2045 msgid "Exact Conversion" msgstr "精确转æ¢" #: src/otherwindow.c:2045 msgid "Use Current Palette" msgstr "使用当å‰è°ƒè‰²æ¿" #: src/otherwindow.c:2046 msgid "PNN Quantize (slow, better quality)" msgstr "PNN é‡åŒ–ï¼ˆæ…¢ä½†è´¨é‡æ›´å¥½ï¼‰" #: src/otherwindow.c:2047 msgid "Wu Quantize (fast)" msgstr "Wu é‡åŒ–(快速)" #: src/otherwindow.c:2048 msgid "Max-Min Quantize (best for small palettes and dithering)" msgstr "最大 - 最å°é‡åŒ–(适åˆå°è°ƒè‰²ç›˜å’ŒæŠ–动)" #: src/otherwindow.c:2049 src/otherwindow.c:2495 src/otherwindow.c:2756 #: src/png.c:2794 src/prefs.c:377 msgid "None" msgstr "æ— " #: src/otherwindow.c:2049 msgid "Floyd-Steinberg" msgstr "Floyd-Steinberg" #: src/otherwindow.c:2049 msgid "Stucki" msgstr "" #: src/otherwindow.c:2052 msgid "Floyd-Steinberg (quick)" msgstr "Floyd-Steinberg(快速)" #: src/otherwindow.c:2052 msgid "Dithered (effect)" msgstr "抖动(效果)" #: src/otherwindow.c:2053 msgid "Scattered (effect)" msgstr "分散(效果)" #: src/otherwindow.c:2054 msgid "Gamut" msgstr "色域" #: src/otherwindow.c:2054 msgid "Weakly" msgstr "弱化" #: src/otherwindow.c:2054 msgid "Strongly" msgstr "强化" #: src/otherwindow.c:2055 msgid "Off" msgstr "关闭" #: src/otherwindow.c:2055 msgid "Separate/Sum" msgstr "å•独/总和" #: src/otherwindow.c:2055 msgid "Separate/Split" msgstr "å•独/分割" #: src/otherwindow.c:2056 msgid "Length/Sum" msgstr "长度/总和" #: src/otherwindow.c:2056 msgid "Length/Split" msgstr "长度/分割" #: src/otherwindow.c:2057 msgid "Largest (Linf)" msgstr "最大(Linf)" #: src/otherwindow.c:2057 msgid "Sum (L1)" msgstr "总和(L1)" #: src/otherwindow.c:2057 msgid "Euclidean (L2)" msgstr "欧几里德(L2)" #: src/otherwindow.c:2061 msgid "Create Quantized" msgstr "建立é‡åŒ–" #: src/otherwindow.c:2062 msgid "Convert To Indexed" msgstr "转æ¢åˆ°ç´¢å¼•" #: src/otherwindow.c:2065 msgid "Indexed Colours To Use" msgstr "所使用的索引颜色" #: src/otherwindow.c:2078 msgid "Truncate palette" msgstr "缩短调色æ¿" #: src/otherwindow.c:2079 msgid "Diameter based weighting" msgstr "基于直径的称é‡" #: src/otherwindow.c:2084 msgid "Dither" msgstr "抖动" #: src/otherwindow.c:2087 src/otherwindow.c:2584 src/otherwindow.c:2928 msgid "Colour space" msgstr "色彩空间" #: src/otherwindow.c:2088 src/otherwindow.c:2929 msgid "Difference measure" msgstr "差异度测é‡" #: src/otherwindow.c:2089 msgid "Reduce colour bleed" msgstr "å‡å°‘渗色" #: src/otherwindow.c:2090 msgid "Serpentine scan" msgstr "蛇形扫æ" #: src/otherwindow.c:2092 msgid "Error propagation, %" msgstr "误差传播,%" #: src/otherwindow.c:2093 msgid "Selective error propagation" msgstr "选择性误差传播" #: src/otherwindow.c:2097 msgid "Full error precision" msgstr "全误差精度" #: src/otherwindow.c:2302 msgid "Backward HSV" msgstr "HSV åå‘" #: src/otherwindow.c:2303 src/otherwindow.c:2326 msgid "Constant" msgstr "常é‡" #: src/otherwindow.c:2307 msgid "Edit Gradient" msgstr "编辑æ¸å˜" #: src/otherwindow.c:2329 msgid "Points:" msgstr "点:" #: src/otherwindow.c:2493 msgid "Linear" msgstr "线性的" #: src/otherwindow.c:2493 src/otherwindow.c:2703 msgid "Bilinear" msgstr "åŒçº¿æ€§" #: src/otherwindow.c:2493 msgid "Radial" msgstr "放射状的" #: src/otherwindow.c:2494 msgid "Square" msgstr "方形的" #: src/otherwindow.c:2494 msgid "Angular" msgstr "有角的" #: src/otherwindow.c:2494 msgid "Conical" msgstr "锥形的" #: src/otherwindow.c:2495 msgid "Level " msgstr "" #: src/otherwindow.c:2495 msgid "Repeat" msgstr "é‡å¤" #: src/otherwindow.c:2496 msgid "A to B" msgstr "A 到 B" #: src/otherwindow.c:2496 msgid "A to B (RGB)" msgstr "A 到 B (RGB)" #: src/otherwindow.c:2497 msgid "A to B (sRGB)" msgstr "" #: src/otherwindow.c:2497 msgid "A to B (HSV)" msgstr "A 到 B (HSV)" #: src/otherwindow.c:2497 msgid "A to B (backward HSV)" msgstr "A 到 B (åå‘HSV)" #: src/otherwindow.c:2498 msgid "A only" msgstr "ä»… A" #: src/otherwindow.c:2498 src/otherwindow.c:2500 msgid "Custom" msgstr "自定义" #: src/otherwindow.c:2499 msgid "Current to 0" msgstr "当å‰åˆ° 0" #: src/otherwindow.c:2499 msgid "Current only" msgstr "仅当å‰" #: src/otherwindow.c:2504 msgid "Configure Gradient" msgstr "设置æ¸å˜" #: src/otherwindow.c:2507 src/png.c:1001 msgid "Channel" msgstr "通é“" #: src/otherwindow.c:2512 msgid "Length" msgstr "长度" #: src/otherwindow.c:2513 msgid "Repeat length" msgstr "é‡å¤é•¿åº¦" #: src/otherwindow.c:2515 msgid "Gradient type" msgstr "æ¸å˜ç±»åž‹" #: src/otherwindow.c:2516 msgid "Extension type" msgstr "扩展类型" #: src/otherwindow.c:2517 msgid "Distance type" msgstr "" #: src/otherwindow.c:2518 msgid "Preview opacity" msgstr "预览ä¸é€æ˜Žåº¦" #: src/otherwindow.c:2527 src/otherwindow.c:2533 src/toolbar.c:309 msgid "Reverse" msgstr "åå‘" #: src/otherwindow.c:2528 src/otherwindow.c:2534 msgid "Edit Custom" msgstr "编辑自定义" #: src/otherwindow.c:2592 msgid "Pick Gradient" msgstr "" #: src/otherwindow.c:2668 msgid "Horizontal " msgstr "æ°´å¹³ " #: src/otherwindow.c:2674 msgid "At distance" msgstr "è·ç¦»" #: src/otherwindow.c:2675 msgid "Vertical" msgstr "垂直线" #: src/otherwindow.c:2756 msgid "Unchanged" msgstr "未改å˜" #: src/otherwindow.c:2761 msgid "Tracing Image" msgstr "ææ‘¹å›¾åƒ" #: src/otherwindow.c:2763 src/toolbar.c:315 msgid "Source" msgstr "æ¥æº" #: src/otherwindow.c:2768 msgid "Origin" msgstr "ä½ç§»" #: src/otherwindow.c:2771 msgid "Relative scale" msgstr "相对比例" #: src/otherwindow.c:2774 msgid "Display" msgstr "显示" #: src/otherwindow.c:2926 msgid "Segment Image" msgstr "" #: src/otherwindow.c:2931 src/toolbar.c:304 msgid "Threshold" msgstr "" #: src/otherwindow.c:2933 msgid "Level" msgstr "水平的" #: src/otherwindow.c:2934 msgid "Minimum size" msgstr "" #: src/otherwindow.c:3053 msgid "Max" msgstr "" #: src/otherwindow.c:3053 msgid "Min" msgstr "" #: src/otherwindow.c:3057 msgid "Threshold Image" msgstr "" #: src/otherwindow.c:3158 msgid "Seed" msgstr "" #: src/otherwindow.c:3160 msgid "X span" msgstr "" #: src/otherwindow.c:3161 msgid "Y span" msgstr "" #: src/otherwindow.c:3162 msgid "Octaves" msgstr "" #: src/png.c:620 #, c-format msgid "Saving %s image" msgstr "ä¿å­˜å›¾åƒ %s 中" #: src/png.c:620 #, c-format msgid "Loading %s image" msgstr "加载 %s 图åƒä¸­" #: src/png.c:998 msgid "Layer" msgstr "图层" #: src/png.c:3577 msgid "Lossless" msgstr "" #: src/png.c:3577 msgid "Default" msgstr "" #: src/png.c:3577 msgid "Picture" msgstr "" #: src/png.c:3577 msgid "Photo" msgstr "" #: src/png.c:3578 msgid "Drawing" msgstr "" #: src/png.c:3578 msgid "Icon" msgstr "" #: src/png.c:8370 msgid "Applying colour profile" msgstr "" #: src/png.c:8792 #, c-format msgid "%d out of %d frames could not be saved as %s - saved as PNG instead" msgstr "%d/%d 的帧ä¸èƒ½ä¿å­˜ä¸º%s,改为以 PNG æ ¼å¼ä¿å­˜" #: src/png.c:8809 msgid "Explode frames" msgstr "" #: src/prefs.c:56 msgid "Default System Language" msgstr "系统默认语言" #: src/prefs.c:57 msgid "Chinese (Simplified)" msgstr "简体中文" #: src/prefs.c:57 msgid "Chinese (Taiwanese)" msgstr "ç¹ä½“中文" #: src/prefs.c:57 msgid "Czech" msgstr "æ·å…‹è¯­" #: src/prefs.c:58 msgid "Dutch" msgstr "è·å…°è¯­" #: src/prefs.c:58 msgid "English (UK)" msgstr "英语(英国)" #: src/prefs.c:58 msgid "French" msgstr "法语" #: src/prefs.c:58 msgid "Galician" msgstr "加利西亚语" #: src/prefs.c:58 msgid "German" msgstr "德语" #: src/prefs.c:59 msgid "Hungarian" msgstr "" #: src/prefs.c:59 msgid "Italian" msgstr "æ„大利语" #: src/prefs.c:59 msgid "Japanese" msgstr "日语" #: src/prefs.c:59 msgid "Kabyle" msgstr "" #: src/prefs.c:59 msgid "Polish" msgstr "波兰语" #: src/prefs.c:60 msgid "Portuguese" msgstr "è‘¡è„牙语" #: src/prefs.c:60 msgid "Portuguese (Brazilian)" msgstr "è‘¡è„牙语(巴西)" #: src/prefs.c:60 msgid "Russian" msgstr "俄语" #: src/prefs.c:60 msgid "Slovak" msgstr "斯洛ä¼å…‹è¯­" #: src/prefs.c:61 msgid "Spanish" msgstr "西ç­ç‰™è¯­" #: src/prefs.c:61 msgid "Swedish" msgstr "瑞典语" #: src/prefs.c:61 msgid "Tagalog" msgstr "" #: src/prefs.c:61 msgid "Turkish" msgstr "土耳其语" #: src/prefs.c:81 msgid "Current Device" msgstr "当å‰è®¾å¤‡" #: src/prefs.c:135 msgid "Pressure" msgstr "压力" #: src/prefs.c:149 msgid "Preferences" msgstr "首选项" #: src/prefs.c:163 msgid "Max threads (0 to autodetect)" msgstr "" #: src/prefs.c:164 msgid "Min kpixels per render thread" msgstr "" #: src/prefs.c:171 msgid "Max memory used for undo (MB)" msgstr "用于还原的最大内存(MB)" #: src/prefs.c:172 msgid "Max undo levels" msgstr "最大撤销次数" #: src/prefs.c:173 msgid "Communal layer undo space (%)" msgstr "图层共享还原内存(%)" #: src/prefs.c:175 msgid "Bayer master pattern" msgstr "" #: src/prefs.c:178 msgid "Use gamma correction by default" msgstr "默认使用伽马修正" #: src/prefs.c:179 msgid "Use gamma correction when painting" msgstr "" #: src/prefs.c:180 msgid "Separate patterns for A & B" msgstr "" #: src/prefs.c:183 msgid "Optimize alpha chequers" msgstr "ä¼˜åŒ–é€æ˜Žæ–¹æ ¼" #: src/prefs.c:184 msgid "Disable view window transparencies" msgstr "åœç”¨æŸ¥çœ‹çª—å£é€æ˜Ž" #: src/prefs.c:185 msgid "Enable overlays by layer" msgstr "" #: src/prefs.c:189 msgid "Language" msgstr "语言" #: src/prefs.c:191 msgid "" "Select preferred language translation\n" "\n" "You will need to restart mtPaint\n" "for this to take full effect" msgstr "" "选择首选翻译语言\n" "\n" "您需è¦é‡å¯mtPaint\n" "让其完全生效" #: src/prefs.c:198 msgid "Interface" msgstr "界é¢" #: src/prefs.c:200 msgid "Greyscale backdrop" msgstr "ç°åº¦èƒŒæ™¯" #: src/prefs.c:201 msgid "Selection nudge pixels" msgstr "选框跳越åƒç´ è®¾ç½®" #: src/prefs.c:202 msgid "Max Pan Window Size" msgstr "最大全景窗å£å¤§å°" #: src/prefs.c:204 msgid "Display clipboard while pasting" msgstr "粘贴时显示剪贴æ¿å›¾åƒ" #: src/prefs.c:205 msgid "Mouse cursor = Tool" msgstr "鼠标光标 = 工具" #: src/prefs.c:206 msgid "Confirm Exit" msgstr "确认退出" #: src/prefs.c:207 msgid "Q key quits mtPaint" msgstr "Q 键退出 mtPaint" #: src/prefs.c:208 msgid "Arrow keys scroll canvas" msgstr "" #: src/prefs.c:209 msgid "Changing tool commits paste" msgstr "改æ¢å·¥å…·æ—¶ç²˜è´´" #: src/prefs.c:210 msgid "Centre tool settings dialogs" msgstr "工具é…ç½®å¯¹è¯æ¡†å±…中" #: src/prefs.c:211 msgid "New image sets zoom to 100%" msgstr "新图åƒç¼©æ”¾è®¾ç½®ä¸º100%" #: src/prefs.c:212 msgid "Zoom on cursor position" msgstr "" #: src/prefs.c:214 msgid "Mouse Scroll Wheel = Zoom" msgstr "鼠标滚轮 = 缩放" #: src/prefs.c:215 msgid "Use menu icons" msgstr "使用èœå•图标" #: src/prefs.c:220 msgid "Files" msgstr "文件" #: src/prefs.c:223 msgid "XBM X hotspot" msgstr "XBM X 热点" #: src/prefs.c:224 msgid "XBM Y hotspot" msgstr "XBM Y 热点" #: src/prefs.c:228 msgid "Recently Used Files" msgstr "最近使用的文件" #: src/prefs.c:229 msgid "Progress bar silence limit" msgstr "è¿›åº¦æ¡æ²‰é»˜é™åˆ¶" #: src/prefs.c:232 msgid "Read 16-bit TGAs as 5:6:5 BGR" msgstr "读å–16 ä½ TGA 为5:6:5 BGR" #: src/prefs.c:233 msgid "Write TGAs in bottom-up row order" msgstr "以自下而上的行åºå†™ TGA" #: src/prefs.c:234 msgid "Undoable image loading" msgstr "å¯é€†å›¾åƒåŠ è½½ä¸­" #: src/prefs.c:245 msgid "Compression (RGB)" msgstr "" #: src/prefs.c:246 msgid "Compression (indexed)" msgstr "" #: src/prefs.c:247 msgid "Compression (monochrome)" msgstr "" #: src/prefs.c:255 msgid "Enable predictor" msgstr "" #: src/prefs.c:262 msgid "Compression mode" msgstr "" #: src/prefs.c:271 msgid "Channel for Mask Plane" msgstr "" #: src/prefs.c:273 msgid "Ignore Transparent Colour" msgstr "" #: src/prefs.c:274 msgid "PackBits Compression" msgstr "" #: src/prefs.c:275 msgid "Write Indexed as Planar Bitmap (PBM)" msgstr "" #: src/prefs.c:280 msgid "Paths" msgstr "路径" #: src/prefs.c:281 msgid "Clipboard Files" msgstr "å‰ªè´´æ¿æ–‡ä»¶" #: src/prefs.c:281 msgid "Select Clipboard File" msgstr "选å–å‰ªè´´æ¿æ–‡ä»¶" #: src/prefs.c:283 msgid "HTML Browser Program" msgstr "HTML æµè§ˆç¨‹åº" #: src/prefs.c:283 msgid "Select Browser Program" msgstr "选择æµè§ˆç¨‹åº" #: src/prefs.c:285 msgid "Location of Handbook index" msgstr "索引手册ä½ç½®" #: src/prefs.c:285 msgid "Select Handbook Index File" msgstr "选择索引手册文件" #: src/prefs.c:287 msgid "Default Palette" msgstr "默认调色æ¿" #: src/prefs.c:287 msgid "Select Default Palette" msgstr "选择默认调色æ¿" #: src/prefs.c:289 msgid "Default Patterns" msgstr "默认图案" #: src/prefs.c:289 msgid "Select Default Patterns File" msgstr "选择默认图案" #: src/prefs.c:292 msgid "Default CSS" msgstr "" #: src/prefs.c:292 msgid "Select Default CSS File" msgstr "" #: src/prefs.c:295 msgid "Default Theme" msgstr "" #: src/prefs.c:295 msgid "Select Default Theme File" msgstr "" #: src/prefs.c:300 msgid "Status Bar" msgstr "çŠ¶æ€æ " #: src/prefs.c:301 msgid "Canvas Geometry" msgstr "画布宽度和高度" #: src/prefs.c:302 msgid "Cursor X,Y" msgstr "光标 X,Y" #: src/prefs.c:303 msgid "Pixel [I] {RGB}" msgstr "åƒç´ [I] {RGB}" #: src/prefs.c:304 msgid "Selection Geometry" msgstr "矩形选择区宽度和高度" #: src/prefs.c:305 msgid "Undo / Redo" msgstr "撤销/é‡åš" #: src/prefs.c:308 msgid "Tablet" msgstr "绘图æ¿" #: src/prefs.c:309 msgid "Device Settings" msgstr "设备设置" #: src/prefs.c:313 msgid "Configure Device" msgstr "é…置设备" #: src/prefs.c:319 msgid "Tool Variable" msgstr "工具å˜é‡" #: src/prefs.c:322 src/toolbar.c:454 msgid "Flow" msgstr "æµç•…" #: src/prefs.c:330 msgid "Test Area" msgstr "测试区域" #: src/prefs.c:373 msgid "Factor" msgstr "系数" #: src/prefs.c:459 msgid "This key is builtin" msgstr "" #: src/prefs.c:462 #, c-format msgid "" "This key is mapped to:\n" "\"%s\"" msgstr "" #: src/prefs.c:465 msgid "Remap" msgstr "" #: src/prefs.c:510 msgid "Keyboard Shortcuts" msgstr "" #: src/shifter.c:147 msgid "Frames" msgstr "帧" #: src/shifter.c:258 msgid "Palette Shifter" msgstr "调色æ¿å˜æ¢" #: src/shifter.c:263 msgid "Start" msgstr "开始" #: src/shifter.c:265 msgid "Finish" msgstr "完æˆ" #: src/shifter.c:284 msgid "Fix Palette" msgstr "ä¿®å¤è°ƒè‰²æ¿" #: src/spawn.c:651 msgid "Configure File Actions" msgstr "é…置文件动作" #: src/spawn.c:657 src/spawn.c:663 msgid "Command" msgstr "命令" #: src/spawn.c:922 #, c-format msgid "Error %i reported when trying to run %s" msgstr "å°è¯•è¿è¡Œ %2$s 时报告错误 %1$i" #: src/spawn.c:979 msgid "" "I am unable to find the documentation. Either you need to download the " "mtPaint Handbook from the web site and install it, or you need to set the " "correct location in the Preferences window." msgstr "" "我无法找到文档。您需è¦ä»Žç½‘上下载 mtPaint 手册并安装它,或者在首选项窗å£ä¸­è®¾ç½®" "正确的路径。" #: src/spawn.c:1018 msgid "" "There was a problem running the HTML browser. You need to set the correct " "program name in the Preferences window." msgstr "è¿è¡Œ HTML æµè§ˆå™¨å‡ºçŽ°é—®é¢˜ã€‚æ‚¨éœ€è¦åœ¨é¦–选项窗å£ä¸­è®¾ç½®æ­£ç¡®çš„程åºå。" #: src/thread.c:361 msgid "Helper thread is not responding. Save your work and exit the program." msgstr "" #: src/toolbar.c:147 msgid "RGB Cube" msgstr "RGB 立方体" #: src/toolbar.c:148 msgid "By image channel" msgstr "æ ¹æ®å›¾åƒé€šé“" #: src/toolbar.c:149 msgid "Gradient-driven" msgstr "æ¸å˜é©±åЍ" #: src/toolbar.c:157 msgid "Fill settings" msgstr "填充设置" #: src/toolbar.c:170 msgid "Respect opacity mode" msgstr "顾åŠä¸é€æ˜Žæ¨¡å¼" #: src/toolbar.c:176 msgid "Smudge settings" msgstr "斑点é…ç½®" #: src/toolbar.c:215 msgid "Aligned" msgstr "" #: src/toolbar.c:222 msgid "Clone settings" msgstr "" #: src/toolbar.c:228 msgid "By selection channel" msgstr "" #: src/toolbar.c:234 msgid "Lasso settings" msgstr "" #: src/toolbar.c:252 msgid "Brush spacing" msgstr "绘制的时间间隔" #: src/toolbar.c:299 src/toolbar.c:341 msgid "Normal" msgstr "正常" #: src/toolbar.c:300 msgid "Colour" msgstr "颜色" #: src/toolbar.c:300 msgid "Saturate More" msgstr "更多饱和度" #: src/toolbar.c:301 msgid "Multiply" msgstr "å åŠ " #: src/toolbar.c:301 msgid "Divide" msgstr "分割" #: src/toolbar.c:301 msgid "Dodge" msgstr "凿·¡" #: src/toolbar.c:302 msgid "Burn" msgstr "加深" #: src/toolbar.c:302 msgid "Hard Light" msgstr "强光" #: src/toolbar.c:302 msgid "Soft Light" msgstr "柔光" #: src/toolbar.c:302 msgid "Difference" msgstr "差异" #: src/toolbar.c:303 msgid "Darken" msgstr "较暗" #: src/toolbar.c:303 msgid "Lighten" msgstr "较亮" #: src/toolbar.c:303 msgid "Grain Extract" msgstr "颗粒æå–" #: src/toolbar.c:304 msgid "Grain Merge" msgstr "颗粒åˆå¹¶" #: src/toolbar.c:330 msgid "Blend mode" msgstr "æ··åˆæ¨¡å¼" #: src/toolbar.c:417 msgid "Continuous Mode" msgstr "连续模å¼" #: src/toolbar.c:421 msgid "Opacity Mode" msgstr "ä¸é€æ˜Žæ¨¡å¼" #: src/toolbar.c:424 msgid "Tint Mode" msgstr "色调模å¼" #: src/toolbar.c:427 msgid "Tint +-" msgstr "色调 +-" #: src/toolbar.c:434 msgid "Blend Mode" msgstr "æ··åˆæ¨¡å¼" #: src/toolbar.c:438 msgid "Disable All Masks" msgstr "åœç”¨å…¨éƒ¨é®ç½©" #: src/toolbar.c:441 msgid "Gradient Mode" msgstr "æ¸å˜æ¨¡å¼" #: src/toolbar.c:486 msgid "Settings Toolbar" msgstr "设置工具æ " #: src/toolbar.c:546 msgid "Cut" msgstr "剪切" #: src/toolbar.c:548 msgid "Copy" msgstr "å¤åˆ¶" #: src/toolbar.c:550 msgid "Paste" msgstr "粘贴" #: src/toolbar.c:553 msgid "Undo" msgstr "撤消" #: src/toolbar.c:555 msgid "Redo" msgstr "é‡åš" #: src/toolbar.c:559 src/viewer.c:328 msgid "Pan Window" msgstr "全景窗å£" #: src/toolbar.c:560 src/toolbar.c:640 msgid "More..." msgstr "更多…" #: src/toolbar.c:574 msgid "Paint" msgstr "绘制" #: src/toolbar.c:580 msgid "Shuffle" msgstr "éšæœº" #: src/toolbar.c:583 msgid "Flood Fill" msgstr "å¡«å……" #: src/toolbar.c:587 msgid "Straight Line" msgstr "直线" #: src/toolbar.c:590 msgid "Smudge" msgstr "涂抹" #: src/toolbar.c:594 msgid "Clone" msgstr "克隆" #: src/toolbar.c:597 msgid "Make Selection" msgstr "建立选区" #: src/toolbar.c:600 msgid "Polygon Selection" msgstr "多边形选择" #: src/toolbar.c:603 msgid "Place Gradient" msgstr "放置æ¸å˜" #: src/toolbar.c:606 msgid "Lasso Selection" msgstr "套索选择" #: src/toolbar.c:614 msgid "Ellipse Outline" msgstr "æè¾¹æ¤­åœ†" #: src/toolbar.c:617 msgid "Filled Ellipse" msgstr "填充椭圆" #: src/toolbar.c:620 msgid "Outline Selection" msgstr "æè¾¹é€‰æ‹©" #: src/toolbar.c:623 msgid "Fill Selection" msgstr "填充选择" #: src/toolbar.c:627 msgid "Flip Selection Vertically" msgstr "垂直翻转选择区域" #: src/toolbar.c:630 msgid "Flip Selection Horizontally" msgstr "水平翻转选择区域" #: src/toolbar.c:633 msgid "Rotate Selection Clockwise" msgstr "顺时针旋转选择区域" #: src/toolbar.c:636 msgid "Rotate Selection Anti-Clockwise" msgstr "逆时针旋转选择区域" #: src/vcode.c:5201 msgid "Browse" msgstr "æµè§ˆ" #: src/vcode.c:7886 msgid "New key ..." msgstr "" #: src/vcode.c:9909 #, c-format msgid "'%s' does not match any widget" msgstr "" #: src/vcode.c:9910 #, c-format msgid "'%s' value does not fit '%s' widget" msgstr "" #: src/viewer.c:115 msgid "About" msgstr "关于" #: src/viewer.c:1179 msgid "No font selected" msgstr "" #: src/viewer.c:1209 msgid "Left" msgstr "" #: src/viewer.c:1209 msgid "Right" msgstr "" #~ msgid "Create GIF frames" #~ msgstr "创建 GIF 帧" #~ msgid "" #~ "You are trying to save an XPM file with more than 4096 colours. Either " #~ "use another format or posterize the image to 4 bits, or otherwise reduce " #~ "the number of colours." #~ msgstr "" #~ "您正试图ä¿å­˜å¤šäºŽ 4096 ç§é¢œè‰²çš„ XPM 文件。建议您或者使用å¦å¤–ä¸€ç§æ ¼å¼ï¼Œ 或者" #~ "将多色调图åƒåˆ†è‰²ä¸º 4 ä½ï¼Œæˆ–者å‡å°‘颜色数。" #~ msgid "Store Values" #~ msgstr "ä¿å­˜æ•°å€¼" #~ msgid "File: %s invalid - palette not updated" #~ msgstr "文件:%s 无效 è°ƒè‰²æ¿æœªæ›´æ–°" #~ msgid "Distance to A+B" #~ msgstr "到 A+B çš„è·ç¦»" #~ msgid "Edit Frames" #~ msgstr "编辑帧" #~ msgid "The palette does not contain enough colours to do a merge" #~ msgstr "调色盘ä¸åŒ…å«è¶³å¤Ÿçš„颜色æ¥åšåˆå¹¶" #~ msgid "There are too many identical palette items to be reduced." #~ msgstr "有太多相åŒçš„调色盘项目å¯ä»¥æ¥ç¼©å°ã€‚" #~ msgid "/View/Command Line Window" #~ msgstr "/查看/命令列窗å£" #~ msgid "Grid colour RGB" #~ msgstr "格线颜色RGB" #~ msgid "Zoom" #~ msgstr "缩放" #~ msgid "%i Files on Command Line" #~ msgstr "%i个文件在命令列上" mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/po/zh_TW.po000066400000000000000000002673321471325446300222010ustar00rootroot00000000000000# Traditional Chinese translation for mtpaint. # This file is distributed under the same license as the mtpaint package. # Wei-Lun Chao , 2006, 07. # msgid "" msgstr "" "Project-Id-Version: mtpaint 3.11\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-01-04 21:31+0200\n" "PO-Revision-Date: 2007-04-19 10:32+0800\n" "Last-Translator: Wei-Lun Chao \n" "Language-Team: Chinese (traditional) \n" "Language: zh_TW\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Rosetta-Version: 0.1\n" "Plural-Forms: nplurals=2; plural=n != 1\n" #: src/ani.c:647 msgid "Animation Preview" msgstr "å‹•ç•«é è¦½" #: src/ani.c:650 src/shifter.c:275 msgid "Play" msgstr "播放" #: src/ani.c:654 msgid "Fix" msgstr "修復" #: src/ani.c:655 src/ani.c:1005 src/font.c:1624 src/font.c:1643 #: src/shifter.c:286 src/viewer.c:97 msgid "Close" msgstr "關閉" #: src/ani.c:709 src/ani.c:812 src/ani.c:1022 src/ani.c:1028 src/canvas.c:356 #: src/canvas.c:708 src/canvas.c:989 src/canvas.c:1353 src/canvas.c:1383 #: src/canvas.c:1470 src/canvas.c:1545 src/canvas.c:1988 src/canvas.c:1994 #: src/canvas.c:2077 src/canvas.c:2217 src/canvas.c:2240 src/font.c:1352 #: src/fpick.c:636 src/fpick.c:754 src/layer.c:524 src/layer.c:815 #: src/layer.c:970 src/mainwindow.c:341 src/mainwindow.c:370 #: src/mainwindow.c:534 src/mainwindow.c:578 src/mainwindow.c:604 #: src/mainwindow.c:3797 src/mainwindow.c:4045 src/otherwindow.c:931 #: src/otherwindow.c:980 src/otherwindow.c:982 src/prefs.c:459 src/spawn.c:924 #: src/spawn.c:978 src/spawn.c:1017 src/thread.c:360 src/vcode.c:9912 #: src/viewer.c:1161 src/viewer.c:1179 msgid "Error" msgstr "錯誤" #: src/ani.c:709 msgid "Unable to create output directory" msgstr "無法建立輸出目錄" #: src/ani.c:759 msgid "Creating Animation Frames" msgstr "正在建立動畫圖框" #: src/ani.c:812 msgid "Unable to save image" msgstr "無法儲存圖åƒ" #: src/ani.c:840 src/canvas.c:1171 src/fpick.c:731 src/layer.c:311 #: src/layer.c:379 src/layer.c:826 src/layer.c:840 src/mainwindow.c:375 #: src/mainwindow.c:1026 src/png.c:8794 src/prefs.c:464 msgid "Warning" msgstr "警告" #: src/ani.c:840 msgid "" "Do you really want to clear all of the position and cycle data for all of " "the layers?" msgstr "您真的è¦åœ¨æ‰€æœ‰åœ–層上清除全部的ä½ç½®å’Œå¾ªç’°è³‡æ–™å—Žï¼Ÿ" #: src/ani.c:841 src/fpick.c:731 src/layer.c:311 src/layer.c:842 #: src/mainwindow.c:375 msgid "No" msgstr "å¦" #: src/ani.c:841 src/fpick.c:731 src/layer.c:311 src/layer.c:842 #: src/mainwindow.c:375 msgid "Yes" msgstr "是" #: src/ani.c:954 msgid "Set Key Frame" msgstr "è¨­å®šä¸»è¦æ¡†æž¶" #: src/ani.c:961 msgid "Configure Animation" msgstr "é…置動畫" #: src/ani.c:964 msgid "Output Files" msgstr "輸出檔案" #: src/ani.c:967 msgid "Start frame" msgstr "開始圖框" #: src/ani.c:969 msgid "End frame" msgstr "çµæŸåœ–框" #: src/ani.c:971 src/shifter.c:267 msgid "Delay" msgstr "å»¶é²" #: src/ani.c:973 msgid "Output path" msgstr "輸出路徑" #: src/ani.c:973 src/font.c:1637 src/spawn.c:664 msgid "Select Directory" msgstr "" #: src/ani.c:976 msgid "File prefix" msgstr "檔案å‰ç¶´" #: src/ani.c:978 src/canvas.c:2096 msgid "File Format" msgstr "檔案格å¼" #: src/ani.c:982 msgid "Positions" msgstr "ä½ç½®" #: src/ani.c:997 msgid "Cycling" msgstr "循環中" #: src/ani.c:1006 msgid "Save" msgstr "儲存" #: src/ani.c:1007 src/font.c:1577 src/otherwindow.c:868 src/otherwindow.c:1615 #: src/otherwindow.c:1728 src/otherwindow.c:2938 src/otherwindow.c:3071 #: src/otherwindow.c:3170 msgid "Preview" msgstr "é è¦½" #: src/ani.c:1008 src/shifter.c:285 msgid "Create Frames" msgstr "建立圖框" #: src/ani.c:1022 msgid "You must have at least 2 layers to create an animation" msgstr "您必須至少有 2 層圖層以建立動畫" #: src/ani.c:1028 msgid "You must save your layers file before creating an animation" msgstr "您必須在建立動畫之å‰å„²å­˜æ‚¨çš„圖層檔案" #: src/canvas.c:357 msgid "The image is too large to transform." msgstr "圖åƒå¤ªå¤§è€Œç„¡æ³•變æ›ã€‚" #: src/canvas.c:393 src/canvas.c:430 src/otherwindow.c:1613 #: src/otherwindow.c:2524 src/otherwindow.c:2583 src/otherwindow.c:3179 msgid "Gradient" msgstr "漸層" #: src/canvas.c:393 src/otherwindow.c:840 src/otherwindow.c:842 #: src/otherwindow.c:2074 src/otherwindow.c:3180 msgid "Palette" msgstr "調色盤" #: src/canvas.c:393 src/info.c:265 src/otherwindow.c:847 src/otherwindow.c:2757 #: src/otherwindow.c:3180 src/png.c:781 src/png.c:995 msgid "Clipboard" msgstr "剪貼簿" #: src/canvas.c:394 src/cpick.c:831 src/toolbar.c:299 msgid "Value" msgstr "" #: src/canvas.c:394 src/cpick.c:811 src/otherwindow.c:575 src/otherwindow.c:859 #: src/otherwindow.c:3053 src/toolbar.c:318 msgid "Red" msgstr "紅色" #: src/canvas.c:394 src/cpick.c:815 src/otherwindow.c:575 src/otherwindow.c:860 #: src/otherwindow.c:3053 src/toolbar.c:319 msgid "Green" msgstr "綠色" #: src/canvas.c:394 src/cpick.c:819 src/otherwindow.c:575 src/otherwindow.c:861 #: src/otherwindow.c:3053 src/toolbar.c:320 msgid "Blue" msgstr "è—色" #: src/canvas.c:399 msgid "From " msgstr "" #: src/canvas.c:403 msgid "To " msgstr "" #: src/canvas.c:410 msgid "Map" msgstr "" #: src/canvas.c:429 msgid "MT" msgstr "" #: src/canvas.c:429 msgid "Sobel" msgstr "" #: src/canvas.c:429 msgid "Prewitt" msgstr "" #: src/canvas.c:429 msgid "Kirsch" msgstr "" #: src/canvas.c:430 msgid "Roberts" msgstr "" #: src/canvas.c:430 msgid "Laplace" msgstr "" #: src/canvas.c:430 msgid "Morphological" msgstr "" #: src/canvas.c:442 msgid "Edge Detect" msgstr "" #: src/canvas.c:464 msgid "Edge Sharpen" msgstr "邊緣銳化" #: src/canvas.c:472 msgid "Edge Soften" msgstr "邊緣柔化" #: src/canvas.c:521 msgid "Different X/Y" msgstr "差異度 X/Y" #: src/canvas.c:522 src/canvas.c:562 src/canvas.c:603 src/canvas.c:637 #: src/canvas.c:722 src/otherwindow.c:1037 src/otherwindow.c:2685 msgid "Gamma corrected" msgstr "γ 值已修正" #: src/canvas.c:530 src/memory.c:8219 msgid "Gaussian Blur" msgstr "高斯模糊" #: src/canvas.c:558 msgid "Radius" msgstr "åŠå¾‘" #: src/canvas.c:559 msgid "Amount" msgstr "數é‡" #: src/canvas.c:560 msgid "Threshold " msgstr "臨界值" #: src/canvas.c:570 src/memory.c:8360 msgid "Unsharp Mask" msgstr "去銳利化é®ç½©" #: src/canvas.c:599 msgid "Outer radius" msgstr "" #: src/canvas.c:600 msgid "Inner radius" msgstr "" #: src/canvas.c:602 src/info.c:280 msgid "Normalize" msgstr "æ­£è¦åŒ–" #: src/canvas.c:611 src/memory.c:8512 msgid "Difference of Gaussians" msgstr "" #: src/canvas.c:636 msgid "Protect details" msgstr "" #: src/canvas.c:645 msgid "Kuwahara-Nagao Blur" msgstr "" #: src/canvas.c:709 msgid "The image is too large for this rotation." msgstr "此旋轉所用圖åƒå¤ªå¤§ã€‚" #: src/canvas.c:723 msgid "Smooth" msgstr "平滑" #: src/canvas.c:732 msgid "Free Rotate" msgstr "自由旋轉" #: src/canvas.c:989 src/viewer.c:1161 msgid "Not enough memory to create clipboard" msgstr "建立剪貼簿所需記憶體ä¸è¶³" #: src/canvas.c:1172 msgid "" "You have not allocated enough memory in the Preferences window to undo this " "action." msgstr "" #: src/canvas.c:1353 msgid "Invalid palette file" msgstr "" #: src/canvas.c:1383 msgid "Invalid channel file." msgstr "ç„¡æ•ˆçš„é€šé“æª”案。" #: src/canvas.c:1401 msgid "Raw frames" msgstr "" #: src/canvas.c:1401 msgid "Composited frames" msgstr "" #: src/canvas.c:1402 msgid "Composited frames with nonzero delay" msgstr "" #: src/canvas.c:1406 msgid "Load Frames" msgstr "" #: src/canvas.c:1409 msgid "Load into Layers" msgstr "" #: src/canvas.c:1415 msgid "Load First Frame" msgstr "" #: src/canvas.c:1416 msgid "Explode Frames" msgstr "" #: src/canvas.c:1418 msgid "View Animation" msgstr "檢視動畫" #: src/canvas.c:1434 #, c-format msgid "This is an animated %s file." msgstr "此為 %s 的動畫檔案。" #: src/canvas.c:1435 #, c-format msgid "This is a multipage %s file." msgstr "" #: src/canvas.c:1459 #, c-format msgid "File is too big, must be <= to width=%i height=%i" msgstr "" #: src/canvas.c:1461 msgid "Unable to explode frames" msgstr "" #: src/canvas.c:1463 msgid "Unable to load file" msgstr "無法載入檔案" #: src/canvas.c:1465 msgid "" "The file import library had to terminate due to a problem with the file " "(possibly corrupt image data or a truncated file). I have managed to load " "some data as the header seemed fine, but I would suggest you save this image " "to a new file to ensure this does not happen again." msgstr "" "檔案匯入函å¼åº«å¿…須由於檔案å•題而終止 (å¯èƒ½æ˜¯åœ–åƒè³‡æ–™ç ´ææˆ–是檔案被截斷)。因為" "檔頭似乎還好,我有試著載入æŸäº›è³‡æ–™ï¼Œä½†æ˜¯æˆ‘會建議您儲存此圖åƒåˆ°æ–°çš„æª”案,以確" "ä¿é€™ä¸æœƒå†æ¬¡ç™¼ç”Ÿã€‚" #: src/canvas.c:1467 msgid "The animation is too long to load all of it into layers." msgstr "" #: src/canvas.c:1469 msgid "Could not explode all the frames in the animation." msgstr "" #: src/canvas.c:1481 src/font.c:1556 src/fpick.c:937 src/otherwindow.c:2765 #: src/prefs.c:321 src/toolbar.c:451 msgid "Size" msgstr "大å°" #: src/canvas.c:1484 src/otherwindow.c:244 msgid "Width" msgstr "寬度" #: src/canvas.c:1485 src/otherwindow.c:245 msgid "Height" msgstr "高度" #: src/canvas.c:1489 src/channels.c:253 src/channels.c:317 src/fpick.c:666 #: src/fpick.c:957 src/mainwindow.c:3990 src/otherwindow.c:255 #: src/otherwindow.c:517 src/otherwindow.c:591 src/otherwindow.c:867 #: src/otherwindow.c:1058 src/otherwindow.c:1727 src/otherwindow.c:2101 #: src/otherwindow.c:2336 src/otherwindow.c:2538 src/otherwindow.c:2691 #: src/otherwindow.c:2776 src/otherwindow.c:2937 src/otherwindow.c:3070 #: src/otherwindow.c:3169 src/prefs.c:338 src/prefs.c:464 src/prefs.c:538 #: src/spawn.c:666 src/viewer.c:1258 msgid "Cancel" msgstr "å–æ¶ˆ" #: src/canvas.c:1490 src/channels.c:253 src/channels.c:317 src/fpick.c:956 #: src/info.c:297 src/mainwindow.c:3992 src/mygtk.c:233 src/mygtk.c:535 #: src/otherwindow.c:591 src/otherwindow.c:871 src/otherwindow.c:1058 #: src/otherwindow.c:1729 src/otherwindow.c:2101 src/otherwindow.c:2336 #: src/otherwindow.c:2538 src/otherwindow.c:2691 src/otherwindow.c:2776 #: src/otherwindow.c:3072 src/otherwindow.c:3171 src/prefs.c:338 #: src/prefs.c:538 src/spawn.c:666 msgid "OK" msgstr "確定" #: src/canvas.c:1504 #, c-format msgid "This is a scalable %s file." msgstr "" #: src/canvas.c:1545 msgid "Cannot open file" msgstr "無法開啟檔案" #: src/canvas.c:1546 msgid "Unsupported file format" msgstr "䏿”¯æ´çš„æª”案格å¼" #: src/canvas.c:1673 #, c-format msgid "File: %s already exists. Do you want to overwrite it?" msgstr "檔案:%s 已經存在。您è¦è¦†å¯«å®ƒå—Žï¼Ÿ" #: src/canvas.c:1674 msgid "File Found" msgstr "找到檔案" #: src/canvas.c:1674 src/mainwindow.c:1095 msgid "NO" msgstr "å¦" #: src/canvas.c:1674 src/mainwindow.c:1095 msgid "YES" msgstr "是" #: src/canvas.c:1988 msgid "Unable to export undo images" msgstr "無法匯出復原圖åƒ" #: src/canvas.c:1994 msgid "Unable to export ASCII file" msgstr "無法匯出 ASCII 檔案" #: src/canvas.c:2076 src/layer.c:814 src/mainwindow.c:529 #, c-format msgid "Unable to save file: %s" msgstr "無法儲存檔案:%s" #: src/canvas.c:2101 src/prefs.c:222 msgid "Transparency index" msgstr "逿˜Žåº¦ç´¢å¼•" #: src/canvas.c:2103 msgid "TIFF Compression" msgstr "" #: src/canvas.c:2105 src/prefs.c:225 msgid "JPEG Save Quality (100=High)" msgstr "JPEG 儲存å“質 (100=高)" #: src/canvas.c:2107 msgid "ZIP Compression (0=None)" msgstr "" #: src/canvas.c:2108 src/prefs.c:227 msgid "PNG Compression (0=None)" msgstr "" #: src/canvas.c:2111 src/prefs.c:249 msgid "LZMA2 Compression (0=None)" msgstr "" #: src/canvas.c:2113 src/prefs.c:252 msgid "ZSTD Compression Level" msgstr "" #: src/canvas.c:2115 src/prefs.c:231 msgid "TGA RLE Compression" msgstr "" #: src/canvas.c:2117 msgid "LBM PackBits Compression" msgstr "" #: src/canvas.c:2118 src/prefs.c:226 msgid "JPEG2000 Compression (0=Lossless)" msgstr "" #: src/canvas.c:2120 msgid "WebP Compression" msgstr "" #: src/canvas.c:2122 msgid "WebP Save Quality (100=High)" msgstr "" #: src/canvas.c:2123 src/prefs.c:263 msgid "V8 Save Quality (100=High)" msgstr "" #: src/canvas.c:2125 src/prefs.c:264 msgid "V8L Compression (0=None)" msgstr "" #: src/canvas.c:2127 msgid "Hotspot at X =" msgstr "ä½œç”¨é»žä½æ–¼ X =" #: src/canvas.c:2129 msgid "Y =" msgstr "Y =" #: src/canvas.c:2133 msgid "Animation delay" msgstr "å‹•ç•«å»¶é²" #: src/canvas.c:2136 src/otherwindow.c:253 msgid "Undoable" msgstr "" #: src/canvas.c:2138 src/prefs.c:236 msgid "Apply colour profile" msgstr "" #: src/canvas.c:2176 src/toolbar.c:543 msgid "Load Image File" msgstr "è¼‰å…¥åœ–åƒæª”" #: src/canvas.c:2191 src/toolbar.c:544 msgid "Save Image File" msgstr "å„²å­˜åœ–åƒæª”" #: src/canvas.c:2196 msgid "Load Palette File" msgstr "載入調色盤檔案" #: src/canvas.c:2202 msgid "Save Palette File" msgstr "儲存調色盤檔案" #: src/canvas.c:2207 msgid "Export Undo Images" msgstr "匯出復原圖åƒ" #: src/canvas.c:2212 msgid "Export Undo Images (reversed)" msgstr "åŒ¯å‡ºå¾©åŽŸåœ–åƒ (åå‘)" #: src/canvas.c:2217 msgid "You must have 16 or fewer palette colours to export ASCII art." msgstr "您必須有 16 或更少的調色盤é¡è‰²ä»¥åŒ¯å‡º ASCII 圖案。" #: src/canvas.c:2220 msgid "Export ASCII Art" msgstr "匯出 ASCII 圖案" #: src/canvas.c:2224 msgid "Save Layer Files" msgstr "儲存圖層檔案" #: src/canvas.c:2234 msgid "Choose frames directory" msgstr "é¸å–圖框目錄" #: src/canvas.c:2240 msgid "You must save at least one frame to create an animated GIF." msgstr "您必須儲存至少一個圖框以建立動畫的 GIF。" #: src/canvas.c:2243 msgid "Export GIF animation" msgstr "匯出 GIF å‹•ç•«" #: src/canvas.c:2247 msgid "Load Channel" msgstr "載入通é“" #: src/canvas.c:2255 msgid "Save Channel" msgstr "儲存通é“" #: src/canvas.c:2260 msgid "Save Composite Image" msgstr "å„²å­˜åˆæˆåœ–åƒ" #: src/channels.c:243 msgid "Create Channel" msgstr "建立通é“" #: src/channels.c:244 msgid "Channel Type" msgstr "通é“型態" #: src/channels.c:247 msgid "Initial Channel State" msgstr "åˆå§‹é€šé“狀態" #: src/channels.c:251 msgid "Inverted" msgstr "å·²å相" #: src/channels.c:265 msgid "Cleared" msgstr "已清除" #: src/channels.c:266 msgid "Set" msgstr "設定" #: src/channels.c:267 msgid "Set colour A radius B" msgstr "設定é¡è‰² A åŠå¾‘ B" #: src/channels.c:268 msgid "Set blend A to B" msgstr "設定混色 A 到 B" #: src/channels.c:269 msgid "Image Red" msgstr "紅色圖åƒ" #: src/channels.c:270 msgid "Image Green" msgstr "綠色圖åƒ" #: src/channels.c:271 msgid "Image Blue" msgstr "è—色圖åƒ" #: src/channels.c:273 src/channels.c:313 src/mainwindow.c:67 #: src/otherwindow.c:1679 msgid "Alpha" msgstr "α" #: src/channels.c:274 src/channels.c:314 src/mainwindow.c:67 #: src/otherwindow.c:1683 msgid "Selection" msgstr "鏿“‡" #: src/channels.c:275 src/channels.c:315 src/mainwindow.c:67 #: src/otherwindow.c:1687 msgid "Mask" msgstr "é®ç½©" #: src/channels.c:312 msgid "Delete Channels" msgstr "刪除通é“" #: src/channels.c:367 msgid "Threshold Channel" msgstr "臨界通é“" #: src/cpick.c:823 src/otherwindow.c:573 src/otherwindow.c:820 #: src/toolbar.c:299 msgid "Hue" msgstr "色調" #: src/cpick.c:827 src/otherwindow.c:573 src/otherwindow.c:818 #: src/toolbar.c:299 msgid "Saturation" msgstr "飽和度" #: src/cpick.c:835 msgid "Hex" msgstr "" #: src/cpick.c:840 src/layer.c:1109 src/otherwindow.c:2530 src/prefs.c:323 #: src/toolbar.c:457 msgid "Opacity" msgstr "æ¿åº¦" #: src/font.c:982 msgid "Creating Font Index" msgstr "" #: src/font.c:1353 msgid "You must select at least one directory to search for fonts." msgstr "" #: src/font.c:1529 src/font.c:1624 src/toolbar.c:609 src/viewer.c:1213 #: src/viewer.c:1258 msgid "Paste Text" msgstr "貼上文字" #: src/font.c:1533 src/font.c:1572 src/png.c:3578 msgid "Text" msgstr "" #: src/font.c:1540 msgid "Font" msgstr "" #: src/font.c:1548 msgid "Style" msgstr "" #: src/font.c:1566 msgid "Filename" msgstr "" #: src/font.c:1567 msgid "Face" msgstr "" #: src/font.c:1587 src/viewer.c:1222 msgid "Antialias" msgstr "å鋸齒" #: src/font.c:1590 src/viewer.c:1224 msgid "Invert" msgstr "å相" #: src/font.c:1593 src/viewer.c:1226 msgid "Background colour =" msgstr "背景é¡è‰² =" #: src/font.c:1601 src/viewer.c:1233 msgid "DPI =" msgstr "" #: src/font.c:1610 msgid "Oblique" msgstr "" #: src/font.c:1612 src/viewer.c:1244 msgid "Angle of rotation =" msgstr "旋轉角度 =" #: src/font.c:1617 src/viewer.c:1248 msgid "Align" msgstr "" #: src/font.c:1620 src/viewer.c:1253 msgid "Spacing" msgstr "" #: src/font.c:1629 msgid "Font Directories" msgstr "" #: src/font.c:1634 src/spawn.c:664 msgid "Directory" msgstr "" #: src/font.c:1637 msgid "New Directory" msgstr "" #: src/font.c:1644 src/prefs.c:532 msgid "Add" msgstr "" #: src/font.c:1645 src/prefs.c:533 msgid "Remove" msgstr "" #: src/font.c:1646 msgid "Create Index" msgstr "" #: src/font.c:1660 src/viewer.c:1267 msgid "Enter Text Here" msgstr "在此輸入文字" #: src/fpick.c:635 #, c-format msgid "Could not access directory %s" msgstr "" #: src/fpick.c:668 src/fpick.c:698 msgid "Delete" msgstr "" #: src/fpick.c:669 src/fpick.c:698 msgid "Rename" msgstr "" #: src/fpick.c:672 src/otherwindow.c:255 src/otherwindow.c:1666 msgid "Create" msgstr "建立" #: src/fpick.c:699 msgid "Enter the new filename" msgstr "" #: src/fpick.c:704 msgid "Create Directory" msgstr "" #: src/fpick.c:705 msgid "Enter the name of the new directory" msgstr "" #: src/fpick.c:729 #, c-format msgid "Do you really want to delete \"%s\" ?" msgstr "" #: src/fpick.c:735 msgid "Unable to delete" msgstr "" #: src/fpick.c:741 msgid "Unable to rename" msgstr "" #: src/fpick.c:750 msgid "Unable to create directory" msgstr "" #: src/fpick.c:924 msgid "Up" msgstr "" #: src/fpick.c:925 msgid "Home" msgstr "" #: src/fpick.c:926 msgid "Create New Directory" msgstr "" #: src/fpick.c:927 msgid "Show Hidden Files" msgstr "" #: src/fpick.c:929 msgid "Case Insensitive Sort" msgstr "" #: src/fpick.c:936 msgid "Name" msgstr "" #: src/fpick.c:938 msgid "Type" msgstr "" #: src/fpick.c:939 msgid "Modified" msgstr "" #: src/help.c:25 src/prefs.c:160 msgid "General" msgstr "一般" #: src/help.c:26 msgid "Keyboard shortcuts" msgstr "éµç›¤æ·å¾‘" #: src/help.c:27 msgid "Mouse shortcuts" msgstr "滑鼠æ·å¾‘" #: src/help.c:28 msgid "Credits" msgstr "é³´è¬" #: src/help.c:32 msgid "mtPaint 3.51 - Copyright (C) 2004-2021 The Authors\n" msgstr "mtPaint 3.51 - 版權 (C) 2004-2021 作者群\n" #: src/help.c:33 msgid "See 'Credits' section for a list of the authors.\n" msgstr "作者表列請åƒçœ‹ã€Œé³´è¬ã€å€æ®µã€‚\n" #: src/help.c:34 msgid "" "mtPaint 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.\n" msgstr "" "mtPaint 為自由軟體;基於自由軟體基金會發布的 GNU 通用公共許å¯ï¼Œæ‚¨å¯ä»¥å†æ¬¡æ•£å¸ƒ" "它和/或修改它;å¯ä¾ç‰ˆæœ¬ 3 的授權,或是 (便‚¨çš„鏿“‡) 任何之後的版本。\n" #: src/help.c:35 msgid "" "mtPaint 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.\n" msgstr "" "mtPaint 是希望它會有用而發行的,但是ä¸åšä»»ä½•ä¿è­‰ï¼›ä¹Ÿä¸æš—示任何的é©éŠ·æ€§æˆ–ç‰¹å®š" "目的的åˆç”¨æ€§ã€‚ åƒçœ‹ GNU 通用公共許å¯ä¾†ç²å¾—更多細節。\n" #: src/help.c:36 msgid "" "mtPaint is a simple GTK+1/2/3 painting program designed for creating icons " "and pixel based artwork. It can edit indexed palette or 24 bit RGB images " "and offers basic painting and palette manipulation tools. It also has " "several other more powerful features such as channels, layers and animation. " "Due to its simplicity and lack of dependencies it runs well on GNU/Linux, " "Windows and older PC hardware.\n" msgstr "" "mtPaint 為簡單的 GTK+1/2/3 繪圖程å¼ï¼Œè¨­è¨ˆç”¨ä¾†å»ºç«‹åœ–示和基於åƒç´ çš„原圖。它å¯ä»¥" "編輯索引éŽçš„調色盤或 24 ä½å…ƒçš„ RGB 圖åƒä»¥åŠæä¾›åŸºæœ¬ç¹ªåœ–å’Œèª¿è‰²ç›¤è™•ç†å·¥å…·ã€‚它也" "æœ‰æ›´å¤šå…¶ä»–çš„å¼·å¤§ç‰¹å¾µåƒæ˜¯é€šé“ã€åœ–å±¤å’Œå‹•ç•«ã€‚ç”±æ–¼å®ƒçš„ç°¡æ˜“æ€§å’Œè¼ƒå°‘çš„ç›¸ä¾æ€§ï¼Œå®ƒåœ¨ " "GNU/Linuxã€Windows 和舊的 PC 硬體上é‹è¡Œåœ°å¾ˆå¥½ã€‚\n" #: src/help.c:37 msgid "" "There is full documentation of mtPaint's features contained in a handbook. " "If you don't already have this, you can download it from the mtPaint " "website.\n" msgstr "" "完整的 mtPaint 特色文件包å«åœ¨æ‰‹å†Šä¹‹ä¸­ã€‚ 如果您尚未得到它,您å¯ä»¥å¾ž mtPaint ç¶²" "站下載。\n" #: src/help.c:38 msgid "" "If you like mtPaint and you want to keep up to date with new releases, or " "you want to give some feedback, then the mailing lists may be of interest to " "you:\n" msgstr "" "如果您喜歡 mtPaint 並且è¦ä¿æŒä½¿ç”¨æ›´æ–°çš„版本,或是想è¦ä¾›çµ¦æŸäº›å›žé¥‹ï¼Œé‚£éº¼æ‚¨ä¹Ÿè¨±" "會å°éƒµéžè«–壇感到興趣:\n" #: src/help.c:39 msgid "http://sourceforge.net/mail/?group_id=155874" msgstr "" #: src/help.c:42 msgid " Ctrl-N Create new image" msgstr " Ctrl-N 建立新圖åƒ" #: src/help.c:43 msgid " Ctrl-O Open Image" msgstr " Ctrl-O 開啟圖åƒ" #: src/help.c:44 msgid " Ctrl-S Save Image" msgstr " Ctrl-S 儲存圖åƒ" #: src/help.c:45 msgid " Ctrl-Shift-S Save layers file" msgstr "" #: src/help.c:46 msgid " Ctrl-Q Quit program\n" msgstr " Ctrl-Q 離開程å¼\n" #: src/help.c:47 msgid " Ctrl-A Select whole image" msgstr " Ctrl-A é¸å–整個圖åƒ" #: src/help.c:48 msgid " Escape Select nothing, cancel paste box" msgstr " Escape 沒有é¸å–任何æ±è¥¿ï¼Œå–消貼上方框" #: src/help.c:49 msgid " J Lasso selection\n" msgstr "" #: src/help.c:50 msgid " Ctrl-C Copy selection to clipboard" msgstr " Ctrl-C è¤‡è£½é¸æ“‡åˆ°å‰ªè²¼ç°¿" #: src/help.c:51 msgid "" " Ctrl-X Copy selection to clipboard, and then paint current " "pattern to selection area" msgstr " Ctrl-X è¤‡è£½é¸æ“‡åˆ°å‰ªè²¼ç°¿ï¼Œç„¶å¾Œç¹ªè£½ç›®å‰å¼æ¨£åˆ°é¸æ“‡å€åŸŸ" #: src/help.c:52 msgid " Ctrl-V Paste clipboard to centre of current view" msgstr " Ctrl-V 貼上剪貼簿到目å‰çš„æª¢è¦–中心" #: src/help.c:53 msgid " Ctrl-K Paste clipboard to location it was copied from" msgstr " Ctrl-K 貼上剪貼簿到它複製而來的ä½ç½®" #: src/help.c:54 msgid " Ctrl-Shift-V Paste clipboard to new layer" msgstr "" #: src/help.c:55 msgid " Enter/Return Commit paste to canvas" msgstr " Enter/Return èªå¯è²¼ä¸Šåˆ°ç•«å¸ƒ" #: src/help.c:56 msgid " Shift+Enter/Return Commit paste and swap canvas into the clipboard\n" msgstr "" #: src/help.c:57 msgid " Arrow keys Paint Mode - Move the mouse pointer" msgstr " Arrow keys ç¹ªè£½æ¨¡å¼ - 變更é¡è‰² A 或 B" #: src/help.c:58 msgid "" " Arrow keys Selection Mode - Nudge selection box or paste box by one " "pixel" msgstr " Arrow keys 鏿“‡æ¨¡å¼ - 微動é¸å–方塊或ä½ç§»ä¸€å€‹åƒç´ å¾Œè²¼ä¸Šæ–¹æ¡†" #: src/help.c:59 msgid "" " Shift+Arrow keys Nudge mouse pointer, selection box or paste box by x " "pixels - x is defined by the Preferences window" msgstr "" " Shift+Arrow keys 輕推é¸å–方塊或ä½ç§» x åƒç´ å†è²¼ä¸Šæ–¹æ¡† - x ç”±å好設定視窗所" "定義" #: src/help.c:60 msgid " Ctrl+Arrows Move layer or resize selection box" msgstr " Ctrl+Arrows 移動圖層或調整大å°é¸å–方塊" #: src/help.c:61 msgid " Ctrl+Shift+Arrows Move layer or resize selection box by x pixels\n" msgstr "" #: src/help.c:62 msgid " Enter/Return Paint Mode - Simulate left click" msgstr "" #: src/help.c:63 msgid " Backspace Paint Mode - Simulate right click\n" msgstr "" #: src/help.c:64 msgid "" " [ or ] Change colour A to the next or previous palette item" msgstr " [ or ] 變更é¡è‰² A 為下一個或上一個調色盤項目" #: src/help.c:65 msgid "" " Shift+[ or ] Change colour B to the next or previous palette item\n" msgstr " Shift+[ or ] 變更é¡è‰² B 為下一個或上一個調色盤項目\n" #: src/help.c:66 msgid " Delete Crop image to selection" msgstr " Delete è£å‰ªåœ–åƒä¹‹å¾Œé¸æ“‡" #: src/help.c:67 msgid "" " Insert Transform colours - i.e. Brightness, Contrast, " "Saturation, Posterize, Gamma" msgstr " Insert 變æ›é¡è‰² -也就是亮度ã€å°æ¯”ã€é£½å’Œåº¦ã€è‰²èª¿åˆ†é›¢ã€Î³ 值" #: src/help.c:68 msgid " Ctrl-G Greyscale the image" msgstr " Ctrl-G 圖åƒç°éšŽåŒ–" #: src/help.c:69 msgid " Shift-Ctrl-G Greyscale the image (Gamma corrected)" msgstr " Shift-Ctrl-G 圖åƒç°éšŽåŒ– (γ 值已修正)" #: src/help.c:70 msgid " Ctrl+M Mirror the image" msgstr "" #: src/help.c:71 msgid " Shift-Ctrl-I Invert the image\n" msgstr "" #: src/help.c:72 msgid "" " Ctrl-T Draw a rectangle around the selection area with the " "current fill" msgstr " Ctrl-T 以目å‰å¡«å……è‰²åœ¨é¸æ“‡å€åŸŸå‘¨åœç¹ªè£½çŸ©å½¢" #: src/help.c:73 msgid " Ctrl-Shift-T Fill in the selection area with the current fill" msgstr " Ctrl-Shift-T 以目å‰å¡«å……è‰²å¡«æ»¿é¸æ“‡å€åŸŸ" #: src/help.c:74 msgid " Ctrl-L Draw an ellipse spanning the selection area" msgstr " Ctrl-L ç¹ªè£½å±•é–‹é¸æ“‡å€åŸŸçš„æ©¢åœ“" #: src/help.c:75 msgid " Ctrl-Shift-L Draw a filled ellipse spanning the selection area\n" msgstr " Ctrl-Shift-L ç¹ªè£½å±•é–‹é¸æ“‡å€åŸŸçš„填色橢圓\n" #: src/help.c:76 msgid " Ctrl-E Edit the RGB values for colours A & B" msgstr " Ctrl-E 編輯用於é¡è‰² A & B çš„ RGB 值" #: src/help.c:77 msgid " Ctrl-W Edit all palette colours\n" msgstr " Ctrl-W 編輯所有調色盤é¡è‰²\n" #: src/help.c:78 msgid " Ctrl-P Preferences" msgstr " Ctrl-P å好設定" #: src/help.c:79 msgid " Ctrl-I Information\n" msgstr " Ctrl-I 資訊\n" #: src/help.c:80 msgid " Ctrl-Z Undo last action" msgstr " Ctrl-Z 復原最後一筆動作" #: src/help.c:81 msgid " Ctrl-R Redo an undone action\n" msgstr " Ctrl-R é‡åšå·²å¾©åŽŸå‹•ä½œ\n" #: src/help.c:82 msgid " Shift-T Text Tool (GTK+)" msgstr "" #: src/help.c:83 msgid " T Text Tool (FreeType)\n" msgstr "" #: src/help.c:84 msgid " V View Window" msgstr " V 檢視視窗" #: src/help.c:85 msgid " L Layers Window\n" msgstr " L 圖層視窗\n" #: src/help.c:86 msgid " Ctrl-H Toggle Hide Image mode" msgstr "" #: src/help.c:87 msgid " B Toggle Snap to Tile Grid mode\n" msgstr "" #: src/help.c:88 msgid " X Swap Colours A & B" msgstr "" #: src/help.c:89 msgid " E Choose Colour\n" msgstr "" #: src/help.c:90 msgid "" " A Draw open arrow head when using the line tool (size set " "by flow setting)" msgstr "" #: src/help.c:91 msgid "" " S Draw closed arrow head when using the line tool (size " "set by flow setting)\n" msgstr "" #: src/help.c:92 msgid " D Line Tool" msgstr "" #: src/help.c:93 msgid " F Flood Fill Tool\n" msgstr "" #: src/help.c:94 msgid " +,= Main edit window - Zoom in" msgstr " +,= 主è¦ç·¨è¼¯è¦–窗 - 放大" #: src/help.c:95 msgid " - Main edit window - Zoom out" msgstr " - 主è¦ç·¨è¼¯è¦–窗 - 縮å°" #: src/help.c:96 msgid " Shift +,= View window - Zoom in" msgstr " Shift +,= 檢視視窗 - 放大" #: src/help.c:97 msgid " Shift - View window - Zoom out\n" msgstr " Shift - 檢視視窗 - 縮å°\n" #: src/help.c:98 #, fuzzy, c-format msgid " 1 10% zoom" msgstr " 1 10% 縮放" #: src/help.c:99 #, fuzzy, c-format msgid " 2 25% zoom" msgstr " 2 25% 縮放" #: src/help.c:100 #, fuzzy, c-format msgid " 3 50% zoom" msgstr " 3 50% 縮放" #: src/help.c:101 #, fuzzy, c-format msgid " 4 100% zoom" msgstr " 4 100% 縮放" #: src/help.c:102 #, fuzzy, c-format msgid " 5 400% zoom" msgstr " 5 400% 縮放" #: src/help.c:103 #, fuzzy, c-format msgid " 6 800% zoom" msgstr " 6 800% 縮放" #: src/help.c:104 #, fuzzy, c-format msgid " 7 1200% zoom" msgstr " 7 1200% 縮放" #: src/help.c:105 #, fuzzy, c-format msgid " 8 1600% zoom" msgstr " 8 1600% 縮放" #: src/help.c:106 #, fuzzy, c-format msgid " 9 2000% zoom\n" msgstr " 9 2000% 縮放\n" #: src/help.c:107 msgid " Shift + 1 Edit image channel" msgstr " Shift + 1 編輯圖åƒé€šé“" #: src/help.c:108 msgid " Shift + 2 Edit alpha channel" msgstr " Shift + 2 編輯 α 通é“" #: src/help.c:109 msgid " Shift + 3 Edit selection channel" msgstr " Shift + 3 編輯é¸å–通é“" #: src/help.c:110 msgid " Shift + 4 Edit mask channel\n" msgstr " Shift + 4 編輯é®ç½©é€šé“\n" #: src/help.c:111 msgid " F1 Help" msgstr " F1 說明" #: src/help.c:112 msgid " F2 Choose Pattern" msgstr " F2 é¸å–弿¨£" #: src/help.c:113 msgid " F3 Choose Brush" msgstr " F3 é¸å–筆刷" #: src/help.c:114 msgid " F4 Paint Tool" msgstr " F4 繪製工具" #: src/help.c:115 msgid " F5 Toggle Main Toolbar" msgstr " F5 切æ›ä¸»å·¥å…·åˆ—" #: src/help.c:116 msgid " F6 Toggle Tools Toolbar" msgstr " F6 切æ›å·¥å…·å·¥å…·åˆ—" #: src/help.c:117 msgid " F7 Toggle Settings Toolbar" msgstr " F7 切æ›è¨­å®šå€¼å·¥å…·åˆ—" #: src/help.c:118 msgid " F8 Toggle Palette" msgstr " F8 切æ›èª¿è‰²ç›¤" #: src/help.c:119 msgid " F9 Selection Tool" msgstr " F9 鏿“‡å·¥å…·" #: src/help.c:120 msgid " F12 Toggle Dock Area\n" msgstr "" #: src/help.c:121 msgid " Ctrl + F1 - F12 Save current clipboard to file 1-12" msgstr " Ctrl + F1 - F12 儲存目å‰å‰ªè²¼ç°¿åˆ°æª”案 1-12" #: src/help.c:122 msgid " Shift + F1 - F12 Load clipboard from file 1-12\n" msgstr " Shift + F1 - F12 從檔案 1-12 載入剪貼簿\n" #: src/help.c:123 msgid "" " Ctrl + 1, 2, ... , 0 Set opacity to 10%, 20%, ... , 100% (main or keypad " "numbers)" msgstr " Ctrl + 1, 2,…,0 設定æ¿åº¦åˆ° 10%, 20%,…,100% (主éµå€æˆ–數字éµå€æ•¸å­—)" #: src/help.c:124 msgid " Ctrl + + or = Increase opacity by 1" msgstr " Ctrl + + 或 = 增加æ¿åº¦ 1" #: src/help.c:125 msgid " Ctrl + - Decrease opacity by 1\n" msgstr " Ctrl + - 減少æ¿åº¦ 1\n" #: src/help.c:126 msgid "" " Home Show or hide main window menu/toolbar/status bar/palette" msgstr " Home 顯示或隱è—主視窗é¸å–®/工具列/狀態列/調色盤" #: src/help.c:127 msgid " Page Up Scale Image" msgstr " Page Up 伸縮圖åƒ" #: src/help.c:128 msgid " Page Down Resize Image canvas" msgstr " Page Down 調整圖åƒç•«å¸ƒå¤§å°" #: src/help.c:129 msgid " End Pan Window" msgstr " End 全景視窗" #: src/help.c:132 msgid " Left button Paint to canvas using the current tool" msgstr " å·¦éµ ä½¿ç”¨ç›®å‰å·¥å…·ç¹ªè£½åˆ°ç•«å¸ƒ" #: src/help.c:133 msgid "" " Middle button Selects the point which will be the centre of the " "image after the next zoom" msgstr "" " ä¸­éµ è¨­å®šç”¨æ–¼ä¸‹ä¸€æ¬¡ç¸®æ”¾ä¹‹å¾Œçš„ä¸­å¿ƒ" #: src/help.c:134 msgid "" " Right button Commit paste to canvas / Stop drawing current line / " "Cancel selection\n" msgstr "" " å³éµ èªå¯è²¼ä¸Šåˆ°ç•«å¸ƒ/åœæ­¢ç¹ªè£½ç›®å‰ç·š" "æ¢/å–æ¶ˆé¸æ“‡\n" #: src/help.c:135 msgid "" " Scroll Wheel In GTK+2/3 the user can have the scroll wheel zoom in " "or out via the Preferences window\n" msgstr "" " 滾輪 在 GTK+2/3 中使用者å¯ä»¥é€éŽå好設" "定視窗來用滾輪放大或縮å°\n" #: src/help.c:136 msgid " Ctrl+Left button Choose colour A from under mouse pointer" msgstr " Ctrl+å·¦éµ å¾žæ»‘é¼ æŒ‡æ¨™ä¸‹æ–¹é¸å–é¡è‰² A" #: src/help.c:137 msgid " Ctrl+Left button Clone tool - Select source" msgstr "" #: src/help.c:138 msgid "" " Ctrl+Middle button Create colour A/B and pattern based on the RGB colour " "in A (RGB images only)" msgstr "" #: src/help.c:139 msgid " Ctrl+Right button Choose colour B from under mouse pointer" msgstr " Ctrl+å³éµ 從滑鼠指標下方é¸å–é¡è‰² B" #: src/help.c:140 msgid "" " Ctrl+Right button Polygon tool - Delete last point / Delete nearest " "point" msgstr "" #: src/help.c:141 msgid " Ctrl+Scroll Wheel Scroll the main edit window left or right\n" msgstr " Ctrl+滾輪 å‘左或å‘峿»¾å‹•主è¦ç·¨è¼¯è¦–窗\n" #: src/help.c:142 msgid "" " Ctrl+Double click Set colour A or B to average colour under brush " "square or selection marquee (RGB only)\n" msgstr "" #: src/help.c:143 msgid "" " Shift+Right button Selects the point which will be the centre of the " "image after the next zoom\n" "\n" msgstr "" " Shift+å³éµ 設定用於下一次縮放之後的中心\n" "\n" #: src/help.c:144 msgid "You can fixate the X/Y co-ordinates while moving the mouse:\n" msgstr "移動滑鼠時,您å¯ä»¥ä¿®æ­£ X/Y 座標:\n" #: src/help.c:145 msgid " Shift Constrain mouse movements to vertical line" msgstr " Shift ç›¸å°æ–¼åž‚直線等比例滑鼠移動" #: src/help.c:146 msgid " Shift+Ctrl Constrain mouse movements to horizontal line" msgstr " Shift+Ctrl ç›¸å°æ–¼æ°´å¹³ç·šç­‰æ¯”例滑鼠移動" #: src/help.c:149 msgid "mtPaint is maintained by Dmitry Groshev.\n" msgstr "mtPaint 是由 Dmitry Groshev 所維護。\n" #: src/help.c:150 msgid "wjaguar@users.sourceforge.net" msgstr "" #: src/help.c:151 msgid "http://mtpaint.sourceforge.net/\n" msgstr "" #: src/help.c:152 msgid "" "The following people (in alphabetical order) have contributed directly to " "the project, and are therefore worthy of gracious thanks for their " "generosity and hard work:\n" "\n" msgstr "" "下列人士 (ä¾å­—æ¯æŽ’åº) å°æ–¼è¨ˆç•«æœ‰ç›´æŽ¥çš„è²¢ç»ï¼Œå› è€Œå€¼å¾—å°æ–¼å®ƒå€‘çš„æ…·æ…¨å’ŒåŠªåŠ›æˆæžœ" "表示由衷的感è¬ï¼š\n" "\n" #: src/help.c:153 msgid "Authors\n" msgstr "作者\n" #: src/help.c:154 msgid "" "Dmitry Groshev - Contributing developer for version 2.30. Lead developer and " "maintainer from version 3.00 to the present." msgstr "" "Dmitry Groshev - å”助開發版本 2.30。從版本 3.00 起到目å‰ç‚ºæ­¢çš„領導開發者與維" "護者。" #: src/help.c:155 msgid "" "Mark Tyler - Original author and maintainer up to version 3.00, occasional " "contributor thereafter." msgstr "Mark Tyler - 原來的作者與維護者到版本 3.00 ç‚ºæ­¢ï¼Œä¹‹å¾Œä¸æ™‚有所貢ç»ã€‚" #: src/help.c:156 msgid "" "Xiaolin Wu - Wrote the Wu quantizing method - see wu.c for more " "information.\n" "\n" msgstr "" "Xiaolin Wu - 編寫 Wu é‡åŒ–方法 - åƒçœ‹ wu.c 以ç²å¾—更多資訊。\n" "\n" #: src/help.c:157 msgid "" "General Contributions (Feedback and Ideas for improvements unless otherwise " "stated)\n" msgstr "一般貢ç»(若無é¡å¤–記載表示æ„見回饋與改進想法)\n" #: src/help.c:158 msgid "Abdulla Al Muhairi - Website redesign April 2005" msgstr "Abdulla Al Muhairi - 2005 å¹´ 4 æœˆç¶²ç«™é‡æ–°è¨­è¨ˆ" #: src/help.c:159 msgid "Alan Horkan" msgstr "" #: src/help.c:160 msgid "Alexandre Prokoudine" msgstr "" #: src/help.c:161 msgid "Antonio Andrea Bianco" msgstr "" #: src/help.c:162 msgid "Charlie Ledocq" msgstr "" #: src/help.c:163 msgid "Dennis Lee" msgstr "" #: src/help.c:164 msgid "Donald White" msgstr "" #: src/help.c:165 msgid "Ed Jason" msgstr "" #: src/help.c:166 msgid "" "Eddie Kohler - Created Gifsicle which is needed for the creation and viewing " "of animated GIF files http://www.lcdf.org/gifsicle/" msgstr "" "Eddie Kohler - 建立 Gifsicle åšç‚ºå»ºç«‹å’Œè§€çœ‹å‹•ç•« GIF 所需的檔案 http://www." "lcdf.org/gifsicle/" #: src/help.c:167 msgid "" "Guadalinex Team (Junta de Andalucia) - man page, Launchpad/Rosetta " "registration" msgstr "" "Guadalinex 團隊 (Junta de Andalucia) - 線上手冊ã€Launchpad/Rosetta 註冊" #: src/help.c:168 msgid "Lou Afonso" msgstr "" #: src/help.c:169 msgid "Magnus Hjorth" msgstr "" #: src/help.c:170 msgid "Martin Zelaia" msgstr "" #: src/help.c:171 msgid "Pasi Kallinen" msgstr "" #: src/help.c:172 msgid "Pavel Ruzicka" msgstr "" #: src/help.c:173 msgid "Puppy Linux (Barry Kauler)" msgstr "" #: src/help.c:174 msgid "Victor Copovi" msgstr "" #: src/help.c:175 msgid "Vlastimil Krejcir" msgstr "" #: src/help.c:176 msgid "" "William Kern\n" "\n" msgstr "" #: src/help.c:177 msgid "Translations\n" msgstr "翻譯\n" #: src/help.c:178 msgid "Brazilian Portuguese - Paulo Trevizan, Valter Nazianzeno" msgstr "è‘¡è„牙語(巴西) - Paulo Trevizan, Valter Nazianzeno" #: src/help.c:179 msgid "Czech - Pavel Ruzicka, Martin Petricek, Roman Hornik, Pavel Fric" msgstr "æ·å…‹èªž - Pavel Ruzicka, Martin Petricek, Roman Hornik, Pavel Fric" #: src/help.c:180 msgid "Dutch - Hans Strijards, Pjotr" msgstr "" #: src/help.c:181 msgid "" "French - Nicolas Velin, Pascal Billard, Sylvain Cresto, Johan Serre, " "Philippe Etienne, Victor Copovi" msgstr "" "法語 - Nicolas Velin, Pascal Billard, Sylvain Cresto, Johan Serre, Philippe " "Etienne" #: src/help.c:182 msgid "Galician - Miguel Anxo Bouzada" msgstr "" #: src/help.c:183 msgid "German - Oliver Frommel, B. Clausius, Ulrich Ringel, Simon Brixel" msgstr "德語 - Oliver Frommel, B. Clausius, Ulrich Ringel, Simon Brixel" #: src/help.c:184 msgid "Hungarian - Ur Balazs" msgstr "" #: src/help.c:185 msgid "Italian - Angelo Gemmi" msgstr "" #: src/help.c:186 msgid "Japanese - Norihiro YONEDA" msgstr "" #: src/help.c:187 msgid "Kabyle - Yacine Bouklif" msgstr "" #: src/help.c:188 msgid "Polish - Bartosz Kaszubowski, LucaS" msgstr "波蘭語 - Bartosz Kaszubowski, LucaS" #: src/help.c:189 msgid "Portuguese - Israel G. Lugo, Tiago Silva" msgstr "è‘¡è„牙語 - Israel G.Lugo, Tiago Silva" #: src/help.c:190 msgid "Russian - Sergey Irupin, Dmitry Groshev" msgstr "" #: src/help.c:191 msgid "Simplified Chinese - Cecc" msgstr "" #: src/help.c:192 msgid "Slovak - Jozef Riha" msgstr "斯洛ä¼å…‹èªž - Jozef Riha" #: src/help.c:193 msgid "" "Spanish - Guadalinex Team (Junta de Andalucia), Antonio Sanchez Leon, Miguel " "Anxo Bouzada, Francisco Jose Rey, Adolfo Jayme" msgstr "" "西ç­ç‰™èªž - Guadalinex 團隊 (Junta de Andalucia), Antonio Sanchez Leon, " "Miguel Anxo Bouzada, Francisco Jose Rey, Adolfo Jayme" #: src/help.c:194 msgid "Swedish - Daniel Nylander, Daniel Eriksson" msgstr "" #: src/help.c:195 msgid "Tagalog - Anjelo delCarmen" msgstr "" #: src/help.c:196 msgid "Taiwanese Chinese - Wei-Lun Chao" msgstr "中文(臺ç£) - 趙惟倫" #: src/help.c:197 msgid "Turkish - Muhammet Kara, Tutku Dalmaz" msgstr "土耳其語 - Muhammet Karaã€Tutku Dalmaz" #: src/info.c:258 msgid "Information" msgstr "資訊" #: src/info.c:260 msgid "Memory" msgstr "記憶體" #: src/info.c:261 msgid "Total memory for main + undo images" msgstr "ç”¨æ–¼ä¸»è¦ + 復原圖åƒçš„記憶體總計" #: src/info.c:263 msgid "Undo / Redo / Max levels used" msgstr "復原/é‡åš/最大使用級數" #: src/info.c:265 msgid "Unused" msgstr "未使用的" #: src/info.c:269 msgid "Unique RGB pixels" msgstr "唯一 RGB åƒç´ " #: src/info.c:272 src/layer.c:121 msgid "Layers" msgstr "圖層" #: src/info.c:273 msgid "Total layer memory usage" msgstr "圖層記憶體用é‡ç¸½è¨ˆ" #: src/info.c:277 msgid "Colour Histogram" msgstr "é¡è‰²é•·æ¢åœ–" #: src/info.c:289 src/otherwindow.c:1614 msgid "Index" msgstr "索引" #: src/info.c:290 msgid "Canvas pixels" msgstr "畫布åƒç´ " #: src/info.c:328 #, c-format msgid "Clipboard = %i x %i" msgstr "剪貼簿 = %i x %i" #: src/info.c:328 #, c-format msgid "Clipboard = %i x %i x RGB" msgstr "剪貼簿 = %i x %i x RGB" #: src/info.c:377 msgid "Orphans" msgstr "段è½å‰åˆ†é " #: src/info.c:383 #, c-format msgid "Colour index totals - %i of %i used" msgstr "é¡è‰²ç´¢å¼•總計 - 已使用 %2$i çš„ %1$i" #: src/inifile.c:966 msgid "" "Could not find home directory. Using current directory as home directory." msgstr "找ä¸åˆ°ä¸»ç›®éŒ„。使用目å‰ç›®éŒ„åšç‚ºä¸»ç›®éŒ„。" #: src/layer.c:63 msgid "Background" msgstr "背景" #: src/layer.c:122 src/mainwindow.c:5931 msgid "(Modified)" msgstr "(已修改)" #: src/layer.c:123 src/mainwindow.c:5932 msgid "Untitled" msgstr "無標題" #: src/layer.c:308 #, c-format msgid "Do you really want to delete layer %i (%s) ?" msgstr "您真的è¦åˆªé™¤åœ–層 %i (%s) 嗎?" #: src/layer.c:380 msgid "" "One or more of the layers contains changes that have not been saved. Do you " "really want to lose these changes?" msgstr "ä¸€å€‹æˆ–æ›´å¤šçš„æœªå„²å­˜åœ–å±¤å«æœ‰è®Šæ›´ã€‚ 您真的è¦ä¸Ÿæ£„這些變更嗎?" #: src/layer.c:381 src/mainwindow.c:1028 msgid "Cancel Operation" msgstr "å–æ¶ˆä½œæ¥­" #: src/layer.c:381 src/mainwindow.c:1028 msgid "Lose Changes" msgstr "丟棄變更" #: src/layer.c:523 #, c-format msgid "%d layers failed to load" msgstr "%d 個圖層載入時失敗" #: src/layer.c:826 msgid "" "One or more of the image layers has not been saved. You must save each " "image individually before saving the layers text file in order to load this " "composite image in the future." msgstr "" "一個或更多的圖åƒåœ–層未儲存。 您必須在儲存圖層文字檔案之å‰ï¼Œå€‹åˆ¥åœ°å„²å­˜æ¯å€‹åœ–" "åƒï¼Œä»¥ä¾¿åœ¨ä¹‹å¾Œè¼‰å…¥é€™å€‹åˆæˆåœ–åƒã€‚" #: src/layer.c:841 msgid "Do you really want to delete all of the layers?" msgstr "您真的è¦åˆªé™¤å…¨éƒ¨çš„圖層嗎?" #: src/layer.c:970 msgid "You cannot add any more layers." msgstr "您無法å†åŠ å…¥ä»»ä½•åœ–å±¤ã€‚" #: src/layer.c:1083 src/otherwindow.c:241 msgid "New Layer" msgstr "新增圖層" #: src/layer.c:1085 msgid "Raise" msgstr "æå‡" #: src/layer.c:1087 msgid "Lower" msgstr "é™ä½Ž" #: src/layer.c:1089 msgid "Duplicate Layer" msgstr "é‡è£½åœ–層" #: src/layer.c:1091 msgid "Centralise Layer" msgstr "圖層置中" #: src/layer.c:1093 msgid "Delete Layer" msgstr "刪除圖層" #: src/layer.c:1095 msgid "Close Layers Window" msgstr "關閉圖層視窗" #: src/layer.c:1101 msgid "Layer Name" msgstr "圖層å稱" #: src/layer.c:1104 src/toolbar.c:209 msgid "Position" msgstr "ä½ç½®" #: src/layer.c:1112 msgid "Transparent Colour" msgstr "逿˜Žè‰²" #: src/layer.c:1117 msgid "Show all layers in main window" msgstr "在主視窗中顯示全部圖層" #: src/mainwindow.c:67 src/otherwindow.c:844 src/otherwindow.c:2756 #: src/toolbar.c:342 msgid "Image" msgstr "圖åƒ" #: src/mainwindow.c:69 src/mainwindow.c:489 src/otherwindow.c:1613 #: src/otherwindow.c:2302 msgid "RGB" msgstr "" #: src/mainwindow.c:69 src/otherwindow.c:1613 src/otherwindow.c:2302 msgid "sRGB" msgstr "" #: src/mainwindow.c:342 msgid "There were no unused colours to remove!" msgstr "沒有未使用的é¡è‰²å¯ç§»é™¤ï¼" #: src/mainwindow.c:371 msgid "The palette does not contain 2 colours that have identical RGB values" msgstr "調色盤ä¸åŒ…å«å…©ç¨®å…·æœ‰ç›¸åŒ RGB 值的é¡è‰²" #: src/mainwindow.c:374 #, c-format msgid "" "The palette contains %i colours that have identical RGB values. Do you " "really want to merge them into one index and realign the canvas?" msgstr "" "èª¿è‰²ç›¤å«æœ‰ %i 種具有相等 RGB 值的é¡è‰²ã€‚ 您真的è¦å°‡å®ƒå€‘åˆä½µç‚ºä¸€å€‹ç´¢å¼•å’Œé‡æ–°å°" "整畫布嗎?" #: src/mainwindow.c:492 msgid "indexed" msgstr "" #: src/mainwindow.c:498 #, c-format msgid "" "You are trying to save an %s image to an %s file which is not possible. I " "would suggest you save with a PNG extension." msgstr "" #: src/mainwindow.c:500 #, c-format msgid "" "You are trying to save an %s file with a palette of more than %d colours. " "Either use another format or reduce the palette to %d colours." msgstr "" #: src/mainwindow.c:578 msgid "Unable to load clipboard" msgstr "無法載入剪貼簿" #: src/mainwindow.c:604 msgid "Unable to save clipboard" msgstr "無法儲存剪貼簿" #: src/mainwindow.c:775 msgid "Zoom in" msgstr "" #: src/mainwindow.c:777 msgid "Zoom out" msgstr "" #: src/mainwindow.c:779 #, c-format msgid "10% zoom" msgstr "" #: src/mainwindow.c:781 #, c-format msgid "25% zoom" msgstr "" #: src/mainwindow.c:783 #, c-format msgid "50% zoom" msgstr "" #: src/mainwindow.c:785 #, c-format msgid "100% zoom" msgstr "" #: src/mainwindow.c:787 #, c-format msgid "400% zoom" msgstr "" #: src/mainwindow.c:789 #, c-format msgid "600% zoom" msgstr "" #: src/mainwindow.c:791 #, c-format msgid "800% zoom" msgstr "" #: src/mainwindow.c:793 #, c-format msgid "1000% zoom" msgstr "" #: src/mainwindow.c:795 #, c-format msgid "1200% zoom" msgstr "" #: src/mainwindow.c:797 #, c-format msgid "1600% zoom" msgstr "" #: src/mainwindow.c:799 #, c-format msgid "2000% zoom" msgstr "" #: src/mainwindow.c:801 #, c-format msgid "4000% zoom" msgstr "" #: src/mainwindow.c:803 #, c-format msgid "8000% zoom" msgstr "" #: src/mainwindow.c:805 #, c-format msgid "10% opacity" msgstr "" #: src/mainwindow.c:807 #, c-format msgid "20% opacity" msgstr "" #: src/mainwindow.c:809 #, c-format msgid "30% opacity" msgstr "" #: src/mainwindow.c:811 #, c-format msgid "40% opacity" msgstr "" #: src/mainwindow.c:813 #, c-format msgid "50% opacity" msgstr "" #: src/mainwindow.c:815 #, c-format msgid "60% opacity" msgstr "" #: src/mainwindow.c:817 #, c-format msgid "70% opacity" msgstr "" #: src/mainwindow.c:819 #, c-format msgid "80% opacity" msgstr "" #: src/mainwindow.c:821 #, c-format msgid "90% opacity" msgstr "" #: src/mainwindow.c:823 #, c-format msgid "100% opacity" msgstr "" #: src/mainwindow.c:825 msgid "Increase opacity" msgstr "" #: src/mainwindow.c:827 msgid "Decrease opacity" msgstr "" #: src/mainwindow.c:829 msgid "Draw open arrow head" msgstr "" #: src/mainwindow.c:831 msgid "Draw closed arrow head" msgstr "" #: src/mainwindow.c:833 msgid "Previous colour A" msgstr "" #: src/mainwindow.c:835 msgid "Next colour A" msgstr "" #: src/mainwindow.c:837 msgid "Previous colour B" msgstr "" #: src/mainwindow.c:839 msgid "Next colour B" msgstr "" #: src/mainwindow.c:841 msgid "Previous pattern" msgstr "" #: src/mainwindow.c:843 msgid "Next pattern" msgstr "" #: src/mainwindow.c:845 msgid "Larger brush" msgstr "" #: src/mainwindow.c:847 msgid "Smaller brush" msgstr "" #: src/mainwindow.c:849 msgid "View window - Zoom in" msgstr "" #: src/mainwindow.c:851 msgid "View window - Zoom out" msgstr "" #: src/mainwindow.c:1027 msgid "" "This canvas/palette contains changes that have not been saved. Do you " "really want to lose these changes?" msgstr "此畫布/èª¿è‰²ç›¤å«æœ‰æœªå„²å­˜çš„變更。 您真的è¦ä¸Ÿæ£„這些變更嗎?" #: src/mainwindow.c:1094 msgid "Do you really want to quit?" msgstr "您真的è¦é›¢é–‹å—Žï¼Ÿ" #: src/mainwindow.c:3754 msgid "Empty string or broken quoting" msgstr "" #: src/mainwindow.c:3755 msgid "Script must begin with a command" msgstr "" #: src/mainwindow.c:3756 msgid "Script nesting limit exceeded" msgstr "" #: src/mainwindow.c:3765 #, c-format msgid "'%s' does not match any item" msgstr "" #: src/mainwindow.c:3767 #, c-format msgid "'%s' matches a non-scriptable item" msgstr "" #: src/mainwindow.c:3769 #, c-format msgid "'%s' matches a disabled item" msgstr "" #: src/mainwindow.c:3788 #, c-format msgid "'%s' value does not fit item" msgstr "" #: src/mainwindow.c:3969 msgid "Script" msgstr "" #: src/mainwindow.c:3982 src/spawn.c:656 src/spawn.c:662 msgid "Action" msgstr "" #: src/mainwindow.c:3991 src/spawn.c:666 msgid "Execute" msgstr "" #: src/mainwindow.c:4045 msgid "Unable to load script" msgstr "" #: src/mainwindow.c:5182 msgid "/_File" msgstr "/檔案(_F)" #: src/mainwindow.c:5184 msgid "//New" msgstr "//新增" #: src/mainwindow.c:5186 msgid "//Open ..." msgstr "//開啟…" #: src/mainwindow.c:5188 src/mainwindow.c:5669 msgid "//Save" msgstr "//儲存" #: src/mainwindow.c:5190 src/mainwindow.c:5549 src/mainwindow.c:5627 #: src/mainwindow.c:5671 msgid "//Save As ..." msgstr "//å¦å­˜ç‚ºâ€¦" #: src/mainwindow.c:5192 msgid "//Export Undo Images ..." msgstr "//匯出復原圖åƒâ€¦" #: src/mainwindow.c:5194 msgid "//Export Undo Images (reversed) ..." msgstr "//åŒ¯å‡ºå¾©åŽŸåœ–åƒ (åå‘)…" #: src/mainwindow.c:5196 msgid "//Export ASCII Art ..." msgstr "//匯出 ASCII 圖案…" #: src/mainwindow.c:5198 msgid "//Export Animated GIF ..." msgstr "//匯出動畫 GIF…" #: src/mainwindow.c:5201 msgid "//Actions" msgstr "" #: src/mainwindow.c:5235 src/mainwindow.c:5488 msgid "///Configure" msgstr "" #: src/mainwindow.c:5290 msgid "//Quit" msgstr "//離開" #: src/mainwindow.c:5293 msgid "/_Edit" msgstr "/編輯(_E)" #: src/mainwindow.c:5295 msgid "//Undo" msgstr "//復原" #: src/mainwindow.c:5297 msgid "//Redo" msgstr "//é‡åš" #: src/mainwindow.c:5300 msgid "//Cut" msgstr "//剪下" #: src/mainwindow.c:5302 msgid "//Copy" msgstr "//複製" #: src/mainwindow.c:5304 msgid "//Copy To Palette" msgstr "" #: src/mainwindow.c:5306 msgid "//Paste To Centre" msgstr "//貼到中心" #: src/mainwindow.c:5308 msgid "//Paste To New Layer" msgstr "//貼到新圖層" #: src/mainwindow.c:5310 msgid "//Paste" msgstr "//貼上" #: src/mainwindow.c:5312 msgid "//Paste Text" msgstr "//貼上文字" #: src/mainwindow.c:5318 msgid "//Paste Text (FreeType)" msgstr "" #: src/mainwindow.c:5321 msgid "//Paste Palette" msgstr "" #: src/mainwindow.c:5323 msgid "//Load Clipboard" msgstr "//載入剪貼簿" #: src/mainwindow.c:5350 msgid "//Save Clipboard" msgstr "//儲存剪貼簿" #: src/mainwindow.c:5377 msgid "//Import Clipboard from System" msgstr "" #: src/mainwindow.c:5378 msgid "//Export Clipboard to System" msgstr "" #: src/mainwindow.c:5381 msgid "//Choose Pattern ..." msgstr "//é¸å–弿¨£â€¦" #: src/mainwindow.c:5383 msgid "//Choose Brush ..." msgstr "//é¸å–筆刷…" #: src/mainwindow.c:5385 msgid "//Choose Colour ..." msgstr "" #: src/mainwindow.c:5392 msgid "/_View" msgstr "/檢視(_V)" #: src/mainwindow.c:5394 msgid "//Show Main Toolbar" msgstr "//顯示主工具列" #: src/mainwindow.c:5396 msgid "//Show Tools Toolbar" msgstr "//顯示工具工具列" #: src/mainwindow.c:5399 msgid "//Show Settings Toolbar" msgstr "//顯示設定值工具列" #: src/mainwindow.c:5402 msgid "//Show Dock" msgstr "" #: src/mainwindow.c:5404 msgid "//Show Palette" msgstr "//顯示調色盤" #: src/mainwindow.c:5406 msgid "//Show Status Bar" msgstr "//顯示狀態列" #: src/mainwindow.c:5409 msgid "//Toggle Image View" msgstr "//切æ›åœ–åƒæª¢è¦–" #: src/mainwindow.c:5413 msgid "//Centralize Image" msgstr "//圖åƒç½®ä¸­" #: src/mainwindow.c:5414 msgid "//Show Zoom Grid" msgstr "//顯示縮放格線" #: src/mainwindow.c:5415 msgid "//Snap To Tile Grid" msgstr "" #: src/mainwindow.c:5417 msgid "//Configure Grid ..." msgstr "" #: src/mainwindow.c:5418 msgid "//Tracing Image ..." msgstr "" #: src/mainwindow.c:5421 msgid "//View Window" msgstr "//檢視視窗" #: src/mainwindow.c:5423 msgid "//Horizontal Split" msgstr "//水平分隔" #: src/mainwindow.c:5425 msgid "//Focus View Window" msgstr "//焦點檢視視窗" #: src/mainwindow.c:5427 msgid "//Pan Window" msgstr "//全景視窗" #: src/mainwindow.c:5430 msgid "//Layers Window" msgstr "//圖層視窗" #: src/mainwindow.c:5433 msgid "/_Image" msgstr "/圖åƒ(_I)" #: src/mainwindow.c:5436 msgid "//Convert To RGB" msgstr "//轉æ›åˆ° RGB" #: src/mainwindow.c:5438 msgid "//Convert To Indexed ..." msgstr "//轉æ›åˆ°ç´¢å¼•值…" #: src/mainwindow.c:5441 msgid "//Scale Canvas ..." msgstr "//伸縮畫布…" #: src/mainwindow.c:5443 msgid "//Resize Canvas ..." msgstr "//調整畫布大å°â€¦" #: src/mainwindow.c:5445 msgid "//Crop" msgstr "//è£å‰ª" #: src/mainwindow.c:5448 src/mainwindow.c:5517 msgid "//Flip Vertically" msgstr "//垂直翻轉" #: src/mainwindow.c:5449 src/mainwindow.c:5519 msgid "//Flip Horizontally" msgstr "//水平翻轉" #: src/mainwindow.c:5452 src/mainwindow.c:5521 msgid "//Rotate Clockwise" msgstr "//é †æ™‚é‡æ—‹è½‰" #: src/mainwindow.c:5453 src/mainwindow.c:5523 msgid "//Rotate Anti-Clockwise" msgstr "//é€†æ™‚é‡æ—‹è½‰" #: src/mainwindow.c:5454 msgid "//Free Rotate ..." msgstr "//自由旋轉…" #: src/mainwindow.c:5455 msgid "//Skew ..." msgstr "" #: src/mainwindow.c:5458 msgid "//Segment ..." msgstr "" #: src/mainwindow.c:5462 msgid "//Script ..." msgstr "" #: src/mainwindow.c:5464 msgid "//Scripts" msgstr "" #: src/mainwindow.c:5491 msgid "//Information ..." msgstr "//資訊…" #: src/mainwindow.c:5494 msgid "//Preferences ..." msgstr "//å好設定…" #: src/mainwindow.c:5497 msgid "/_Selection" msgstr "/鏿“‡(_S)" #: src/mainwindow.c:5499 msgid "//Select All" msgstr "//å…¨é¸" #: src/mainwindow.c:5501 msgid "//Select None (Esc)" msgstr "//全部ä¸é¸ (Esc)" #: src/mainwindow.c:5503 msgid "//Lasso Selection" msgstr "//å¥—ç´¢é¸æ“‡" #: src/mainwindow.c:5505 msgid "//Lasso Selection Cut" msgstr "//å‰ªä¸‹å¥—ç´¢é¸æ“‡" #: src/mainwindow.c:5508 msgid "//Outline Selection" msgstr "//æé‚Šé¸æ“‡" #: src/mainwindow.c:5510 msgid "//Fill Selection" msgstr "//填充鏿“‡" #: src/mainwindow.c:5512 msgid "//Outline Ellipse" msgstr "//æé‚Šæ©¢åœ“" #: src/mainwindow.c:5514 msgid "//Fill Ellipse" msgstr "//填充橢圓" #: src/mainwindow.c:5526 msgid "//Horizontal Ramp" msgstr "" #: src/mainwindow.c:5528 msgid "//Vertical Ramp" msgstr "" #: src/mainwindow.c:5531 msgid "//Alpha Blend A,B" msgstr "//α 混色 A,B" #: src/mainwindow.c:5533 msgid "//Move Alpha to Mask" msgstr "//移動 α 到é®ç½©" #: src/mainwindow.c:5535 msgid "//Mask Colour A,B" msgstr "//é®ç½©é¡è‰² A,B" #: src/mainwindow.c:5537 msgid "//Unmask Colour A,B" msgstr "//å–æ¶ˆé®ç½©é¡è‰² A,B" #: src/mainwindow.c:5539 msgid "//Mask All Colours" msgstr "//é®ç½©æ‰€æœ‰é¡è‰²" #: src/mainwindow.c:5541 msgid "//Clear Mask" msgstr "//清除é®ç½©" #: src/mainwindow.c:5544 msgid "/_Palette" msgstr "/調色盤(_P)" #: src/mainwindow.c:5548 src/mainwindow.c:5626 msgid "//Load ..." msgstr "//載入…" #: src/mainwindow.c:5550 msgid "//Load Default" msgstr "//載入é è¨­" #: src/mainwindow.c:5552 msgid "//Mask All" msgstr "//全部é®ç½©" #: src/mainwindow.c:5553 msgid "//Mask None" msgstr "//全無é®ç½©" #: src/mainwindow.c:5555 msgid "//Swap A & B" msgstr "//äº¤æ› A & B" #: src/mainwindow.c:5557 msgid "//Edit Colour A & B ..." msgstr "//編輯é¡è‰² A & B…" #: src/mainwindow.c:5559 msgid "//Dither A" msgstr "" #: src/mainwindow.c:5561 msgid "//Palette Editor ..." msgstr "//調色盤編輯器…" #: src/mainwindow.c:5563 msgid "//Set Palette Size ..." msgstr "//設定調色盤大å°â€¦" #: src/mainwindow.c:5564 msgid "//Merge Duplicate Colours" msgstr "//åˆä½µé‡è£½é¡è‰²" #: src/mainwindow.c:5566 msgid "//Remove Unused Colours" msgstr "//移除未使用的é¡è‰²" #: src/mainwindow.c:5569 msgid "//Create Quantized ..." msgstr "//建立é‡åŒ–…" #: src/mainwindow.c:5572 msgid "//Sort Colours ..." msgstr "//排åºé¡è‰²â€¦" #: src/mainwindow.c:5573 msgid "//Palette Shifter ..." msgstr "//調色盤轉移器…" #: src/mainwindow.c:5574 msgid "//Pick Gradient ..." msgstr "" #: src/mainwindow.c:5576 msgid "/Effe_cts" msgstr "/效果(_C)" #: src/mainwindow.c:5578 msgid "//Transform Colour ..." msgstr "//變æ›é¡è‰²â€¦" #: src/mainwindow.c:5580 msgid "//Invert" msgstr "//å相" #: src/mainwindow.c:5582 msgid "//Greyscale" msgstr "//ç°éšŽ" #: src/mainwindow.c:5584 msgid "//Greyscale (Gamma corrected)" msgstr "//ç°éšŽ (γ 值已修正)" #: src/mainwindow.c:5586 msgid "//Normalize" msgstr "" #: src/mainwindow.c:5587 src/mainwindow.c:5658 msgid "//Threshold ..." msgstr "//臨界值…" #: src/mainwindow.c:5588 msgid "//Map ..." msgstr "" #: src/mainwindow.c:5590 msgid "//Isometric Transformation" msgstr "//ç­‰é‡è®Šæ›" #: src/mainwindow.c:5592 msgid "///Left Side Down" msgstr "///å·¦å´å‘下" #: src/mainwindow.c:5593 msgid "///Right Side Down" msgstr "///å³å´å‘下" #: src/mainwindow.c:5594 msgid "///Top Side Right" msgstr "///頂端å‘å³" #: src/mainwindow.c:5595 msgid "///Bottom Side Right" msgstr "///底å´å‘å³" #: src/mainwindow.c:5598 msgid "//Edge Detect ..." msgstr "//é‚Šç·£åµæ¸¬â€¦" #: src/mainwindow.c:5600 msgid "//Difference of Gaussians ..." msgstr "" #: src/mainwindow.c:5602 msgid "//Sharpen ..." msgstr "//銳化…" #: src/mainwindow.c:5604 msgid "//Unsharp Mask ..." msgstr "//去銳化é®ç½©â€¦" #: src/mainwindow.c:5606 msgid "//Soften ..." msgstr "//柔化…" #: src/mainwindow.c:5608 msgid "//Gaussian Blur ..." msgstr "//高斯模糊…" #: src/mainwindow.c:5610 msgid "//Kuwahara-Nagao Blur ..." msgstr "" #: src/mainwindow.c:5612 msgid "//Emboss" msgstr "//浮雕" #: src/mainwindow.c:5614 msgid "//Dilate" msgstr "" #: src/mainwindow.c:5616 msgid "//Erode" msgstr "" #: src/mainwindow.c:5619 msgid "//Solid Noise ..." msgstr "" #: src/mainwindow.c:5620 msgid "//Bacteria ..." msgstr "//èŒåŒ–…" #: src/mainwindow.c:5623 msgid "/Cha_nnels" msgstr "/通é“(_N)" #: src/mainwindow.c:5625 msgid "//New ..." msgstr "//新增…" #: src/mainwindow.c:5628 msgid "//Delete ..." msgstr "//刪除…" #: src/mainwindow.c:5632 msgid "//Edit Image" msgstr "//編輯圖åƒ" #: src/mainwindow.c:5635 msgid "//Edit Alpha" msgstr "//編輯 α" #: src/mainwindow.c:5638 msgid "//Edit Selection" msgstr "//ç·¨è¼¯é¸æ“‡" #: src/mainwindow.c:5641 msgid "//Edit Mask" msgstr "//編輯é®ç½©" #: src/mainwindow.c:5645 msgid "//Hide Image" msgstr "//éš±è—圖åƒ" #: src/mainwindow.c:5648 msgid "//Disable Alpha" msgstr "//åœç”¨ α" #: src/mainwindow.c:5651 msgid "//Disable Selection" msgstr "//åœç”¨é¸æ“‡" #: src/mainwindow.c:5654 msgid "//Disable Mask" msgstr "//åœç”¨é®ç½©" #: src/mainwindow.c:5657 msgid "//Couple RGBA Operations" msgstr "//æŽ¥åˆ RGBA 計算" #: src/mainwindow.c:5659 msgid "//Unassociate Alpha" msgstr "" #: src/mainwindow.c:5663 msgid "//View Alpha as an Overlay" msgstr "//視 α 為外罩" #: src/mainwindow.c:5664 msgid "//Configure Overlays ..." msgstr "//é…置外罩…" #: src/mainwindow.c:5666 msgid "/_Layers" msgstr "/圖層(_L)" #: src/mainwindow.c:5668 msgid "//New Layer" msgstr "" #: src/mainwindow.c:5672 msgid "//Save Composite Image ..." msgstr "//å„²å­˜åˆæˆåœ–åƒâ€¦" #: src/mainwindow.c:5673 msgid "//Composite to New Layer" msgstr "" #: src/mainwindow.c:5674 msgid "//Remove All Layers" msgstr "//移除所有圖層" #: src/mainwindow.c:5676 msgid "//Configure Animation ..." msgstr "//é…置動畫…" #: src/mainwindow.c:5677 msgid "//Preview Animation ..." msgstr "//é è¦½å‹•畫…" #: src/mainwindow.c:5678 msgid "//Set Key Frame ..." msgstr "//è¨­å®šé—œéµæ¡†æž¶â€¦" #: src/mainwindow.c:5679 msgid "//Remove All Key Frames ..." msgstr "//移除所有關éµåœ–框…" #: src/mainwindow.c:5681 msgid "/More..." msgstr "" #: src/mainwindow.c:5683 msgid "/_Help" msgstr "/求助(_H)" #: src/mainwindow.c:5684 msgid "//Documentation" msgstr "//文件" #: src/mainwindow.c:5686 msgid "//About" msgstr "//關於" #: src/mainwindow.c:5689 msgid "//Keyboard Shortcuts ..." msgstr "" #: src/mainwindow.c:5690 msgid "//Rebind Shortcut Keycodes" msgstr "//釿–°é€£çµå¿«æ·éµ" #: src/memory.c:2800 msgid "Quantize Pass 1" msgstr "" #: src/memory.c:2854 msgid "Quantize Pass 2" msgstr "" #: src/memory.c:3073 src/memory.c:3458 msgid "Converting to Indexed Palette" msgstr "轉æ›åˆ°ç´¢å¼•éŽçš„調色盤" #: src/memory.c:5135 src/otherwindow.c:540 msgid "Bacteria Effect" msgstr "èŒåŒ–效果" #: src/memory.c:5170 msgid "Rotating" msgstr "旋轉" #: src/memory.c:5511 msgid "Free Rotation" msgstr "自由旋轉" #: src/memory.c:6096 msgid "Scaling Image" msgstr "伸縮圖åƒ" #: src/memory.c:7560 msgid "Counting Unique RGB Pixels" msgstr "計數唯一的 RGB åƒç´ " #: src/memory.c:7608 msgid "Applying Effect" msgstr "套用效果" #: src/memory.c:8792 msgid "Kuwahara-Nagao Filter" msgstr "" #: src/memory.c:10456 src/otherwindow.c:2665 msgid "Skew" msgstr "" #: src/memory.c:10630 msgid "Segmentation Pass 1" msgstr "" #: src/memory.c:10757 msgid "Segmentation Pass 2" msgstr "" #: src/memory.c:11019 src/otherwindow.c:3156 msgid "Solid Noise" msgstr "" #: src/mygtk.c:134 src/mygtk.c:163 msgid "Please Wait ..." msgstr "è«‹ç¨å¾……" #: src/mygtk.c:141 msgid "STOP" msgstr "åœæ­¢" #: src/mygtk.c:504 msgid "Disabled" msgstr "" #: src/mygtk.c:504 src/toolbar.c:301 msgid "Screen" msgstr "" #: src/mygtk.c:504 msgid "Window" msgstr "" #: src/mygtk.c:508 msgid "Input" msgstr "" #: src/mygtk.c:512 msgid "Device:" msgstr "" #: src/mygtk.c:514 msgid "Mode:" msgstr "" #: src/mygtk.c:519 msgid "Axes" msgstr "" #: src/mygtk.c:524 msgid "X:" msgstr "" #: src/mygtk.c:525 msgid "Y:" msgstr "" #: src/mygtk.c:526 msgid "Pressure:" msgstr "" #: src/mygtk.c:527 msgid "X tilt:" msgstr "" #: src/mygtk.c:528 msgid "Y tilt:" msgstr "" #: src/mygtk.c:529 msgid "Wheel:" msgstr "" #: src/mygtk.c:579 msgid "none" msgstr "" #: src/otherwindow.c:236 msgid "24 bit RGB" msgstr "24 ä½å…ƒ RGB" #: src/otherwindow.c:236 src/otherwindow.c:3179 msgid "Greyscale" msgstr "ç°éšŽ" #: src/otherwindow.c:237 msgid "Indexed Palette" msgstr "索引éŽçš„調色盤" #: src/otherwindow.c:237 msgid "From Clipboard" msgstr "" #: src/otherwindow.c:237 msgid "Grab Screenshot" msgstr "抓å–螢幕快照" #: src/otherwindow.c:242 src/toolbar.c:542 msgid "New Image" msgstr "新增圖åƒ" #: src/otherwindow.c:246 src/otherwindow.c:3164 msgid "Colours" msgstr "é¡è‰²" #: src/otherwindow.c:409 msgid "Pattern Chooser" msgstr "弿¨£é¸æ“‡å™¨" #: src/otherwindow.c:497 msgid "Set Palette Size" msgstr "設定調色盤大å°" #: src/otherwindow.c:517 src/otherwindow.c:591 src/otherwindow.c:870 #: src/otherwindow.c:2538 src/otherwindow.c:2776 src/otherwindow.c:2939 #: src/prefs.c:338 src/prefs.c:538 msgid "Apply" msgstr "套用" #: src/otherwindow.c:573 msgid "Luminance" msgstr "照度" #: src/otherwindow.c:573 src/otherwindow.c:814 msgid "Brightness" msgstr "亮度" #: src/otherwindow.c:574 msgid "Distance to A" msgstr "到 A çš„è·é›¢" #: src/otherwindow.c:575 msgid "Projection to A->B" msgstr "投影到 A->B" #: src/otherwindow.c:576 msgid "Frequency" msgstr "頻率" #: src/otherwindow.c:580 msgid "Sort Palette Colours" msgstr "排åºèª¿è‰²ç›¤é¡è‰²" #: src/otherwindow.c:582 msgid "Start Index" msgstr "開始索引" #: src/otherwindow.c:583 msgid "End Index" msgstr "çµæŸç´¢å¼•" #: src/otherwindow.c:589 msgid "Reverse Order" msgstr "å呿ޒåº" #: src/otherwindow.c:805 msgid "Bitwise" msgstr "" #: src/otherwindow.c:805 msgid "Truncated" msgstr "" #: src/otherwindow.c:805 msgid "Rounded" msgstr "" #: src/otherwindow.c:809 src/toolbar.c:311 src/toolbar.c:558 msgid "Transform Colour" msgstr "變æ›é¡è‰²" #: src/otherwindow.c:812 msgid "Gamma" msgstr "γ 值" #: src/otherwindow.c:816 msgid "Contrast" msgstr "å°æ¯”" #: src/otherwindow.c:822 src/otherwindow.c:1674 msgid "Posterize" msgstr "色調分離" #: src/otherwindow.c:831 msgid "Show Detail" msgstr "顯示細節" #: src/otherwindow.c:836 msgid "Posterize type" msgstr "" #: src/otherwindow.c:857 msgid "Auto-Preview" msgstr "自動é è¦½" #: src/otherwindow.c:869 msgid "Reset" msgstr "é‡ç½®" #: src/otherwindow.c:931 msgid "New geometry is the same as now - nothing to do." msgstr "新的座標ä½ç½®èˆ‡ç¾åœ¨ç›¸åŒ - 無事å¯åšã€‚" #: src/otherwindow.c:980 msgid "The operating system cannot allocate the memory for this operation." msgstr "作業系統無法為此作業é…置記憶體。" #: src/otherwindow.c:982 msgid "" "You have not allocated enough memory in the Preferences window for this " "operation." msgstr "å°æ–¼æ­¤ä½œæ¥­æ‚¨åœ¨å好設定視窗中未é…置足夠的記憶體。" #: src/otherwindow.c:993 src/otherwindow.c:2495 msgid "Mirror" msgstr "é¡åƒ" #: src/otherwindow.c:993 src/otherwindow.c:994 msgid "Tile" msgstr "並排" #: src/otherwindow.c:993 msgid "Void" msgstr "" #: src/otherwindow.c:994 src/shifter.c:283 msgid "Clear" msgstr "清除" #: src/otherwindow.c:994 msgid "Mirror tile" msgstr "é¡åƒä¸¦æŽ’" #: src/otherwindow.c:996 msgid "Nearest Neighbour" msgstr "最近的鄰居" #: src/otherwindow.c:997 msgid "Bilinear / Area Mapping" msgstr "雙線性/å€åŸŸå°æ˜ " #: src/otherwindow.c:998 msgid "Bicubic" msgstr "雙立體" #: src/otherwindow.c:999 msgid "Bicubic edged" msgstr "雙立體邊緣化" #: src/otherwindow.c:1000 msgid "Bicubic better" msgstr "雙立體優化" #: src/otherwindow.c:1001 msgid "Bicubic sharper" msgstr "雙立體銳化" #: src/otherwindow.c:1002 msgid "Blackman-Harris" msgstr "Blackman-Harris" #: src/otherwindow.c:1008 msgid "Scale Canvas" msgstr "伸縮畫布" #: src/otherwindow.c:1009 msgid "Resize Canvas" msgstr "調整畫布大å°" #: src/otherwindow.c:1012 msgid "Original " msgstr "原值 " #: src/otherwindow.c:1013 msgid "New" msgstr "新值" #: src/otherwindow.c:1014 msgid "Width " msgstr "寬度 " #: src/otherwindow.c:1018 msgid "Height " msgstr "高度 " #: src/otherwindow.c:1023 src/otherwindow.c:2514 src/otherwindow.c:2672 #: src/toolbar.c:212 msgid "Offset" msgstr "åç§»" #: src/otherwindow.c:1026 src/otherwindow.c:1615 src/viewer.c:1209 msgid "Centre" msgstr "置中" #: src/otherwindow.c:1033 src/otherwindow.c:1052 msgid "Fix Aspect Ratio" msgstr "修復寬高比" #: src/otherwindow.c:1039 src/otherwindow.c:2070 src/toolbar.c:312 msgid "Settings" msgstr "設定值" #: src/otherwindow.c:1046 msgid "Sharper image reduction" msgstr "" #: src/otherwindow.c:1047 msgid "Boundary extension" msgstr "" #: src/otherwindow.c:1613 src/otherwindow.c:2302 msgid "HSV" msgstr "" #: src/otherwindow.c:1614 msgid "Highlight" msgstr "" #: src/otherwindow.c:1615 msgid "Limit" msgstr "é™åˆ¶" #: src/otherwindow.c:1616 msgid "Sphere" msgstr "çƒé«”" #: src/otherwindow.c:1616 src/otherwindow.c:2670 msgid "Angle" msgstr "角度" #: src/otherwindow.c:1616 msgid "Cube" msgstr "立方體" #: src/otherwindow.c:1617 msgid "Opaque" msgstr "" #: src/otherwindow.c:1617 msgid "Border" msgstr "" #: src/otherwindow.c:1618 msgid "Transparent" msgstr "" #: src/otherwindow.c:1618 msgid "Tile " msgstr "" #: src/otherwindow.c:1618 msgid "Segment" msgstr "" #: src/otherwindow.c:1656 msgid "Scale" msgstr "尺度" #: src/otherwindow.c:1657 src/otherwindow.c:3059 msgid "From" msgstr "從" #: src/otherwindow.c:1659 src/otherwindow.c:3061 msgid "To" msgstr "到" #: src/otherwindow.c:1699 msgid "Range" msgstr "範åœ" #: src/otherwindow.c:1702 msgid "Inverse" msgstr "åå‘" #: src/otherwindow.c:1710 msgid "Smart grid" msgstr "" #: src/otherwindow.c:1712 msgid "Tile grid" msgstr "" #: src/otherwindow.c:1714 msgid "Minimum grid zoom" msgstr "æœ€å°æ ¼ç·šç¸®æ”¾" #: src/otherwindow.c:1717 msgid "Tile width" msgstr "" #: src/otherwindow.c:1720 msgid "Tile height" msgstr "" #: src/otherwindow.c:1744 msgid "Palette Editor" msgstr "調色盤編輯器" #: src/otherwindow.c:1763 msgid "Configure Overlays" msgstr "é…置外罩" #: src/otherwindow.c:1782 msgid "Colour Editor" msgstr "é¡è‰²ç·¨è¼¯å™¨" #: src/otherwindow.c:1818 src/toolbar.c:430 msgid "Colour-Selective Mode" msgstr "é¡è‰²é¸æ“‡æ¨¡å¼" #: src/otherwindow.c:1843 msgid "Configure Grid" msgstr "" #: src/otherwindow.c:2045 msgid "Exact Conversion" msgstr "精確轉æ›" #: src/otherwindow.c:2045 msgid "Use Current Palette" msgstr "使用目å‰èª¿è‰²ç›¤" #: src/otherwindow.c:2046 msgid "PNN Quantize (slow, better quality)" msgstr "" #: src/otherwindow.c:2047 msgid "Wu Quantize (fast)" msgstr "" #: src/otherwindow.c:2048 msgid "Max-Min Quantize (best for small palettes and dithering)" msgstr "" #: src/otherwindow.c:2049 src/otherwindow.c:2495 src/otherwindow.c:2756 #: src/png.c:2794 src/prefs.c:377 msgid "None" msgstr "ç„¡" #: src/otherwindow.c:2049 msgid "Floyd-Steinberg" msgstr "Floyd-Steinberg" #: src/otherwindow.c:2049 msgid "Stucki" msgstr "Stucki" #: src/otherwindow.c:2052 msgid "Floyd-Steinberg (quick)" msgstr "Floyd-Steinberg (快速)" #: src/otherwindow.c:2052 msgid "Dithered (effect)" msgstr "å·²éžè‰² (效果)" #: src/otherwindow.c:2053 msgid "Scattered (effect)" msgstr "已散射 (效果)" #: src/otherwindow.c:2054 msgid "Gamut" msgstr "全音階" #: src/otherwindow.c:2054 msgid "Weakly" msgstr "å¼±" #: src/otherwindow.c:2054 msgid "Strongly" msgstr "å¼·" #: src/otherwindow.c:2055 msgid "Off" msgstr "é—œ" #: src/otherwindow.c:2055 msgid "Separate/Sum" msgstr "分隔/總和" #: src/otherwindow.c:2055 msgid "Separate/Split" msgstr "分隔/拆開" #: src/otherwindow.c:2056 msgid "Length/Sum" msgstr "長度/總和" #: src/otherwindow.c:2056 msgid "Length/Split" msgstr "長度/拆開" #: src/otherwindow.c:2057 msgid "Largest (Linf)" msgstr "最大 (Linf)" #: src/otherwindow.c:2057 msgid "Sum (L1)" msgstr "總和 (L1)" #: src/otherwindow.c:2057 msgid "Euclidean (L2)" msgstr "æ­å¼å¹¾ä½• (L2)" #: src/otherwindow.c:2061 msgid "Create Quantized" msgstr "建立é‡åŒ–" #: src/otherwindow.c:2062 msgid "Convert To Indexed" msgstr "轉æ›åˆ°ç´¢å¼•色" #: src/otherwindow.c:2065 msgid "Indexed Colours To Use" msgstr "所使用的索引色" #: src/otherwindow.c:2078 msgid "Truncate palette" msgstr "" #: src/otherwindow.c:2079 msgid "Diameter based weighting" msgstr "" #: src/otherwindow.c:2084 msgid "Dither" msgstr "éžè‰²" #: src/otherwindow.c:2087 src/otherwindow.c:2584 src/otherwindow.c:2928 msgid "Colour space" msgstr "é¡è‰²ç©ºé–“" #: src/otherwindow.c:2088 src/otherwindow.c:2929 msgid "Difference measure" msgstr "差異測é‡" #: src/otherwindow.c:2089 msgid "Reduce colour bleed" msgstr "減低é¡è‰²æŠ½å–" #: src/otherwindow.c:2090 msgid "Serpentine scan" msgstr "彎曲的掃æ" #: src/otherwindow.c:2092 msgid "Error propagation, %" msgstr "錯誤傳播,%" #: src/otherwindow.c:2093 msgid "Selective error propagation" msgstr "鏿“‡æ€§éŒ¯èª¤å‚³æ’­" #: src/otherwindow.c:2097 msgid "Full error precision" msgstr "" #: src/otherwindow.c:2302 msgid "Backward HSV" msgstr "åå‘ HSV" #: src/otherwindow.c:2303 src/otherwindow.c:2326 msgid "Constant" msgstr "常數" #: src/otherwindow.c:2307 msgid "Edit Gradient" msgstr "編輯漸層" #: src/otherwindow.c:2329 msgid "Points:" msgstr "點數:" #: src/otherwindow.c:2493 msgid "Linear" msgstr "線性" #: src/otherwindow.c:2493 src/otherwindow.c:2703 msgid "Bilinear" msgstr "雙線性" #: src/otherwindow.c:2493 msgid "Radial" msgstr "放射" #: src/otherwindow.c:2494 msgid "Square" msgstr "方形" #: src/otherwindow.c:2494 msgid "Angular" msgstr "" #: src/otherwindow.c:2494 msgid "Conical" msgstr "" #: src/otherwindow.c:2495 msgid "Level " msgstr "" #: src/otherwindow.c:2495 msgid "Repeat" msgstr "é‡è¦†" #: src/otherwindow.c:2496 msgid "A to B" msgstr "A 到 B" #: src/otherwindow.c:2496 msgid "A to B (RGB)" msgstr "A 到 B (RGB)" #: src/otherwindow.c:2497 msgid "A to B (sRGB)" msgstr "" #: src/otherwindow.c:2497 msgid "A to B (HSV)" msgstr "A 到 B (HSV)" #: src/otherwindow.c:2497 msgid "A to B (backward HSV)" msgstr "A 到 B (åå‘ HSV)" #: src/otherwindow.c:2498 msgid "A only" msgstr "åªæœ‰ A" #: src/otherwindow.c:2498 src/otherwindow.c:2500 msgid "Custom" msgstr "自訂" #: src/otherwindow.c:2499 msgid "Current to 0" msgstr "ç›®å‰å€¼åˆ° 0" #: src/otherwindow.c:2499 msgid "Current only" msgstr "åªæœ‰ç›®å‰å€¼" #: src/otherwindow.c:2504 msgid "Configure Gradient" msgstr "é…置漸層" #: src/otherwindow.c:2507 src/png.c:1001 msgid "Channel" msgstr "通é“" #: src/otherwindow.c:2512 msgid "Length" msgstr "長度" #: src/otherwindow.c:2513 msgid "Repeat length" msgstr "é‡è¦†é•·åº¦" #: src/otherwindow.c:2515 msgid "Gradient type" msgstr "漸層類型" #: src/otherwindow.c:2516 msgid "Extension type" msgstr "擴充類型" #: src/otherwindow.c:2517 msgid "Distance type" msgstr "" #: src/otherwindow.c:2518 msgid "Preview opacity" msgstr "é è¦½æ¿åº¦" #: src/otherwindow.c:2527 src/otherwindow.c:2533 src/toolbar.c:309 msgid "Reverse" msgstr "åå‘" #: src/otherwindow.c:2528 src/otherwindow.c:2534 msgid "Edit Custom" msgstr "編輯自訂" #: src/otherwindow.c:2592 msgid "Pick Gradient" msgstr "" #: src/otherwindow.c:2668 msgid "Horizontal " msgstr "" #: src/otherwindow.c:2674 msgid "At distance" msgstr "" #: src/otherwindow.c:2675 msgid "Vertical" msgstr "" #: src/otherwindow.c:2756 msgid "Unchanged" msgstr "" #: src/otherwindow.c:2761 msgid "Tracing Image" msgstr "" #: src/otherwindow.c:2763 src/toolbar.c:315 msgid "Source" msgstr "" #: src/otherwindow.c:2768 msgid "Origin" msgstr "" #: src/otherwindow.c:2771 msgid "Relative scale" msgstr "" #: src/otherwindow.c:2774 msgid "Display" msgstr "" #: src/otherwindow.c:2926 msgid "Segment Image" msgstr "" #: src/otherwindow.c:2931 src/toolbar.c:304 msgid "Threshold" msgstr "" #: src/otherwindow.c:2933 msgid "Level" msgstr "å¹³é¢" #: src/otherwindow.c:2934 msgid "Minimum size" msgstr "" #: src/otherwindow.c:3053 msgid "Max" msgstr "" #: src/otherwindow.c:3053 msgid "Min" msgstr "" #: src/otherwindow.c:3057 msgid "Threshold Image" msgstr "" #: src/otherwindow.c:3158 msgid "Seed" msgstr "" #: src/otherwindow.c:3160 msgid "X span" msgstr "" #: src/otherwindow.c:3161 msgid "Y span" msgstr "" #: src/otherwindow.c:3162 msgid "Octaves" msgstr "" #: src/png.c:620 #, c-format msgid "Saving %s image" msgstr "" #: src/png.c:620 #, c-format msgid "Loading %s image" msgstr "" #: src/png.c:998 msgid "Layer" msgstr "" #: src/png.c:3577 msgid "Lossless" msgstr "" #: src/png.c:3577 msgid "Default" msgstr "" #: src/png.c:3577 msgid "Picture" msgstr "" #: src/png.c:3577 msgid "Photo" msgstr "" #: src/png.c:3578 msgid "Drawing" msgstr "" #: src/png.c:3578 msgid "Icon" msgstr "" #: src/png.c:8370 msgid "Applying colour profile" msgstr "" #: src/png.c:8792 #, c-format msgid "%d out of %d frames could not be saved as %s - saved as PNG instead" msgstr "%2$d 中的 %1$d 張圖框無法儲存為 %3$s - 轉而儲存為 PNG" #: src/png.c:8809 msgid "Explode frames" msgstr "" #: src/prefs.c:56 msgid "Default System Language" msgstr "é è¨­ç³»çµ±èªžè¨€" #: src/prefs.c:57 msgid "Chinese (Simplified)" msgstr "" #: src/prefs.c:57 msgid "Chinese (Taiwanese)" msgstr "中文 (臺ç£)" #: src/prefs.c:57 msgid "Czech" msgstr "æ·å…‹èªž" #: src/prefs.c:58 msgid "Dutch" msgstr "" #: src/prefs.c:58 msgid "English (UK)" msgstr "英語 (英國)" #: src/prefs.c:58 msgid "French" msgstr "法語" #: src/prefs.c:58 msgid "Galician" msgstr "" #: src/prefs.c:58 msgid "German" msgstr "德語" #: src/prefs.c:59 msgid "Hungarian" msgstr "" #: src/prefs.c:59 msgid "Italian" msgstr "" #: src/prefs.c:59 msgid "Japanese" msgstr "" #: src/prefs.c:59 msgid "Kabyle" msgstr "" #: src/prefs.c:59 msgid "Polish" msgstr "波蘭語" #: src/prefs.c:60 msgid "Portuguese" msgstr "è‘¡è„牙語" #: src/prefs.c:60 msgid "Portuguese (Brazilian)" msgstr "è‘¡è„牙語 (巴西)" #: src/prefs.c:60 msgid "Russian" msgstr "" #: src/prefs.c:60 msgid "Slovak" msgstr "斯洛ä¼å…‹èªž" #: src/prefs.c:61 msgid "Spanish" msgstr "西ç­ç‰™èªž" #: src/prefs.c:61 msgid "Swedish" msgstr "" #: src/prefs.c:61 msgid "Tagalog" msgstr "" #: src/prefs.c:61 msgid "Turkish" msgstr "土耳其語" #: src/prefs.c:81 msgid "Current Device" msgstr "ç›®å‰è£ç½®" #: src/prefs.c:135 msgid "Pressure" msgstr "壓力" #: src/prefs.c:149 msgid "Preferences" msgstr "å好設定" #: src/prefs.c:163 msgid "Max threads (0 to autodetect)" msgstr "" #: src/prefs.c:164 msgid "Min kpixels per render thread" msgstr "" #: src/prefs.c:171 msgid "Max memory used for undo (MB)" msgstr "用於復原的最大記憶體 (MB)" #: src/prefs.c:172 msgid "Max undo levels" msgstr "" #: src/prefs.c:173 msgid "Communal layer undo space (%)" msgstr "" #: src/prefs.c:175 msgid "Bayer master pattern" msgstr "" #: src/prefs.c:178 msgid "Use gamma correction by default" msgstr "é è¨­ä½¿ç”¨ γ 修正" #: src/prefs.c:179 msgid "Use gamma correction when painting" msgstr "" #: src/prefs.c:180 msgid "Separate patterns for A & B" msgstr "" #: src/prefs.c:183 msgid "Optimize alpha chequers" msgstr "最佳化 α 審核器" #: src/prefs.c:184 msgid "Disable view window transparencies" msgstr "åœç”¨æª¢è¦–è¦–çª—é€æ˜Žåº¦" #: src/prefs.c:185 msgid "Enable overlays by layer" msgstr "" #: src/prefs.c:189 msgid "Language" msgstr "語言" #: src/prefs.c:191 msgid "" "Select preferred language translation\n" "\n" "You will need to restart mtPaint\n" "for this to take full effect" msgstr "" "é¸å–喜好的語言翻譯\n" "\n" "您需è¦é‡æ–°å•Ÿå‹• mtPaint\n" "以便é”到完全的效果" #: src/prefs.c:198 msgid "Interface" msgstr "" #: src/prefs.c:200 msgid "Greyscale backdrop" msgstr "ç°éšŽèƒŒæ™¯" #: src/prefs.c:201 msgid "Selection nudge pixels" msgstr "鏿“‡å¾®å‹•åƒç´ " #: src/prefs.c:202 msgid "Max Pan Window Size" msgstr "最大全景視窗大å°" #: src/prefs.c:204 msgid "Display clipboard while pasting" msgstr "貼上時顯示剪貼簿" #: src/prefs.c:205 msgid "Mouse cursor = Tool" msgstr "滑鼠游標 = 工具" #: src/prefs.c:206 msgid "Confirm Exit" msgstr "確èªé›¢é–‹" #: src/prefs.c:207 msgid "Q key quits mtPaint" msgstr "Q éµé›¢é–‹ mtPaint" #: src/prefs.c:208 msgid "Arrow keys scroll canvas" msgstr "" #: src/prefs.c:209 msgid "Changing tool commits paste" msgstr "èªå¯è²¼ä¸Šè®Šæ›´å·¥å…·" #: src/prefs.c:210 msgid "Centre tool settings dialogs" msgstr "置中工具設定å°è©±æ¡†" #: src/prefs.c:211 msgid "New image sets zoom to 100%" msgstr "新圖åƒè¨­å®šç¸®æ”¾ç‚º 100%" #: src/prefs.c:212 msgid "Zoom on cursor position" msgstr "" #: src/prefs.c:214 msgid "Mouse Scroll Wheel = Zoom" msgstr "滑鼠æ²å‹•輪 = 縮放" #: src/prefs.c:215 msgid "Use menu icons" msgstr "" #: src/prefs.c:220 msgid "Files" msgstr "檔案" #: src/prefs.c:223 msgid "XBM X hotspot" msgstr "XBM X 熱點" #: src/prefs.c:224 msgid "XBM Y hotspot" msgstr "XBM Y 熱點" #: src/prefs.c:228 msgid "Recently Used Files" msgstr "最近使用的檔案" #: src/prefs.c:229 msgid "Progress bar silence limit" msgstr "進度æ¢éœæ­¢é™åˆ¶" #: src/prefs.c:232 msgid "Read 16-bit TGAs as 5:6:5 BGR" msgstr "" #: src/prefs.c:233 msgid "Write TGAs in bottom-up row order" msgstr "" #: src/prefs.c:234 msgid "Undoable image loading" msgstr "" #: src/prefs.c:245 msgid "Compression (RGB)" msgstr "" #: src/prefs.c:246 msgid "Compression (indexed)" msgstr "" #: src/prefs.c:247 msgid "Compression (monochrome)" msgstr "" #: src/prefs.c:255 msgid "Enable predictor" msgstr "" #: src/prefs.c:262 msgid "Compression mode" msgstr "" #: src/prefs.c:271 msgid "Channel for Mask Plane" msgstr "" #: src/prefs.c:273 msgid "Ignore Transparent Colour" msgstr "" #: src/prefs.c:274 msgid "PackBits Compression" msgstr "" #: src/prefs.c:275 msgid "Write Indexed as Planar Bitmap (PBM)" msgstr "" #: src/prefs.c:280 msgid "Paths" msgstr "" #: src/prefs.c:281 msgid "Clipboard Files" msgstr "剪貼簿檔案" #: src/prefs.c:281 msgid "Select Clipboard File" msgstr "é¸å–剪貼簿檔案" #: src/prefs.c:283 msgid "HTML Browser Program" msgstr "HTML ç€è¦½ç¨‹å¼" #: src/prefs.c:283 msgid "Select Browser Program" msgstr "é¸å–ç€è¦½ç¨‹å¼" #: src/prefs.c:285 msgid "Location of Handbook index" msgstr "手冊索引ä½ç½®" #: src/prefs.c:285 msgid "Select Handbook Index File" msgstr "é¸å–手冊索引檔" #: src/prefs.c:287 msgid "Default Palette" msgstr "" #: src/prefs.c:287 msgid "Select Default Palette" msgstr "" #: src/prefs.c:289 msgid "Default Patterns" msgstr "" #: src/prefs.c:289 msgid "Select Default Patterns File" msgstr "" #: src/prefs.c:292 msgid "Default CSS" msgstr "" #: src/prefs.c:292 msgid "Select Default CSS File" msgstr "" #: src/prefs.c:295 msgid "Default Theme" msgstr "" #: src/prefs.c:295 msgid "Select Default Theme File" msgstr "" #: src/prefs.c:300 msgid "Status Bar" msgstr "狀態列" #: src/prefs.c:301 msgid "Canvas Geometry" msgstr "畫布幾何ä½ç½®" #: src/prefs.c:302 msgid "Cursor X,Y" msgstr "游標 X,Y" #: src/prefs.c:303 msgid "Pixel [I] {RGB}" msgstr "åƒç´  [I] {RGB}" #: src/prefs.c:304 msgid "Selection Geometry" msgstr "鏿“‡å¹¾ä½•ä½ç½®" #: src/prefs.c:305 msgid "Undo / Redo" msgstr "復原/é‡åš" #: src/prefs.c:308 msgid "Tablet" msgstr "繪圖æ¿" #: src/prefs.c:309 msgid "Device Settings" msgstr "è£ç½®è¨­å®šå€¼" #: src/prefs.c:313 msgid "Configure Device" msgstr "é…ç½®è£ç½®" #: src/prefs.c:319 msgid "Tool Variable" msgstr "工具變數" #: src/prefs.c:322 src/toolbar.c:454 msgid "Flow" msgstr "æµæš¢" #: src/prefs.c:330 msgid "Test Area" msgstr "測試å€åŸŸ" #: src/prefs.c:373 msgid "Factor" msgstr "係數" #: src/prefs.c:459 msgid "This key is builtin" msgstr "" #: src/prefs.c:462 #, c-format msgid "" "This key is mapped to:\n" "\"%s\"" msgstr "" #: src/prefs.c:465 msgid "Remap" msgstr "" #: src/prefs.c:510 msgid "Keyboard Shortcuts" msgstr "" #: src/shifter.c:147 msgid "Frames" msgstr "圖框" #: src/shifter.c:258 msgid "Palette Shifter" msgstr "調色盤轉移器" #: src/shifter.c:263 msgid "Start" msgstr "é–‹å§‹" #: src/shifter.c:265 msgid "Finish" msgstr "çµæŸ" #: src/shifter.c:284 msgid "Fix Palette" msgstr "修正調色盤" #: src/spawn.c:651 msgid "Configure File Actions" msgstr "" #: src/spawn.c:657 src/spawn.c:663 msgid "Command" msgstr "" #: src/spawn.c:922 #, c-format msgid "Error %i reported when trying to run %s" msgstr "試著é‹è¡Œ %2$s 時回報錯誤 %1$i" #: src/spawn.c:979 msgid "" "I am unable to find the documentation. Either you need to download the " "mtPaint Handbook from the web site and install it, or you need to set the " "correct location in the Preferences window." msgstr "" "æˆ‘ç„¡æ³•æ‰¾åˆ°æ–‡ä»¶ã€‚è‹¥éžæ‚¨éœ€è¦å¾žç¶²ç«™ä¸‹è¼‰ mtPaint 手冊並安è£å®ƒï¼Œå°±æ˜¯æ‚¨éœ€è¦åœ¨ã€Œå好" "設定ã€è¦–窗中設定正確的ä½ç½®ã€‚" #: src/spawn.c:1018 msgid "" "There was a problem running the HTML browser. You need to set the correct " "program name in the Preferences window." msgstr "" "執行 HTML ç€è¦½å™¨æ™‚發生å•題。您需è¦åœ¨ã€Œå好設定ã€è¦–窗中設定正確的程å¼å稱。" #: src/thread.c:361 msgid "Helper thread is not responding. Save your work and exit the program." msgstr "" #: src/toolbar.c:147 msgid "RGB Cube" msgstr "RGB 立方體" #: src/toolbar.c:148 msgid "By image channel" msgstr "ä¾åœ–åƒé€šé“" #: src/toolbar.c:149 msgid "Gradient-driven" msgstr "å—æ¼¸å±¤é©…使" #: src/toolbar.c:157 msgid "Fill settings" msgstr "填充設定值" #: src/toolbar.c:170 msgid "Respect opacity mode" msgstr "相關æ¿åº¦æ¨¡å¼" #: src/toolbar.c:176 msgid "Smudge settings" msgstr "塗抹設定值" #: src/toolbar.c:215 msgid "Aligned" msgstr "" #: src/toolbar.c:222 msgid "Clone settings" msgstr "" #: src/toolbar.c:228 msgid "By selection channel" msgstr "" #: src/toolbar.c:234 msgid "Lasso settings" msgstr "" #: src/toolbar.c:252 msgid "Brush spacing" msgstr "" #: src/toolbar.c:299 src/toolbar.c:341 msgid "Normal" msgstr "" #: src/toolbar.c:300 msgid "Colour" msgstr "" #: src/toolbar.c:300 msgid "Saturate More" msgstr "" #: src/toolbar.c:301 msgid "Multiply" msgstr "" #: src/toolbar.c:301 msgid "Divide" msgstr "" #: src/toolbar.c:301 msgid "Dodge" msgstr "" #: src/toolbar.c:302 msgid "Burn" msgstr "" #: src/toolbar.c:302 msgid "Hard Light" msgstr "" #: src/toolbar.c:302 msgid "Soft Light" msgstr "" #: src/toolbar.c:302 msgid "Difference" msgstr "" #: src/toolbar.c:303 msgid "Darken" msgstr "" #: src/toolbar.c:303 msgid "Lighten" msgstr "" #: src/toolbar.c:303 msgid "Grain Extract" msgstr "" #: src/toolbar.c:304 msgid "Grain Merge" msgstr "" #: src/toolbar.c:330 msgid "Blend mode" msgstr "" #: src/toolbar.c:417 msgid "Continuous Mode" msgstr "連續模å¼" #: src/toolbar.c:421 msgid "Opacity Mode" msgstr "æ¿åº¦æ¨¡å¼" #: src/toolbar.c:424 msgid "Tint Mode" msgstr "色調模å¼" #: src/toolbar.c:427 msgid "Tint +-" msgstr "色調 +-" #: src/toolbar.c:434 msgid "Blend Mode" msgstr "" #: src/toolbar.c:438 msgid "Disable All Masks" msgstr "åœç”¨å…¨éƒ¨é®ç½©" #: src/toolbar.c:441 msgid "Gradient Mode" msgstr "漸層模å¼" #: src/toolbar.c:486 msgid "Settings Toolbar" msgstr "設定值工具列" #: src/toolbar.c:546 msgid "Cut" msgstr "剪下" #: src/toolbar.c:548 msgid "Copy" msgstr "複製" #: src/toolbar.c:550 msgid "Paste" msgstr "貼上" #: src/toolbar.c:553 msgid "Undo" msgstr "復原" #: src/toolbar.c:555 msgid "Redo" msgstr "é‡åš" #: src/toolbar.c:559 src/viewer.c:328 msgid "Pan Window" msgstr "全景視窗" #: src/toolbar.c:560 src/toolbar.c:640 msgid "More..." msgstr "" #: src/toolbar.c:574 msgid "Paint" msgstr "繪製" #: src/toolbar.c:580 msgid "Shuffle" msgstr "æ¬ç§»" #: src/toolbar.c:583 msgid "Flood Fill" msgstr "å¡«å……" #: src/toolbar.c:587 msgid "Straight Line" msgstr "ç›´ç·š" #: src/toolbar.c:590 msgid "Smudge" msgstr "塗抹" #: src/toolbar.c:594 msgid "Clone" msgstr "仿製" #: src/toolbar.c:597 msgid "Make Selection" msgstr "鏿“‡" #: src/toolbar.c:600 msgid "Polygon Selection" msgstr "å¤šé‚Šå½¢é¸æ“‡" #: src/toolbar.c:603 msgid "Place Gradient" msgstr "放置漸層" #: src/toolbar.c:606 msgid "Lasso Selection" msgstr "å¥—ç´¢é¸æ“‡" #: src/toolbar.c:614 msgid "Ellipse Outline" msgstr "橢圓æé‚Š" #: src/toolbar.c:617 msgid "Filled Ellipse" msgstr "填滿的橢圓" #: src/toolbar.c:620 msgid "Outline Selection" msgstr "æé‚Šé¸æ“‡å€åŸŸ" #: src/toolbar.c:623 msgid "Fill Selection" msgstr "填充鏿“‡å€åŸŸ" #: src/toolbar.c:627 msgid "Flip Selection Vertically" msgstr "åž‚ç›´ç¿»è½‰é¸æ“‡å€åŸŸ" #: src/toolbar.c:630 msgid "Flip Selection Horizontally" msgstr "æ°´å¹³ç¿»è½‰é¸æ“‡å€åŸŸ" #: src/toolbar.c:633 msgid "Rotate Selection Clockwise" msgstr "é †æ™‚é‡æ—‹è½‰é¸æ“‡å€åŸŸ" #: src/toolbar.c:636 msgid "Rotate Selection Anti-Clockwise" msgstr "é€†æ™‚é‡æ—‹è½‰é¸æ“‡å€åŸŸ" #: src/vcode.c:5201 msgid "Browse" msgstr "ç€è¦½" #: src/vcode.c:7886 msgid "New key ..." msgstr "" #: src/vcode.c:9909 #, c-format msgid "'%s' does not match any widget" msgstr "" #: src/vcode.c:9910 #, c-format msgid "'%s' value does not fit '%s' widget" msgstr "" #: src/viewer.c:115 msgid "About" msgstr "關於" #: src/viewer.c:1179 msgid "No font selected" msgstr "" #: src/viewer.c:1209 msgid "Left" msgstr "" #: src/viewer.c:1209 msgid "Right" msgstr "" #~ msgid "Create GIF frames" #~ msgstr "建立 GIF 圖框" #~ msgid "File: %s invalid - palette not updated" #~ msgstr "檔案:%s 無效 - 調色盤未更新" #~ msgid "Distance to A+B" #~ msgstr "到 A+B çš„è·é›¢" #~ msgid "Edit Frames" #~ msgstr "編輯圖框" #~ msgid " C Command Line Window" #~ msgstr " C 命令列視窗" #~ msgid "The palette does not contain enough colours to do a merge" #~ msgstr "調色盤ä¸åŒ…å«è¶³å¤ çš„é¡è‰²ä¾†åšåˆä½µ" #~ msgid "There are too many identical palette items to be reduced." #~ msgstr "有太多相åŒçš„調色盤項目å¯ä»¥ä¾†ç¸®å°ã€‚" #~ msgid "/View/Command Line Window" #~ msgstr "/檢視(V)/命令列視窗" #~ msgid "Grid colour RGB" #~ msgstr "格線é¡è‰² RGB" #~ msgid "Zoom" #~ msgstr "縮放" #~ msgid "%i Files on Command Line" #~ msgstr "%i 個檔案在命令列上" #~ msgid "Not enough memory to rotate image" #~ msgstr "æ—‹è½‰åœ–åƒæ‰€éœ€è¨˜æ†¶é«”ä¸è¶³" #~ msgid "Not enough memory to rotate clipboard" #~ msgstr "旋轉剪貼簿所需記憶體ä¸è¶³" #~ msgid "File is too big, must be <= to width=%i height=%i : %s" #~ msgstr "檔案太大,必須是 <= 寬度=%i 高度=%i:%s" #~ msgid "" #~ "Dennis Lee - Wrote the two quantizing methods DL1 & 3 - see quantizer.c " #~ "for more information." #~ msgstr "" #~ "Dennis Lee - 編寫兩個é‡åŒ–方法 DL1 & 3 - åƒçœ‹ quantizer.c 以ç²å¾—更多資訊。" #~ msgid "Magnus Hjorth - Wrote inifile.c/h, from mhWaveEdit 1.3.0." #~ msgstr "Magnus Hjorth - 編寫 inifile.c/h,來自 mhWaveEdit 1.3.0." #~ msgid "Could not open %s: %s" #~ msgstr "無法開啟 %s:%s" #~ msgid "Error closing %s: %s" #~ msgstr "關閉 %s 時發生錯誤:%s" #~ msgid "Could not write to %s: %s" #~ msgstr "無法寫入 %s:%s" #~ msgid "patterns_user.c could not be opened in current directory" #~ msgstr "patterns_user.c 無法在目å‰çš„目錄中開啟" #~ msgid "Done" #~ msgstr "已完æˆ" #~ msgid "patterns_user.c created in current directory" #~ msgstr "patterns_user.c 建立在目å‰çš„目錄中" #~ msgid "Current image is not 94x94x3 so I cannot create patterns_user.c" #~ msgstr "ç›®å‰åœ–åƒä¸¦éž 94x94x3 因而我無法建立 patterns_user.c" #~ msgid "" #~ "You are trying to save an RGB image to an XPM file which is not " #~ "possible. I would suggest you save with a PNG extension." #~ msgstr "" #~ "您正試著儲存 RGB 圖åƒåˆ° XPM 檔案,而這並ä¸å¯èƒ½ã€‚我會建議您儲存為 PNG 延伸" #~ "æ ¼å¼ã€‚" #~ msgid "" #~ "You are trying to save an RGB image to a GIF file which is not possible. " #~ "I would suggest you save with a PNG extension." #~ msgstr "" #~ "您正試著儲存 RGB 圖åƒåˆ° GIF 檔案,而這並ä¸å¯èƒ½ã€‚我會建議您儲存為 PNG 延伸" #~ "æ ¼å¼ã€‚" #~ msgid "" #~ "You are trying to save an XBM file with a palette of more than 2 " #~ "colours. Either use another format or reduce the palette to 2 colours." #~ msgstr "" #~ "您正試著儲存 XBM æª”æ¡ˆï¼Œå®ƒçš„èª¿è‰²ç›¤æœ‰è¶…éŽ 2 種é¡è‰²ã€‚è‹¥éžä½¿ç”¨å…¶ä»–æ ¼å¼ï¼Œå°±ç¸®å°" #~ "調色æ¿åˆ° 2 種é¡è‰²ã€‚" #~ msgid "" #~ "You are trying to save an indexed canvas to a JPEG file which is not " #~ "possible. I would suggest you save with a PNG extension." #~ msgstr "" #~ "您正試著儲存索引éŽçš„畫布為 JPEG 檔案,而這並ä¸å¯èƒ½ã€‚ 我會建議您儲存為 PNG " #~ "延伸格å¼ã€‚" #~ msgid "" #~ "You are trying to save an LSS16 file with a palette of more than 16 " #~ "colours. Either use another format or reduce the palette to 16 colours." #~ msgstr "" #~ "您正試著儲存 LSS16 æª”æ¡ˆï¼Œå®ƒçš„èª¿è‰²ç›¤æœ‰è¶…éŽ 16 種é¡è‰²ã€‚è‹¥éžä½¿ç”¨å…¶ä»–æ ¼å¼ï¼Œå°±" #~ "縮å°èª¿è‰²ç›¤åˆ° 16 種é¡è‰²ã€‚" #~ msgid "/Edit/Create Patterns" #~ msgstr "/編輯(E)/å»ºç«‹å¼æ¨£" #~ msgid "/View/Toggle Image View (Home)" #~ msgstr "/檢視(V)/切æ›åœ–åƒæª¢è¦– (個人資料夾)" #~ msgid "/Palette/Create Quantized (DL1)" #~ msgstr "/調色盤(P)/建立é‡åŒ– (DL1)" #~ msgid "/Palette/Create Quantized (DL3)" #~ msgstr "/調色盤(P)/建立é‡åŒ– (DL3)" #~ msgid "/Palette/Create Quantized (Wu)" #~ msgstr "/調色盤(P)/建立é‡åŒ– (Wu)" #~ msgid "/File/%i" #~ msgstr "/檔案(F)/%i" #~ msgid "Lanczos3" #~ msgstr "Lanczos3" #~ msgid "DL1 Quantize (fastest)" #~ msgstr "DL1 é‡åŒ– (最快)" #~ msgid "DL3 Quantize (very slow, better quality)" #~ msgstr "DL3 é‡åŒ– (很慢,較好å“質)" #~ msgid "Wu Quantize (best method for small palettes)" #~ msgstr "Wu é‡åŒ– (用於å°èª¿è‰²ç›¤çš„æœ€å¥½æ–¹æ³•)" #~ msgid "Loading PNG image" #~ msgstr "載入 PNG 圖åƒ" #~ msgid "Loading clipboard image" #~ msgstr "載入剪貼簿圖åƒ" #~ msgid "Saving PNG image" #~ msgstr "儲存 PNG 圖åƒ" #~ msgid "Saving Clipboard image" #~ msgstr "儲存剪貼簿圖åƒ" #~ msgid "Saving Layer image" #~ msgstr "儲存圖層圖åƒ" #~ msgid "Saving Channel image" #~ msgstr "儲存通é“圖åƒ" #~ msgid "Loading GIF image" #~ msgstr "載入 GIF 圖åƒ" #~ msgid "Saving GIF image" #~ msgstr "儲存 GIF 圖åƒ" #~ msgid "Loading JPEG image" #~ msgstr "載入 JPEG 圖åƒ" #~ msgid "Saving JPEG image" #~ msgstr "儲存 JPEG 圖åƒ" #~ msgid "Loading TIFF image" #~ msgstr "載入 TIFF 圖åƒ" #~ msgid "Saving TIFF image" #~ msgstr "儲存 TIFF 圖åƒ" #~ msgid "Loading BMP image" #~ msgstr "載入 BMP 圖åƒ" #~ msgid "Saving BMP image" #~ msgstr "儲存 BMP 圖åƒ" #~ msgid "Loading XPM image" #~ msgstr "載入 XPM 圖åƒ" #~ msgid "Saving XPM image" #~ msgstr "儲存 XPM 圖åƒ" #~ msgid "Loading XBM image" #~ msgstr "載入 XBM 圖åƒ" #~ msgid "Saving XBM image" #~ msgstr "儲存 XBM 圖åƒ" #~ msgid "Loading LSS16 image" #~ msgstr "載入 LSS16 圖åƒ" #~ msgid "Saving LSS16 image" #~ msgstr "儲存 LSS16 圖åƒ" #~ msgid "Saving UNDO images" #~ msgstr "儲存復原圖åƒ" #~ msgid "JPEG Save Quality (100=High) " #~ msgstr "JPEG 儲存å“質 (100=高) " mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/000077500000000000000000000000001471325446300207425ustar00rootroot00000000000000mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/Makefile000066400000000000000000000012741471325446300224060ustar00rootroot00000000000000include ../_conf.txt # Generate identical object files if possible CFLAGS = $(CFLAG) $(SET_RANDSEED) LDFLAGS = $(LDFLAG) BIN = mtpaint$(EXEEXT) OBJS = main.o mainwindow.o inifile.o png.o memory.o canvas.o otherwindow.o mygtk.o\ viewer.o polygon.o layer.o info.o wu.o prefs.o ani.o mtlib.o\ toolbar.o channels.o csel.o shifter.o spawn.o font.o fpick.o icons.o\ cpick.o thread.o vcode.o $(BIN): $(OBJS) $(CC) $(OBJS) -o $(BIN) $(LDFLAGS) $(OBJS): *.h graphics/* .c.o: $(CC) $(CFLAGS) -c -o $*.o $*.c clean: rm -f *.o $(BIN)* $(LIBNAME) $(LIBNAME2) $(SLIBNAME) install: mkdir -p $(DESTDIR)$(BIN_INSTALL) cp $(BIN) $(DESTDIR)$(BIN_INSTALL) uninstall: rm $(DESTDIR)$(BIN_INSTALL)/$(BIN) mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/ani.c000066400000000000000000000720241471325446300216620ustar00rootroot00000000000000/* ani.c Copyright (C) 2005-2021 Mark Tyler and Dmitry Groshev This file is part of mtPaint. mtPaint 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. mtPaint 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 mtPaint in the file COPYING. */ #include #include #include #include "global.h" #undef _ #define _(X) X #include "mygtk.h" #include "memory.h" #include "vcode.h" #include "ani.h" #include "png.h" #include "mainwindow.h" #include "otherwindow.h" #include "canvas.h" #include "viewer.h" #include "layer.h" #include "spawn.h" #include "inifile.h" #include "mtlib.h" #include "wu.h" typedef struct { int frame1, frame2; int nlayer, lnum, layer; int ftype, ftypes[NUM_FTYPES]; int lock; char *pos, *cyc; // text buffers char **ftnames; void **posw, **cycw; void **save, **preview, **frames; } anim_dd; typedef struct { void **awin; int fix; int frame[3]; void **fslider; } apview_dd; /// GLOBALS int ani_state; int ani_frame1 = 1, ani_frame2 = 1, ani_gif_delay = 10; static int ani_play_state, ani_timer_state; /// FORM VARIABLES ani_cycle ani_cycle_table[MAX_CYC_SLOTS]; static char ani_output_path[PATHBUF], ani_file_prefix[ANI_PREFIX_LEN+2]; static int ani_format; static void ani_win_read_widgets(void **wdata); static void ani_widget_changed(anim_dd *dt) // Widget changed so flag the layers as changed { if (!dt->lock) layers_changed = 1; } static void set_layer_from_slot( int layer, int slot ) // Set layer x, y, opacity from slot { ani_slot *ani = layer_table[layer].image->ani_.pos + slot; layer_table[layer].x = ani->x; layer_table[layer].y = ani->y; layer_table[layer].opacity = ani->opacity; } static void set_layer_inbetween( int layer, int i, int frame, int effect ) // Calculate in between value for layer from slot i & (i+1) at given frame { MT_Coor c[4], co_res, lenz; float p1, p2; int f0, f1, f2, f3, ii[4] = {i-1, i, i+1, i+2}, j; ani_slot *ani = layer_table[layer].image->ani_.pos; f1 = ani[i].frame; f2 = ani[i + 1].frame; if (i > 0) f0 = ani[i - 1].frame; else { f0 = f1; ii[0] = ii[1]; } if ((i >= MAX_POS_SLOTS - 2) || !(f3 = ani[i + 2].frame)) { f3 = f2; ii[3] = ii[2]; } // Linear in between p1 = ( (float) (f2-frame) ) / ( (float) (f2-f1) ); // % of (i-1) slot p2 = 1-p1; // % of i slot layer_table[layer].x = rint(p1 * ani[i].x + p2 * ani[i + 1].x); layer_table[layer].y = rint(p1 * ani[i].y + p2 * ani[i + 1].y); layer_table[layer].opacity = rint(p1 * ani[i].opacity + p2 * ani[i + 1].opacity); if ( effect == 1 ) // Interpolated smooth in between - use p2 value { for ( i=0; i<4; i++ ) c[i].z = 0; // Unused plane lenz.x = f1 - f0; lenz.y = f2 - f1; // Frames for each line lenz.z = f3 - f2; if ( lenz.x<1 ) lenz.x = 1; if ( lenz.y<1 ) lenz.y = 1; if ( lenz.z<1 ) lenz.z = 1; // Set up coords for ( j=0; j<4; j++ ) { c[j].x = ani[ii[j]].x; c[j].y = ani[ii[j]].y; } co_res = MT_palin(p2, 0.35, c[0], c[1], c[2], c[3], lenz); layer_table[layer].x = co_res.x; layer_table[layer].y = co_res.y; } } static void ani_set_frame_state(int frame) { int i, j, k, v, c, f, p; ani_slot *ani; ani_cycle *cc; unsigned char *cp; // !!! Maybe make background x/y settable here too? for (k = 1; k <= layers_total; k++) { /* Set x, y, opacity for layer */ ani = layer_table[k].image->ani_.pos; /* Find first frame in position list that excedes or equals 'frame' */ for (i = 0; i < MAX_POS_SLOTS; i++) { /* End of list */ if (ani[i].frame <= 0) break; /* Exact match or one exceding it found */ if (ani[i].frame >= frame) break; } /* If no slots have been defined * leave the layer x, y, opacity as now */ if (ani[0].frame <= 0); /* All position slots < 'frame' * Set layer pos/opac to last slot values */ else if ((i >= MAX_POS_SLOTS) || !ani[i].frame) set_layer_from_slot(k, i - 1); /* If closest frame = requested frame, set all values to this * ditto if i=0, i.e. no better matches exist */ else if ((ani[i].frame == frame) || !i) set_layer_from_slot(k, i); /* i is currently pointing to slot that excedes 'frame', * so in between this and the previous slot */ else set_layer_inbetween(k, i - 1, frame, ani[i - 1].effect); /* Set visibility for layer by processing cycle table */ /* !!! Table must be sorted by cycle # */ v = -1; // Leave alone by default cp = layer_table[k].image->ani_.cycles; for (i = c = 0; i < MAX_CYC_ITEMS; i++ , c = j) { if (!(j = *cp++)) break; // Cycle # + 1 p = *cp++; cc = ani_cycle_table + j - 1; if (!(f = cc->frame0)) continue; // Paranoia if (f > frame) continue; // Not yet active /* Special case for enabling/disabling en-masse */ if (cc->frame1 == f) { if (j != c) v = !p; // Ignore entries after 1st } /* Inside a normal cycle */ else if (cc->frame1 >= frame) { if (j != c) v = 0; // Hide initially v |= (frame - f) % cc->len == p; // Show if matched } } if (v >= 0) layer_table[k].visible = v; } } #define ANI_CYC_ROWLEN (MAX_CYC_ITEMS * 2 + 1) #define ANI_CYC_TEXT_MAX (128 + MAX_CYC_ITEMS * 10) /* Convert cycle header & layers list to text */ static void ani_cyc_sprintf(char *txt, ani_cycle *chead, unsigned char *cdata) { int j, l, b; char *tmp = txt + sprintf(txt, "%i\t%i\t", chead->frame0, chead->frame1); l = *cdata++; if (!l); // Empty group else if (chead->frame0 == chead->frame1) // Batch toggle group { while (TRUE) { tmp += sprintf(tmp, "%s%i", cdata[0] ? "-" : "", cdata[1]); if (--l <= 0) break; *tmp++ = ','; cdata += 2; } } else // Regular cycle { b = -1; while (TRUE) { j = cdata[0] - b; while (--j > 0) *tmp++ = '0' , *tmp++ = ','; b = cdata[0]; if (--l <= 0) break; if ((cdata[2] == b) && (j >= 0)) *tmp++ = '('; tmp += sprintf(tmp, "%i%s,", cdata[1], (cdata[2] != b) && (j < 0) ? ")" : ""); cdata += 2; } tmp += sprintf(tmp, "%i%s", cdata[1], j < 0 ? ")" : ""); j = chead->len - cdata[0]; while (--j > 0) *tmp++ = ',' , *tmp++ = '0'; } strcpy(tmp, "\n"); } /* Parse text into cycle header & layers list */ static int ani_cyc_sscanf(char *txt, ani_cycle *chead, unsigned char *cdata) { char *tail; unsigned char *cntp; int j, l, f, f0, f1, b; while (*txt && (*txt < 32)) txt++; // Skip non ascii chars if (!*txt) return (FALSE); f0 = f1 = -1; // Default state if invalid l = 0; sscanf(txt, "%i\t%i\t%n", &f0, &f1, &l); chead->frame0 = f0; chead->frame1 = f1; chead->len = *cdata = 0; if (!l) return (TRUE); // Invalid cycle is a cycle still txt += l; cntp = cdata++; f = b = 0; while (cdata - cntp < ANI_CYC_ROWLEN) { while (*txt && (*txt <= 32)) txt++; // Skip whitespace etc if (*txt == '(') { b = 1; txt++; while (*txt && (*txt <= 32)) txt++; // Skip whitespace etc } j = strtol(txt, &tail, 0); if (tail - txt <= 0) break; // No number there if (f0 == f1) if ((f = j < 0)) j = -j; // Batch toggle group if ((j < 0) || (j > MAX_LAYERS)) j = 0; // Out of range *cdata++ = f; // Position *cdata++ = j; // Layer cntp[0]++; txt = tail; while (*txt && (*txt <= 32)) txt++; // Skip whitespace etc if (*txt == ')') { b = 0; txt++; while (*txt && (*txt <= 32)) txt++; // Skip whitespace etc } if (*txt++ != ',') break; // Stop if no comma f += 1 - b; } if (*cntp) chead->len = *(cdata - 2) + 1; return (TRUE); } static int cmp_frames(const void *f1, const void *f2) { int n = (int)((unsigned char *)f1)[0] - ((unsigned char *)f2)[0]; return (n ? n : (int)((unsigned char *)f1)[1] - ((unsigned char *)f2)[1]); } /* Assemble cycles info from per-layer lists into per-cycle ones */ static void ani_cyc_get(unsigned char *buf) { unsigned char *ptr, *cycles; int i, j, k, l; memset(buf, 0, MAX_CYC_SLOTS * ANI_CYC_ROWLEN); // Clear buf -= ANI_CYC_ROWLEN; // 1-based for (i = 1; i <= layers_total; i++) { cycles = layer_table[i].image->ani_.cycles; for (j = 0; j < MAX_CYC_ITEMS; j++) { if (!(k = *cycles++)) break; // Cycle # + 1 l = *cycles++; // Position if ((k > MAX_CYC_SLOTS) || (l >= MAX_CYC_ITEMS)) continue; ptr = buf + ANI_CYC_ROWLEN * k; if (ptr[0] >= MAX_CYC_ITEMS) continue; k = ptr[0]++; ptr += k * 2 + 1; ptr[0] = l; // Position ptr[1] = i; // Layer } } for (i = 1; i <= MAX_CYC_SLOTS; i++) // Sort by position & layer { ptr = buf + ANI_CYC_ROWLEN * i; if (*ptr > 1) qsort(ptr + 1, *ptr, 2, cmp_frames); } } /* Distribute out cycles info from per-cycle to per-layer lists */ static void ani_cyc_put(unsigned char *buf) { unsigned char *ptr, *cycles; int i, j, k, l, cnt[MAX_LAYERS + 1]; memset(cnt, 0, sizeof(cnt)); // Clear buf -= ANI_CYC_ROWLEN; // 1-based for (i = 1; i <= MAX_CYC_SLOTS; i++) { ptr = buf + ANI_CYC_ROWLEN * i; j = *ptr++; while (j-- > 0) { l = *ptr++; // Position k = *ptr++; // Layer if (!k || (k > layers_total)) continue; if (cnt[k] >= MAX_CYC_ITEMS) continue; cycles = layer_table[k].image->ani_.cycles + cnt[k]++ * 2; cycles[0] = i; // Cycle # + 1 cycles[1] = l; // Position } } for (i = 0; i <= layers_total; i++) // Mark end of list if (cnt[i] < MAX_CYC_ITEMS) layer_table[i].image->ani_.cycles[cnt[i] * 2] = 0; } #define ANI_POS_TEXT_MAX 256 static void ani_pos_sprintf(char *txt, ani_slot *ani) { sprintf(txt, "%i\t%i\t%i\t%i\t%i\n", ani->frame, ani->x, ani->y, ani->opacity, ani->effect); } static int ani_pos_sscanf(char *txt, ani_slot *ani) { ani_slot data = { -1, -1, -1, -1, -1 }; while (*txt && (*txt < 32)) txt++; // Skip non ascii chars if (!*txt) return (FALSE); // !!! Ignoring parse errors sscanf(txt, "%i\t%i\t%i\t%i\t%i", &data.frame, &data.x, &data.y, &data.opacity, &data.effect); *ani = data; return (TRUE); } static void ani_read_layer_data() // Save current layer state { memcpy(layer_table_p = layer_table + (MAX_LAYERS + 1), layer_table, (MAX_LAYERS + 1) * sizeof(layer_table[0])); } static void ani_write_layer_data(int final) // Restore layer state { memcpy(layer_table, layer_table_p, (MAX_LAYERS + 1) * sizeof(layer_table[0])); if (final) layer_table_p = layer_table; } static char *ani_cyc_txt() // Text for the cycle text widget { memx2 mem; char txt[ANI_CYC_TEXT_MAX]; unsigned char buf[MAX_CYC_SLOTS * ANI_CYC_ROWLEN]; int i; memset(&mem, 0, sizeof(mem)); ani_cyc_get(buf); for (i = 0; i < MAX_CYC_SLOTS; i++) { if (!ani_cycle_table[i].frame0) break; ani_cyc_sprintf(txt, ani_cycle_table + i, buf + ANI_CYC_ROWLEN * i); addstr(&mem, txt, 1); } return (mem.buf); } static char *ani_pos_txt(int idx) // Text for the position text widget { memx2 mem; char txt[ANI_POS_TEXT_MAX]; int j; ani_slot *ani; memset(&mem, 0, sizeof(mem)); if (idx <= 0) return ""; // Must no be for background layer or negative => PANIC! for (j = 0; j < MAX_POS_SLOTS; j++) { ani = layer_table[idx].image->ani_.pos + j; if (ani->frame <= 0) break; // Add a line if one exists ani_pos_sprintf(txt, ani); addstr(&mem, txt, 1); } return (mem.buf); } void ani_init() // Initialize variables/arrays etc. before loading or on startup { int j; ani_frame1 = 1; ani_frame2 = 100; ani_gif_delay = 10; for (j = 0; j <= layers_total; j++) memset(&layer_table[j].image->ani_, 0, sizeof(ani_info)); memset(ani_cycle_table, 0, sizeof(ani_cycle_table)); strcpy(ani_output_path, "frames"); strcpy(ani_file_prefix, "f"); ani_format = FT_GIF; } /// EXPORT ANIMATION FRAMES WINDOW static void create_frames_ani(); static void ani_btn(anim_dd *dt, void **wdata, int what, void **where) { ani_win_read_widgets(wdata); ani_write_layer_data(what == op_EVT_CANCEL); if (what == op_EVT_CANCEL) { run_destroy(wdata); ani_state = ANI_NONE; update_stuff(UPD_ALLV); return; } where = origin_slot(where); if (where == dt->preview) ani_but_preview(wdata); else if (where == dt->frames) { cmd_showhide(GET_WINDOW(wdata), FALSE); create_frames_ani(); cmd_showhide(GET_WINDOW(wdata), TRUE); } else layer_press_save(); // "Save" } /* Read current positions in text input and store */ static void ani_parse_store_positions(char *tx, int layer) { char *txt, *tmp; ani_slot *ani = layer_table[layer].image->ani_.pos; int i; tmp = tx; for (i = 0; i < MAX_POS_SLOTS; i++) { if (!(txt = tmp)) break; tmp = strchr(txt, '\n'); if (tmp) *tmp++ = '\0'; if (!ani_pos_sscanf(txt, ani + i)) break; } if (i < MAX_POS_SLOTS) ani[i].frame = 0; // End delimeter } /* Read current cycles in text input and store */ static void ani_parse_store_cycles(char *tx) { unsigned char buf[MAX_CYC_SLOTS * ANI_CYC_ROWLEN]; char *txt, *tmp; int i; tmp = tx; memset(buf, 0, sizeof(buf)); for (i = 0; i < MAX_CYC_SLOTS; i++) { if (!(txt = tmp)) break; tmp = strchr(txt, '\n'); if (tmp) *tmp++ = '\0'; if (!ani_cyc_sscanf(txt, ani_cycle_table + i, buf + ANI_CYC_ROWLEN * i)) break; } if (i < MAX_CYC_SLOTS) ani_cycle_table[i].frame0 = 0; // End delimeter ani_cyc_put(buf); } static void ani_win_read_widgets(void **wdata) // Read all widgets and set up relevant variables { anim_dd *dt = GET_DDATA(wdata); char *tmp; int a, b; run_query(wdata); ani_parse_store_positions(dt->pos, dt->layer); ani_parse_store_cycles(dt->cyc); /* Update 2 text widgets */ dt->lock = TRUE; cmd_setv(dt->posw, tmp = ani_pos_txt(dt->layer), 0); free(tmp); cmd_setv(dt->cycw, tmp = ani_cyc_txt(), 0); free(tmp); dt->lock = FALSE; a = dt->frame1; b = dt->frame2; ani_frame1 = a < b ? a : b; ani_frame2 = a < b ? b : a; ani_format = dt->ftypes[dt->ftype]; } static gboolean ani_play_timer_call(gpointer data) { if (!ani_play_state) { ani_timer_state = 0; return FALSE; // Stop animating } else { apview_dd *dt = data; int i; cmd_read(dt->fslider, dt); i = dt->frame[0] + 1; if (i > dt->frame[2]) i = dt->frame[1]; cmd_set(dt->fslider, i); return TRUE; } } /// PREVIEW WINDOW CALLBACKS static void ani_frame_slider_moved(apview_dd *dt, void **wdata, int what, void **where) { image_info *image = !layer_selected ? &mem_image : &layer_table[0].image->image_; cmd_read(where, dt); ani_set_frame_state(dt->frame[0]); // Update only view window lr_update_area(LR_ANIM, 0, 0, image->width, image->height); } static void ani_play_btn(apview_dd *dt, void **wdata, int what, void **where) { if (what == op_EVT_CANCEL) { void **awin = dt->awin; // for after run_destroy() ani_play_state = FALSE; // Stop animation playing if necessary run_destroy(wdata); if (awin) cmd_showhide(GET_WINDOW(awin), TRUE); else { ani_write_layer_data(TRUE); ani_state = ANI_NONE; update_stuff(UPD_ALLV); } } else if (what == op_EVT_CHANGE) // Play toggle { cmd_read(where, dt); if (ani_play_state && !ani_timer_state) // Start timer ani_timer_state = threads_timeout_add(ani_gif_delay * 10, ani_play_timer_call, dt); } else /* if (what == op_EVT_CLICK) */ // Fix { ani_read_layer_data(); layers_notify_changed(); update_stuff(UPD_RENDER); } } #define WBbase apview_dd static void *apview_code[] = { WPWHEREVER, WINDOWm(_("Animation Preview")), WXYWH("ani_prev", 200, 0), HBOXB, // !!! Originally the window was that way, and had no vbox UTOGGLEv(_("Play"), ani_play_state, ani_play_btn), BORDER(SPINSLIDE, 0), REF(fslider), MINWIDTH(200), XSPINSLIDEa(frame), EVENT(CHANGE, ani_frame_slider_moved), TRIGGER, IF(fix), UBUTTON(_("Fix"), ani_play_btn), UCANCELBTN(_("Close"), ani_play_btn), WSHOW }; #undef WBbase void ani_but_preview(void **awin) { apview_dd tdata = { awin, !awin, { ani_frame1, ani_frame1, ani_frame2 } }; ani_read_layer_data(); view_show(); // Ensure the view window is shown ani_play_state = FALSE; // Stopped if (awin) cmd_showhide(GET_WINDOW(awin), FALSE); else { ani_state = ANI_PLAY; update_stuff(UPD_ALLV); } run_create(apview_code, &tdata, sizeof(tdata)); } static void create_frames_ani() { image_info *image; ls_settings settings; png_color pngpal[256], *trans; unsigned char *layer_rgb, *irgb; char output_path[PATHBUF], *command, *wild_path; int a, b, k, i, tr, cols, layer_w, layer_h, npt, l = 0; layer_press_save(); // Save layers data file if (path_type(ani_output_path) == PT_REL) { command = strrchr(layers_filename, DIR_SEP); if (command) l = command - layers_filename + 1; } wjstrcat(output_path, PATHBUF, layers_filename, l, ani_output_path, NULL); l = strlen(output_path); if (!ani_output_path[0]); // Reusing layers file directory #ifdef WIN32 else if (mkdir(output_path)) #else else if (mkdir(output_path, 0777)) #endif { if ( errno != EEXIST ) { alert_box(_("Error"), _("Unable to create output directory"), NULL); return; // Failure to create directory } } // Create output path and pointer for first char of filename a = ani_frame1 < ani_frame2 ? ani_frame1 : ani_frame2; b = ani_frame1 < ani_frame2 ? ani_frame2 : ani_frame1; image = layer_selected ? &layer_table[0].image->image_ : &mem_image; layer_w = image->width; layer_h = image->height; layer_rgb = malloc(layer_w * layer_h * 4); // Primary layer image for RGB version if (!layer_rgb) { memory_errors(1); return; } irgb = layer_rgb + layer_w * layer_h * 3; // For indexed or alpha /* Prepare settings */ init_ls_settings(&settings, NULL); settings.mode = FS_COMPOSITE_SAVE; settings.width = layer_w; settings.height = layer_h; settings.colors = 256; settings.silent = TRUE; settings.ftype = ani_format; /* Indexed */ if (!(file_formats[ani_format].flags & FF_RGB)) { settings.img[CHN_IMAGE] = irgb; settings.bpp = 1; settings.pal = pngpal; } /* RGB */ else { if (!comp_need_alpha(ani_format)) irgb = NULL; settings.img[CHN_IMAGE] = layer_rgb; settings.img[CHN_ALPHA] = irgb; settings.bpp = 3; /* Background transparency */ settings.xpm_trans = tr = image->trans; settings.rgb_trans = tr < 0 ? -1 : PNG_2_INT(image->pal[tr]); } progress_init(_("Creating Animation Frames"), 1); for ( k=a; k<=b; k++ ) // Create each frame and save it as a PNG or GIF image { if (progress_update(b == a ? 0.0 : (k - a) / (float)(b - a))) break; ani_set_frame_state(k); // Change layer positions memset(layer_rgb, 0, layer_w * layer_h * 4); // Init for RGBA compositing view_render_rgb( layer_rgb, 0, 0, layer_w, layer_h, 1 ); // Render layer snprintf(output_path + l, PATHBUF - l, DIR_SEP_STR "%s%05d.%s", ani_file_prefix, k, file_formats[ani_format].ext); if (settings.bpp == 1) // Prepare palette { cols = mem_cols_used_real(layer_rgb, layer_w, layer_h, pngpal); // Count & collect colours in image if (cols > 256) // If >256 use Wu to quantize { cols = 256; if (wu_quant(layer_rgb, layer_w, layer_h, cols, pngpal)) goto failure2; // No memory // Create new indexed image (cannot fail if no dither) mem_dumb_dither(layer_rgb, irgb, pngpal, layer_w, layer_h, cols, FALSE); } // Create new indexed image (cannot fail w/ exact palette) else mem_convert_indexed(irgb, layer_rgb, layer_w * layer_h, cols, pngpal); settings.xpm_trans = -1; // Default is no transparency if (image->trans >= 0) // Background has transparency { trans = image->pal + image->trans; npt = PNG_2_INT(*trans); for (i = 0; i < cols; i++) { // Does it exist in the composite frame? if (PNG_2_INT(pngpal[i]) != npt) continue; // Transparency found so note it settings.xpm_trans = i; break; } } } else if (irgb) { collect_alpha(irgb, layer_w, layer_h); mem_demultiply(layer_rgb, irgb, layer_w * layer_h, 3); } if (save_image(output_path, &settings) < 0) { alert_box(_("Error"), _("Unable to save image"), NULL); goto failure2; } } /* all GIF files created OK so lets give them to gifsicle */ if (ani_format == FT_GIF) { wild_path = wjstrcat(NULL, 0, output_path, l, DIR_SEP_STR, ani_file_prefix, "?????.gif", NULL); snprintf(output_path + l, PATHBUF - l, DIR_SEP_STR "%s.gif", ani_file_prefix); if (!run_def_action(DA_GIF_CREATE, wild_path, output_path, ani_gif_delay) && !cmd_mode) /* Don't launch GUI from commandline */ run_def_action(DA_GIF_PLAY, output_path, NULL, 0); free(wild_path); } failure2: progress_end(); free( layer_rgb ); } void pressed_remove_key_frames() { int i, j; i = alert_box(_("Warning"), _("Do you really want to clear all of the position and cycle data for all of the layers?"), _("No"), _("Yes"), NULL); if ( i==2 ) { for (j = 0; j <= layers_total; j++) memset(&layer_table[j].image->ani_, 0, sizeof(ani_info)); memset(ani_cycle_table, 0, sizeof(ani_cycle_table)); } } static void ani_set_key_frame(int key) // Set key frame postions & cycles as per current layers { unsigned char buf[MAX_CYC_SLOTS * ANI_CYC_ROWLEN]; unsigned char *cp; ani_slot *ani; ani_cycle *cc; int i, j, k, l; // !!! Maybe make background x/y settable here too? for ( k=1; k<=layers_total; k++ ) // Add current position for each layer { ani = layer_table[k].image->ani_.pos; // Find first occurence of 0 or frame # < 'key' for ( i=0; i key || ani[i].frame == 0) break; } if ( i>=MAX_POS_SLOTS ) i=MAX_POS_SLOTS-1; // Shift remaining data down a slot for ( j=MAX_POS_SLOTS-1; j>i; j-- ) { ani[j] = ani[j - 1]; } // Enter data for the current state ani[i].frame = key; ani[i].x = layer_table[k].x; ani[i].y = layer_table[k].y; ani[i].opacity = layer_table[k].opacity; ani[i].effect = 0; // No effect } // Find first occurence of 0 or frame # < 'key' for ( i=0; i key || ani_cycle_table[i].frame0 == 0 ) break; } if ( i>=MAX_CYC_SLOTS ) i=MAX_CYC_SLOTS-1; // Shift remaining data down a slot l = MAX_CYC_SLOTS - 1 - i; ani_cyc_get(buf); cp = buf + ANI_CYC_ROWLEN * i; memmove(cp + ANI_CYC_ROWLEN, cp, l * ANI_CYC_ROWLEN); cc = ani_cycle_table + i; memmove(cc + 1, cc, l * sizeof(ani_cycle)); // Enter data for the current state l = layers_total; if (l > MAX_CYC_ITEMS) l = MAX_CYC_ITEMS; cc->frame0 = cc->frame1 = key; cc->len = *cp++ = l; for (j = 1; j <= l; j++) { *cp++ = !layer_table[j].visible; // Position *cp++ = j; // Layer } // Write back ani_cyc_put(buf); } static void ani_layer_select(anim_dd *dt, void **wdata, int what, void **where) { char *tmp; int j; cmd_read(where, dt); // !!! Allow background here when/if added to the list (no +1 then) j = dt->nlayer + 1; if (j != dt->layer) // If switching out of layer { cmd_read(dt->posw, dt); // Parse & store text inputs ani_parse_store_positions(dt->pos, dt->layer); } dt->layer = j; /* Refresh the text in the widget */ dt->lock = TRUE; cmd_setv(dt->posw, tmp = ani_pos_txt(j), 0); free(tmp); dt->lock = FALSE; } static int do_set_key_frame(spin1_dd *dt, void **wdata) { run_query(wdata); ani_set_key_frame(dt->n[0]); layers_notify_changed(); return (TRUE); } void pressed_set_key_frame() { spin1_dd tdata = { { _("Set Key Frame"), spin1_code, FW_FN(do_set_key_frame) }, { ani_frame1, ani_frame1, ani_frame2 } }; run_create(filterwindow_code, &tdata, sizeof(tdata)); } #define WBbase anim_dd static void *anim_code[] = { WPWHEREVER, WINDOWm(_("Configure Animation")), WXYWH("ani", 200, 200), NBOOK, PAGE(_("Output Files")), BORDER(TABLE, 0), BORDER(ENTRY, 0), BORDER(PATH, 0), XTABLE(2, 6), TSPIN(_("Start frame"), frame1, 1, MAX_FRAME), EVENT(CHANGE, ani_widget_changed), TSPIN(_("End frame"), frame2, 1, MAX_FRAME), EVENT(CHANGE, ani_widget_changed), TSPINv(_("Delay"), ani_gif_delay, 1, MAX_DELAY), EVENT(CHANGE, ani_widget_changed), TPATHv(_("Output path"), _("Select Directory"), FS_SELECT_DIR, ani_output_path), EVENT(CHANGE, ani_widget_changed), TPENTRYv(_("File prefix"), ani_file_prefix, ANI_PREFIX_LEN), EVENT(CHANGE, ani_widget_changed), TOPTDe(_("File Format"), ftnames, ftype, ani_widget_changed), WDONE, // XTABLE WDONE, /// LAYERS TABLES PAGE(_("Positions")), XHBOX, // !!! Originally the page was an hbox BORDER(SCROLL, 0), SCROLL(0, 1), // never/auto WLIST, // !!! Maybe allow background here too, for x/y? (set base=0 here then) IDXCOLUMN(1, 1, 40, 1), // center TXTCOLUMNv(layer_table[1].name, sizeof(layer_table[1]), 0, 0), // left WIDTH(150), LISTCCr(nlayer, lnum, ani_layer_select), TRIGGER, XVBOX, // !!! what for? REF(posw), TEXT(pos), EVENT(CHANGE, ani_widget_changed), WDONE, WDONE, WDONE, /// CYCLES TAB PAGE(_("Cycling")), REF(cycw), TEXT(cyc), EVENT(CHANGE, ani_widget_changed), WDONE, WDONE, /* NBOOK */ /// MAIN BUTTONS // !!! Maybe better make buttons equal, with EQBOX HBOX, CANCELBTN(_("Close"), ani_btn), REF(save), BUTTON(_("Save"), ani_btn), REF(preview), BUTTON(_("Preview"), ani_btn), REF(frames), BUTTON(_("Create Frames"), ani_btn), WDONE, WSHOW }; #undef WBbase void pressed_animate_window() { char *names[NUM_FTYPES + 1]; anim_dd tdata; if ( layers_total < 1 ) // Only background layer available { alert_box(_("Error"), _("You must have at least 2 layers to create an animation"), NULL); return; } if (!layers_filename[0]) { alert_box(_("Error"), _("You must save your layers file before creating an animation"), NULL); return; } delete_layers_window(); // Lose the layers window if its up ani_read_layer_data(); memset(&tdata, 0, sizeof(tdata)); tdata.frame1 = ani_frame1; tdata.frame2 = ani_frame2; tdata.cyc = ani_cyc_txt(); // !!! Maybe allow background here too, for x/y? (set base=0 here then) tdata.lnum = layers_total; tdata.nlayer = layers_total - 1; // last layer in list tdata.layer = layers_total; // regular index of same tdata.ftype = ftype_selector(FF_256 | FF_RGB, "", ani_format, tdata.ftnames = names, tdata.ftypes); run_create(anim_code, &tdata, sizeof(tdata)); free(tdata.cyc); ani_state = ANI_CONF; update_stuff(UPD_ALLV); } /// FILE HANDLING void ani_read_file( FILE *fp ) // Read data from layers file already opened { unsigned char buf[MAX_CYC_SLOTS * ANI_CYC_ROWLEN]; char tin[2048]; int i, j, k, tot; ani_init(); do { if (!fgets(tin, 2000, fp)) return; // BAILOUT - invalid line string_chop( tin ); } while ( strcmp( tin, ANIMATION_HEADER ) != 0 ); // Look for animation header i = read_file_num(fp, tin); if ( i<0 ) return; // BAILOUT - invalid # ani_frame1 = i; i = read_file_num(fp, tin); if ( i<0 ) return; // BAILOUT - invalid # ani_frame2 = i; if (!fgets(tin, 2000, fp)) return; // BAILOUT - invalid line string_chop( tin ); strncpy0(ani_output_path, tin, PATHBUF); if (!fgets(tin, 2000, fp)) return; // BAILOUT - invalid # string_chop( tin ); strncpy0(ani_file_prefix, tin, ANI_PREFIX_LEN + 1); i = read_file_num(fp, tin); if ( i<0 ) { ani_format = FT_PNG; ani_gif_delay = -i; } else { ani_format = FT_GIF; ani_gif_delay = i; } /// CYCLE DATA i = read_file_num(fp, tin); if ( i<0 || i>MAX_CYC_SLOTS ) return; // BAILOUT - invalid # tot = i; memset(buf, 0, sizeof(buf)); for ( j=0; jMAX_POS_SLOTS ) return; // BAILOUT - invalid # tot = i; for ( j=0; jani_.pos + j); } if ( jani_.pos[j].frame = 0; // Mark end } } void ani_write_file( FILE *fp ) // Write data to layers file already opened { char txt[ANI_CYC_TEXT_MAX]; unsigned char buf[MAX_CYC_SLOTS * ANI_CYC_ROWLEN]; int gifcode = ani_gif_delay, i, j, k; if ( layers_total == 0 ) return; // No layers memory allocated so bail out if (ani_format != FT_GIF) gifcode = -gifcode; // HEADER fprintf( fp, "%s\n", ANIMATION_HEADER ); fprintf( fp, "%i\n%i\n%s\n%s\n%i\n", ani_frame1, ani_frame2, ani_output_path, ani_file_prefix, gifcode ); // CYCLE INFO // Count number of cycles, and output this data (if any) for ( i=0; iani_.pos; for ( i=0; i 127 #error "Layer indices cannot fit in ani_cycle structure" #endif typedef struct { int frame0, frame1, len; } ani_cycle; typedef struct { int frame, x, y, opacity, effect; } ani_slot; /* !!! cycles[] must be kept sorted by cycle */ typedef struct { ani_slot pos[MAX_POS_SLOTS]; unsigned char cycles[MAX_CYC_ITEMS * 2]; } ani_info; enum { ANI_NONE = 0, ANI_PLAY, ANI_CONF }; int ani_state; int ani_frame1, ani_frame2, ani_gif_delay; ani_cycle ani_cycle_table[MAX_CYC_SLOTS]; void ani_init(); // Initialize variables/arrays etc. void pressed_animate_window(); void pressed_set_key_frame(); void pressed_remove_key_frames(); void ani_read_file( FILE *fp ); // Read data from layers file already opened void ani_write_file( FILE *fp ); // Write data to layers file already opened void ani_but_preview(void **awin); // Preview the animation mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/canvas.c000066400000000000000000002674261471325446300224020ustar00rootroot00000000000000/* canvas.c Copyright (C) 2004-2024 Mark Tyler and Dmitry Groshev This file is part of mtPaint. mtPaint 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. mtPaint 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 mtPaint in the file COPYING. */ #include "global.h" #undef _ #define _(X) X #include "mygtk.h" #include "memory.h" #include "vcode.h" #include "ani.h" #include "png.h" #include "mainwindow.h" #include "otherwindow.h" #include "inifile.h" #include "canvas.h" #include "viewer.h" #include "layer.h" #include "polygon.h" #include "wu.h" #include "prefs.h" #include "spawn.h" #include "channels.h" #include "toolbar.h" #include "font.h" float can_zoom = 1; // Zoom factor 1..MAX_ZOOM int margin_main_xy[2]; // Top left of image from top left of canvas int margin_view_xy[2]; int marq_status = MARQUEE_NONE, marq_xy[4] = { -1, -1, -1, -1 }; // Selection marquee int marq_drag_x, marq_drag_y; // Marquee dragging offset int line_status = LINE_NONE, line_xy[4]; // Line tool int poly_status = POLY_NONE; // Polygon selection tool int clone_status, clone_x, clone_y, clone_dx, clone_dy; // Clone tool state int clone_mode = TRUE, clone_x0 = -1, clone_y0 = -1, // Clone settings clone_dx0, clone_dy0; int recent_files; // Current recent files setting char *recent_filenames[MAX_RECENT]; // Recent filenames themselves int show_paste, // Show contents of clipboard while pasting col_reverse, // Painting with right button status_on[STATUS_ITEMS], // Show status bar items? text_paste, // Are we pasting text? canvas_image_centre, // Are we centering the image? chequers_optimize, // Are we optimizing the chequers for speed? cursor_zoom // Are we zooming at cursor position? ; int brush_spacing; // Step in non-continuous mode; 0 means use event coords int lasso_sel; // Lasso by selection channel (just trim it) if present int preserved_gif_delay = 10, undo_load; static int update_later; /// STATUS BAR void **label_bar[STATUS_ITEMS]; static void update_image_bar() { char txt[128], txt2[16], *tmp = cspnames[CSPACE_RGB]; if (!status_on[STATUS_GEOMETRY]) return; if (mem_img_bpp == 1) sprintf(tmp = txt2, "%i", mem_cols); tmp = txt + snprintf(txt, 80, "%s %i x %i x %s", channames[mem_channel], mem_width, mem_height, tmp); if ( mem_img[CHN_ALPHA] || mem_img[CHN_SEL] || mem_img[CHN_MASK] ) { strcpy(tmp, " + "); tmp += 3; if (mem_img[CHN_ALPHA]) *tmp++ = 'A'; if (mem_img[CHN_SEL]) *tmp++ = 'S'; if (mem_img[CHN_MASK]) *tmp++ = 'M'; // !!! String not NUL-terminated at this point } if ( layers_total>0 ) tmp += sprintf(tmp, " (%i/%i)", layer_selected, layers_total); if ( mem_xpm_trans>=0 ) tmp += sprintf(tmp, " (T=%i)", mem_xpm_trans); strcpy(tmp, " "); cmd_setv(label_bar[STATUS_GEOMETRY], txt, LABEL_VALUE); } void update_sel_bar(int now) // Update selection stats on status bar { char txt[64] = ""; int rect[4]; float lang, llen; grad_info *grad = gradient + mem_channel; if (!status_on[STATUS_SELEGEOM]) return; update_later |= CF_SELBAR; if (script_cmds && !now) return; update_later &= ~CF_SELBAR; if ((((tool_type == TOOL_SELECT) || (tool_type == TOOL_POLYGON)) && (marq_status > MARQUEE_NONE)) || ((tool_type == TOOL_GRADIENT) && (grad->status != GRAD_NONE)) || ((tool_type == TOOL_LINE) && (line_status != LINE_NONE))) { if (tool_type == TOOL_GRADIENT) { copy4(rect, grad->xy); rect[2] -= rect[0]; rect[3] -= rect[1]; lang = (180.0 / M_PI) * atan2(rect[2], -rect[3]); } else if (tool_type == TOOL_LINE) { copy4(rect, line_xy); rect[2] -= rect[0]; rect[3] -= rect[1]; lang = (180.0 / M_PI) * atan2(rect[2], -rect[3]); } else { marquee_at(rect); lang = (180.0 / M_PI) * atan2(marq_x2 - marq_x1, marq_y1 - marq_y2); } llen = sqrt(rect[2] * rect[2] + rect[3] * rect[3]); snprintf(txt, 60, " %i,%i : %i x %i %.1f' %.1f\"", rect[0], rect[1], rect[2], rect[3], lang, llen); } else if (tool_type == TOOL_POLYGON) { snprintf(txt, 60, " (%i)%c", poly_points, poly_status != POLY_DONE ? '+' : '\0'); } cmd_setv(label_bar[STATUS_SELEGEOM], txt, LABEL_VALUE); } static char *chan_txt_cat(char *txt, int chan, int x, int y) { if (!mem_img[chan]) return (txt); return (txt + sprintf(txt, "%i", mem_img[chan][x + mem_width*y])); } void update_xy_bar(int x, int y) { char txt[96], *tmp = txt; int pixel; if (status_on[STATUS_CURSORXY]) { snprintf(txt, 60, "%i,%i", x, y); cmd_setv(label_bar[STATUS_CURSORXY], txt, LABEL_VALUE); } if (!status_on[STATUS_PIXELRGB]) return; *tmp = '\0'; if ((x >= 0) && (x < mem_width) && (y >= 0) && (y < mem_height)) { pixel = get_pixel_img(x, y); if (mem_img_bpp == 1) tmp += sprintf(tmp, "[%u] = {%i,%i,%i}", pixel, mem_pal[pixel].red, mem_pal[pixel].green, mem_pal[pixel].blue); else tmp += sprintf(tmp, "{%i,%i,%i}", INT_2_R(pixel), INT_2_G(pixel), INT_2_B(pixel)); if (mem_img[CHN_ALPHA] || mem_img[CHN_SEL] || mem_img[CHN_MASK]) { strcpy(tmp, " + {"); tmp += 4; tmp = chan_txt_cat(tmp, CHN_ALPHA, x, y); *tmp++ = ','; tmp = chan_txt_cat(tmp, CHN_SEL, x, y); *tmp++ = ','; tmp = chan_txt_cat(tmp, CHN_MASK, x, y); strcpy(tmp, "}"); } } cmd_setv(label_bar[STATUS_PIXELRGB], txt, LABEL_VALUE); } static void update_undo_bar() { char txt[32]; if (status_on[STATUS_UNDOREDO]) { sprintf(txt, "%i+%i", mem_undo_done, mem_undo_redo); cmd_setv(label_bar[STATUS_UNDOREDO], txt, LABEL_VALUE); } } void init_status_bar() { int i; for (i = 0; i < STATUS_ITEMS; i++) cmd_showhide(label_bar[i], status_on[i]); update_image_bar(); update_undo_bar(); } void commit_paste(int swap, int *update) { image_info ti; unsigned char *image, *xbuf, *mask, *alpha = NULL; unsigned char *old_image, *old_alpha; int op = 255, opacity = tool_opacity, bpp = MEM_BPP; int fx, fy, fw, fh, fx2, fy2; // Screen coords int i, ua, cmask, ofs, iofs, upd = UPD_IMGP, fail = TRUE; fx = marq_x1 > 0 ? marq_x1 : 0; fy = marq_y1 > 0 ? marq_y1 : 0; fx2 = marq_x2 < mem_width ? marq_x2 : mem_width - 1; fy2 = marq_y2 < mem_height ? marq_y2 : mem_height - 1; fw = fx2 - fx + 1; fh = fy2 - fy + 1; mask = multialloc(MA_SKIP_ZEROSIZE, &mask, fw, &alpha, ((mem_channel == CHN_IMAGE) && RGBA_mode && mem_img[CHN_ALPHA] && !mem_clip_alpha && !channel_dis[CHN_ALPHA]) * fw, &xbuf, NEED_XBUF_PASTE * fw * bpp, NULL); if (!mask) goto quit; // Not enough memory if (alpha) memset(alpha, channel_col_A[CHN_ALPHA], fw); /* Ignore clipboard alpha if disabled */ ua = channel_dis[CHN_ALPHA] | !mem_clip_alpha; if (swap) /* Prepare to convert image contents into new clipboard */ { cmask = CMASK_IMAGE | CMASK_SEL; if ((mem_channel == CHN_IMAGE) && mem_img[CHN_ALPHA] && !channel_dis[CHN_ALPHA]) cmask |= CMASK_ALPHA; if (!mem_alloc_image(AI_CLEAR | AI_NOINIT, &ti, fw, fh, MEM_BPP, cmask, NULL)) goto quit; copy_area(&ti, &mem_image, fx, fy); } /* Offset in memory */ ofs = (fy - marq_y1) * mem_clip_w + (fx - marq_x1); image = mem_clipboard + ofs * mem_clip_bpp; iofs = fy * mem_width + fx; mem_undo_next(UNDO_PASTE); // Do memory stuff for undo old_image = mem_img[mem_channel]; old_alpha = mem_img[CHN_ALPHA]; if (mem_undo_opacity) { old_image = mem_undo_previous(mem_channel); old_alpha = mem_undo_previous(CHN_ALPHA); } if (IS_INDEXED) op = opacity = 0; for (i = 0; i < fh; i++) { unsigned char *wa = ua ? alpha : mem_clip_alpha + ofs; unsigned char *wm = mem_clip_mask ? mem_clip_mask + ofs : NULL; unsigned char *img = image; row_protected(fx, fy + i, fw, mask); if (swap) { unsigned char *ws = ti.img[CHN_SEL] + i * fw; memcpy(ws, mask, fw); process_mask(0, 1, fw, ws, NULL, NULL, ti.img[CHN_ALPHA] ? NULL : wa, wm, op, 0); } process_mask(0, 1, fw, mask, mem_img[CHN_ALPHA] && wa ? mem_img[CHN_ALPHA] + iofs : NULL, old_alpha + iofs, wa, wm, opacity, 0); if (mem_clip_bpp < bpp) { /* Convert paletted clipboard to RGB */ do_convert_rgb(0, 1, fw, xbuf, img, mem_clip_paletted ? mem_clip_pal : mem_pal); img = xbuf; } process_img(0, 1, fw, mask, mem_img[mem_channel] + iofs * bpp, old_image + iofs * bpp, img, xbuf, bpp, 0); image += mem_clip_w * mem_clip_bpp; ofs += mem_clip_w; iofs += mem_width; } if (swap) { if ((fw - mem_clip_w) | (fh - mem_clip_h)) upd |= UPD_CGEOM & ~UPD_IMGMASK; /* Remove new mask if it's all 255 */ if (is_filled(ti.img[CHN_SEL], 255, fw * fh)) { free(ti.img[CHN_SEL]); ti.img[CHN_SEL] = NULL; } mem_clip_new(fw, fh, MEM_BPP, 0, NULL); memcpy(mem_clip.img, ti.img, sizeof(chanlist)); // !!! marq_x2, marq_y2 will be set by update_stuff() mem_clip_x = marq_x1 = fx; mem_clip_y = marq_y1 = fy; } fail = FALSE; quit: free(mask); if (fail) memory_errors(1); /* Warn and not update */ else if (!update) /* Update right now */ { update_stuff(upd); lr_update_area(layer_selected, fx, fy, fw, fh); } else /* Accumulate update area for later */ { /* !!! Swap does not use this branch, and isn't supported here */ fw += fx; fh += fy; if (fx < update[0]) update[0] = fx; if (fy < update[1]) update[1] = fy; if (fw > update[2]) update[2] = fw; if (fh > update[3]) update[3] = fh; } } void iso_trans(int mode) { int i = mem_isometrics(mode); if (!i) update_stuff(UPD_GEOM); else if (i == -5) alert_box(_("Error"), _("The image is too large to transform."), NULL); else memory_errors(i); } void pressed_inv(int what) { spot_undo(UNDO_INV); if (what == FILT_INVERT) mem_invert(); else mem_normalize(); mem_undo_prepare(); update_stuff(UPD_COL); } static int map_from, map_to; typedef struct { filterwindow_dd fw; int noclip; } map_dd; static int do_map(map_dd *dt, void **wdata) { unsigned char map[768]; run_query(wdata); spot_undo(UNDO_FILT); mem_prepare_map(map, map_from + MAP_GRAD); mem_remap_rgb(map, map_to); mem_undo_prepare(); return TRUE; } static char *map_from_txt[3] = { _("Gradient"), _("Palette"), _("Clipboard") }; static char *map_to_txt[4] = { _("Value"), _("Red"), _("Green"), _("Blue") }; #define WBbase map_dd static void *map_code[] = { TABLE2(2), TLABEL(_("From ")), UNLESS(noclip), TLOPTv(map_from_txt, 3, map_from, 1, 0), IF(noclip), TLOPTv(map_from_txt, 2, map_from, 1, 0), ALTNAME(""), // default TOPTv(_("To "), map_to_txt, 4, map_to), WDONE, RET }; #undef WBbase void pressed_map() { map_dd tdata = { { _("Map"), map_code, FW_FN(do_map) }, !mem_clipboard }; run_create_(filterwindow_code, &tdata, sizeof(tdata), script_cmds); } static int edge_mode; static int do_edge(filterwindow_dd *dt, void **wdata) { static const unsigned char fxmap[] = { FX_EDGE, FX_SOBEL, FX_PREWITT, FX_KIRSCH, FX_GRADIENT, FX_ROBERTS, FX_LAPLACE, FX_MORPHEDGE }; run_query(wdata); spot_undo(UNDO_FILT); do_effect(fxmap[edge_mode], 0); mem_undo_prepare(); return TRUE; } static char *fnames_txt[] = { _("MT"), _("Sobel"), _("Prewitt"), _("Kirsch"), _("Gradient"), _("Roberts"), _("Laplace"), _("Morphological"), NULL }; #define WBbase filterwindow_dd static void *edge_code[] = { BORDER(RPACK, 0), RPACKv(fnames_txt, 0, 4, edge_mode), RET }; #undef WBbase void pressed_edge_detect() { static filterwindow_dd tdata = { _("Edge Detect"), edge_code, FW_FN(do_edge) }; run_create_(filterwindow_code, &tdata, sizeof(tdata), script_cmds); } typedef struct { spin1_dd s1; int fx; } spin1f_dd; static int do_fx(spin1f_dd *dt, void **wdata) { run_query(wdata); spot_undo(UNDO_FILT); do_effect(dt->fx, dt->s1.n[0]); mem_undo_prepare(); return TRUE; } void pressed_sharpen() { static spin1f_dd tdata = { { { _("Edge Sharpen"), spin1_code, FW_FN(do_fx) }, { 50, 1, 100 } }, FX_SHARPEN }; run_create_(filterwindow_code, &tdata, sizeof(tdata), script_cmds); } void pressed_soften() { static spin1f_dd tdata = { { { _("Edge Soften"), spin1_code, FW_FN(do_fx) }, { 50, 1, 100 } }, FX_SOFTEN }; run_create_(filterwindow_code, &tdata, sizeof(tdata), script_cmds); } void pressed_fx(int what) { spot_undo(UNDO_FILT); do_effect(what, 0); mem_undo_prepare(); update_stuff(UPD_IMG); } typedef struct { filterwindow_dd fw; int rgb; int x, y, xy, gamma; void **yspin; } gauss_dd; static int do_gauss(gauss_dd *dt, void **wdata) { int radiusX, radiusY, gcor = FALSE; run_query(wdata); if (mem_channel == CHN_IMAGE) gcor = dt->gamma; radiusX = radiusY = dt->x; if (dt->xy) radiusY = dt->y; spot_undo(UNDO_DRAW); mem_gauss(radiusX * 0.01, radiusY * 0.01, gcor); mem_undo_prepare(); return TRUE; } static void gauss_xy_click(gauss_dd *dt, void **wdata, int what, void **where) { cmd_read(where, dt); cmd_sensitive(dt->yspin, dt->xy); } #define WBbase gauss_dd static void *gauss_code[] = { VBOXPS, BORDER(SPIN, 0), FSPIN(x, 0, 20000), ALTNAME("X"), REF(yspin), FSPIN(y, 0, 20000), INSENS, OPNAME("Y"), CHECK(_("Different X/Y"), xy), EVENT(CHANGE, gauss_xy_click), IF(rgb), CHECK(_("Gamma corrected"), gamma), WDONE, RET }; #undef WBbase void pressed_gauss() { gauss_dd tdata = { { _("Gaussian Blur"), gauss_code, FW_FN(do_gauss) }, mem_channel == CHN_IMAGE, 100, 100, FALSE, use_gamma }; run_create_(filterwindow_code, &tdata, sizeof(tdata), script_cmds); } typedef struct { filterwindow_dd fw; int rgb; int radius, amount, threshold, gamma; } unsharp_dd; static int do_unsharp(unsharp_dd *dt, void **wdata) { run_query(wdata); // !!! No RGBA mode for now, so UNDO_DRAW isn't needed spot_undo(UNDO_FILT); mem_unsharp(dt->radius * 0.01, dt->amount * 0.01, dt->threshold, (mem_channel == CHN_IMAGE) && dt->gamma); mem_undo_prepare(); return TRUE; } #define WBbase unsharp_dd static void *unsharp_code[] = { VBOXPS, BORDER(TABLE, 0), TABLE2(3), OPNAME0, TFSPIN(_("Radius"), radius, 0, 20000), TFSPIN(_("Amount"), amount, 0, 1000), TSPIN(_("Threshold "), threshold, 0, 255), WDONE, IF(rgb), CHECK(_("Gamma corrected"), gamma), WDONE, RET }; #undef WBbase void pressed_unsharp() { unsharp_dd tdata = { { _("Unsharp Mask"), unsharp_code, FW_FN(do_unsharp) }, mem_channel == CHN_IMAGE, 500, 50, 0, use_gamma }; run_create_(filterwindow_code, &tdata, sizeof(tdata), script_cmds); } typedef struct { filterwindow_dd fw; int rgb; int outer, inner, norm, gamma; } dog_dd; static int do_dog(dog_dd *dt, void **wdata) { run_query(wdata); if (dt->outer <= dt->inner) return (FALSE); /* Invalid parameters */ spot_undo(UNDO_FILT); mem_dog(dt->outer * 0.01, dt->inner * 0.01, dt->norm, (mem_channel == CHN_IMAGE) && dt->gamma); mem_undo_prepare(); return TRUE; } #define WBbase dog_dd static void *dog_code[] = { VBOXPS, BORDER(TABLE, 0), TABLE2(2), OPNAME0, TFSPIN(_("Outer radius"), outer, 0, 20000), TFSPIN(_("Inner radius"), inner, 0, 20000), WDONE, CHECK(_("Normalize"), norm), IF(rgb), CHECK(_("Gamma corrected"), gamma), WDONE, RET }; #undef WBbase void pressed_dog() { dog_dd tdata = { { _("Difference of Gaussians"), dog_code, FW_FN(do_dog) }, mem_channel == CHN_IMAGE, 300, 100, TRUE, use_gamma }; run_create_(filterwindow_code, &tdata, sizeof(tdata), script_cmds); } typedef struct { filterwindow_dd fw; int r, detail, gamma; } kuw_dd; static int do_kuwahara(kuw_dd *dt, void **wdata) { run_query(wdata); spot_undo(UNDO_COL); // Always processes RGB image channel mem_kuwahara(dt->r, dt->gamma, dt->detail); mem_undo_prepare(); return (TRUE); } #define WBbase kuw_dd static void *kuw_code[] = { VBOXPS, BORDER(SPIN, 0), SPIN(r, 1, 127), CHECK(_("Protect details"), detail), CHECK(_("Gamma corrected"), gamma), WDONE, RET }; #undef WBbase void pressed_kuwahara() { kuw_dd tdata = { { _("Kuwahara-Nagao Blur"), kuw_code, FW_FN(do_kuwahara) }, 1, FALSE, use_gamma }; run_create_(filterwindow_code, &tdata, sizeof(tdata), script_cmds); } void pressed_convert_rgb() { unsigned char *old_img = mem_img[CHN_IMAGE]; int res = undo_next_core(UC_NOCOPY, mem_width, mem_height, 3, CMASK_IMAGE); if (res) memory_errors(res); else { do_convert_rgb(0, 1, mem_width * mem_height, mem_img[CHN_IMAGE], old_img, mem_pal); update_stuff(UPD_2RGB); } } void pressed_greyscale(int mode) { spot_undo(UNDO_COL); mem_greyscale(mode); mem_undo_prepare(); update_stuff(UPD_COL); } void pressed_rotate_image(int dir) { int i = mem_image_rot(dir); if (i) memory_errors(i); else update_stuff(UPD_GEOM); } void pressed_rotate_sel(int dir) { if (mem_sel_rot(dir)) memory_errors(1); else update_stuff(UPD_CGEOM); } static int angle = 4500; typedef struct { filterwindow_dd fw; int rgb; int smooth, gamma; } rfree_dd; static int do_rotate_free(rfree_dd *dt, void **wdata) { int j, smooth = 0, gcor = 0; run_query(wdata); if (mem_img_bpp == 3) { gcor = dt->gamma; smooth = dt->smooth; } j = mem_rotate_free(angle * 0.01, smooth, gcor, FALSE); if (!j) update_stuff(UPD_GEOM); else { if (j == -5) alert_box(_("Error"), _("The image is too large for this rotation."), NULL); else memory_errors(j); } return TRUE; } #define WBbase rfree_dd static void *rfree_code[] = { VBOXPS, BORDER(SPIN, 0), FSPINv(angle, -36000, 36000), IFx(rgb, 1), CHECK(_("Gamma corrected"), gamma), CHECK(_("Smooth"), smooth), ENDIF(1), WDONE, RET }; #undef WBbase void pressed_rotate_free() { rfree_dd tdata = { { _("Free Rotate"), rfree_code, FW_FN(do_rotate_free) }, mem_img_bpp == 3, TRUE, use_gamma }; run_create_(filterwindow_code, &tdata, sizeof(tdata), script_cmds); } void pressed_clip_mask(int val) { int i; if ( mem_clip_mask == NULL ) { i = mem_clip_mask_init(val ^ 255); if (i) { memory_errors(1); // Not enough memory return; } } mem_clip_mask_set(val); update_stuff(UPD_CLIP); } static int do_clip_alphamask() { unsigned char *old_mask = mem_clip_mask; int i, j = mem_clip_w * mem_clip_h, k; if (!mem_clipboard || !mem_clip_alpha) return FALSE; mem_clip_mask = mem_clip_alpha; mem_clip_alpha = NULL; if (old_mask) { for (i = 0; i < j; i++) { k = old_mask[i] * mem_clip_mask[i]; mem_clip_mask[i] = (k + (k >> 8) + 1) >> 8; } free(old_mask); } return TRUE; } void pressed_clip_alphamask() { if (do_clip_alphamask()) update_stuff(UPD_CLIP); } void pressed_clip_alpha_scale() { if (!mem_clipboard || (mem_clip_bpp != 3)) return; if (!mem_clip_mask) mem_clip_mask_init(255); if (!mem_clip_mask) return; mem_scale_alpha(mem_clipboard, mem_clip_mask, mem_clip_w, mem_clip_h, TRUE); update_stuff(UPD_CLIP); } void pressed_clip_mask_all() { if (mem_clip_mask_init(0)) memory_errors(1); // Not enough memory else update_stuff(UPD_CLIP); } void pressed_clip_mask_clear() { if (!mem_clip_mask) return; mem_clip_mask_clear(); update_stuff(UPD_CLIP); } void pressed_flip_image_v() { int i; unsigned char *temp; temp = malloc(mem_width * mem_img_bpp); if (!temp) return; /* Not enough memory for temp buffer */ spot_undo(UNDO_XFORM); for (i = 0; i < NUM_CHANNELS; i++) { if (!mem_img[i]) continue; mem_flip_v(mem_img[i], temp, mem_width, mem_height, BPP(i)); } free(temp); mem_undo_prepare(); update_stuff(UPD_IMG); } void pressed_flip_image_h() { int i; spot_undo(UNDO_XFORM); for (i = 0; i < NUM_CHANNELS; i++) { if (!mem_img[i]) continue; mem_flip_h(mem_img[i], mem_width, mem_height, BPP(i)); } mem_undo_prepare(); update_stuff(UPD_IMG); } void pressed_flip_sel_v() { unsigned char *temp; int i, bpp = mem_clip_bpp; temp = malloc(mem_clip_w * mem_clip_bpp); if (!temp) return; /* Not enough memory for temp buffer */ for (i = 0; i < NUM_CHANNELS; i++ , bpp = 1) { if (!mem_clip.img[i]) continue; mem_flip_v(mem_clip.img[i], temp, mem_clip_w, mem_clip_h, bpp); } update_stuff(UPD_CLIP); } void pressed_flip_sel_h() { int i, bpp = mem_clip_bpp; for (i = 0; i < NUM_CHANNELS; i++ , bpp = 1) { if (!mem_clip.img[i]) continue; mem_flip_h(mem_clip.img[i], mem_clip_w, mem_clip_h, bpp); } update_stuff(UPD_CLIP); } static void locate_marquee(int *xy, int snap); #define MIN_VISIBLE 16 /* No less than a square this large must be visible */ void pressed_paste(int centre) { if (!mem_clipboard) return; pressed_select(FALSE); change_to_tool(TTB_SELECT); marq_status = MARQUEE_PASTE; cursor_corner = -1; marq_x1 = mem_clip_x; marq_y1 = mem_clip_y; while (centre) { int marq0[4], mxy[4], vxy[4]; canvas_center(mem_ic); marq_x1 = mem_width * mem_icx - mem_clip_w * 0.5; marq_y1 = mem_height * mem_icy - mem_clip_h * 0.5; if (!tgrid_snap) break; /* Snap to grid */ copy4(marq0, marq_xy); locate_marquee(mxy, TRUE); if (script_cmds) break; // Scripting must behave consistently /* Undo snap if not enough of paste area is left visible */ // !!! Could use CSCROLL_XYSIZE here instead cmd_peekv(drawing_canvas, vxy, sizeof(vxy), CANVAS_VPORT); if (!clip(vxy, vxy[0] - margin_main_x, vxy[1] - margin_main_y, vxy[2] - margin_main_x, vxy[3] - margin_main_y, mxy) || ((vxy[2] - vxy[0] < MIN_VISIBLE) && (vxy[2] - vxy[0] < mxy[2] - mxy[0])) || ((vxy[3] - vxy[1] < MIN_VISIBLE) && (vxy[3] - vxy[1] < mxy[3] - mxy[1]))) copy4(marq_xy, marq0); break; } // !!! marq_x2, marq_y2 will be set by update_stuff() update_stuff(UPD_PASTE); } #undef MIN_VISIBLE void pressed_rectangle(int filled) { int sb; spot_undo(UNDO_DRAW); /* Shapeburst mode */ sb = STROKE_GRADIENT; if ( tool_type == TOOL_POLYGON ) { if (sb) { int l2, l3, ixy[4] = { 0, 0, mem_width, mem_height }; l2 = l3 = filled ? 1 : tool_size; l2 >>= 1; l3 -= l2; clip(sb_rect, poly_min_x - l2, poly_min_y - l2, poly_max_x + l3, poly_max_y + l3, ixy); sb_rect[2] -= sb_rect[0]; sb_rect[3] -= sb_rect[1]; sb = init_sb(); } if (!filled) poly_outline(); else poly_paint(); } else { int l2 = 2 * tool_size, rect[4]; marquee_at(rect); if (sb) { copy4(sb_rect, rect); sb = init_sb(); } if (filled || (l2 >= rect[2]) || (l2 >= rect[3])) f_rectangle(rect[0], rect[1], rect[2], rect[3]); else { f_rectangle(rect[0], rect[1], rect[2], tool_size); f_rectangle(rect[0], rect[1] + rect[3] - tool_size, rect[2], tool_size); f_rectangle(rect[0], rect[1] + tool_size, tool_size, rect[3] - l2); f_rectangle(rect[0] + rect[2] - tool_size, rect[1] + tool_size, tool_size, rect[3] - l2); } } if (sb) render_sb(NULL); mem_undo_prepare(); update_stuff(UPD_IMG); } void pressed_ellipse(int filled) { spot_undo(UNDO_DRAW); mem_ellipse(marq_x1, marq_y1, marq_x2, marq_y2, filled ? 0 : tool_size); mem_undo_prepare(); update_stuff(UPD_IMG); } static int copy_clip() { int rect[4], bpp = MEM_BPP, cmask = CMASK_IMAGE; if ((mem_channel == CHN_IMAGE) && mem_img[CHN_ALPHA] && !channel_dis[CHN_ALPHA]) cmask = CMASK_RGBA; marquee_at(rect); mem_clip_new(rect[2], rect[3], bpp, cmask, NULL); if (!mem_clipboard) { alert_box(_("Error"), _("Not enough memory to create clipboard"), NULL); return (FALSE); } mem_clip_x = rect[0]; mem_clip_y = rect[1]; copy_area(&mem_clip, &mem_image, mem_clip_x, mem_clip_y); return (TRUE); } static int channel_mask() { int i, j, ofs, delta; if (!mem_img[CHN_SEL] || channel_dis[CHN_SEL]) return (FALSE); if (mem_channel > CHN_ALPHA) return (FALSE); if (!mem_clip_mask) mem_clip_mask_init(255); if (!mem_clip_mask) return (FALSE); ofs = mem_clip_y * mem_width + mem_clip_x; delta = 0; for (i = 0; i < mem_clip_h; i++) { for (j = 0; j < mem_clip_w; j++) mem_clip_mask[delta + j] &= mem_img[CHN_SEL][ofs + j]; ofs += mem_width; delta += mem_clip_w; } return (TRUE); } static void cut_clip() { int i, sb = 0; spot_undo(UNDO_DRAW); /* Shapeburst mode */ if (STROKE_GRADIENT) { sb_rect[0] = mem_clip_x; sb_rect[1] = mem_clip_y; sb_rect[2] = mem_clip_w; sb_rect[3] = mem_clip_h; sb = init_sb(); } for (i = 0; i < mem_clip_h; i++) { put_pixel_row(mem_clip_x, mem_clip_y + i, mem_clip_w, mem_clip_mask ? mem_clip_mask + i * mem_clip_w : NULL); } if (sb) render_sb(mem_clip_mask); mem_undo_prepare(); } static void trim_clip() { chanlist old_img; unsigned char *tmp; int i, j, k, offs, offd, maxx, maxy, minx, miny, nw, nh; minx = MAX_WIDTH; miny = MAX_HEIGHT; maxx = maxy = 0; /* Find max & min values for shrink wrapping */ for (j = 0; j < mem_clip_h; j++) { offs = mem_clip_w * j; for (i = 0; i < mem_clip_w; i++) { if (!mem_clip_mask[offs + i]) continue; if (i < minx) minx = i; if (i > maxx) maxx = i; if (j < miny) miny = j; if (j > maxy) maxy = j; } } /* No live pixels found */ if (minx > maxx) return; nw = maxx - minx + 1; nh = maxy - miny + 1; /* No decrease so no resize either */ if ((nw == mem_clip_w) && (nh == mem_clip_h)) return; /* Pack data to front */ for (j = miny; j <= maxy; j++) { offs = j * mem_clip_w + minx; offd = (j - miny) * nw; memmove(mem_clipboard + offd * mem_clip_bpp, mem_clipboard + offs * mem_clip_bpp, nw * mem_clip_bpp); for (k = 1; k < NUM_CHANNELS; k++) { if (!(tmp = mem_clip.img[k])) continue; memmove(tmp + offd, tmp + offs, nw); } } /* Try to realloc memory for smaller clipboard */ tmp = realloc(mem_clipboard, nw * nh * mem_clip_bpp); if (tmp) mem_clipboard = tmp; for (k = 1; k < NUM_CHANNELS; k++) { if (!(tmp = mem_clip.img[k])) continue; tmp = realloc(tmp, nw * nh); if (tmp) mem_clip.img[k] = tmp; } /* Reset clipboard to new size */ mem_clip_new(nw, nh, mem_clip_bpp, 0, old_img); memcpy(mem_clip.img, old_img, sizeof(chanlist)); mem_clip_x += minx; mem_clip_y += miny; if (marq_status >= MARQUEE_PASTE) // We're trimming live paste area { marq_x2 = (marq_x1 += minx) + nw - 1; marq_y2 = (marq_y1 += miny) + nh - 1; } } void pressed_copy(int cut) { if (!copy_clip()) return; if (tool_type == TOOL_POLYGON) poly_mask(); channel_mask(); if (cut) cut_clip(); update_stuff(cut ? UPD_CUT : UPD_COPY); } void pressed_lasso(int cut) { /* Lasso a new selection */ if (((marq_status > MARQUEE_NONE) && (marq_status < MARQUEE_PASTE)) || (poly_status == POLY_DONE)) { if (!copy_clip()) return; if (tool_type == TOOL_POLYGON) poly_mask(); else mem_clip_mask_init(255); if (!lasso_sel || !channel_mask()) { poly_lasso(poly_status == POLY_DONE); channel_mask(); } trim_clip(); if (cut) cut_clip(); pressed_paste(TRUE); } /* Trim an existing clipboard */ else { if (!lasso_sel || !mem_clip_mask) { unsigned char *oldmask = mem_clip_mask; mem_clip_mask = NULL; mem_clip_mask_init(255); poly_lasso(FALSE); if (mem_clip_mask && oldmask) { int i, j = mem_clip_w * mem_clip_h; for (i = 0; i < j; i++) oldmask[i] &= mem_clip_mask[i]; mem_clip_mask_clear(); } if (!mem_clip_mask) mem_clip_mask = oldmask; } trim_clip(); update_stuff(UPD_CGEOM); } } void update_menus() // Update edit/undo menu { static int memwarn; unsigned int statemap; int i, j; if (mem_undo_fail && !memwarn) memwarn = alert_box(_("Warning"), _("You have not allocated enough memory in the Preferences window to undo this action."), "", NULL); // Not an error update_undo_bar(); statemap = mem_img_bpp == 3 ? NEED_24 | NEED_NOIDX : NEED_IDX; if (mem_channel != CHN_IMAGE) statemap |= NEED_NOIDX; if ((mem_img_bpp == 3) && mem_img[CHN_ALPHA]) statemap |= NEED_RGBA; if (mem_clipboard) statemap |= NEED_PCLIP; if (mem_clipboard && (mem_clip_bpp == 3)) statemap |= NEED_ACLIP; if ( marq_status == MARQUEE_NONE ) { // statemap &= ~(NEED_SEL | NEED_CROP); if (poly_status == POLY_DONE) statemap |= NEED_MARQ | NEED_LASSO; } else { statemap |= NEED_MARQ; /* If we are pasting disallow copy/cut/crop */ if (marq_status < MARQUEE_PASTE) statemap |= NEED_SEL | NEED_CROP | NEED_LASSO; /* Only offer the crop option if the user hasn't selected everything */ if (!((abs(marq_x1 - marq_x2) < mem_width - 1) || (abs(marq_y1 - marq_y2) < mem_height - 1))) statemap &= ~NEED_CROP; } /* Forbid RGB-to-indexed paste, but allow indexed-to-RGB */ if (mem_clipboard && (mem_clip_bpp <= MEM_BPP)) statemap |= NEED_CLIP; if (mem_undo_done) statemap |= NEED_UNDO; if (mem_undo_redo) statemap |= NEED_REDO; cmd_set(menu_slots[MENU_CHAN0 + mem_channel], TRUE); cmd_set(menu_slots[MENU_DCHAN0], hide_image); cmd_set(menu_slots[MENU_OALPHA], overlay_alpha); for (i = j = 0; i < NUM_CHANNELS; i++) // Enable/disable channel enable/disable { if (mem_img[i]) j++; cmd_sensitive(menu_slots[MENU_DCHAN0 + i], !!mem_img[i]); } if (j > 1) statemap |= NEED_CHAN; cmd_setv(main_window_, (void *)statemap, WDATA_ACTMAP); /* Switch to default tool if active smudge tool got disabled */ if ((tool_type == TOOL_SMUDGE) && !cmd_checkv(icon_buttons[SMUDGE_TOOL_ICON], SLOT_SENSITIVE)) change_to_tool(DEFAULT_TOOL_ICON); } void update_stuff(int flags) { /* Always check current channel first */ if (!mem_img[mem_channel]) { mem_channel = CHN_IMAGE; flags |= UPD_CHAN; } /* And check paste validity too */ if ((marq_status >= MARQUEE_PASTE) && (!mem_clipboard || (mem_clip_bpp > MEM_BPP))) pressed_select(FALSE); if (flags & CF_CAB) flags |= mem_channel == CHN_IMAGE ? UPD_AB : UPD_GRAD; if (flags & CF_GEOM) { int wh[2]; canvas_size(wh + 0, wh + 1); cmd_setv(drawing_canvas, wh, CANVAS_SIZE); } if (flags & CF_CGEOM) if (marq_status >= MARQUEE_PASTE) flags |= CF_DRAW; if (flags & (CF_GEOM | CF_CGEOM)) check_marquee(); if (flags & CF_PAL) { int wh[2] = { PALETTE_WIDTH, mem_cols * PALETTE_SWATCH_H + PALETTE_SWATCH_Y * 2 }; if (mem_col_A >= mem_cols) mem_col_A = 0; if (mem_col_B >= mem_cols) mem_col_B = 0; mem_mask_init(); // Reinit RGB masks cmd_setv(drawing_palette, wh, CANVAS_SIZE); } if (flags & CF_AB) { mem_pat_update(); if (text_paste && (marq_status >= MARQUEE_PASTE)) { if (text_paste == TEXT_PASTE_FT) ft_render_text(); else /* if ( text_paste == TEXT_PASTE_GTK ) */ render_text(); check_marquee(); flags |= CF_PMODE; } } if (flags & CF_GRAD) grad_def_update(-1); if (flags & CF_PREFS) { update_undo_depth(); // If undo depth was changed update_recent_files(FALSE); init_status_bar(); // Takes care of all statusbar parts } if (flags & CF_MENU) update_menus(); if (flags & CF_SET) toolbar_update_settings(); #if 0 // !!! Too risky for now - need a safe path which only calls update_xy_bar() if (flags & CF_PIXEL) move_mouse(0, 0, 0); // To cause update of XY bar #endif if (flags & CF_PMODE) if ((marq_status >= MARQUEE_PASTE) && show_paste) flags |= CF_DRAW; if (flags & CF_GMODE) if ((tool_type == TOOL_GRADIENT) && grad_opacity) flags |= CF_DRAW; /* The next parts can be done later in a cumulative update */ flags |= update_later; if (script_cmds && !(flags & CF_NOW)) flags ^= update_later = flags & (CF_NAME | CF_IMGBAR | CF_SELBAR | CF_TRANS | CF_CURSOR | CF_DRAW | CF_VDRAW | CF_PDRAW | CF_TDRAW | CF_ALIGN | CF_VALIGN); update_later &= ~flags; if (flags & CF_NAME) update_titlebar(); if (flags & CF_IMGBAR) update_image_bar(); if (flags & CF_SELBAR) update_sel_bar(TRUE); if (flags & CF_CURSOR) set_cursor(NULL); if (flags & CF_DRAW) if (drawing_canvas) cmd_repaint(drawing_canvas); if (flags & CF_VDRAW) if (view_showing && vw_drawing) cmd_repaint(vw_drawing); if (flags & CF_PDRAW) { mem_pal_init(); // Update palette RGB on screen cmd_repaint(drawing_palette); } if (flags & CF_TDRAW) { update_top_swatch(); cmd_repaint(drawing_col_prev); } if (flags & CF_ALIGN) realign_size(); if (flags & CF_VALIGN) vw_realign(); if (flags & CF_TRANS) layer_show_trans(); } void pressed_do_undo(int redo, int cnt) { while (cnt--) mem_do_undo(redo); update_stuff(UPD_ALL | CF_NAME); } static int load_pal(char *filename) // Load palette file { int ftype, res = -1; ftype = detect_palette_format(filename); if (ftype < 0) return (-1); /* Silently fail if no file */ if (ftype != FT_NONE) res = load_image(filename, FS_PALETTE_LOAD, ftype); /* Successful... */ if (res == 1) update_stuff(UPD_UPAL); /* ...or not */ else alert_box(_("Error"), _("Invalid palette file"), NULL); return (res == 1 ? 0 : -1); } void set_new_filename(int layer, char *fname) { mem_replace_filename(layer, fname); if (layer == layer_selected) update_stuff(UPD_NAME); } static int populate_channel(char *filename) { int ftype, res = -1; ftype = detect_image_format(filename); if (ftype < 0) return (-1); /* Silently fail if no file */ /* Don't bother with mismatched formats */ if (file_formats[ftype].flags & (MEM_BPP == 1 ? FF_IDX : FF_RGB)) res = load_image(filename, FS_CHANNEL_LOAD, ftype); /* Successful */ if (res == 1) update_stuff(UPD_UIMG); /* Not enough memory available */ else if (res == FILE_MEM_ERROR) memory_errors(1); /* Unspecified error */ else alert_box(_("Error"), _("Invalid channel file."), NULL); return (res == 1 ? 0 : -1); } /// FILE SELECTION WINDOW static int anim_mode = ANM_COMP - ANM_RAW; typedef struct { int is_anim; char *what; void **lload, **load1, **explode; void **res; } animfile_dd; static char *modes_txt[] = { _("Raw frames"), _("Composited frames"), _("Composited frames with nonzero delay") }; #define WBbase animfile_dd static void *animfile_code[] = { WINDOWm(_("Load Frames")), MLABELcp(what), EQBOXB, // !!! why not HBOXB ? REF(lload), BUTTON(_("Load into Layers"), dialog_event), FOCUS, WDONE, BORDER(RPACK, 0), IF(is_anim), RPACKv(modes_txt, 3, 0, anim_mode), HSEP, EQBOXB, REF(load1), CANCELBTN(_("Load First Frame"), dialog_event), REF(explode), BUTTON(_("Explode Frames"), dialog_event), #ifndef WIN32 IF(is_anim), BUTTON(_("View Animation"), dialog_event), #endif WDONE, RAISED, WDIALOG(res) }; #undef WBbase static int anim_file_dialog(int ftype, int is_anim) { animfile_dd tdata, *dt; void **res, **where; char *tmp; int i; tdata.is_anim = is_anim; tmp = g_strdup_printf(is_anim ? __("This is an animated %s file.") : __("This is a multipage %s file."), file_formats[ftype & FTM_FTYPE].name); tdata.what = tmp; res = run_create(animfile_code, &tdata, sizeof(tdata)); // run dialog g_free(tmp); /* Retrieve results */ run_query(res); dt = GET_DDATA(res); where = origin_slot(dt->res); i = where == dt->lload ? 3 : where == dt->load1 ? 0 : where == dt->explode ? 1 : 2; run_destroy(res); return (i); } static void handle_file_error(int res) { char mess[256], *txt = NULL; /* Image was too large for OS */ if (res == FILE_MEM_ERROR) memory_errors(1); else if (res == TOO_BIG) snprintf(txt = mess, 250, __("File is too big, must be <= to width=%i height=%i"), MAX_WIDTH, MAX_HEIGHT); else if (res == EXPLODE_FAILED) txt = _("Unable to explode frames"); else if (res <= 0) txt = _("Unable to load file"); else if (res == FILE_LIB_ERROR) txt = _("The file import library had to terminate due to a problem with the file (possibly corrupt image data or a truncated file). I have managed to load some data as the header seemed fine, but I would suggest you save this image to a new file to ensure this does not happen again."); else if (res == FILE_TOO_LONG) txt = _("The animation is too long to load all of it into layers."); else if (res == FILE_EXP_BREAK) txt = _("Could not explode all the frames in the animation."); if (txt) alert_box(_("Error"), txt, NULL); } typedef struct { char *what; void **ok, **res; int w, h; } scale_dd; #define WBbase scale_dd static void *scale_code[] = { WINDOWm(_("Size")), MLABELpx(what, 5, 5, 4), TABLE2(2), TSPIN(_("Width"), w, 0, MAX_WIDTH), TSPIN(_("Height"), h, 0, MAX_HEIGHT), WDONE, HSEP, EQBOXB, CANCELBTN(_("Cancel"), dialog_event), REF(ok), OKBTN(_("OK"), dialog_event), WDONE, RAISED, WDIALOG(res) }; #undef WBbase static void scale_file_dialog(int ftype, int *w, int *h) { scale_dd tdata, *dt; void **res; char *tmp; memset(&tdata, 0, sizeof(tdata)); tdata.what = tmp = g_strdup_printf(__("This is a scalable %s file."), file_formats[ftype & FTM_FTYPE].name); res = run_create(scale_code, &tdata, sizeof(tdata)); // run dialog g_free(tmp); /* Retrieve results */ run_query(res); dt = GET_DDATA(res); if (origin_slot(dt->res) == dt->ok) *w = dt->w , *h = dt->h; run_destroy(res); } typedef struct { void **pathbox; char *title, **ftnames, **tiffnames; char *frames_name, *ex_path; int frames_ftype, frames_anim, load_lr; int mode, fpmode; int fmask, ftype, ftypes[NUM_FTYPES]; int need_save, need_anim, need_undo, need_icc, script; int jpeg_c, png_c, tga_c, jp2_c, xtrans[3], xx[3], xy[3]; int tiff_m, lzma_c, zstd_c; int webp_p, webp_q, webp_c; int lbm_c, lbm_p; int gif_delay, undo, icc; int w, h; /* Note: filename is in system encoding */ char filename[PATHBUF]; } fselector_dd; int do_a_load_x(char *fname, int undo, void *v) { char real_fname[PATHBUF]; int res, ftype, mult = 0, w = 0, h = 0, got_frame1 = FALSE; resolve_path(real_fname, PATHBUF, fname); ftype = detect_image_format(real_fname); if ((ftype < 0) || (ftype == FT_NONE)) { alert_box(_("Error"), ftype < 0 ? _("Cannot open file") : _("Unsupported file format"), NULL); return (1); } set_image(FALSE); if (ftype == FT_LAYERS1) mult = res = load_layers(real_fname); else { if (script_cmds && v) { fselector_dd *dt = v; w = dt->w; h = dt->h; } else if (!script_cmds && (file_formats[ftype].flags & FF_SCALE)) scale_file_dialog(ftype, &w, &h); res = load_image_scale(real_fname, FS_PNG_LOAD, ftype | (undo ? FTM_UNDO : 0), w, h); } /* Multiframe file was loaded so tell user */ if ((res == FILE_HAS_FRAMES) || (res == FILE_HAS_ANIM)) { int i, is_anim = res == FILE_HAS_ANIM; /* First frame was loaded OK */ got_frame1 = TRUE; res = 1; /* Don't ask user in viewer mode */ // !!! When implemented, load as frameset & run animation in that case instead if (viewer_mode && view_image_only) i = 0; /* Don't ask in script mode too */ else if (script_cmds && v) { fselector_dd *dt = v; i = dt->ex_path ? -1 : dt->load_lr ? 3 : 0; } else if (script_cmds) i = 0; else i = anim_file_dialog(ftype, is_anim); is_anim = is_anim ? anim_mode + ANM_RAW : ANM_PAGE; if (i == 3) { /* Make current layer, with first frame in it, background */ if (layer_selected) { /* Simply swap layer data pointers */ layer_image *tip = layer_table[layer_selected].image; layer_table[layer_selected].image = layer_table[0].image; layer_table[0].image = tip; layer_selected = 0; } mult = res = load_to_layers(real_fname, ftype, is_anim); } else if (i == -1) /* Explode frames into preset directory */ { fselector_dd *dt = v; i = dt->ftypes[dt->ftype]; res = explode_frames(dt->ex_path, is_anim, real_fname, ftype, i == FT_NONE ? ftype : i); } else if (i == 1) /* Ask for directory to explode frames to */ { void *xdata[3]; /* Needed when starting new mtpaint process later */ xdata[0] = real_fname; xdata[1] = (void *)ftype; xdata[2] = (void *)is_anim; file_selector_x(FS_EXPLODE_FRAMES, xdata); } else if (i == 2) run_def_action(ftype == FT_WEBP ? DA_WEBP_PLAY : ftype == FT_PNG ? DA_APNG_PLAY : DA_GIF_PLAY, real_fname, NULL, 0); } /* An error happened */ if (res != 1) { handle_file_error(res); if ((res <= 0) && !got_frame1) // Hard error { set_image(TRUE); return (1); } } /* Whether we loaded something or failed to, old image is gone anyway */ if (!script_cmds) register_file(real_fname); // Ignore what scripts do if (mult <= 0) /* A single image */ { char *nm = NULL; /* To prevent 1st frame overwriting a multiframe file */ if (got_frame1) nm = tailed_name(NULL, real_fname, ".000", PATHBUF); set_new_filename(layer_selected, nm ? nm : real_fname); free(nm); if ( layers_total>0 ) layers_notify_changed(); // We loaded an image into the layers, so notify change } else /* A whole bunch of layers */ { // pressed_layers(); // We have just loaded a layers file so ensure view window is open view_show(); } /* Show new image */ if (!undo) reset_tools(); else // No reason to reset tools in undoable mode { notify_unchanged(NULL); update_stuff(UPD_ALL); } set_image(TRUE); return (0); } int check_file( char *fname ) // Does file already exist? Ask if OK to overwrite { char *msg, *f8; int res = 0; if ( valid_file(fname) == 0 ) { f8 = gtkuncpy(NULL, fname, 0); msg = g_strdup_printf(__("File: %s already exists. Do you want to overwrite it?"), f8); res = alert_box(_("File Found"), msg, _("NO"), _("YES"), NULL) != 2; g_free(msg); g_free(f8); } return (res); } static void change_image_format(fselector_dd *dt, void **wdata, int what, void **where) { int ftype; unsigned int xflags; if (!dt->need_save) return; // no use cmd_read(where, dt); ftype = dt->ftypes[dt->ftype]; xflags = ftype != FT_TIFF ? file_formats[ftype].xflags : tiff_formats[dt->tiff_m].xflags; if (ftype == FT_WEBP) xflags |= dt->webp_p ? XF_COMPV8 : XF_COMPV8L; if ((ftype == FT_LBM) && (dt->fmask & FF_IDX)) xflags |= XF_PBM; /* Hide/show name/value widget pairs */ cmd_setv(wdata, (void *)xflags, WDATA_ACTMAP); } int ftype_selector(int mask, char *ext, int def, char **names, int *ftypes) { fformat *ff; int i, j, k, l, ft_sort[NUM_FTYPES], ft_key[NUM_FTYPES]; ft_key[0] = ft_sort[0] = 0; k = def == FT_NONE; // Include FT_NONE if default for (i = 0; i < NUM_FTYPES; i++) // Populate sorted filetype list { ff = file_formats + i; if (ff->flags & FF_NOSAVE) continue; if (!(ff->flags & mask)) continue; l = (ff->name[0] << 16) + (ff->name[1] << 8) + ff->name[2]; for (j = k; j > 0; j--) { if (ft_key[j - 1] < l) break; ft_sort[j] = ft_sort[j - 1]; ft_key[j] = ft_key[j - 1]; } ft_key[j] = l; ft_sort[j] = i; k++; } j = -1; for (l = 0; l < k; l++) // Prepare to generate option menu { i = ft_sort[l]; if ((j < 0) && (i == def)) j = l; // Default type if not saved yet ff = file_formats + i; if (!strncasecmp(ext, ff->ext, LONGEST_EXT) || (ff->ext2[0] && !strncasecmp(ext, ff->ext2, LONGEST_EXT))) j = l; names[l] = ff->name; } names[k] = NULL; memcpy(ftypes, ft_sort, sizeof(int) * k); return (j); } int tiff_type_selector(int mask, int def, char **names) { int i, n; for (n = i = 0; tiff_formats[i].name; i++) { names[i] = ""; if (tiff_formats[i].flags & mask) { names[i] = tiff_formats[i].name; if (i == def) n = i; } } names[i] = NULL; return (n); } void init_ls_settings(ls_settings *settings, void **wdata) { png_color *pal = mem_pal; /* Set defaults */ memset(settings, 0, sizeof(ls_settings)); settings->ftype = FT_NONE; settings->xpm_trans = mem_xpm_trans; settings->hot_x = mem_xbm_hot_x; settings->hot_y = mem_xbm_hot_y; settings->req_w = settings->req_h = 0; settings->jpeg_quality = jpeg_quality; settings->png_compression = png_compression; settings->lzma_preset = lzma_preset; settings->zstd_level = zstd_level; settings->tiff_type = -1; /* Use default */ settings->tga_RLE = tga_RLE; settings->jp2_rate = jp2_rate; settings->webp_preset = webp_preset; settings->webp_quality = webp_quality; settings->webp_compression = webp_compression; settings->lbm_pack = lbm_pack; settings->lbm_pbm = lbm_pbm; settings->gif_delay = preserved_gif_delay; /* Read in settings */ if (wdata) { fselector_dd *dt = GET_DDATA(wdata); settings->xpm_trans = dt->xtrans[0]; settings->hot_x = dt->xx[0]; settings->hot_y = dt->xy[0]; settings->jpeg_quality = dt->jpeg_c; settings->png_compression = dt->png_c; settings->lzma_preset = dt->lzma_c; settings->zstd_level = dt->zstd_c; settings->tiff_type = dt->tiff_m; settings->tga_RLE = dt->tga_c; settings->jp2_rate = dt->jp2_c; settings->webp_preset = dt->webp_p; settings->webp_quality = dt->webp_q; settings->webp_compression = dt->webp_c; settings->lbm_pack = dt->lbm_c; settings->lbm_pbm = dt->lbm_p; settings->gif_delay = dt->gif_delay; settings->mode = dt->mode; settings->ftype = dt->fmask ? dt->ftypes[dt->ftype] : /* For animation, hardcoded GIF format for now */ dt->mode == FS_EXPORT_GIF ? FT_GIF : FT_NONE; undo_load = dt->undo; #ifdef U_LCMS apply_icc = dt->icc; #endif // Use background's palette if ((dt->mode == FS_COMPOSITE_SAVE) && layer_selected) pal = layer_table[0].image->image_.pal; } /* Default expansion of xpm_trans */ settings->rgb_trans = settings->xpm_trans < 0 ? -1 : PNG_2_INT(pal[settings->xpm_trans]); } static void store_ls_settings(ls_settings *settings) { int ftype = settings->ftype, ttype = settings->tiff_type; unsigned int xflags = (ftype == FT_TIFF) && (ttype >= 0) ? tiff_formats[ttype].xflags : file_formats[ftype].xflags; switch (settings->mode) { case FS_PNG_SAVE: if (xflags & XF_TRANS) mem_set_trans(settings->xpm_trans); if (xflags & XF_SPOT) { mem_xbm_hot_x = settings->hot_x; mem_xbm_hot_y = settings->hot_y; } // Fallthrough case FS_CHANNEL_SAVE: case FS_COMPOSITE_SAVE: if (xflags & XF_COMPJ) jpeg_quality = settings->jpeg_quality; if (xflags & (XF_COMPZ | XF_COMPZT)) png_compression = settings->png_compression; if (xflags & XF_COMPLZ) lzma_preset = settings->lzma_preset; if (xflags & XF_COMPZS) zstd_level = settings->zstd_level; if (xflags & XF_COMPR) tga_RLE = settings->tga_RLE; if (xflags & XF_COMPJ2) jp2_rate = settings->jp2_rate; if (xflags & XF_COMPW) { webp_preset = settings->webp_preset; if (webp_preset) webp_quality = settings->webp_quality; else webp_compression = settings->webp_compression; } if (xflags & XF_COMPWT) webp_quality = settings->webp_quality; if ((xflags & XF_COMPT) && (ttype >= 0)) { /* Remember selection for incompatible types separately; * image is not set up yet, so use the mode instead */ *(settings->mode == FS_COMPOSITE_SAVE ? &tiff_rtype : (settings->mode == FS_CHANNEL_SAVE) && (mem_channel != CHN_IMAGE) ? &tiff_itype : mem_img_bpp == 3 ? &tiff_rtype : mem_cols > 2 ? &tiff_itype : &tiff_btype) = ttype; } if (xflags & XF_COMPRL) lbm_pack = settings->lbm_pack; /* !!! XF_PBM is only for indexed LBMs, but a complicated check * for that like for TIFFs above would add nothing of value here */ if (ftype == FT_LBM) lbm_pbm = settings->lbm_pbm; break; case FS_EXPORT_GIF: preserved_gif_delay = settings->gif_delay; break; } } static void fs_ok(fselector_dd *dt, void **wdata) { ls_settings settings; char fname[PATHTXT], *msg, *f8; char *c, *ext, *ext2, *gif, *gif2; int i, j, res, redo = 1; run_query(wdata); /* Pick up extra info */ init_ls_settings(&settings, wdata); /* Looks better if no dialog under progressbar */ cmd_showhide(GET_WINDOW(wdata), FALSE); /* File extension */ cmd_peekv(GET_WINDOW(wdata), fname, PATHTXT, FPICK_RAW); // raw filename c = strrchr(fname, '.'); while (TRUE) { /* Cut the extension off */ if ((settings.mode == FS_CLIP_FILE) || (settings.mode == FS_EXPLODE_FRAMES) || (settings.mode == FS_EXPORT_UNDO) || (settings.mode == FS_EXPORT_UNDO2)) { if (!c) break; *c = '\0'; } /* Modify the file extension if needed */ else if (settings.mode == FS_PNG_LOAD) break; else { ext = file_formats[settings.ftype].ext; if (!ext[0]) break; if (c) /* There is an extension */ { /* Same extension? */ if (!strncasecmp(c + 1, ext, 256)) break; /* Alternate extension? */ ext2 = file_formats[settings.ftype].ext2; if (ext2[0] && !strncasecmp(c + 1, ext2, 256)) break; /* Another file type? */ for (i = 0; i < NUM_FTYPES; i++) { if (strncasecmp(c + 1, file_formats[i].ext, 256) && strncasecmp(c + 1, file_formats[i].ext2, 256)) continue; /* Truncate */ *c = '\0'; break; } } i = strlen(fname); j = strlen(ext); if (i + j >= PATHTXT - 1) break; /* Too long */ fname[i] = '.'; strncpy(fname + i + 1, ext, j + 1); } cmd_setv(GET_WINDOW(wdata), fname, FPICK_RAW); // raw filename break; } /* Get filename the proper way, in system filename encoding */ cmd_read(GET_WINDOW(wdata), dt); switch (settings.mode) { case FS_PNG_LOAD: if (do_a_load_x(dt->filename, undo_load, dt) == 1) break; redo = 0; break; case FS_PNG_SAVE: if (check_file(dt->filename)) break; store_ls_settings(&settings); // Update data in memory if (gui_save(dt->filename, &settings) < 0) break; if (layers_total > 0) { /* Filename has changed so layers file needs re-saving to be correct */ if (!mem_filename || strcmp(dt->filename, mem_filename)) layers_notify_changed(); } set_new_filename(layer_selected, dt->filename); redo = 0; break; case FS_PALETTE_LOAD: if (load_pal(dt->filename)) break; notify_changed(); redo = 0; break; case FS_PALETTE_SAVE: if (check_file(dt->filename)) break; settings.pal = mem_pal; settings.colors = mem_cols; redo = 2; if (save_image(dt->filename, &settings)) break; redo = 0; break; case FS_CLIP_FILE: case FS_SELECT_FILE: case FS_SELECT_DIR: if (dt->pathbox) cmd_setv(dt->pathbox, dt->filename, PATH_VALUE); redo = 0; break; case FS_EXPORT_UNDO: case FS_EXPORT_UNDO2: if (export_undo(dt->filename, &settings)) alert_box(_("Error"), _("Unable to export undo images"), NULL); redo = 0; break; case FS_EXPORT_ASCII: if (check_file(dt->filename)) break; if (export_ascii(dt->filename)) alert_box(_("Error"), _("Unable to export ASCII file"), NULL); redo = 0; break; case FS_LAYER_SAVE: if (check_file(dt->filename)) break; if (save_layers(dt->filename) != 1) break; redo = 0; break; case FS_EXPLODE_FRAMES: gif = dt->frames_name; res = dt->frames_ftype; i = dt->frames_anim; res = explode_frames(dt->filename, i, gif, res, settings.ftype); if (res != 1) handle_file_error(res); if (res > 0) // Success or nonfatal error { c = strrchr(gif, DIR_SEP); if (!c) c = gif; else c++; c = file_in_dir(NULL, dt->filename, c, PATHBUF); run_def_action(DA_GIF_EDIT, c, NULL, preserved_gif_delay); free(c); redo = 0; } break; case FS_EXPORT_GIF: if (check_file(dt->filename)) break; store_ls_settings(&settings); // Update data in memory gif2 = g_strdup(mem_filename); // Guaranteed to be non-NULL for (i = strlen(gif2) - 1; i >= 0; i--) { if (gif2[i] == DIR_SEP) break; if ((unsigned char)(gif2[i] - '0') <= 9) gif2[i] = '?'; } if (!run_def_action(DA_GIF_CREATE, gif2, dt->filename, settings.gif_delay) && !cmd_mode) /* Don't launch GUI from commandline */ run_def_action(DA_GIF_PLAY, dt->filename, NULL, 0); g_free(gif2); redo = 0; break; case FS_CHANNEL_LOAD: if (populate_channel(dt->filename)) break; redo = 0; break; case FS_CHANNEL_SAVE: if (check_file(dt->filename)) break; store_ls_settings(&settings); // Update data in memory settings.img[CHN_IMAGE] = mem_img[mem_channel]; settings.width = mem_width; settings.height = mem_height; if (mem_channel == CHN_IMAGE) { settings.pal = mem_pal; settings.bpp = mem_img_bpp; settings.colors = mem_cols; } else { settings.pal = NULL; /* Greyscale one 'll be created */ settings.bpp = 1; settings.colors = 256; settings.xpm_trans = -1; } redo = 2; if (save_image(dt->filename, &settings)) break; redo = 0; break; case FS_COMPOSITE_SAVE: if (check_file(dt->filename)) break; store_ls_settings(&settings); // Update data in memory redo = 2; if (layer_save_composite(dt->filename, &settings)) break; redo = 0; break; default: // Paranoia redo = 0; break; } if (redo > 1) /* Report error */ { f8 = gtkuncpy(NULL, dt->filename, 0); msg = g_strdup_printf(__("Unable to save file: %s"), f8); alert_box(_("Error"), msg, NULL); g_free(msg); g_free(f8); } if (redo && !script_cmds) /* Redo */ { cmd_showhide(GET_WINDOW(wdata), TRUE); return; } /* Done */ user_break |= redo; // Paranoia update_menus(); run_destroy(wdata); } #define WBbase fselector_dd static void *fselector_code[] = { FPICKpm(title, fpmode, filename, fs_ok, NULL), IFx(fmask, 1), MLABEL(_("File Format")), OPTDe(ftnames, ftype, change_image_format), TRIGGER, ENDIF(1), IFx(need_save, 1), VISMASK(~0), HEIGHTBAR, MLABELr(_("Transparency index")), ACTMAP(XF_TRANS), SPINa(xtrans), ACTMAP(XF_TRANS), MLABELr(_("TIFF Compression")), ACTMAP(XF_COMPT), OPTDe(tiffnames, tiff_m, change_image_format), ACTMAP(XF_COMPT), MLABELr(_("JPEG Save Quality (100=High)")), ACTMAP(XF_COMPJ), SPIN(jpeg_c, 0, 100), ACTMAP(XF_COMPJ), MLABELr(_("ZIP Compression (0=None)")), ACTMAP(XF_COMPZT), MLABELr(_("PNG Compression (0=None)")), ACTMAP(XF_COMPZ), SPIN(png_c, 0, 9), ACTMAP(XF_COMPZ | XF_COMPZT), ALTNAME("ZIP Compression (0=None)"), MLABELr(_("LZMA2 Compression (0=None)")), ACTMAP(XF_COMPLZ), SPIN(lzma_c, 0, 9), ACTMAP(XF_COMPLZ), MLABELr(_("ZSTD Compression Level")), ACTMAP(XF_COMPZS), SPIN(zstd_c, ZSTD_MIN, ZSTD_MAX), ACTMAP(XF_COMPZS), CHECK(_("TGA RLE Compression"), tga_c), ACTMAP(XF_COMPR), CHECK("PBM", lbm_p), ACTMAP(XF_PBM), CHECK(_("LBM PackBits Compression"), lbm_c), ACTMAP(XF_COMPRL), MLABELr(_("JPEG2000 Compression (0=Lossless)")), ACTMAP(XF_COMPJ2), SPIN(jp2_c, 0, 100), ACTMAP(XF_COMPJ2), MLABELr(_("WebP Compression")), ACTMAP(XF_COMPW), OPTe(webp_presets, 0, webp_p, change_image_format), ACTMAP(XF_COMPW), MLABELr(_("WebP Save Quality (100=High)")), ACTMAP(XF_COMPWT), MLABELr(_("V8 Save Quality (100=High)")), ACTMAP(XF_COMPV8), SPIN(webp_q, 0, 100), ACTMAP(XF_COMPV8 | XF_COMPWT), MLABELr(_("V8L Compression (0=None)")), ACTMAP(XF_COMPV8L), SPIN(webp_c, 0, 9), ACTMAP(XF_COMPV8L), MLABELr(_("Hotspot at X =")), ACTMAP(XF_SPOT), SPINa(xx), ACTMAP(XF_SPOT), MLABELr(_("Y =")), ACTMAP(XF_SPOT), SPINa(xy), ACTMAP(XF_SPOT), ENDIF(1), IFx(need_anim, 1), MLABEL(_("Animation delay")), SPIN(gif_delay, 1, MAX_DELAY), ENDIF(1), IF(need_undo), CHECK(_("Undoable"), undo), #ifdef U_LCMS IF(need_icc), CHECK(_("Apply colour profile"), icc), #endif WDONE, IFx(script, 1), /* For loading multiframe files */ CHECK("Load into Layers", load_lr), uPATHSTR(ex_path), OPNAME("Explode Frames"), OPTv(modes_txt, 3, anim_mode), OPNAME("Frames"), /* For loading scalable images */ SPIN(w, 0, MAX_WIDTH), OPNAME("Width"), SPIN(h, 0, MAX_HEIGHT), OPNAME("Height"), ENDIF(1), WXYWH("fs_window", 550, 500), CLEANUP(frames_name), RAISED, WSHOW }; #undef WBbase void file_selector_x(int action_type, void **xdata) { fselector_dd tdata; char *names[NUM_FTYPES + 1], *tiffnames[TIFF_MAX_TYPES], *ext = NULL; int def = FT_PNG; memset(&tdata, 0, sizeof(tdata)); tdata.script = !!script_cmds; tdata.mode = action_type; tdata.fpmode = FPICK_ENTRY; tdata.xtrans[0] = mem_xpm_trans; tdata.xtrans[1] = -1; tdata.xtrans[2] = mem_cols - 1; switch (action_type) { case FS_PNG_LOAD: if ((!script_cmds || !undo_load) && ((layers_total ? check_layers_for_changes() : check_for_changes()) == 1)) return; tdata.title = _("Load Image File"); tdata.fpmode = FPICK_LOAD; tdata.need_undo = TRUE; #ifdef U_LCMS tdata.need_icc = TRUE; #endif if (script_cmds) { tdata.fmask = FF_IMAGE; ext = ""; def = FT_NONE; } break; case FS_PNG_SAVE: tdata.fmask = FF_SAVE_MASK; tdata.title = _("Save Image File"); if (mem_filename) strncpy(tdata.filename, mem_filename, PATHBUF); tdata.need_save = TRUE; break; case FS_PALETTE_LOAD: tdata.title = _("Load Palette File"); tdata.fpmode = FPICK_LOAD; break; case FS_PALETTE_SAVE: tdata.fmask = FF_PALETTE; def = FT_GPL; tdata.title = _("Save Palette File"); break; case FS_EXPORT_UNDO: if (!mem_undo_done) return; tdata.fmask = FF_IMAGE; tdata.title = _("Export Undo Images"); break; case FS_EXPORT_UNDO2: if (!mem_undo_done) return; tdata.fmask = FF_IMAGE; tdata.title = _("Export Undo Images (reversed)"); break; case FS_EXPORT_ASCII: if (mem_cols > 16) { alert_box( _("Error"), _("You must have 16 or fewer palette colours to export ASCII art."), NULL); return; } tdata.title = _("Export ASCII Art"); break; case FS_LAYER_SAVE: /* !!! No selectable layer file format yet */ if (check_layers_all_saved()) return; tdata.title = _("Save Layer Files"); strncpy(tdata.filename, layers_filename, PATHBUF); break; case FS_EXPLODE_FRAMES: tdata.frames_name = strdup(xdata[0]); tdata.frames_ftype = (int)xdata[1]; tdata.frames_anim = (int)xdata[2]; ext = file_formats[tdata.frames_ftype].ext; tdata.fmask = FF_IMAGE; tdata.title = _("Choose frames directory"); tdata.fpmode = FPICK_DIRS_ONLY; break; case FS_EXPORT_GIF: /* !!! No selectable formats yet */ if (!mem_filename) { alert_box(_("Error"), _("You must save at least one frame to create an animated GIF."), NULL); return; } tdata.title = _("Export GIF animation"); tdata.need_anim = TRUE; break; case FS_CHANNEL_LOAD: tdata.title = _("Load Channel"); tdata.fpmode = FPICK_LOAD; #ifdef U_LCMS tdata.need_icc = MEM_BPP == 3; #endif break; case FS_CHANNEL_SAVE: tdata.fmask = mem_channel != CHN_IMAGE ? FF_256 : FF_SAVE_MASK; tdata.title = _("Save Channel"); tdata.need_save = TRUE; break; case FS_COMPOSITE_SAVE: tdata.fmask = FF_RGB; tdata.title = _("Save Composite Image"); tdata.need_save = TRUE; if (layer_selected) // Use background's transparency { image_info *image = &layer_table[0].image->image_; tdata.xtrans[0] = image->trans; tdata.xtrans[2] = image->cols - 1; } break; case FS_CLIP_FILE: case FS_SELECT_FILE: case FS_SELECT_DIR: tdata.fpmode = action_type == FS_SELECT_DIR ? FPICK_LOAD | FPICK_DIRS_ONLY : FPICK_LOAD; tdata.title = xdata[0]; tdata.pathbox = xdata[1]; // pathbox slot cmd_peekv(xdata[1], tdata.filename, PATHBUF, PATH_VALUE); break; default: /* FS_LAYER_LOAD, FS_PATTERN_LOAD, FS_CLIPBOARD, FS_PALETTE_DEF */ return; /* These are not for here */ } /* Default filename */ if (!tdata.filename[0]) file_in_dir(tdata.filename, inifile_get("last_dir", get_home_directory()), action_type == FS_LAYER_SAVE ? "layers.txt" : "", PATHBUF); if (!ext) { ext = strrchr(tdata.filename, '.'); ext = ext ? ext + 1 : ""; } /* Filetype selectors */ if (tdata.fmask) { tdata.ftype = ftype_selector(tdata.fmask, ext, def, tdata.ftnames = names, tdata.ftypes); tdata.tiff_m = tiff_type_selector(tdata.fmask, tdata.fmask & FF_RGB ? tiff_rtype : tdata.fmask & FF_BW ? tiff_btype : tiff_itype, tdata.tiffnames = tiffnames); } tdata.xx[0] = mem_xbm_hot_x; tdata.xx[1] = -1; tdata.xx[2] = mem_width - 1; tdata.xy[0] = mem_xbm_hot_y; tdata.xy[1] = -1; tdata.xy[2] = mem_height - 1; tdata.jpeg_c = jpeg_quality; tdata.png_c = png_compression; tdata.tga_c = tga_RLE; tdata.jp2_c = jp2_rate; tdata.lzma_c = lzma_preset; tdata.zstd_c = zstd_level; tdata.webp_p = webp_preset; tdata.webp_q = webp_quality; tdata.webp_c = webp_compression; tdata.gif_delay = preserved_gif_delay; tdata.undo = undo_load; #ifdef U_LCMS tdata.icc = apply_icc; #endif run_create_(fselector_code, &tdata, sizeof(tdata), script_cmds); } void file_selector(int action_type) { file_selector_x(action_type, NULL); } void canvas_center(float ic[2]) // Center of viewable area { int w, h, xyhv[4]; ic[0] = ic[1] = 0.5; if (script_cmds) return; cmd_peekv(scrolledwindow_canvas, xyhv, sizeof(xyhv), CSCROLL_XYSIZE); canvas_size(&w, &h); if (xyhv[2] < w) ic[0] = (xyhv[0] + xyhv[2] * 0.5) / w; if (xyhv[3] < h) ic[1] = (xyhv[1] + xyhv[3] * 0.5) / h; } void align_size(float new_zoom) // Set new zoom level { static int zoom_flag; if (zoom_flag) return; // Needed as we could be called twice per iteration if (new_zoom < MIN_ZOOM) new_zoom = MIN_ZOOM; if (new_zoom > MAX_ZOOM) new_zoom = MAX_ZOOM; if (new_zoom == can_zoom) return; zoom_flag = 1; if (!mem_ics && !cmd_mode) { int xc, yc, dx, dy, w, h, x, y, xyhv[4]; cmd_peekv(scrolledwindow_canvas, xyhv, sizeof(xyhv), CSCROLL_XYSIZE); xc = xyhv[0] * 2 + (w = xyhv[2]); yc = xyhv[1] * 2 + (h = xyhv[3]); dx = dy = 0; if (cursor_zoom) { mouse_ext m; cmd_peekv(drawing_canvas, &m, sizeof(m), CANVAS_FIND_MOUSE); x = m.x - xyhv[0]; y = m.y - xyhv[1]; if ((x >= 0) && (x < w) && (y >= 0) && (y < h)) dx = x * 2 - w , dy = y * 2 - h; } mem_icx = ((xc + dx - margin_main_x * 2) / can_zoom - dx / new_zoom) / (mem_width * 2); mem_icy = ((yc + dy - margin_main_y * 2) / can_zoom - dy / new_zoom) / (mem_height * 2); } mem_ics = 0; can_zoom = new_zoom; realign_size(); zoom_flag = 0; } void realign_size() // Reapply old zoom { int xyhv[4], xywh[4]; if (cmd_mode) return; cmd_peekv(scrolledwindow_canvas, xyhv, sizeof(xyhv), CSCROLL_XYSIZE); canvas_size(xywh + 2, xywh + 3); xywh[0] = xywh[1] = 0; // New positions of scrollbar if (xyhv[2] < xywh[2]) xywh[0] = rint(xywh[2] * mem_icx - xyhv[2] * 0.5); if (xyhv[3] < xywh[3]) xywh[1] = rint(xywh[3] * mem_icy - xyhv[3] * 0.5); /* !!! CSCROLL's self-updating for CANVAS resize is delayed in GTK+, as * is the actual resize; so to communicate new position to that latter * resize, I preset both position and range of CSCROLL here - WJ */ cmd_setv(scrolledwindow_canvas, xywh, CSCROLL_XYRANGE); cmd_setv(drawing_canvas, xywh + 2, CANVAS_SIZE); vw_focus_view(); // View window position may need updating toolbar_zoom_update(); // Zoom factor may have been reset } /* This tool is seamless: doesn't draw pixels twice if not requested to - WJ */ // !!! With GCC inlining this, weird size fluctuations can happen void rec_continuous(int nx, int ny, int w, int h) { linedata line1, line2, line3, line4; int ws2 = w >> 1, hs2 = h >> 1; int i, j, i2, j2, *xv; int dx[3] = {-ws2, w - ws2 - 1, -ws2}; int dy[3] = {-hs2, h - hs2 - 1, -hs2}; i = nx < tool_ox; j = ny < tool_oy; /* Redraw starting square only if need to fill in possible gap when * size changes, or to draw stroke gradient in the proper direction */ if (!tablet_working && !script_cmds && ((tool_type == TOOL_CLONE) || !STROKE_GRADIENT)) { i2 = tool_ox + dx[i + 1] + 1 - i * 2; j2 = tool_oy + dy[j + 1] + 1 - j * 2; xv = &line3[0]; } else { i2 = tool_ox + dx[i]; j2 = tool_oy + dy[j]; xv = &i2; } if (tool_ox == nx) { line_init(line1, tool_ox + dx[i], j2, tool_ox + dx[i], ny + dy[j + 1]); line_init(line3, tool_ox + dx[i + 1], j2, tool_ox + dx[i + 1], ny + dy[j + 1]); line2[2] = line4[2] = -1; } else { line_init(line2, tool_ox + dx[i], tool_oy + dy[j + 1], nx + dx[i], ny + dy[j + 1]); line_nudge(line2, i2, j2); line_init(line3, tool_ox + dx[i + 1], tool_oy + dy[j], nx + dx[i + 1], ny + dy[j]); line_nudge(line3, i2, j2); line_init(line1, *xv, line3[1], *xv, line2[1]); line_init(line4, nx + dx[i + 1], ny + dy[j], nx + dx[i + 1], ny + dy[j + 1]); } /* Prevent overwriting clone source */ while (tool_type == TOOL_CLONE) { if ((j * 2 - 1) * clone_dy <= 0) break; // Ahead of dest if (mem_undo_opacity && (mem_undo_previous(mem_channel) != mem_img[mem_channel])) break; // In another frame #if 0 /* No real reason to spend code on avoiding the flip */ i = abs(ny - tool_oy) + h - 1; if ((clone_dy < -i) || (clone_dy > i)) break; // Out Y range i = abs(nx - tool_ox) + w - 1; if ((clone_dx < -i) || (clone_dx > i)) break; // Out X range #endif line_flip(line1); line_flip(line3); if (tool_ox == nx) break; // Only 2 lines line_flip(line2); line_flip(line4); draw_quad(line2, line1, line4, line3); return; } draw_quad(line1, line2, line3, line4); } static struct { float c_zoom; int points; int xy[2 * MAX_POLY + 2]; // int step[MAX_POLY + 1]; } poly_cache; static void poly_update_cache() { // int dx, dy, *ps; int i, i0, last, *pxy, ds, zoom = 1, scale = 1; i0 = poly_cache.c_zoom == can_zoom ? poly_cache.points : 0; last = poly_points + (poly_status == POLY_DONE); if (i0 >= last) return; // Up to date /* !!! This uses the fact that zoom factor is either N or 1/N !!! */ if (can_zoom < 1.0) zoom = rint(1.0 / can_zoom); else scale = rint(can_zoom); ds = scale >> 1; poly_cache.c_zoom = can_zoom; poly_cache.points = last; /* Get locations */ pxy = poly_cache.xy + i0 * 2; for (i = i0; i < poly_points; i++) { *pxy++ = floor_div(poly_mem[i][0] * scale, zoom) + ds; *pxy++ = floor_div(poly_mem[i][1] * scale, zoom) + ds; } /* Join 1st & last point if finished */ if (poly_status == POLY_DONE) { *pxy++ = poly_cache.xy[0]; *pxy++ = poly_cache.xy[1]; } #if 0 /* No need for now */ /* Get distances */ poly_cache.step[0] = 0; if (!i0) i0 = 1; ps = poly_cache.step + i0 - 1; pxy = poly_cache.xy + i0 * 2 - 2; for (i = i0; i < last; i++ , pxy += 2 , ps++) { dx = abs(pxy[2] - pxy[0]); dy = abs(pxy[3] - pxy[1]); ps[1] = ps[0] + (dx > dy ? dx : dy); } #endif } void stretch_poly_line(int x, int y) // Clear old temp line, draw next temp line { int old[4]; if (!poly_points || (poly_points >= MAX_POLY)) return; if ((line_x2 == x) && (line_y2 == y)) return; // This check reduces flicker copy4(old, line_xy); line_x2 = x; line_y2 = y; line_x1 = poly_mem[poly_points - 1][0]; line_y1 = poly_mem[poly_points - 1][1]; repaint_line(old); } static void refresh_lines(const int xy0[4], const int xy1[4]); static void poly_conclude() { if (!poly_points) poly_status = POLY_NONE; else { int n = poly_points - 1, edge[4] = { poly_mem[0][0], poly_mem[0][1], poly_mem[n][0], poly_mem[n][1] }; poly_status = POLY_DONE; poly_bounds(); check_marquee(); poly_update_cache(); /* Combine erasing old line with drawing final segment: * there is no new line to be drawn */ refresh_lines(line_xy, edge); } update_stuff(UPD_PSEL); } static void poly_add_po(int x, int y) { if (!poly_points) poly_cache.c_zoom = 0; // Invalidate else if (!((x - poly_mem[poly_points - 1][0]) | (y - poly_mem[poly_points - 1][1]))) return; // Never stack poly_add(x, y); if (poly_points >= MAX_POLY) poly_conclude(); else { int n = poly_points > 1 ? poly_points - 2 : 0; int old[4], edge[4] = { poly_mem[n][0], poly_mem[n][1], x, y }; poly_update_cache(); copy4(old, line_xy); line_x1 = line_x2 = x; line_y1 = line_y2 = y; /* Combine erasing old line with redrawing new segment: * the 1-point new line will be drawn as part of it */ refresh_lines(old, edge); update_sel_bar(FALSE); } } static void poly_delete_po(int x, int y) { if ((poly_status != POLY_SELECTING) && (poly_status != POLY_DONE)) return; // Do nothing if (poly_points < 2) // Remove the only point { pressed_select(FALSE); return; } if (poly_status == POLY_SELECTING) // Delete last { poly_points--; /* New place for line */ line_x2 = x; line_y2 = y; line_x1 = poly_mem[poly_points - 1][0]; line_y1 = poly_mem[poly_points - 1][1]; } else // Delete nearest { int i, ll, idx = 0, l = INT_MAX; for (i = 0; i < poly_points; i++) { ll = (poly_mem[i][0] - x) * (poly_mem[i][0] - x) + (poly_mem[i][1] - y) * (poly_mem[i][1] - y); if (ll < l) idx = i , l = ll; } memmove(poly_mem[idx], poly_mem[idx + 1], sizeof(poly_mem[0]) * (--poly_points - idx)); poly_bounds(); check_marquee(); } poly_cache.c_zoom = 0; // Invalidate update_stuff(UPD_PSEL | UPD_RENDER); } static int tool_draw(int x, int y, int first_point, int *update) { static int ncx, ncy; int minx, miny, xw, yh, ts2, tr2; int i, j, k, ox, oy, px, py, rx, ry, sx, sy, off1, off2; ts2 = tool_size >> 1; tr2 = tool_size - ts2 - 1; minx = x - ts2; miny = y - ts2; xw = yh = tool_size; /* Save the brush coordinates for next step */ ox = ncx; oy = ncy; ncx = x; ncy = y; switch (tool_type) { case TOOL_SQUARE: case TOOL_CLONE: f_rectangle(x - ts2, y - ts2, tool_size, tool_size); break; case TOOL_CIRCLE: f_circle(x, y, tool_size); break; case TOOL_HORIZONTAL: miny = y; yh = 1; sline(x - ts2, y, x + tr2, y); break; case TOOL_VERTICAL: minx = x; xw = 1; sline(x, y - ts2, x, y + tr2); break; case TOOL_SLASH: sline(x + tr2, y - ts2, x - ts2, y + tr2); break; case TOOL_BACKSLASH: sline(x - ts2, y - ts2, x + tr2, y + tr2); break; case TOOL_SPRAY: for (j = 0; j < tool_flow; j++) { rx = x - ts2 + rand() % tool_size; ry = y - ts2 + rand() % tool_size; IF_IN_RANGE(rx, ry) put_pixel(rx, ry); } break; case TOOL_SHUFFLE: for (j = 0; j < tool_flow; j++) { rx = x - ts2 + rand() % tool_size; ry = y - ts2 + rand() % tool_size; sx = x - ts2 + rand() % tool_size; sy = y - ts2 + rand() % tool_size; IF_IN_RANGE(rx, ry) IF_IN_RANGE(sx, sy) { /* !!! Or do something for partial mask too? !!! */ if (pixel_protected(rx, ry) || pixel_protected(sx, sy)) continue; off1 = rx + ry * mem_width; off2 = sx + sy * mem_width; if ((mem_channel == CHN_IMAGE) && RGBA_mode && mem_img[CHN_ALPHA]) { px = mem_img[CHN_ALPHA][off1]; py = mem_img[CHN_ALPHA][off2]; mem_img[CHN_ALPHA][off1] = py; mem_img[CHN_ALPHA][off2] = px; } k = MEM_BPP; off1 *= k; off2 *= k; for (i = 0; i < k; i++) { px = mem_img[mem_channel][off1]; py = mem_img[mem_channel][off2]; mem_img[mem_channel][off1++] = py; mem_img[mem_channel][off2++] = px; } } } break; case TOOL_SMUDGE: if (first_point) return (FALSE); mem_smudge(ox, oy, x, y); break; default: return (FALSE); /* Stop this nonsense now! */ } /* Accumulate update info */ if (minx < update[0]) update[0] = minx; if (miny < update[1]) update[1] = miny; xw += minx; yh += miny; if (xw > update[2]) update[2] = xw; if (yh > update[3]) update[3] = yh; return (TRUE); } void line_to_gradient() { if (STROKE_GRADIENT) { grad_info *grad = gradient + mem_channel; grad->gmode = GRAD_MODE_LINEAR; grad->status = GRAD_DONE; copy4(grad->xy, line_xy); grad_update(grad); } } void do_tool_action(int cmd, int x, int y, int pressure) { static double lstep; linedata ncline; double len1; int update_area[4]; int minx = -1, miny = -1, xw = -1, yh = -1; tool_info o_tool = tool_state; int i, j, ts2, tr2, ox, oy; int oox, ooy; // Continuous smudge stuff int first_point, pswap = FALSE; // Only do something with a new point if (!(first_point = !pen_down) && (cmd & TCF_ONCE) && (tool_ox == x) && (tool_oy == y)) return; // Apply pressure if ((cmd & TCF_PRES) && (tablet_working || script_cmds)) { // !!! Later maybe switch the calculations to integer double p = pressure <= (MAX_PRESSURE * 2 / 10) ? -1.0 : (pressure - MAX_PRESSURE) * (10.0 / (8 * MAX_PRESSURE)); p /= MAX_TF; for (i = 0; i < 3; i++) { if (!tablet_tool_use[i]) continue; tool_state.var[i] *= (tablet_tool_factor[i] > 0) + tablet_tool_factor[i] * p; if (tool_state.var[i] < 1) tool_state.var[i] = 1; } } ts2 = tool_size >> 1; tr2 = tool_size - ts2 - 1; switch (cmd &= TC_OPMASK) { case TC_LINE_START: case TC_LINE_ARROW: line_x2 = x; line_y2 = y; if (line_status == LINE_NONE) { line_x1 = x; line_y1 = y; } // Draw circle at x, y if (line_status == LINE_LINE) { grad_info svgrad = gradient[mem_channel]; /* If not called from draw_arrow() */ if (cmd != TC_LINE_ARROW) line_to_gradient(); mem_undo_next(UNDO_TOOL); if (tool_size > 1) { int oldmode = mem_undo_opacity; mem_undo_opacity = TRUE; f_circle(line_x1, line_y1, tool_size); f_circle(line_x2, line_y2, tool_size); // Draw tool_size thickness line from 1-2 tline(line_x1, line_y1, line_x2, line_y2, tool_size); mem_undo_opacity = oldmode; } else sline(line_x1, line_y1, line_x2, line_y2); minx = (line_x1 < line_x2 ? line_x1 : line_x2) - ts2; miny = (line_y1 < line_y2 ? line_y1 : line_y2) - ts2; xw = abs( line_x2 - line_x1 ) + 1 + tool_size; yh = abs( line_y2 - line_y1 ) + 1 + tool_size; line_x1 = line_x2; line_y1 = line_y2; gradient[mem_channel] = svgrad; } line_status = LINE_START; break; case TC_LINE_NEXT: line_status = LINE_LINE; repaint_line(NULL); break; case TC_LINE_STOP: stop_line(); break; case TC_SEL_CLEAR: pressed_select(FALSE); break; case TC_SEL_START: case TC_SEL_SET_0: case TC_SEL_SET_1: case TC_SEL_SET_2: case TC_SEL_SET_3: if (cmd == TC_SEL_START) { marq_x1 = x; marq_y1 = y; } else { paint_marquee(MARQ_HIDE, 0, 0, NULL); i = cmd - TC_SEL_SET_0; if (!(i & 1) ^ (marq_x1 > marq_x2)) marq_x1 = marq_x2; if (!(i & 2) ^ (marq_y1 > marq_y2)) marq_y1 = marq_y2; set_cursor(NULL); } marq_x2 = x; marq_y2 = y; marq_status = MARQUEE_SELECTING; paint_marquee(MARQ_SNAP, 0, 0, NULL); break; case TC_SEL_TO: paint_marquee(MARQ_SIZE, x, y, NULL); break; case TC_SEL_STOP: marq_status = marq_status == MARQUEE_PASTE_DRAG ? MARQUEE_PASTE : MARQUEE_DONE; cursor_corner = -1; // !!! Here fallthrough to setting cursor break; case TC_POLY_START: case TC_POLY_START_D: poly_status = cmd == TC_POLY_START ? POLY_SELECTING : POLY_DRAGGING; // Fallthrough case TC_POLY_ADD: poly_add_po(x, y); break; case TC_POLY_DEL: poly_delete_po(x, y); break; case TC_POLY_CLOSE: poly_conclude(); break; case TC_PASTE_PSWAP: pswap = TRUE; // Fallthrough case TC_PASTE_DRAG: case TC_PASTE_PAINT: if (marq_status != MARQUEE_PASTE_DRAG) { marq_status = MARQUEE_PASTE_DRAG; marq_drag_x = x - marq_x1; marq_drag_y = y - marq_y1; } else paint_marquee(MARQ_MOVE, x - marq_drag_x, y - marq_drag_y, NULL); if (cmd == TC_PASTE_DRAG) break; cmd = TC_PASTE_COMMIT; // Fallthrough case TC_PAINT_B: if (cmd == TC_PAINT_B) { tint_mode[2] = 3; /* Swap tint +/- */ if (first_point && !tint_mode[0]) { col_reverse = TRUE; mem_swap_cols(FALSE); } } // Fallthrough case TC_PAINT: case TC_PASTE_COMMIT: // Update stroke gradient if (STROKE_GRADIENT) grad_stroke(x, y); /* Handle floodfill here, as too irregular a non-continuous tool */ if (tool_type == TOOL_FLOOD) { /* Non-masked start point, and working fill */ if ((pixel_protected(x, y) < 255) && flood_fill(x, y, get_pixel(x, y))) { // All pixels could change minx = miny = 0; xw = mem_width; yh = mem_height; } /* Undo the color swap if fill failed */ if (!pen_down && col_reverse) { col_reverse = FALSE; mem_swap_cols(FALSE); } break; } // Relativize source coords if that isn't yet done if (tool_type == TOOL_CLONE) { if ((clone_status == CLONE_ABS) || (clone_status == (CLONE_REL | CLONE_TRACK))) clone_dx = clone_x - x , clone_dy = clone_y - y; clone_status = (clone_status & CLONE_ABS) | CLONE_DRAG; } // Do memory stuff for undo mem_undo_next(UNDO_TOOL); /* Handle continuous mode */ if (mem_continuous && !first_point) { minx = tool_ox < x ? tool_ox : x; xw = (tool_ox > x ? tool_ox : x) - minx + tool_size; minx -= ts2; miny = tool_oy < y ? tool_oy : y; yh = (tool_oy > y ? tool_oy : y) - miny + tool_size; miny -= ts2; if ((tool_type == TOOL_CLONE) || (ts2 ? tool_type == TOOL_SQUARE : tool_type < TOOL_SPRAY)) { rec_continuous(x, y, tool_size, tool_size); break; } if (tool_type == TOOL_CIRCLE) { /* Redraw stroke gradient in proper direction */ if (STROKE_GRADIENT) f_circle(tool_ox, tool_oy, tool_size); tline(tool_ox, tool_oy, x, y, tool_size); f_circle(x, y, tool_size); break; } if (tool_type == TOOL_HORIZONTAL) { miny += ts2; yh -= tool_size - 1; rec_continuous(x, y, tool_size, 1); break; } if (tool_type == TOOL_VERTICAL) { minx += ts2; xw -= tool_size - 1; rec_continuous(x, y, 1, tool_size); break; } if (tool_type == TOOL_SLASH) { g_para(x + tr2, y - ts2, x - ts2, y + tr2, tool_ox - x, tool_oy - y); break; } if (tool_type == TOOL_BACKSLASH) { g_para(x - ts2, y - ts2, x + tr2, y + tr2, tool_ox - x, tool_oy - y); break; } if (tool_type == TOOL_SMUDGE) { linedata line; line_init(line, tool_ox, tool_oy, x, y); while (TRUE) { oox = line[0]; ooy = line[1]; if (line_step(line) < 0) break; mem_smudge(oox, ooy, line[0], line[1]); } break; } xw = yh = -1; /* Nothing was done */ } /* Handle non-continuous mode & tools */ update_area[0] = MAX_WIDTH; update_area[1] = MAX_HEIGHT; update_area[2] = update_area[3] = 0; if (first_point) lstep = 0.0; if (first_point || !brush_spacing) /* Single point */ { if (cmd == TC_PASTE_COMMIT) commit_paste(pswap, update_area); // At marquee else tool_draw(x, y, first_point, update_area); } else /* Multiple points */ { /* Use marquee coords for paste */ i = j = 0; ox = marq_x1; oy = marq_y1; if (cmd == TC_PASTE_COMMIT) { i = marq_x1 - x; j = marq_y1 - y; } line_init(ncline, tool_ox + i, tool_oy + j, x + i, y + j); i = abs(x - tool_ox); j = abs(y - tool_oy); len1 = sqrt(i * i + j * j) / (i > j ? i : j); while (TRUE) { if (lstep + (1.0 / 65536.0) >= brush_spacing) { /* Drop error for 1-pixel step */ lstep = brush_spacing == 1 ? 0.0 : lstep - brush_spacing; if (cmd == TC_PASTE_COMMIT) { /* Adjust paste location */ marq_x2 += ncline[0] - marq_x1; marq_y2 += ncline[1] - marq_y1; marq_x1 = ncline[0]; marq_y1 = ncline[1]; commit_paste(pswap, update_area); } else if (!tool_draw(ncline[0], ncline[1], first_point, update_area)) break; } if (line_step(ncline) < 0) break; lstep += len1; } marq_x2 += ox - marq_x1; marq_y2 += oy - marq_y1; marq_x1 = ox; marq_y1 = oy; } /* Convert update limits */ minx = update_area[0]; miny = update_area[1]; xw = update_area[2] - minx; yh = update_area[3] - miny; break; } if ((xw > 0) && (yh > 0)) /* Some drawing action */ { if (xw + minx > mem_width) xw = mem_width - minx; if (yh + miny > mem_height) yh = mem_height - miny; if (minx < 0) xw += minx , minx = 0; if (miny < 0) yh += miny , miny = 0; if ((xw > 0) && (yh > 0)) lr_update_area(layer_selected, minx, miny, xw, yh); } tool_ox = x; // Remember the coords just used as they are needed in continuous mode tool_oy = y; tint_mode[2] = 0; /* Default */ if (tablet_working || script_cmds) tool_state = o_tool; } int tool_action(int count, int button, int x, int y) { int cmd = TC_NONE; /* Handle "exceptional" tools */ if (tool_type == TOOL_LINE) // !!! Is pressure sensitivity even useful here, or is it a misfeature? cmd = button == 1 ? TC_LINE_START | TCF_PRES : TC_LINE_STOP; else if ((tool_type == TOOL_SELECT) || (tool_type == TOOL_POLYGON)) { // User wants to drag the paste box if ((button == 1) || (button == 13) || (button == 2)) { if ((marq_status == MARQUEE_PASTE_DRAG) || ((marq_status == MARQUEE_PASTE) && (x >= marq_x1) && (x <= marq_x2) && (y >= marq_y1) && (y <= marq_y2))) cmd = TC_PASTE_DRAG; } // User wants to commit the paste if (((marq_status == MARQUEE_PASTE_DRAG) || (marq_status == MARQUEE_PASTE)) && (((button == 3) && (count == 1)) || ((button == 13) && !count))) cmd = cmd == TC_PASTE_DRAG ? TC_PASTE_PAINT | TCF_PRES : TC_PASTE_COMMIT | TCF_PRES; if ((tool_type == TOOL_SELECT) && (button == 3) && (marq_status == MARQUEE_DONE)) cmd = TC_SEL_CLEAR; if ((tool_type == TOOL_SELECT) && (button == 1) && ((marq_status == MARQUEE_NONE) || (marq_status == MARQUEE_DONE))) // Starting a selection { if (marq_status == MARQUEE_DONE) cmd = TC_SEL_SET_0 + close_to(x, y); else cmd = TC_SEL_START; } else { if (marq_status == MARQUEE_SELECTING) cmd = TC_SEL_TO; // Continuing to make a selection } if (tool_type == TOOL_POLYGON) { if ((poly_status == POLY_NONE) && (marq_status == MARQUEE_NONE)) { // Start doing something if (button == 1) cmd = TC_POLY_START; else if (button) cmd = TC_POLY_START_D; } if (poly_status == POLY_SELECTING) { /* Add another point to polygon */ if (button == 1) cmd = TC_POLY_ADD; /* Stop adding points */ else if (button == 3) cmd = TC_POLY_CLOSE; } // Add point to polygon if (poly_status == POLY_DRAGGING) cmd = TC_POLY_ADD; } } else /* Some other kind of tool */ { if (button == 1) cmd = TC_PAINT | TCF_PRES; /* Does tool draw with color B when right button pressed? */ else if ((button == 3) && ((tool_type <= TOOL_SPRAY) || (tool_type == TOOL_FLOOD))) cmd = TC_PAINT_B | TCF_PRES; } return (cmd); } void check_marquee() // Check marquee boundaries are OK - may be outside limits via arrow keys { if (marq_status >= MARQUEE_PASTE) { marq_x1 = marq_x1 < 1 - mem_clip_w ? 1 - mem_clip_w : marq_x1 > mem_width - 1 ? mem_width - 1 : marq_x1; marq_y1 = marq_y1 < 1 - mem_clip_h ? 1 - mem_clip_h : marq_y1 > mem_height - 1 ? mem_height - 1 : marq_y1; marq_x2 = marq_x1 + mem_clip_w - 1; marq_y2 = marq_y1 + mem_clip_h - 1; return; } /* Reinit marquee from polygon bounds */ if (poly_status == POLY_DONE) copy4(marq_xy, poly_xy); else if (marq_status == MARQUEE_NONE) return; /* Selection mode in operation */ marq_x1 = marq_x1 < 0 ? 0 : marq_x1 >= mem_width ? mem_width - 1 : marq_x1; marq_x2 = marq_x2 < 0 ? 0 : marq_x2 >= mem_width ? mem_width - 1 : marq_x2; marq_y1 = marq_y1 < 0 ? 0 : marq_y1 >= mem_height ? mem_height - 1 : marq_y1; marq_y2 = marq_y2 < 0 ? 0 : marq_y2 >= mem_height ? mem_height - 1 : marq_y2; } void paint_poly_marquee(rgbcontext *ctx) // Paint polygon marquee { if ((tool_type != TOOL_POLYGON) || !poly_points) return; // !!! Maybe check boundary clipping too poly_update_cache(); draw_poly(poly_cache.xy, poly_cache.points, 0, margin_main_x, margin_main_y, ctx); } static void repaint_clipped(int x0, int y0, int x1, int y1, const int *vxy) { int rxy[4]; if (clip(rxy, x0, y0, x1, y1, vxy)) repaint_canvas(margin_main_x + rxy[0], margin_main_y + rxy[1], rxy[2] - rxy[0], rxy[3] - rxy[1]); } void marquee_at(int *rect) // Read marquee location & size { rect[0] = marq_x1 < marq_x2 ? marq_x1 : marq_x2; rect[1] = marq_y1 < marq_y2 ? marq_y1 : marq_y2; rect[2] = abs(marq_x2 - marq_x1) + 1; rect[3] = abs(marq_y2 - marq_y1) + 1; } static void locate_marquee(int *xy, int snap) { int rxy[4]; int x1, y1, x2, y2, w, h, zoom = 1, scale = 1; if (snap && tgrid_snap) { copy4(rxy, marq_xy); snap_xy(marq_xy); if (marq_status < MARQUEE_PASTE) { snap_xy(marq_xy + 2); marq_xy[(rxy[2] >= rxy[0]) * 2 + 0] += tgrid_dx - 1; marq_xy[(rxy[3] >= rxy[1]) * 2 + 1] += tgrid_dy - 1; } } check_marquee(); /* !!! This uses the fact that zoom factor is either N or 1/N !!! */ if (can_zoom < 1.0) zoom = rint(1.0 / can_zoom); else scale = rint(can_zoom); /* Get onscreen coords */ x1 = floor_div(marq_x1 * scale, zoom); y1 = floor_div(marq_y1 * scale, zoom); x2 = floor_div(marq_x2 * scale, zoom); y2 = floor_div(marq_y2 * scale, zoom); w = abs(x2 - x1) + scale; h = abs(y2 - y1) + scale; xy[2] = (xy[0] = x1 < x2 ? x1 : x2) + w; xy[3] = (xy[1] = y1 < y2 ? y1 : y2) + h; } void paint_marquee(int action, int new_x, int new_y, rgbcontext *ctx) { int xy[4], vxy[4], nxy[4], rxy[4], clips[4 * 3]; int i, nc, rgb, rw, rh, offx, offy, wx, wy, mst = marq_status; vxy[0] = vxy[1] = 0; canvas_size(vxy + 2, vxy + 3); locate_marquee(xy, action == MARQ_SNAP); copy4(nxy, xy); copy4(clips, xy); nc = action < MARQ_HIDE ? 0 : 4; // No clear if showing anew /* Determine which parts moved outside */ while (action >= MARQ_MOVE) { if (action == MARQ_MOVE) // Move { marq_x2 += new_x - marq_x1; marq_x1 = new_x; marq_y2 += new_y - marq_y1; marq_y1 = new_y; } else marq_x2 = new_x , marq_y2 = new_y; // Resize locate_marquee(nxy, TRUE); /* No intersection? */ if (!clip(rxy, xy[0], xy[1], xy[2], xy[3], nxy)) break; /* Horizontal slab */ if (rxy[1] > xy[1]) clips[3] = rxy[1]; // Top else if (rxy[3] < xy[3]) clips[1] = rxy[3]; // Bottom else nc = 0; // None /* Inside area, if left unfilled */ if (!(show_paste && (mst >= MARQUEE_PASTE))) { clips[nc + 0] = nxy[0] + 1; clips[nc + 1] = nxy[1] + 1; clips[nc + 2] = nxy[2] - 1; clips[nc + 3] = nxy[3] - 1; nc += 4; } /* Vertical block */ if (rxy[0] > xy[0]) // Left clips[nc + 0] = xy[0] , clips[nc + 2] = rxy[0]; else if (rxy[2] < xy[2]) // Right clips[nc + 0] = rxy[2] , clips[nc + 2] = xy[2]; else break; // None clips[nc + 1] = rxy[1]; clips[nc + 3] = rxy[3]; nc += 4; break; } /* Clear - only happens in void context */ marq_status = 0; for (i = 0; i < nc; i += 4) { /* Clip to visible portion */ if (!clip(rxy, clips[i + 0], clips[i + 1], clips[i + 2], clips[i + 3], vxy)) continue; /* Redraw entire area */ if (show_paste && (mst >= MARQUEE_PASTE)) repaint_clipped(xy[0], xy[1], xy[2], xy[3], rxy); /* Redraw only borders themselves */ else { repaint_clipped(xy[0], xy[1] + 1, xy[0] + 1, xy[3] - 1, rxy); repaint_clipped(xy[2] - 1, xy[1] + 1, xy[2], xy[3] - 1, rxy); repaint_clipped(xy[0], xy[1], xy[2], xy[1] + 1, rxy); repaint_clipped(xy[0], xy[3] - 1, xy[2], xy[3], rxy); } } marq_status = mst; if (action == MARQ_HIDE) return; // All done for clear /* Determine visible area */ if (ctx) clip(vxy, ctx->xy[0] - margin_main_x, ctx->xy[1] - margin_main_y, ctx->xy[2] - margin_main_x, ctx->xy[3] - margin_main_y, vxy); if (!clip(rxy, nxy[0], nxy[1], nxy[2], nxy[3], vxy)) return; /* Draw */ rgb = RGB_2_INT(255, 0, 0); /* Draw in red */ if (marq_status >= MARQUEE_PASTE) { /* Display paste RGB, only if not being called from repaint_canvas */ if (show_paste && !ctx) repaint_clipped(nxy[0] + 1, nxy[1] + 1, nxy[2] - 1, nxy[3] - 1, vxy); rgb = RGB_2_INT(0, 0, 255); /* Draw in blue */ } rw = rxy[2] - rxy[0]; rh = rxy[3] - rxy[1]; wx = margin_main_x + rxy[0]; wy = margin_main_y + rxy[1]; offx = rxy[0] - nxy[0]; offy = rxy[1] - nxy[1]; if ((nxy[0] >= rxy[0]) && (marq_x1 >= 0) && (marq_x2 >= 0)) draw_dash(rgb, RGB_2_INT(255, 255, 255), offy, wx, wy, 1, rh, ctx); if ((nxy[2] <= rxy[2]) && (marq_x1 < mem_width) && (marq_x2 < mem_width)) draw_dash(rgb, RGB_2_INT(255, 255, 255), offy, wx + rw - 1, wy, 1, rh, ctx); if ((nxy[1] >= rxy[1]) && (marq_y1 >= 0) && (marq_y2 >= 0)) draw_dash(rgb, RGB_2_INT(255, 255, 255), offx, wx, wy, rw, 1, ctx); if ((nxy[3] <= rxy[3]) && (marq_y1 < mem_height) && (marq_y2 < mem_height)) draw_dash(rgb, RGB_2_INT(255, 255, 255), offx, wx, wy + rh - 1, rw, 1, ctx); } int close_to( int x1, int y1 ) // Which corner of selection is coordinate closest to? { return ((x1 + x1 <= marq_x1 + marq_x2 ? 0 : 1) + (y1 + y1 <= marq_y1 + marq_y2 ? 0 : 2)); } static void line_get_xy(int xy[4], linedata line, int y1) { int k, x0, x1, y; xy[1] = y = line[1]; x0 = x1 = line[0]; while ((line[1] < y1) && (line_step(line) >= 0)) x1 = line[0] , y = line[1]; xy[3] = y; k = (x0 > x1) * 2; xy[k] = x0; xy[k ^ 2] = x1; } static void repaint_xy(int xy[4], int scale) { repaint_canvas(margin_main_x + xy[0] * scale, margin_main_y + xy[1] * scale, (xy[2] - xy[0] + 1) * scale, (xy[3] - xy[1] + 1) * scale); } // !!! For now, this function is hardcoded to merge 2 areas static int merge_xy(int cnt, int *xy, int step) { if ((xy[0 + 0] > xy[4 + 2] + step + 1) || (xy[4 + 0] > xy[0 + 2] + step + 1)) return (2); if (xy[0 + 0] > xy[4 + 0]) xy[0 + 0] = xy[4 + 0]; if (xy[0 + 1] > xy[4 + 1]) xy[0 + 1] = xy[4 + 1]; if (xy[0 + 2] < xy[4 + 2]) xy[0 + 2] = xy[4 + 2]; if (xy[0 + 3] < xy[4 + 3]) xy[0 + 3] = xy[4 + 3]; return (1); } /* Only 2 line-quads for now, but will be extended to 4 for line-join drag */ static void refresh_lines(const int xy0[4], const int xy1[4]) { linedata ll1, ll2; int ixy[4], getxy[8], *lines[2] = { ll1, ll2 }; int i, j, y, y1, y2, cnt, step, zoom = 1, scale = 1; if (cmd_mode) return; /* !!! This uses the fact that zoom factor is either N or 1/N !!! */ if (can_zoom < 1.0) zoom = rint(1.0 / can_zoom); else scale = rint(can_zoom); // !!! Could use CSCROLL_XYSIZE here instead cmd_peekv(drawing_canvas, ixy, sizeof(ixy), CANVAS_VPORT); prepare_line_clip(ixy, ixy, scale); for (i = j = 0; j < 2; j++) { const int *xy; int tmp; xy = j ? xy1 : xy0; if (!xy) continue; line_init(lines[i], floor_div(xy[0], zoom), floor_div(xy[1], zoom), floor_div(xy[2], zoom), floor_div(xy[3], zoom)); if (line_clip(lines[i], ixy, &tmp) < 0) continue; if (lines[i][9] < 0) line_flip(lines[i]); i++; } step = scale < 8 ? (16 + scale - 1) / scale : 2; for (cnt = i , y1 = ixy[1]; cnt; y1 += step) { y2 = ixy[3] + 1; for (j = i = 0; i < cnt; i++) { y = lines[i][1]; if (lines[i][2] < 0) // Remove used-up line { lines[i--] = lines[--cnt]; } else if (y >= y1) // Remember not-yet-started line { if (y2 > y) y2 = y; } else line_get_xy(getxy + j++ * 4, lines[i], y1); } if (j) { if (j > 1) j = merge_xy(j, getxy, step); for (i = 0; i < j; i++) repaint_xy(getxy + i * 4, scale); } else y1 = y2; } } static void render_line(int mode, linedata line, int ofs, rgbcontext *ctx) { int rxy[4], cxy[4]; int i, j, x, y, tx, ty, w3, rgb = 0, scale = 1; /* !!! This uses the fact that zoom factor is either N or 1/N !!! */ if (can_zoom > 1.0) scale = rint(can_zoom); copy4(cxy, ctx->xy); w3 = (cxy[2] - cxy[0]) * 3; for (i = ofs; line[2] >= 0; line_step(line) , i++) { x = (tx = line[0]) * scale + margin_main_x; y = (ty = line[1]) * scale + margin_main_y; if (mode == 1) /* Drawing */ { j = ((ty & 7) * 8 + (tx & 7)) * 3; rgb = MEM_2_INT(mem_col_pat24, j); } else if (mode == 2) /* Tracking */ { rgb = ((i >> 2) & 1) * 0xFFFFFF; } else if (mode == 3) /* Gradient */ { rgb = ((i >> 2) & 1) * 0xFFFFFF ^ ((i >> 1) & 1) * 0x00FF00; } if (clip(rxy, x, y, x + scale, y + scale, cxy)) { unsigned char *dest, *tmp; int i, h, l; tmp = dest = ctx->rgb + (rxy[1] - cxy[1]) * w3 + (rxy[0] - cxy[0]) * 3; *tmp++ = INT_2_R(rgb); *tmp++ = INT_2_G(rgb); *tmp++ = INT_2_B(rgb); l = (rxy[2] - rxy[0]) * 3; for (i = l - 3; i; i-- , tmp++) *tmp = *(tmp - 3); tmp = dest; for (h = rxy[3] - rxy[1] - 1; h; h--) { tmp += w3; memcpy(tmp, dest, l); } } } } void repaint_grad(const int *old) { refresh_lines(gradient[mem_channel].xy, old); } void repaint_line(const int *old) { refresh_lines(line_xy, old); } /* lxy is ctx's bounds scaled to "line space" (unchanged for zoom < 0, image * coordinates otherwise) */ void refresh_line(int mode, const int *lxy, rgbcontext *ctx) { linedata line; int j, zoom = 1, *xy; /* !!! This uses the fact that zoom factor is either N or 1/N !!! */ if (can_zoom < 1.0) zoom = rint(1.0 / can_zoom); xy = mode == 3 ? gradient[mem_channel].xy : line_xy; line_init(line, floor_div(xy[0], zoom), floor_div(xy[1], zoom), floor_div(xy[2], zoom), floor_div(xy[3], zoom)); if (line_clip(line, lxy, &j) >= 0) render_line(mode, line, j, ctx); } void update_recent_files(int save) // Update the menu items { char txt[64], *t, txt2[PATHTXT]; int i, j; /* Init from inifile, skipping empty lines */ if (!recent_filenames[0]) { for (i = j = 0; i < MAX_RECENT; i++) { sprintf(txt, "file%i", i + 1); t = inifile_get(txt, ""); if (t[0]) recent_filenames[j++] = strdup(t); } while (j < MAX_RECENT) recent_filenames[j++] = ""; } if (save) /* Store to inifile */ { // !!! Or maybe set everything from recent_files to ""? for (i = 0; i < MAX_RECENT; i++) { sprintf(txt, "file%i", i + 1); inifile_set(txt, recent_filenames[i]); } return; } /* Display recent filenames */ for (i = 0; i < recent_files; i++) { if (!recent_filenames[i][0]) break; // Should only be at end gtkuncpy(txt2, recent_filenames[i], PATHTXT); cmd_setv(menu_slots[MENU_RECENT1 + i], txt2, LABEL_VALUE); cmd_showhide(menu_slots[MENU_RECENT1 + i], TRUE); // Show } /* Hide separator if not needed */ cmd_showhide(menu_slots[MENU_RECENT_S], i); /* Hide extra items */ for (; i < MAX_RECENT; i++) cmd_showhide(menu_slots[MENU_RECENT1 + i], FALSE); } void register_file(char *filename) // Called after successful load/save { char *c; int i; if (!filename[0]) return; // Paranoia c = strrchr(filename, DIR_SEP); if (c) { i = *c; *c = '\0'; // Strip off filename inifile_set("last_dir", filename); *c = i; } /* Is it already in used file list? */ for (i = 0; i < MAX_RECENT; i++) if (!strcmp(recent_filenames[i], filename)) break; /* Copy it into LAST slot if not */ if (i >= MAX_RECENT) { i = MAX_RECENT - 1; if (recent_filenames[i][0]) free(recent_filenames[i]); recent_filenames[i] = strdup(filename); } /* Now rotate it to the top if not already there */ if (i > 0) { filename = recent_filenames[i]; memmove(recent_filenames + 1, recent_filenames, i * sizeof(recent_filenames[0])); recent_filenames[0] = filename; update_recent_files(FALSE); } } void create_default_image() // Create default new image { int nw = inifile_get_gint32("lastnewWidth", DEFAULT_WIDTH ), nh = inifile_get_gint32("lastnewHeight", DEFAULT_HEIGHT ), nc = inifile_get_gint32("lastnewCols", 256 ), nt = inifile_get_gint32("lastnewType", 2 ); do_new_one(nw, nh, nc, nt == 1 ? NULL : mem_pal_def, (nt == 0) || (nt > 2) ? 3 : 1, FALSE); } mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/canvas.h000066400000000000000000000267321471325446300224000ustar00rootroot00000000000000/* canvas.h Copyright (C) 2004-2020 Mark Tyler and Dmitry Groshev This file is part of mtPaint. mtPaint 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. mtPaint 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 mtPaint in the file COPYING. */ float can_zoom; // Zoom factor 1..MAX_ZOOM int margin_main_xy[2]; // Top left of image from top left of canvas int margin_view_xy[2]; int marq_status, marq_xy[4]; // Selection marquee int marq_drag_x, marq_drag_y; // Marquee dragging offset int line_status, line_xy[4]; // Line tool int poly_status; // Polygon selection tool int clone_status, clone_x, clone_y, clone_dx, clone_dy; // Clone tool state int clone_mode, clone_x0, clone_y0, clone_dx0, clone_dy0; // Clone settings int brush_spacing; // Step in non-continuous mode int lasso_sel; // Lasso by selection channel #define margin_main_x margin_main_xy[0] #define margin_main_y margin_main_xy[1] #define margin_view_x margin_view_xy[0] #define margin_view_y margin_view_xy[1] #define marq_x1 marq_xy[0] #define marq_y1 marq_xy[1] #define marq_x2 marq_xy[2] #define marq_y2 marq_xy[3] #define line_x1 line_xy[0] #define line_y1 line_xy[1] #define line_x2 line_xy[2] #define line_y2 line_xy[3] #define MAX_RECENT 20 int recent_files; // Current recent files setting char *recent_filenames[MAX_RECENT]; // Recent filenames themselves int preserved_gif_delay, undo_load; #define STATUS_ITEMS 5 #define STATUS_GEOMETRY 0 #define STATUS_CURSORXY 1 #define STATUS_PIXELRGB 2 #define STATUS_SELEGEOM 3 #define STATUS_UNDOREDO 4 void **label_bar[STATUS_ITEMS]; int col_reverse, // Painting with right button show_paste, // Show contents of clipboard while pasting status_on[STATUS_ITEMS], // Show status bar items? text_paste, // Are we pasting text? canvas_image_centre, // Are we centering the image? chequers_optimize, // Are we optimizing the chequers for speed? cursor_zoom // Are we zooming at cursor position? ; #define LINE_NONE 0 #define LINE_START 1 #define LINE_LINE 2 #define MARQUEE_NONE 0 #define MARQUEE_SELECTING 1 #define MARQUEE_DONE 2 #define MARQUEE_PASTE 3 #define MARQUEE_PASTE_DRAG 4 #define POLY_NONE 0 #define POLY_SELECTING 1 #define POLY_DRAGGING 2 #define POLY_DONE 3 #define GRAD_NONE 0 #define GRAD_START 1 #define GRAD_END 2 #define GRAD_DONE 3 #define CLONE_REL 0 #define CLONE_ABS 1 #define CLONE_TRACK 2 /* Reposition flag */ #define CLONE_DRAG 4 /* Stroke flag */ #define MIN_ZOOM 0.1 #define MAX_ZOOM 80 /* File selector codes */ enum { FS_PNG_LOAD = 1, FS_PNG_SAVE, FS_PALETTE_LOAD, FS_PALETTE_SAVE, FS_CLIP_FILE, FS_EXPORT_UNDO, FS_EXPORT_UNDO2, FS_EXPORT_ASCII, FS_LAYER_SAVE, FS_EXPLODE_FRAMES, FS_EXPORT_GIF, FS_CHANNEL_LOAD, FS_CHANNEL_SAVE, FS_COMPOSITE_SAVE, FS_SELECT_FILE, FS_SELECT_DIR, FS_LAYER_LOAD, FS_PATTERN_LOAD, FS_CLIPBOARD, FS_PALETTE_DEF }; int do_a_load_x(char *fname, int undo, void *v); #define do_a_load(A,B) do_a_load_x(A, B, NULL) void canvas_center(float ic[2]); void align_size(float new_zoom); void realign_size(); int ftype_selector(int mask, char *ext, int def, char **names, int *ftypes); int tiff_type_selector(int mask, int def, char **names); void init_ls_settings(ls_settings *settings, void **wdata); void fs_setup(GtkWidget *fs, int action_type); void file_selector_x(int action_type, void **xdata); void file_selector(int action_type); void set_new_filename(int layer, char *fname); void pressed_do_undo(int redo, int cnt); void line_to_gradient(); // Setup gradient along line tool /* Tool action codes */ enum { TC_NONE = 0, TC_LINE_START, TC_LINE_ARROW, TC_LINE_NEXT, TC_LINE_STOP, TC_SEL_CLEAR, TC_SEL_START, TC_SEL_SET_0, TC_SEL_SET_1, TC_SEL_SET_2, TC_SEL_SET_3, TC_SEL_TO, TC_SEL_STOP, TC_POLY_START, TC_POLY_START_D, TC_POLY_ADD, TC_POLY_DEL, TC_POLY_CLOSE, TC_PASTE_DRAG, TC_PASTE_COMMIT, TC_PASTE_PAINT, TC_PASTE_PSWAP, TC_PAINT, TC_PAINT_B, TC_GRAD_START, TC_GRAD_SET0, TC_GRAD_SET1, TC_GRAD_PICK0, TC_GRAD_PICK1, TC_GRAD_DRAG0, TC_GRAD_DRAG1, TC_GRAD_CLEAR, }; #define TC_OPMASK 0x0FF #define TCF_PRES 0x100 /* Use pressure */ #define TCF_ONCE 0x200 /* Skip repeats */ void do_tool_action(int cmd, int x, int y, int pressure); // Paint some pixels! int tool_action(int count, int button, int x, int y); // Decide what to paint void update_menus(); // Update undo/edit menu int close_to( int x1, int y1 ); #define MARQ_SHOW 0 #define MARQ_SNAP 1 /* show+snap */ #define MARQ_HIDE 2 #define MARQ_MOVE 3 /* +snap */ #define MARQ_SIZE 4 /* +snap */ void paint_marquee(int action, int new_x, int new_y, rgbcontext *ctx); // Draw/clear marquee void paint_poly_marquee(rgbcontext *ctx); // Paint polygon marquee void stretch_poly_line(int x, int y); // Clear old temp line, draw next temp line void update_sel_bar(int now); // Update selection stats on status bar void update_xy_bar(int x, int y); // Update cursor tracking on status bar void init_status_bar(); // Initialize status bar void pressed_lasso(int cut); void pressed_copy(int cut); void pressed_paste(int centre); void pressed_greyscale(int mode); void pressed_convert_rgb(); void pressed_inv(int what); void pressed_map(); void pressed_rectangle(int filled); void pressed_ellipse(int filled); void pressed_edge_detect(); void pressed_sharpen(); void pressed_soften(); void pressed_fx(int what); void pressed_gauss(); void pressed_unsharp(); void pressed_dog(); void pressed_kuwahara(); void pressed_clip_alpha_scale(); void pressed_clip_alphamask(); void pressed_clip_mask(int val); void pressed_clip_mask_all(); void pressed_clip_mask_clear(); void pressed_flip_image_v(); void pressed_flip_image_h(); void pressed_flip_sel_v(); void pressed_flip_sel_h(); void pressed_rotate_image(int dir); void pressed_rotate_sel(int dir); void pressed_rotate_free(); void iso_trans(int mode); void marquee_at(int *rect); // Read marquee location & size void check_marquee(); void commit_paste(int swap, int *update); void repaint_grad(const int *old); // Repaint gradient line and maybe clear old one void repaint_line(const int *old); // Repaint line on canvas and maybe clear old one void refresh_line(int mode, const int *lxy, rgbcontext *ctx); // Refresh a part of line/gradient if needed void register_file( char *filename ); // Called after successful load/save void update_recent_files(int save); // Update the menu items / save to inifile void create_default_image(); // Create default new image /// UPDATE STUFF /* Atomic updates */ #define CF_NAME 0x00000001 /* Name in titlebar */ #define CF_GEOM 0x00000002 /* Image geometry */ #define CF_CGEOM 0x00000004 /* Clipboard geometry */ #define CF_PAL 0x00000008 /* Palette */ #define CF_CAB 0x00000010 /* Current channel's A & B (w/redraw) */ #define CF_AB 0x00000020 /* Colors A & B */ #define CF_GRAD 0x00000040 /* Gradients */ #define CF_MENU 0x00000080 /* Menus and controls */ #define CF_SET 0x00000100 /* Settings toolbar */ #define CF_IMGBAR 0x00000200 /* Image statusbar */ #define CF_SELBAR 0x00000400 /* Selection statusbar */ #define CF_PIXEL 0x00000800 /* Pixel statusbar */ #define CF_PREFS 0x00001000 /* Preferences */ #define CF_CURSOR 0x00002000 /* Cursor */ #define CF_PMODE 0x00004000 /* Paste preview */ #define CF_GMODE 0x00008000 /* Gradient preview */ #define CF_DRAW 0x00010000 /* Image window */ #define CF_VDRAW 0x00020000 /* View window */ #define CF_PDRAW 0x00040000 /* Palette window */ #define CF_TDRAW 0x00080000 /* Color/brush/pattern window */ #define CF_ALIGN 0x00100000 /* Realign image window */ #define CF_VALIGN 0x00200000 /* Realign view window */ #define CF_TRANS 0x00400000 /* Transparent color in layers window */ #define CF_NOW 0x00800000 /* Do not wait for cumulative update */ /* Compound updates */ // Changed image contents #define UPD_IMG (CF_DRAW | CF_VDRAW | CF_PIXEL) // Changed image geometry (+undo) #define UPD_GEOM (CF_GEOM | CF_MENU | CF_IMGBAR | UPD_IMG | UPD_SGEOM) // Added a new channel (+) #define UPD_ADDCH (CF_SET | CF_MENU | CF_IMGBAR | UPD_IMG) // Deleted an existing channel (+) #define UPD_DELCH UPD_ADDCH // Switched to new channel (+) #define UPD_NEWCH (UPD_ADDCH | UPD_CAB | CF_SELBAR) // Switched to existing channel #define UPD_CHAN UPD_NEWCH /* May avoid view window redraw, but won't bother */ // Changed color or value A or B #define UPD_CAB CF_CAB // Changed color A or B #define UPD_AB (CF_AB | CF_GRAD | CF_SET | CF_GMODE | CF_TDRAW | CF_PDRAW) // Changed pattern #define UPD_PAT (CF_AB | CF_TDRAW) // Changed A, B, and pattern #define UPD_ABP UPD_AB // Changed palette #define UPD_PAL (CF_PAL | CF_IMGBAR | CF_PDRAW | UPD_AB | UPD_IMG) // Changed palette and transparent color #define UPD_TPAL (UPD_PAL | CF_TRANS) // Changed drawing mode in some way #define UPD_MODE (CF_PMODE | CF_GMODE) // Toggled gradient mode #define UPD_GMODE CF_DRAW // Changed palette if indexed / image if RGB #define UPD_COL UPD_PAL /* May avoid palette update for RGB, but... */ // Changed image contents (+undo, -redraw) #define UPD_IMGP (CF_MENU | CF_PIXEL) // Copied selection to clipboard #define UPD_COPY CF_MENU // Imported clipboard #define UPD_XCOPY CF_MENU // Converted indexed image to RGB #define UPD_2RGB (CF_MENU | CF_IMGBAR | UPD_IMG | UPD_AB) // Converted RGB image to indexed #define UPD_2IDX (UPD_2RGB | UPD_PAL) // Created or loaded a new image (+) #define UPD_ALL (UPD_GEOM | UPD_PAL | UPD_CAB | CF_TRANS) // Changed clipboard contents #define UPD_CLIP CF_PMODE // Changed rendering options #define UPD_RENDER CF_DRAW // Changed viewing options #define UPD_VIEW CF_VDRAW // Update all views #define UPD_ALLV (CF_DRAW | CF_VDRAW) // Changed clipboard geometry #define UPD_CGEOM (CF_CGEOM | CF_SELBAR) // Changed polygonal selection (-redraw) #define UPD_PSEL (CF_MENU | CF_SELBAR) // Changed selection (-) #define UPD_SEL (UPD_PSEL | CF_CURSOR) // Changed selection geometry (-) #define UPD_SGEOM UPD_PSEL // Initiated pasting something #define UPD_PASTE (UPD_SEL | CF_DRAW | CF_CGEOM) // Changed filename #define UPD_NAME CF_NAME // Changed transparent color (+undo) #define UPD_TRANS (UPD_IMG | CF_IMGBAR | CF_MENU | CF_TRANS) // Changed image contents (+) #define UPD_UIMG (UPD_IMG | CF_MENU) // Cut selection #define UPD_CUT UPD_UIMG // Switched layers #define UPD_LAYER (UPD_ALL | CF_NAME | CF_VALIGN) // Changed color masking #define UPD_CMASK (CF_PDRAW | UPD_MODE) // Changed tool opacity #define UPD_OPAC (CF_GRAD | CF_SET | UPD_MODE) // Done "reset tools" (in addition to UPD_ALL) #define UPD_RESET (CF_NAME | CF_ALIGN | UPD_PAL | UPD_OPAC) // Changed brush #define UPD_BRUSH (CF_SET | CF_CURSOR | CF_TDRAW) // Changed gradient #define UPD_GRAD (CF_GRAD | CF_SET | CF_GMODE) // Changed preferences #define UPD_PREFS (CF_PREFS | CF_MENU | CF_CURSOR | CF_DRAW | CF_VDRAW) // Moved color in palette (no image redraw desired) #define UPD_MVPAL (UPD_PAL & ~UPD_IMG) // Mask covering all kinds of image redraw - for disabling them #define UPD_IMGMASK (UPD_MODE | CF_DRAW | CF_VDRAW) // Changed palette (+undo) #define UPD_UPAL (UPD_PAL | CF_MENU) // !!! Do not forget: CF_MENU also tracks undo stack changes void update_stuff(int flags); mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/channels.c000066400000000000000000000227231471325446300227070ustar00rootroot00000000000000/* channels.c Copyright (C) 2006-2016 Mark Tyler and Dmitry Groshev This file is part of mtPaint. mtPaint 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. mtPaint 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 mtPaint in the file COPYING. */ #include "global.h" #undef _ #define _(X) X #include "mygtk.h" #include "memory.h" #include "vcode.h" #include "png.h" #include "mainwindow.h" #include "otherwindow.h" #include "canvas.h" #include "channels.h" int RGBA_mode; unsigned char channel_rgb[NUM_CHANNELS][3] = { {0, 0, 0}, /* Image */ {0, 0, 255}, /* Alpha */ {255, 255, 0}, /* Selection */ {255, 0, 0} /* Mask */ }; /* The 0-th value is (255 - global opacity) - i.e., image visibility */ unsigned char channel_opacity[NUM_CHANNELS] = {128, 128, 128, 128}; /* 255 for channels where it's better to see inverse values - like alpha */ unsigned char channel_inv[NUM_CHANNELS] = {0, 255, 0, 0}; /* Default fill values for the channels */ unsigned char channel_fill[NUM_CHANNELS] = {0, 255, 0, 0}; /* Per-channel drawing "colours" */ unsigned char channel_col_[2][NUM_CHANNELS] = { {255, 255, 255, 255}, /* A */ {0, 0, 0, 0} /* B */ }; /* Channel disable flags */ int channel_dis[NUM_CHANNELS] = {0, 0, 0, 0}; static void **newchan_window; typedef struct { int chan, state, inv, sens, req; char **names; } cchan_dd; static void click_newchan_cancel(cchan_dd *dt, void **wdata) { cmd_set(menu_slots[MENU_CHAN0 + mem_channel], TRUE); // Stops cancelled new channel showing as selected in the menu run_destroy(wdata); newchan_window = NULL; } #define chan_new_type (dt->chan + CHN_ALPHA) #define chan_new_state (dt->state) static void click_newchan_ok(cchan_dd *dt, void **wdata) { chanlist tlist; int i, ii, j = mem_width * mem_height, range, rgb[3]; unsigned char sq1024[1024], *src, *dest, *tmp; unsigned int k; double r2, rr; run_query(wdata); memcpy(tlist, mem_img, sizeof(chanlist)); if ((chan_new_type == CHN_ALPHA) && (chan_new_state == 3)) i = CMASK_RGBA; else i = CMASK_FOR(chan_new_type); i = undo_next_core(UC_CREATE, mem_width, mem_height, mem_img_bpp, i); if (i) { click_newchan_cancel(dt, wdata); memory_errors(i); return; } dest = mem_img[chan_new_type]; switch (chan_new_state) { case 0: /* Clear */ memset(dest, 0, j); break; case 1: /* Set */ memset(dest, 255, j); break; case 2: /* Colour A radius B */ rgb[0] = mem_col_A24.red; rgb[1] = mem_col_A24.green; rgb[2] = mem_col_A24.blue; range = (mem_col_A24.red - mem_col_B24.red) * (mem_col_A24.red - mem_col_B24.red) + (mem_col_A24.green - mem_col_B24.green) * (mem_col_A24.green - mem_col_B24.green) + (mem_col_A24.blue - mem_col_B24.blue) * (mem_col_A24.blue - mem_col_B24.blue); r2 = 255.0 * 255.0; if (range) r2 /= (double)range; /* Prepare fast-square-root table */ for (i = ii = 0; i < 32; i++) { k = (i + 1) * (i + 1); for (; ii < k; ii++) sq1024[ii] = i; } src = mem_img[CHN_IMAGE]; if (mem_img_bpp == 1) { unsigned char p2l[256]; memset(p2l, 0, 256); for (i = 0; i < mem_cols; i++) { range = (mem_pal[i].red - rgb[0]) * (mem_pal[i].red - rgb[0]) + (mem_pal[i].green - rgb[1]) * (mem_pal[i].green - rgb[1]) + (mem_pal[i].blue - rgb[2]) * (mem_pal[i].blue - rgb[2]); k = rr = r2 * (double)range; /* Fast square root */ if (rr >= (255.0 * 255.0)) ii = 255; else if (k < 1024) ii = sq1024[k]; else { ii = sq1024[k >> 6] << 3; ii = (ii + k / ii) >> 1; ii -= ((k - ii * ii) >> 17) & 1; } p2l[i] = ii ^ 255; } for (i = 0; i < j; i++) { dest[i] = p2l[src[i]]; } } else { for (i = 0; i < j; i++) { range = (src[0] - rgb[0]) * (src[0] - rgb[0]) + (src[1] - rgb[1]) * (src[1] - rgb[1]) + (src[2] - rgb[2]) * (src[2] - rgb[2]); k = rr = r2 * (double)range; /* Fast square root */ if (rr >= (255.0 * 255.0)) ii = 255; else if (k < 1024) ii = sq1024[k]; else { ii = sq1024[k >> 6] << 3; ii += (k - ii * ii) / (ii + ii); ii -= ((k - ii * ii) >> 17) & 1; } dest[i] = ii ^ 255; src += 3; } } break; case 3: /* Blend A to B */ if (mem_img_bpp != 3) goto dofail; memset(dest, 255, j); /* Start with opaque */ if (mem_scale_alpha(mem_img[CHN_IMAGE], dest, mem_width, mem_height, chan_new_type == CHN_ALPHA)) goto dofail; break; case 4: /* Image red */ case 5: /* Image green */ case 6: /* Image blue */ if (mem_img_bpp == 3) /* RGB */ { src = mem_img[CHN_IMAGE] + chan_new_state - 4; for (i = 0; i < j; i++) { dest[i] = *src; src += 3; } } else /* Indexed */ { if (chan_new_state == 4) tmp = &mem_pal[0].red; else if (chan_new_state == 5) tmp = &mem_pal[0].green; else tmp = &mem_pal[0].blue; src = mem_img[CHN_IMAGE]; for (i = 0; i < j; i++) { dest[i] = *(tmp + src[i] * sizeof(png_color)); } } break; case 7: /* Alpha */ case 8: /* Selection */ case 9: /* Mask */ i = chan_new_state - 8; src = tlist[i < 0 ? CHN_ALPHA : !i ? CHN_SEL : CHN_MASK]; if (!src) goto dofail; memcpy(dest, src, j); break; default: /* If all else fails */ dofail: memset(dest, chan_new_type == CHN_ALPHA ? 255 : 0, j); break; } /* Invert */ if (dt->inv) { for (i = 0; i < j; i++) dest[i] ^= 255; } mem_undo_prepare(); if (dt->req >= CHN_ALPHA) { mem_channel = chan_new_type; update_stuff(UPD_NEWCH); } else update_stuff(UPD_ADDCH); click_newchan_cancel(dt, wdata); } #undef chan_new_type #undef chan_new_state #define WBbase cchan_dd static void *cchan_code[] = { WINDOWm(_("Create Channel")), FRPACK(_("Channel Type"), channames_ + CHN_ALPHA, NUM_CHANNELS - CHN_ALPHA, 1, chan), ALTNAME(""), IF(sens), INSENS, FVBOXB(_("Initial Channel State")), BORDER(RPACK, 0), RPACKD(names, 0, state), HSEP, CHECK(_("Inverted"), inv), WDONE, OKBOX(_("OK"), click_newchan_ok, _("Cancel"), click_newchan_cancel), WSHOW }; #undef WBbase #if NUM_CHANNELS > CHN_MASK + 1 #error "Not all channels listed in dialog" #endif void pressed_channel_create(int channel) { char *names2[] = { _("Cleared"), _("Set"), _("Set colour A radius B"), _("Set blend A to B"), _("Image Red"), _("Image Green"), _("Image Blue"), /* I still do not agree that we need to hide these ;-) - WJ */ mem_img[CHN_ALPHA] ? _("Alpha") : "", mem_img[CHN_SEL] ? _("Selection") : "", mem_img[CHN_MASK] ? _("Mask") : "", NULL }; cchan_dd tdata = { channel < CHN_ALPHA ? 0 : channel - CHN_ALPHA, 0, FALSE, channel >= 0, channel, names2 }; newchan_window = run_create_(cchan_code, &tdata, sizeof(tdata), script_cmds); if (script_cmds) newchan_window = NULL; // already destroyed } typedef struct { int cc[NUM_CHANNELS], cf[NUM_CHANNELS]; } dchan_dd; static void click_delete_ok(dchan_dd *dt, void **wdata) { int i, cmask; run_query(wdata); for (i = cmask = 0; i < NUM_CHANNELS; i++) if (dt->cf[i]) cmask |= CMASK_FOR(i); if (cmask) { undo_next_core(UC_DELETE, mem_width, mem_height, mem_img_bpp, cmask); update_stuff(UPD_DELCH); } run_destroy(wdata); } #if NUM_CHANNELS > CHN_MASK + 1 #error "Not all channels listed in dialog" #endif #define WBbase dchan_dd static void *dchan_code[] = { WINDOWm(_("Delete Channels")), IF(cc[CHN_ALPHA]), CHECK(_("Alpha"), cf[CHN_ALPHA]), IF(cc[CHN_SEL]), CHECK(_("Selection"), cf[CHN_SEL]), IF(cc[CHN_MASK]), CHECK(_("Mask"), cf[CHN_MASK]), HSEPl(200), OKBOXB(_("OK"), click_delete_ok, _("Cancel"), NULL), WSHOW }; #undef WBbase void pressed_channel_delete() { dchan_dd tdata; int i, j = FALSE; memset(&tdata, 0, sizeof(tdata)); for (i = CHN_ALPHA; i < NUM_CHANNELS; i++) if (mem_img[i]) j = tdata.cc[i] = TRUE; tdata.cf[mem_channel] = tdata.cc[mem_channel]; /* If utility channels exist at all */ if (j) run_create_(dchan_code, &tdata, sizeof(tdata), script_cmds); } /* Being plugged into update_menus(), this is prone to be called recursively */ void pressed_channel_edit(int state, int channel) { /* Prevent spurious calls */ if (!state || newchan_window || (channel == mem_channel)) return; if (!mem_img[channel]) pressed_channel_create(channel); else { mem_channel = channel; update_stuff(UPD_CHAN); } } void pressed_channel_disable(int state, int channel) { channel_dis[channel] = state; update_stuff(UPD_RENDER); } static int do_threshold(spin1_dd *dt, void **wdata) { run_query(wdata); spot_undo(UNDO_FILT); mem_threshold(mem_img[mem_channel], mem_width * mem_height * MEM_BPP, dt->n[0]); mem_undo_prepare(); return (TRUE); } void pressed_threshold() { static spin1_dd tdata = { { _("Threshold Channel"), spin1_code, FW_FN(do_threshold) }, { 128, 0, 255 } }; run_create_(filterwindow_code, &tdata, sizeof(tdata), script_cmds); } void pressed_unassociate() { if (mem_img_bpp == 1) return; spot_undo(UNDO_COL); mem_demultiply(mem_img[CHN_IMAGE], mem_img[CHN_ALPHA], mem_width * mem_height, 3); mem_undo_prepare(); update_stuff(UPD_IMG); } void pressed_channel_toggle(int state, int what) { int *toggle = what ? &hide_image : &overlay_alpha; *toggle = state; update_stuff(UPD_RENDER); } void pressed_RGBA_toggle(int state) { RGBA_mode = state; update_stuff(UPD_MODE | CF_SET); } mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/channels.h000066400000000000000000000025061471325446300227110ustar00rootroot00000000000000/* channels.h Copyright (C) 2006-2008 Mark Tyler and Dmitry Groshev This file is part of mtPaint. mtPaint 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. mtPaint 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 mtPaint in the file COPYING. */ int RGBA_mode; unsigned char channel_rgb[NUM_CHANNELS][3]; unsigned char channel_opacity[NUM_CHANNELS]; unsigned char channel_inv[NUM_CHANNELS]; unsigned char channel_fill[NUM_CHANNELS]; unsigned char channel_col_[2][NUM_CHANNELS]; #define channel_col_A channel_col_[0] #define channel_col_B channel_col_[1] int channel_dis[NUM_CHANNELS]; void pressed_channel_create(int channel); void pressed_channel_delete(); void pressed_channel_edit(int state, int channel); void pressed_channel_disable(int state, int channel); void pressed_threshold(); void pressed_unassociate(); void pressed_channel_toggle(int state, int what); void pressed_RGBA_toggle(int state); mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/cpick.c000066400000000000000000000775771471325446300222260ustar00rootroot00000000000000/* cpick.c Copyright (C) 2008-2020 Mark Tyler and Dmitry Groshev This file is part of mtPaint. mtPaint 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. mtPaint 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 mtPaint in the file COPYING. */ #include "global.h" #undef _ #define _(X) X #include "mygtk.h" #include "memory.h" #include "vcode.h" #include "inifile.h" #include "png.h" #include "mainwindow.h" #include "icons.h" #include "cpick.h" #ifdef U_CPICK_MTPAINT /* mtPaint dialog */ #if GTK_MAJOR_VERSION == 1 #include // Used by eye dropper #endif #define CPICK_PAL_STRIPS_MIN 1 #define CPICK_PAL_STRIPS_DEFAULT 2 #define CPICK_PAL_STRIPS_MAX 8 /* Max vertical strips the user can have */ #define CPICK_PAL_STRIP_ITEMS 8 /* Colours on each vertical strip */ #define CPICK_PAL_MAX (CPICK_PAL_STRIPS_MAX * CPICK_PAL_STRIP_ITEMS) #define CPICK_SIZE_MIN 64 /* Minimum size of mixer/palette areas */ #define CPICK_SIZE_DEFAULT 128 #define CPICK_SIZE_MAX 1024 /* Maximum size of mixer/palette areas */ #define CPICK_INPUT_RED 0 #define CPICK_INPUT_GREEN 1 #define CPICK_INPUT_BLUE 2 #define CPICK_INPUT_HUE 3 #define CPICK_INPUT_SATURATION 4 #define CPICK_INPUT_VALUE 5 #define CPICK_INPUT_OPACITY 6 #define CPICK_INPUT_HEX 7 #define CPICK_INPUT_TOT 8 /* Manual inputs on the right hand side */ #define CPICK_AREA_PRECUR 0 /* Current / Previous colour swatch */ #define CPICK_AREA_PICKER 1 /* Picker drawing area - Main */ #define CPICK_AREA_HUE 2 /* Picker drawing area - Hue slider */ #define CPICK_AREA_PALETTE 3 /* Palette */ #define CPICK_AREA_OPACITY 4 /* Opacity */ #define CPICK_AREA_TOT 5 #define CPICK_AREA_CURRENT 1 #define CPICK_AREA_PREVIOUS 2 static clipform_dd xcolor = { "application/x-color", NULL, 8, 16 }; typedef struct { int size, // Vertical/horizontal size of main mixer pal_strips, // Number of palette strips input_vals[CPICK_INPUT_TOT], // Current input values rgb_previous[4], // Previous colour/opacity area_size[CPICK_AREA_TOT][3], // Width / height of each wjpixmap lock, // To block input handlers opmask; // To ignore opacity setting } cpicker; typedef struct { void **evt; // Event slot void **drag; // Drag/drop format void **inputs[CPICK_INPUT_TOT], // Spin buttons **areas[CPICK_AREA_TOT]; // Focusable pixmaps unsigned char *imgs[CPICK_AREA_TOT]; // Image buffers int xy[CPICK_AREA_TOT][2]; // Cursor positions int pal[CPICK_PAL_MAX]; // Palette colors int opacity_f; // Opacity flag int drop; // Eyedropper input cpicker c; } cpick_dd; static void cpick_area_picker_create(cpick_dd *dt) { cpicker *win = &dt->c; unsigned char *rgb, *dest, *bw, full[3]; int i, j, k, x, y, w, h, w1, h1, w3, col; double hsv[3]; w = win->area_size[CPICK_AREA_PICKER][0]; h = win->area_size[CPICK_AREA_PICKER][1]; rgb = dt->imgs[CPICK_AREA_PICKER]; w1 = w - 1; h1 = h - 1; w3 = w * 3; // Colour in top right corner hsv[0] = (double)win->input_vals[CPICK_INPUT_HUE] / 255.0; hsv[1] = 1; hsv[2] = 255; hsv2rgb( full, hsv ); /* Bottom row is black->white */ dest = bw = rgb + h1 * w3; for (i = 0; i < w; i++ , dest += 3) dest[0] = dest[1] = dest[2] = (255 * i) / w1; /* And now use it as multiplier for all other rows */ for (y = 0; y < h1; y++) { dest = rgb + y * w3; // Colour on right side, i.e. corner->white k = (255 * (h1 - y)) / h1; for (i = 0; i < 3; i++) { col = (255 * 255) + k * (full[i] - 255); col = (col + (col >> 8) + 1) >> 8; for (x = i; x < w3; x += 3) { j = col * bw[x]; dest[x] = (j + (j >> 8) + 1) >> 8; } } } cmd_reset(dt->areas[CPICK_AREA_PICKER], dt); } static void cpick_precur_paint(int *col, int opacity, unsigned char *rgb, int dx, int w, int ww, int h) { int i, j, k, x, y; unsigned char cols[6], *dest = rgb + dx * 3; for (i = 0; i < 6; i++) { k = greyz[i & 1]; j = 255 * k + opacity * (col[i >> 1] - k); cols[i] = (j + (j >> 8) + 1) >> 8; } ww = (ww - w) * 3; for (y = 0; y < h; y++) { j = (y >> 3) & 1; for (x = 0; x < w; x++) { k = (((x + dx) >> 3) & 1) ^ j; *dest++ = cols[k + 0]; *dest++ = cols[k + 2]; *dest++ = cols[k + 4]; } dest += ww; } } static void cpick_area_precur_create(cpick_dd *dt, int flag) { cpicker *win = &dt->c; unsigned char *rgb; int w, h, w2, w2p; w = win->area_size[CPICK_AREA_PRECUR][0]; h = win->area_size[CPICK_AREA_PRECUR][1]; w2 = w >> 1; w2p = w - w2; rgb = dt->imgs[CPICK_AREA_PRECUR]; if (flag & CPICK_AREA_CURRENT) cpick_precur_paint(win->input_vals + CPICK_INPUT_RED, win->input_vals[CPICK_INPUT_OPACITY], rgb, w2, w2p, w, h); // !!! If I just hide opacity spin, and reorder *_OPACITY after *_GREEN, // it'll be possible to pass all 4 ints for RGBA with a single pointer // Its label doesn't need to be hidden - can still skip creating it like now if (flag & CPICK_AREA_PREVIOUS) cpick_precur_paint(win->rgb_previous, win->rgb_previous[3], rgb, 0, w2, w, h); cmd_reset(dt->areas[CPICK_AREA_PRECUR], dt); } static void cpick_palette_paint(cpick_dd *dt) { unsigned char *dest = dt->imgs[CPICK_AREA_PALETTE]; int i, k, kk, dd, pal_strips = dt->c.pal_strips; dd = dt->c.size / CPICK_PAL_STRIP_ITEMS; for (k = 0; k < CPICK_PAL_STRIP_ITEMS; k++) { unsigned char *tmp; /* Draw one row */ for (kk = 0; kk < pal_strips; kk++) { i = dt->pal[kk * CPICK_PAL_STRIP_ITEMS + k]; tmp = dest + (k * dd * pal_strips + kk) * dd * 3; tmp[0] = INT_2_R(i); tmp[1] = INT_2_G(i); tmp[2] = INT_2_B(i); i = dd * 3 - 3; while (i-- > 0) tmp[3] = *tmp , tmp++; } /* Replicate it */ kk = dd * pal_strips * 3; tmp = dest + k * dd * kk; for (i = 1; i < dd; i++) memcpy(tmp + kk * i, tmp, kk); } } // Forward references static void cpick_area_update_cursors(cpick_dd *dt); static void cpick_refresh_inputs_areas(cpick_dd *dt); static void cpick_get_rgb(cpicker *cp); static void cpick_get_hsv(cpicker *cp); static void set_colour(cpick_dd *dt, int rgb, int opacity) { cpicker *cp = &dt->c; cp->input_vals[CPICK_INPUT_RED] = INT_2_R(rgb); cp->input_vals[CPICK_INPUT_GREEN] = INT_2_G(rgb); cp->input_vals[CPICK_INPUT_BLUE] = INT_2_B(rgb); cp->input_vals[CPICK_INPUT_OPACITY] = (opacity & 0xFF) | cp->opmask; cpick_get_hsv(cp); cpick_refresh_inputs_areas(dt); // Update everything } static void cpick_populate_inputs(cpick_dd *dt) { cpicker *win = &dt->c; int i, n = CPICK_INPUT_OPACITY - !dt->opacity_f; // skip disabled opacity win->lock = TRUE; for (i = 0; i <= n; i++) cmd_set(dt->inputs[i], win->input_vals[i]); cmd_set(dt->inputs[CPICK_INPUT_HEX], RGB_2_INT( win->input_vals[CPICK_INPUT_RED], win->input_vals[CPICK_INPUT_GREEN], win->input_vals[CPICK_INPUT_BLUE])); win->lock = FALSE; } static void cpick_rgba_at(cpick_dd *dt, void **slot, int x, int y, unsigned char *get, unsigned char *set) { cpicker *cp = &dt->c; if (slot == dt->areas[CPICK_AREA_PALETTE]) { char txt[128]; int col, ppc, ini_col; ppc = cp->area_size[CPICK_AREA_PALETTE][1] / CPICK_PAL_STRIP_ITEMS; x /= ppc; y /= ppc; col = y + CPICK_PAL_STRIP_ITEMS * x; if (get) { ini_col = dt->pal[col]; get[0] = INT_2_R(ini_col); get[1] = INT_2_G(ini_col); get[2] = INT_2_B(ini_col); get[3] = cp->input_vals[CPICK_INPUT_OPACITY]; } if (set) { dt->pal[col] = ini_col = MEM_2_INT(set, 0); snprintf(txt, 128, "cpick_pal_%i", col); inifile_set_gint32(txt, ini_col); cpick_palette_paint(dt); cmd_reset(dt->areas[CPICK_AREA_PALETTE], dt); } } else /* if (slot == dt->areas[CPICK_AREA_PRECUR]) */ { int *irgb, *ialpha; int pc = x >= cp->area_size[CPICK_AREA_PRECUR][0] >> 1; if (pc || set) // Current { irgb = cp->input_vals + CPICK_INPUT_RED; ialpha = cp->input_vals + CPICK_INPUT_OPACITY; } else // Previous { irgb = cp->rgb_previous; ialpha = cp->rgb_previous + 3; } if (get) { get[0] = irgb[0]; get[1] = irgb[1]; get[2] = irgb[2]; get[3] = *ialpha; } if (set) { irgb[0] = set[0]; irgb[1] = set[1]; irgb[2] = set[2]; *ialpha = set[3]; if (pc) // Current color changed - announce it { set_colour(dt, MEM_2_INT(set, 0), set[3]); if (dt->evt) do_evt_1_d(dt->evt); } else cpick_area_precur_create(dt, CPICK_AREA_PREVIOUS); } } } static void cpick_area_mouse(void **orig, cpick_dd *dt, int x, int y, int button) { cpicker *cp = &dt->c; int idx, rx, ry, aw, ah, ah1; for (idx = 0; idx < CPICK_AREA_TOT; idx++) if (dt->areas[idx] == orig) break; if (idx >= CPICK_AREA_TOT) return; aw = cp->area_size[idx][0]; ah = cp->area_size[idx][1]; ah1 = ah - 1; rx = x < 0 ? 0 : x >= aw ? aw - 1 : x; ry = y < 0 ? 0 : y > ah1 ? ah1 : y; if ( idx == CPICK_AREA_OPACITY ) { int xy[2] = { aw / 2, ry }; cmd_setv(orig, xy, FCIMAGE_XY); cp->input_vals[CPICK_INPUT_OPACITY] = 255 - (ry * 255) / ah1; } else if ( idx == CPICK_AREA_HUE ) { int xy[2] = { aw / 2, ry }; cmd_setv(orig, xy, FCIMAGE_XY); cp->input_vals[CPICK_INPUT_HUE] = 1529 - (ry * 1529) / ah1; cpick_area_picker_create(dt); cpick_get_rgb(cp); } else if ( idx == CPICK_AREA_PICKER ) { int xy[2] = { rx, ry }; cmd_setv(orig, xy, FCIMAGE_XY); cp->input_vals[CPICK_INPUT_VALUE] = (rx * 255) / (aw - 1); cp->input_vals[CPICK_INPUT_SATURATION] = 255 - (ry * 255) / ah1; cpick_get_rgb(cp); } else if ( idx == CPICK_AREA_PALETTE ) { unsigned char rgba[4]; int ini_col; cpick_rgba_at(dt, orig, rx, ry, rgba, NULL); ini_col = MEM_2_INT(rgba, 0); // Only update if colour is different if (ini_col == RGB_2_INT(cp->input_vals[CPICK_INPUT_RED], cp->input_vals[CPICK_INPUT_GREEN], cp->input_vals[CPICK_INPUT_BLUE])) return; set_colour(dt, ini_col, cp->input_vals[CPICK_INPUT_OPACITY]); } else return; if (idx != CPICK_AREA_PALETTE) // set_colour() does that and more { cpick_populate_inputs(dt); cpick_area_precur_create(dt, CPICK_AREA_CURRENT); } if (dt->evt) do_evt_1_d(dt->evt); } static int cpick_drag_get(cpick_dd *dt, void **wdata, int what, void **where, drag_ext *drag) { void **orig = origin_slot(where); unsigned char drag_rgba[4]; guint16 vals[4]; cpick_rgba_at(dt, orig, drag->x, drag->y, drag_rgba, NULL); if (!drag->format) /* Setting icon color */ cmd_setv(where, (void *)MEM_2_INT(drag_rgba, 0), DRAG_ICON_RGB); else /* Setting drag data */ { void *pp[2] = { vals, vals + 4 }; vals[0] = drag_rgba[0] * 257; vals[1] = drag_rgba[1] * 257; vals[2] = drag_rgba[2] * 257; vals[3] = drag_rgba[3] * 257; cmd_setv(where, pp, DRAG_DATA); } return (TRUE); // Agree to drag } static void cpick_drag_set(cpick_dd *dt, void **wdata, int what, void **where, drag_ext *drag) { void **orig = origin_slot(where); unsigned char rgba[4]; int i; if (drag->len != 8) return; for (i = 0; i < 4; i++) rgba[i] = (((guint16 *)drag->data)[i] + 128) / 257; cpick_rgba_at(dt, orig, drag->x, drag->y, NULL, rgba); } static int cpick_area_event(cpick_dd *dt, void **wdata, int what, void **where, mouse_ext *mouse) { if (mouse->button) cpick_area_mouse(origin_slot(where), dt, mouse->x, mouse->y, mouse->button); return (TRUE); } static void cpick_get_rgb(cpicker *cp) // Calculate RGB values from HSV { unsigned char rgb[3]; double hsv[3] = { (double)cp->input_vals[CPICK_INPUT_HUE] / 255.0, (double)cp->input_vals[CPICK_INPUT_SATURATION] / 255.0, (double)cp->input_vals[CPICK_INPUT_VALUE] }; hsv2rgb( rgb, hsv ); //printf("rgb = %i %i %i\n", rgb[0], rgb[1], rgb[2]); cp->input_vals[CPICK_INPUT_RED] = rgb[0]; cp->input_vals[CPICK_INPUT_GREEN] = rgb[1]; cp->input_vals[CPICK_INPUT_BLUE] = rgb[2]; } static void cpick_get_hsv(cpicker *cp) // Calculate HSV values from RGB { unsigned char rgb[3] = { cp->input_vals[CPICK_INPUT_RED], cp->input_vals[CPICK_INPUT_GREEN], cp->input_vals[CPICK_INPUT_BLUE] }; double hsv[3]; rgb2hsv( rgb, hsv ); // !!! rint() maybe? cp->input_vals[CPICK_INPUT_HUE] = 255 * hsv[0]; cp->input_vals[CPICK_INPUT_SATURATION] = 255 * hsv[1]; cp->input_vals[CPICK_INPUT_VALUE] = hsv[2]; } static void cpick_update(cpick_dd *dt, int what) { cpicker *cp = &dt->c; int new_rgb = FALSE, new_h = FALSE, new_sv = FALSE;//, new_opac = FALSE; switch (what) { case CPICK_INPUT_RED: case CPICK_INPUT_GREEN: case CPICK_INPUT_BLUE: case CPICK_INPUT_HEX: new_rgb = TRUE; break; case CPICK_INPUT_HUE: new_h = TRUE; break; case CPICK_INPUT_SATURATION: case CPICK_INPUT_VALUE: new_sv = TRUE; break; case CPICK_INPUT_OPACITY: // new_opac = TRUE; break; default: return; } if (new_h || new_sv || new_rgb) { if (new_rgb) cpick_get_hsv(cp); else cpick_get_rgb(cp); cpick_populate_inputs(dt); // Update all inputs in dialog // New RGB or Hue so recalc picker if (!new_sv) cpick_area_picker_create(dt); } cpick_area_update_cursors(dt); // Update current colour cpick_area_precur_create(dt, CPICK_AREA_CURRENT); if (dt->evt) do_evt_1_d(dt->evt); } static void cpick_hex_change(cpick_dd *dt, void **wdata, int what, void **where) { int r, g, b, rgb; if (dt->c.lock) return; rgb = *(int *)cmd_read(where, dt); r = INT_2_R(rgb); g = INT_2_G(rgb); b = INT_2_B(rgb); if (!((r ^ dt->c.input_vals[CPICK_INPUT_RED]) | (g ^ dt->c.input_vals[CPICK_INPUT_GREEN]) | (b ^ dt->c.input_vals[CPICK_INPUT_BLUE]))) return; // no change dt->c.input_vals[CPICK_INPUT_RED] = r; dt->c.input_vals[CPICK_INPUT_GREEN] = g; dt->c.input_vals[CPICK_INPUT_BLUE] = b; cpick_update(dt, CPICK_INPUT_HEX); } static void cpick_spin_change(cpick_dd *dt, void **wdata, int what, void **where) { int i, *input; if (dt->c.lock) return; where = origin_slot(where); i = *(input = slot_data(origin_slot(where), dt)); if (*(int *)cmd_read(where, dt) == i) return; // no change cpick_update(dt, input - dt->c.input_vals); } static void dropper_terminate(GtkWidget *widget, gpointer user_data) { gtk_signal_disconnect_by_data(GTK_OBJECT(widget), user_data); undo_grab(widget); } static void dropper_grab_colour(GtkWidget *widget, gint x, gint y, gpointer user_data) { void **slot = user_data, **base = slot[0]; unsigned char rgb[3]; #if GTK_MAJOR_VERSION == 1 if (!wj_get_rgb_image((GdkWindow *)&gdk_root_parent, NULL, rgb, x, y, 1, 1)) return; #else /* #if GTK_MAJOR_VERSION >= 2 */ if (!wj_get_rgb_image(gdk_get_default_root_window(), NULL, rgb, x, y, 1, 1)) return; #endif /* Ungrab before sending signal - better safe than sorry */ dropper_terminate(widget, user_data); *(int *)slot_data(PREV_SLOT(slot), GET_DDATA(base)) = MEM_2_INT(rgb, 0); // self-updating do_evt_1_d(slot); } static gboolean dropper_key_press(GtkWidget *widget, GdkEventKey *event, gpointer user_data) { int x, y; if (arrow_key(event, &x, &y, 20)) move_mouse_relative(x, y); else if (event->keyval == KEY(Escape)) dropper_terminate(widget, user_data); else if ((event->keyval == KEY(Return)) || (event->keyval == KEY(KP_Enter)) || (event->keyval == KEY(space)) || (event->keyval == KEY(KP_Space))) { #if GTK_MAJOR_VERSION == 1 gdk_window_get_pointer((GdkWindow *)&gdk_root_parent, &x, &y, NULL); #else /* #if GTK_MAJOR_VERSION >= 2 */ G_GNUC_BEGIN_IGNORE_DEPRECATIONS gdk_display_get_pointer(gtk_widget_get_display(widget), NULL, &x, &y, NULL); G_GNUC_END_IGNORE_DEPRECATIONS #endif dropper_grab_colour(widget, x, y, user_data); } #if GTK_MAJOR_VERSION == 1 /* Return value alone doesn't stop GTK1 from running other handlers */ gtk_signal_emit_stop_by_name(GTK_OBJECT(widget), "key_press_event"); #endif return (TRUE); } static gboolean dropper_mouse_press(GtkWidget *widget, GdkEventButton *event, gpointer user_data) { if (event->type != GDK_BUTTON_RELEASE) return (FALSE); #if GTK_MAJOR_VERSION == 3 /* GTK+3 sends the release event from button press to grab widget, too */ if (event->window != gtk_widget_get_window(widget)) return (FALSE); #endif dropper_grab_colour(widget, event->x_root, event->y_root, user_data); return (TRUE); } static void click_eyedropper(GtkButton *button, gpointer user_data) { static GdkCursor *cursor; /* !!! If button itself is used for grab widget, it will receive mouse * clicks, with obvious result */ GtkWidget *grab_widget = gtk_widget_get_parent(GTK_WIDGET(button)); if (!cursor) cursor = make_cursor(xbm_picker_bits, xbm_picker_mask_bits, xbm_picker_width, xbm_picker_height, xbm_picker_x_hot, xbm_picker_y_hot); if (do_grab(GRAB_FULL, grab_widget, cursor)) { gtk_signal_connect(GTK_OBJECT(grab_widget), "button_release_event", GTK_SIGNAL_FUNC(dropper_mouse_press), user_data); gtk_signal_connect(GTK_OBJECT(grab_widget), "key_press_event", GTK_SIGNAL_FUNC(dropper_key_press), user_data); } } static int cpick_area_key(cpick_dd *dt, void **wdata, int what, void **where, key_ext *key) { void **orig = origin_slot(where); cpicker *cp = &dt->c; int dx, dy; if (!arrow_key_(key->key, key->state, &dx, &dy, 16)) return (FALSE); if (orig == dt->areas[CPICK_AREA_PICKER]) { int new_sat = cp->input_vals[CPICK_INPUT_SATURATION] - dy, new_val = cp->input_vals[CPICK_INPUT_VALUE] + dx; new_sat = new_sat < 0 ? 0 : new_sat > 255 ? 255 : new_sat; new_val = new_val < 0 ? 0 : new_val > 255 ? 255 : new_val; if ( new_sat != cp->input_vals[CPICK_INPUT_SATURATION] || new_val != cp->input_vals[CPICK_INPUT_VALUE] ) { cp->input_vals[CPICK_INPUT_SATURATION] = new_sat; cp->input_vals[CPICK_INPUT_VALUE] = new_val; cpick_get_rgb(cp); // Update RGB values cpick_area_update_cursors(dt); // Update cursors cpick_refresh_inputs_areas(dt); // Update inputs if (dt->evt) do_evt_1_d(dt->evt); } } else if (!dy); // X isn't used anywhere else else if (orig == dt->areas[CPICK_AREA_OPACITY]) { int new_opac = cp->input_vals[CPICK_INPUT_OPACITY] - dy; new_opac = new_opac < 0 ? 0 : new_opac > 255 ? 255 : new_opac; if ( new_opac != cp->input_vals[CPICK_INPUT_OPACITY] ) { cp->input_vals[CPICK_INPUT_OPACITY] = new_opac; cpick_area_update_cursors(dt); cpick_populate_inputs(dt); // Update all inputs in dialog cpick_area_precur_create(dt, CPICK_AREA_CURRENT); if (dt->evt) do_evt_1_d(dt->evt); } } else if (orig == dt->areas[CPICK_AREA_HUE]) { int new_hue = cp->input_vals[CPICK_INPUT_HUE] - 8*dy; new_hue = new_hue < 0 ? 0 : new_hue > 1529 ? 1529 : new_hue; if ( new_hue != cp->input_vals[CPICK_INPUT_HUE] ) { cp->input_vals[CPICK_INPUT_HUE] = new_hue; // Change hue cpick_get_rgb(cp); // Update RGB values cpick_area_update_cursors(dt); // Update cursors cpick_area_picker_create(dt); // Repaint picker cpick_refresh_inputs_areas(dt); // Update inputs if (dt->evt) do_evt_1_d(dt->evt); } } return (TRUE); } #if GTK_MAJOR_VERSION == 1 #define MIN_ENTRY_WIDTH 150 static void hex_size_req(GtkWidget *widget, GtkRequisition *requisition, gpointer user_data) { int l = gdk_string_width(widget->style->font, "#DDDDDDD"); // if (l > MIN_ENTRY_WIDTH) requisition->width += l - MIN_ENTRY_WIDTH; requisition->width = l + 30; /* Set requisition to a sane value */ } #endif GtkWidget *eyedropper(void **r) { GtkWidget *button = gtk_button_new(); gtk_container_add(GTK_CONTAINER(button), xpm_image(XPM_ICON(picker))); #ifdef GDK_WINDOWING_QUARTZ /* !!! Does not work with that halfbaked backend anyway */ gtk_widget_set_sensitive(button, FALSE); #else gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(click_eyedropper), NEXT_SLOT(r)); #endif return (button); } static gboolean hexentry_change(GtkWidget *widget, GdkEventFocus *event, gpointer user_data) { void **slot = user_data, **base = slot[0]; int c = parse_color((char *)gtk_entry_get_text(GTK_ENTRY(widget))); if (c >= 0) // Valid { *(int *)slot_data(PREV_SLOT(slot), GET_DDATA(base)) = c; // self-updating do_evt_1_d(slot); } return (FALSE); } void set_hexentry(GtkWidget *entry, int c) { char txt[32]; sprintf(txt, "#%06X", c); gtk_entry_set_text(GTK_ENTRY(entry), txt); } GtkWidget *hexentry(int c, void **r) { GtkWidget *entry = gtk_entry_new(); #if GTK_MAJOR_VERSION == 1 gtk_signal_connect(GTK_OBJECT(entry), "size_request", GTK_SIGNAL_FUNC(hex_size_req), NULL); #else /* #if GTK_MAJOR_VERSION >= 2 */ gtk_entry_set_width_chars(GTK_ENTRY(entry), 9); #endif set_hexentry(entry, c); gtk_signal_connect(GTK_OBJECT(entry), "focus_out_event", GTK_SIGNAL_FUNC(hexentry_change), NEXT_SLOT(r)); return (entry); } #define WBbase cpick_dd static void *cpick_code[] = { BORDER(TOPVBOX, 0), TOPVBOX, XHBOXbp(2, 0, 0), // --- Palette/Mixer table BORDER(TABLE, 0), TABLE(4, 2), REF(drag), CLIPFORM(xcolor, 1), /* Palette */ TALLOC(imgs[CPICK_AREA_PALETTE], c.area_size[CPICK_AREA_PALETTE][2]), REF(areas[CPICK_AREA_PALETTE]), TLFCIMAGEPn(imgs[CPICK_AREA_PALETTE], c.area_size[CPICK_AREA_PALETTE], 0, 0), DRAGDROP(drag, cpick_drag_get, cpick_drag_set), EVENT(MOUSE, cpick_area_event), EVENT(MMOUSE, cpick_area_event), /* Picker drawing area - Main */ TALLOC(imgs[CPICK_AREA_PICKER], c.area_size[CPICK_AREA_PICKER][2]), REF(areas[CPICK_AREA_PICKER]), TLFCIMAGEP(imgs[CPICK_AREA_PICKER], xy[CPICK_AREA_PICKER], c.area_size[CPICK_AREA_PICKER], 1, 0), EVENT(MOUSE, cpick_area_event), EVENT(MMOUSE, cpick_area_event), EVENT(KEY, cpick_area_key), /* Picker drawing area - Hue slider */ TALLOC(imgs[CPICK_AREA_HUE], c.area_size[CPICK_AREA_HUE][2]), REF(areas[CPICK_AREA_HUE]), TLFCIMAGEP(imgs[CPICK_AREA_HUE], xy[CPICK_AREA_HUE], c.area_size[CPICK_AREA_HUE], 2, 0), EVENT(MOUSE, cpick_area_event), EVENT(MMOUSE, cpick_area_event), EVENT(KEY, cpick_area_key), /* Opacity */ TALLOC(imgs[CPICK_AREA_OPACITY], c.area_size[CPICK_AREA_OPACITY][2]), REF(areas[CPICK_AREA_OPACITY]), TLFCIMAGEP(imgs[CPICK_AREA_OPACITY], xy[CPICK_AREA_OPACITY], c.area_size[CPICK_AREA_OPACITY], 3, 0), UNLESS(opacity_f), HIDDEN, EVENT(MOUSE, cpick_area_event), EVENT(MMOUSE, cpick_area_event), EVENT(KEY, cpick_area_key), /* Current / Previous colour swatch */ TALLOC(imgs[CPICK_AREA_PRECUR], c.area_size[CPICK_AREA_PRECUR][2]), REF(areas[CPICK_AREA_PRECUR]), TLFCIMAGEPn(imgs[CPICK_AREA_PRECUR], c.area_size[CPICK_AREA_PRECUR], 1, 1), DRAGDROP(drag, cpick_drag_get, cpick_drag_set), EVENT(MOUSE, cpick_area_event), EVENT(MMOUSE, cpick_area_event), EYEDROPPER(drop, cpick_hex_change, 2, 1), WDONE, // table // --- Table for inputs on right hand side BORDER(LABEL, 2), BORDER(SPIN, 0), TABLE(2, 8), TLABELx(_("Red"), 0, 0, 10), REF(inputs[CPICK_INPUT_RED]), T1SPIN(c.input_vals[CPICK_INPUT_RED], 0, 255), EVENT(CHANGE, cpick_spin_change), TLABELx(_("Green"), 0, 0, 10), REF(inputs[CPICK_INPUT_GREEN]), T1SPIN(c.input_vals[CPICK_INPUT_GREEN], 0, 255), EVENT(CHANGE, cpick_spin_change), TLABELx(_("Blue"), 0, 0, 10), REF(inputs[CPICK_INPUT_BLUE]), T1SPIN(c.input_vals[CPICK_INPUT_BLUE], 0, 255), EVENT(CHANGE, cpick_spin_change), TLABELx(_("Hue"), 0, 0, 10), REF(inputs[CPICK_INPUT_HUE]), T1SPIN(c.input_vals[CPICK_INPUT_HUE], 0, 1529), EVENT(CHANGE, cpick_spin_change), TLABELx(_("Saturation"), 0, 0, 10), REF(inputs[CPICK_INPUT_SATURATION]), T1SPIN(c.input_vals[CPICK_INPUT_SATURATION], 0, 255), EVENT(CHANGE, cpick_spin_change), TLABELx(_("Value"), 0, 0, 10), REF(inputs[CPICK_INPUT_VALUE]), T1SPIN(c.input_vals[CPICK_INPUT_VALUE], 0, 255), EVENT(CHANGE, cpick_spin_change), TLABELx(_("Hex"), 0, 0, 10), REF(inputs[CPICK_INPUT_HEX]), HEXENTRY(c.input_vals[CPICK_INPUT_HEX], cpick_hex_change, 1, 6), // !!! Or better just to hide it? IFx(opacity_f, 1), TLABELx(_("Opacity"), 0, 0, 10), REF(inputs[CPICK_INPUT_OPACITY]), T1SPIN(c.input_vals[CPICK_INPUT_OPACITY], 0, 255), EVENT(CHANGE, cpick_spin_change), ENDIF(1), WDONE, // table WDONE, // xhbox WEND }; #undef WBbase GtkWidget *cpick_create(int opacity) { static const unsigned char hue[7][3] = { {255, 0, 0}, {255, 0, 255}, {0, 0, 255}, {0, 255, 255}, {0, 255, 0}, {255, 255, 0}, {255, 0, 0} }; char txt[128]; cpick_dd tdata, *dt; void **res; unsigned char *dest; int i, k, kk, w, h, w3, x, y, dd, d1, hy, oy, size, pal_strips; memset(&tdata, 0, sizeof(tdata)); tdata.opacity_f = opacity; size = inifile_get_gint32("cpickerSize", CPICK_SIZE_DEFAULT); if ((size < CPICK_SIZE_MIN) || (size > CPICK_SIZE_MAX)) size = CPICK_SIZE_DEFAULT; /* Ensure palette swatches are identical in size by adjusting size of * whole area */ tdata.c.size = size -= (size % CPICK_PAL_STRIP_ITEMS); pal_strips = inifile_get_gint32("cpickerStrips", CPICK_PAL_STRIPS_DEFAULT); if ((pal_strips < CPICK_PAL_STRIPS_MIN) || (pal_strips > CPICK_PAL_STRIPS_MAX)) pal_strips = CPICK_PAL_STRIPS_DEFAULT; tdata.c.pal_strips = pal_strips; k = pal_strips * CPICK_PAL_STRIP_ITEMS; for (i = 0; i < k; i++) { snprintf(txt, 128, "cpick_pal_%i", i); tdata.pal[i] = inifile_get_gint32(txt, PNG_2_INT(mem_pal_def[i])); } tdata.c.rgb_previous[3] = 255; tdata.c.input_vals[CPICK_INPUT_SATURATION] = tdata.c.input_vals[CPICK_INPUT_VALUE] = tdata.c.input_vals[CPICK_INPUT_OPACITY] = 255; tdata.c.area_size[CPICK_AREA_PRECUR][0] = size; tdata.c.area_size[CPICK_AREA_PRECUR][1] = 3 * size / 16; tdata.c.area_size[CPICK_AREA_PICKER][0] = size; tdata.c.area_size[CPICK_AREA_PICKER][1] = size; tdata.c.area_size[CPICK_AREA_HUE][0] = 3 * size / 16; tdata.c.area_size[CPICK_AREA_HUE][1] = size; tdata.c.area_size[CPICK_AREA_PALETTE][0] = pal_strips * size / CPICK_PAL_STRIP_ITEMS; tdata.c.area_size[CPICK_AREA_PALETTE][1] = size; tdata.c.area_size[CPICK_AREA_OPACITY][0] = 3 * size / 16; tdata.c.area_size[CPICK_AREA_OPACITY][1] = size; for (i = 0; i < CPICK_AREA_TOT; i++) tdata.c.area_size[i][2] = tdata.c.area_size[i][0] * tdata.c.area_size[i][1] * 3; tdata.c.opmask = opacity ? 0 : 0xFF; res = run_create(cpick_code, &tdata, sizeof(tdata)); dt = GET_DDATA(res); /* Prepare hue area */ w = dt->c.area_size[CPICK_AREA_HUE][0]; h = dt->c.area_size[CPICK_AREA_HUE][1]; w3 = w * 3; dest = dt->imgs[CPICK_AREA_HUE]; for (hy = y = k = 0; k < 6; k++) { oy = hy; hy = ((k + 1) * h) / 6; dd = hy - oy; for (; y < hy; y++) { d1 = y - oy; for (i = 0; i < 3; i++) *dest++ = hue[k][i] + ((hue[k + 1][i] - hue[k][i]) * d1) / dd; for (; i < w3; i++ , dest++) *dest = *(dest - 3); } } /* Prepare palette area */ cpick_palette_paint(dt); /* Prepare opacity area */ w = dt->c.area_size[CPICK_AREA_OPACITY][0]; h = dt->c.area_size[CPICK_AREA_OPACITY][1]; dest = dt->imgs[CPICK_AREA_OPACITY]; for (y = h - 1; y >= 0; y--) { k = 255 - (255 * y) / h; kk = (y >> 3) & 1; for (x = 0; x < w; x++ , dest += 3) { i = k * greyz[((x >> 3) & 1) ^ kk]; dest[0] = dest[1] = dest[2] = (i + (i >> 8) + 1) >> 8; } } cpick_area_precur_create(dt, CPICK_AREA_CURRENT | CPICK_AREA_PREVIOUS); cpick_area_picker_create(dt); cpick_area_update_cursors(dt); return (GET_REAL_WINDOW(res)); } void cpick_set_evt(GtkWidget *w, void **r) { cpick_dd *dt = GET_DDATA(get_wdata(w, NULL)); dt->evt = r; } /* These formulas perfectly reverse ones in cpick_area_mouse() when possible; * however, for sizes > 255 it's impossible in principle - WJ */ static void cpick_area_update_cursors(cpick_dd *dt) { cpicker *cp = &dt->c; int xy[2], l; l = cp->area_size[CPICK_AREA_PICKER][0] - 1; xy[0] = (cp->input_vals[CPICK_INPUT_VALUE] * l + l - 1) / 255; l = cp->area_size[CPICK_AREA_PICKER][1] - 1; xy[1] = ((255 - cp->input_vals[CPICK_INPUT_SATURATION]) * l + l - 1) / 255; cmd_setv(dt->areas[CPICK_AREA_PICKER], xy, FCIMAGE_XY); xy[0] = cp->area_size[CPICK_AREA_HUE][0] / 2; l = cp->area_size[CPICK_AREA_HUE][1] - 1; xy[1] = ((1529 - cp->input_vals[CPICK_INPUT_HUE]) * l + l - 1) / 1529; cmd_setv(dt->areas[CPICK_AREA_HUE], xy, FCIMAGE_XY); xy[0] = cp->area_size[CPICK_AREA_OPACITY][0] / 2; l = cp->area_size[CPICK_AREA_OPACITY][1] - 1; xy[1] = ((255 - cp->input_vals[CPICK_INPUT_OPACITY]) * l + l - 1) / 255; cmd_setv(dt->areas[CPICK_AREA_OPACITY], xy, FCIMAGE_XY); } /* Update whole dialog according to values */ static void cpick_refresh_inputs_areas(cpick_dd *dt) { cpick_populate_inputs(dt); // Update all inputs in dialog cpick_area_precur_create(dt, CPICK_AREA_CURRENT); // Update current colour cpick_area_picker_create(dt); // Update picker colours cpick_area_update_cursors(dt); // Update area cursors } int cpick_get_colour(GtkWidget *w, int *opacity) { cpick_dd *dt = GET_DDATA(get_wdata(w, NULL)); cpicker *cp = &dt->c; if (opacity) *opacity = cp->input_vals[CPICK_INPUT_OPACITY]; return (RGB_2_INT(cp->input_vals[CPICK_INPUT_RED], cp->input_vals[CPICK_INPUT_GREEN], cp->input_vals[CPICK_INPUT_BLUE])); } void cpick_set_colour(GtkWidget *w, int rgb, int opacity) { cpick_dd *dt = GET_DDATA(get_wdata(w, NULL)); set_colour(dt, rgb, opacity); } void cpick_set_colour_previous(GtkWidget *w, int rgb, int opacity) { cpick_dd *dt = GET_DDATA(get_wdata(w, NULL)); cpicker *cp = &dt->c; cp->rgb_previous[0] = INT_2_R(rgb); cp->rgb_previous[1] = INT_2_G(rgb); cp->rgb_previous[2] = INT_2_B(rgb); cp->rgb_previous[3] = (opacity & 0xFF) | cp->opmask; // Update previous colour cpick_area_precur_create(dt, CPICK_AREA_PREVIOUS); } #endif /* mtPaint dialog */ #ifdef U_CPICK_GTK /* GtkColorSelection dialog */ G_GNUC_BEGIN_IGNORE_DEPRECATIONS /* Obviously */ GtkWidget *cpick_create(int opacity) { GtkWidget *w = gtk_color_selection_new(); #if GTK_MAJOR_VERSION == 1 gtk_color_selection_set_opacity(GTK_COLOR_SELECTION(w), opacity); #else /* #if GTK_MAJOR_VERSION >= 2 */ gtk_color_selection_set_has_palette(GTK_COLOR_SELECTION(w), TRUE); gtk_color_selection_set_has_opacity_control(GTK_COLOR_SELECTION(w), opacity); #endif return (w); } void cpick_set_evt(GtkWidget *w, void **r) { gtk_signal_connect_object(GTK_OBJECT(w), "color_changed", GTK_SIGNAL_FUNC(do_evt_1_d), (gpointer)r); } #if GTK_MAJOR_VERSION == 1 int cpick_get_colour(GtkWidget *w, int *opacity) { gdouble color[4]; gtk_color_selection_get_color(GTK_COLOR_SELECTION(w), color); if (opacity) *opacity = rint(255 * color[3]); return (RGB_2_INT((int)rint(255 * color[0]), (int)rint(255 * color[1]), (int)rint(255 * color[2]))); } void cpick_set_colour(GtkWidget *w, int rgb, int opacity) { GtkColorSelection *cs = GTK_COLOR_SELECTION(w); gdouble current[4] = { (gdouble)INT_2_R(rgb) / 255.0, (gdouble)INT_2_G(rgb) / 255.0, (gdouble)INT_2_B(rgb) / 255.0, (gdouble)opacity / 255.0 }; gdouble previous[4]; // Set current without losing previous memcpy(previous, cs->old_values + 3, sizeof(previous)); gtk_color_selection_set_color( cs, previous ); gtk_color_selection_set_color( cs, current ); } void cpick_set_colour_previous(GtkWidget *w, int rgb, int opacity) { gdouble current[4], previous[4] = { (gdouble)INT_2_R(rgb) / 255.0, (gdouble)INT_2_G(rgb) / 255.0, (gdouble)INT_2_B(rgb) / 255.0, (gdouble)opacity / 255.0 }; GtkColorSelection *cs = GTK_COLOR_SELECTION(w); // Set previous without losing current memcpy(current, cs->values + 3, sizeof(current)); gtk_color_selection_set_color( cs, previous ); gtk_color_selection_set_color( cs, current ); } #else /* #if GTK_MAJOR_VERSION >= 2 */ int cpick_get_colour(GtkWidget *w, int *opacity) { GdkColor c; gtk_color_selection_get_current_color(GTK_COLOR_SELECTION(w), &c); if (opacity) *opacity = (gtk_color_selection_get_current_alpha( GTK_COLOR_SELECTION(w)) + 128) / 257; return (RGB_2_INT((c.red + 128) / 257, (c.green + 128) / 257, (c.blue + 128) / 257)); } void cpick_set_colour(GtkWidget *w, int rgb, int opacity) { GdkColor c; c.pixel = 0; c.red = INT_2_R(rgb) * 257; c.green = INT_2_G(rgb) * 257; c.blue = INT_2_B(rgb) * 257; gtk_color_selection_set_current_color(GTK_COLOR_SELECTION(w), &c); gtk_color_selection_set_current_alpha(GTK_COLOR_SELECTION(w), opacity * 257); } void cpick_set_colour_previous(GtkWidget *w, int rgb, int opacity) { GdkColor c; c.pixel = 0; c.red = INT_2_R(rgb) * 257; c.green = INT_2_G(rgb) * 257; c.blue = INT_2_B(rgb) * 257; gtk_color_selection_set_previous_color(GTK_COLOR_SELECTION(w), &c); gtk_color_selection_set_previous_alpha(GTK_COLOR_SELECTION(w), opacity * 257); } #endif /* GTK+2&3 */ G_GNUC_END_IGNORE_DEPRECATIONS #endif /* GtkColorSelection dialog */ mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/cpick.h000066400000000000000000000021321471325446300222020ustar00rootroot00000000000000/* cpick.h Copyright (C) 2008-2014 Mark Tyler and Dmitry Groshev This file is part of mtPaint. mtPaint 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. mtPaint 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 mtPaint in the file COPYING. */ #ifdef U_CPICK_MTPAINT /* mtPaint dialog */ GtkWidget *eyedropper(void **r); void set_hexentry(GtkWidget *entry, int c); GtkWidget *hexentry(int c, void **r); #endif GtkWidget *cpick_create(int opacity); void cpick_set_evt(GtkWidget *w, void **r); int cpick_get_colour(GtkWidget *w, int *opacity); void cpick_set_colour(GtkWidget *w, int rgb, int opacity); void cpick_set_colour_previous(GtkWidget *w, int rgb, int opacity); mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/csel.c000066400000000000000000000404571471325446300220460ustar00rootroot00000000000000/* csel.c Copyright (C) 2006-2020 Dmitry Groshev This file is part of mtPaint. mtPaint 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. mtPaint 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 mtPaint in the file COPYING. */ #include "global.h" #include "mygtk.h" #include "memory.h" #include "otherwindow.h" #include "channels.h" #include "csel.h" #include "thread.h" /* Use sRGB gamma if defined, ITU-R 709 gamma otherwise */ /* From my point of view, ITU-R 709 is a better model of a real CRT */ // #define SRGB /* Use distorted L*X*N* model; the distortion possibly makes it better for * * smaller colour differences, but at extrema, error becomes unacceptable */ // #define DISTORT_LXN #define CIENUM 8192 #define EXPNUM 1024 #define EXPLOW (-0.1875) csel_info *csel_data; int csel_preview = 0x00FF00, csel_preview_a = 128, csel_overlay; double gamma256[256], gamma64[64]; double midgamma256[256]; #ifndef NATIVE_DOUBLES float Fgamma256[256]; #endif static float CIE[CIENUM + 2]; static float EXP[EXPNUM]; /* This nightmarish code does conversion from CIE XYZ into my own perceptually * uniform colour space L*X*N*. To produce it, I combined McAdam's colour space * and CIE lightness function, like it was done for L*u*v* space - the result * is a bitch to evaluate and impossible to reverse, but works much better * than both L*a*b and L*u*v for colour comparison - WJ */ static double wXN[2]; static void xyz2XN(double *XN, double x, double y, double z) { double xyz = x + y + z; double k, xk, yk, sxk; /* Black is a darker white ;) */ if (xyz == 0.0) { XN[0] = wXN[0]; XN[1] = wXN[1]; return; } k = 10.0 / (x * 2.4 + y * 34.0 + xyz); xk = x * k; yk = y * k; sxk = sqrt(xk); XN[0] = (xk * xk * (3751.0 - xk * xk * 10.0) - yk * yk * (520.0 - yk * 13295.0) + xk * yk * (32327.0 - xk * 25491.0 - yk * 41672.0 + xk * xk * 10.0) - sxk * 5227.0 + sqrt(sxk) * 2952.0) / 900.0; #ifndef DISTORT_LXN /* Do transform properly */ k = 10.0 / (y * 4.2 - x + xyz); #else /* This equation is incorrect, but I felt that in reality it's better - * it compresses the colour plane so that green and blue are farther * from red than from each other, which conforms to human perception. * Yet for pure colours, distortion tends to become too high. - WJ */ k = 10.0 / (y * 5.2 - x + xyz); #endif xk = x * k; yk = y * k; XN[1] = (yk * (404.0 - yk * (185.0 - yk * 52.0)) + xk * (69.0 - yk * (yk * (69.0 - yk * 30.0) + xk * 3.0))) / 900.0; } static inline double CIElum(double x) { int n; x *= CIENUM; n = x; return (CIE[n] + (CIE[n + 1] - CIE[n]) * (x - n)); } static inline double exp10(double x) { int n; x = (x - EXPLOW) * (EXPNUM + EXPNUM); n = x; return (EXP[n] + (EXP[n + 1] - EXP[n]) * (x - n)); } /* MinGW has cube root function, glibc hasn't */ #ifndef WIN32 #define cbrt(X) pow((X), 1.0 / 3.0) #endif #define XX1 (16.0 / 116.0) #define XX2 ((116.0 * 116.0) / (24.0 * 24.0 * 3.0)) #define XX3 ((24.0 * 24.0 * 24.0) / (116.0 * 116.0 * 116.0)) static inline double CIEpow(double x) { return ((x > XX3) ? cbrt(x) : x * XX2 + XX1); } static double rxyz[3], gxyz[3], bxyz[3], wy; void rgb2LXN(double *tmp, double r, double g, double b) { double x = r * rxyz[0] + g * gxyz[0] + b * bxyz[0]; double y = r * rxyz[1] + g * gxyz[1] + b * bxyz[1]; double z = r * rxyz[2] + g * gxyz[2] + b * bxyz[2]; double L = CIElum(y); // double L = CIEpow(y) * 116.0 - 16.0; double XN[2]; xyz2XN(XN, x, y, z); /* Luminance's range must be near to chrominance's _diameter_ */ #ifndef DISTORT_LXN /* As recommended in literature (but sqrt(3) may be better) */ tmp[0] = L * 2.0; #else /* As felt good in practice */ tmp[0] = L * M_SQRT2; #endif tmp[1] = (XN[0] - wXN[0]) * L * 13.0; tmp[2] = (XN[1] - wXN[1]) * L * 13.0; } /* Get subjective brightness measure, by using Ware-Cowan formula */ double rgb2B(double r, double g, double b) { double x = r * rxyz[0] + g * gxyz[0] + b * bxyz[0]; double y = r * rxyz[1] + g * gxyz[1] + b * bxyz[1]; double z = r * rxyz[2] + g * gxyz[2] + b * bxyz[2]; z += x + y; if (z <= 0.0) return (y); z = 1.0 / z; x *= z; z *= y; /* It's not Z now, but y */ z = 0.256 + (-0.184 + (-2.527 + 4.656 * x * x + 4.657 * z * z * z) * x) * z; y *= exp10(z) * wy; return (y > 1.0 ? 1.0 : y); } #if 0 /* Disable while not in use */ void rgb2Lab(double *tmp, double r, double g, double b) { double x = r * rxyz[0] + g * gxyz[0] + b * bxyz[0]; double y = r * rxyz[1] + g * gxyz[1] + b * bxyz[1]; double z = r * rxyz[2] + g * gxyz[2] + b * bxyz[2]; double L = CIElum(y); tmp[0] = L; tmp[1] = (CIElum(x * (WHITE_Y / WHITE_X)) - L) * (500.0 / 116.0); tmp[2] = (L - CIElum(z * (WHITE_Y / (1.0 - WHITE_X - WHITE_Y))) * (200.0 / 116.0); } #endif /* ITU-R 709 */ #define RED_X 0.640 #define RED_Y 0.330 #define GREEN_X 0.300 #define GREEN_Y 0.600 #define BLUE_X 0.150 #define BLUE_Y 0.060 #if 1 /* 6500K whitepoint (D65) */ #define WHITE_X 0.3127 #define WHITE_Y 0.3290 /* Some, like lcms, use y=0.3291, but that isn't how ITU-R BT.709-5 defines D65, * but instead how SMPTE 240M does - WJ */ #else /* 9300K whitepoint */ #define WHITE_X 0.2848 #define WHITE_Y 0.2932 #endif static inline double det(double x1, double y1, double x2, double y2, double x3, double y3) { return ((y1 - y2) * x3 + (y2 - y3) * x1 + (y3 - y1) * x2); } static void make_rgb_xyz(void) { double rgbdet = det(RED_X, RED_Y, GREEN_X, GREEN_Y, BLUE_X, BLUE_Y) * WHITE_Y; double wr = det(WHITE_X, WHITE_Y, GREEN_X, GREEN_Y, BLUE_X, BLUE_Y) / rgbdet; double wg = det(RED_X, RED_Y, WHITE_X, WHITE_Y, BLUE_X, BLUE_Y) / rgbdet; double wb = det(RED_X, RED_Y, GREEN_X, GREEN_Y, WHITE_X, WHITE_Y) / rgbdet; rxyz[0] = RED_X * wr; rxyz[1] = RED_Y * wr; rxyz[2] = (1.0 - RED_X - RED_Y) * wr; gxyz[0] = GREEN_X * wg; gxyz[1] = GREEN_Y * wg; gxyz[2] = (1.0 - GREEN_X - GREEN_Y) * wg; bxyz[0] = BLUE_X * wb; bxyz[1] = BLUE_Y * wb; bxyz[2] = (1.0 - BLUE_X - BLUE_Y) * wb; xyz2XN(wXN, WHITE_X / WHITE_Y, 1.0, (1 - WHITE_X - WHITE_Y) / WHITE_Y); /* Normalize brightness of white */ wy = 1.0 / exp10(0.256 + (-0.184 + (-2.527 + 4.656 * WHITE_X * WHITE_X + 4.657 * WHITE_Y * WHITE_Y * WHITE_Y) * WHITE_X) * WHITE_Y); } #ifdef SRGB #define GAMMA_POW 2.4 #define GAMMA_OFS 0.055 #if 1 /* Standard */ #define GAMMA_SPLIT 0.04045 #define GAMMA_DIV 12.92 #else /* C1 continuous */ #define GAMMA_SPLIT 0.03928 #define GAMMA_DIV 12.92321 #endif #define KGAMMA 800 #define KGAMMA64K 12900 #else /* ITU-R 709 */ #define GAMMA_POW (1.0 / 0.45) #define GAMMA_OFS 0.099 #define GAMMA_SPLIT 0.081 #define GAMMA_DIV 4.5 #define KGAMMA 300 #define KGAMMA64K 4550 #endif static void make_gamma(double *Gamma, int cnt) { int i, k; double mult = 1.0 / (double)(cnt - 1); k = (int)(GAMMA_SPLIT * (cnt - 1)) + 1; for (i = k; i < cnt; i++) { Gamma[i] = pow(((double)i * mult + GAMMA_OFS) / (1.0 + GAMMA_OFS), GAMMA_POW); } mult /= GAMMA_DIV; for (i = 0; i < k; i++) { Gamma[i] = (double)i * mult; } } int kgamma256 = KGAMMA * 4; unsigned char ungamma256[KGAMMA * 4 + 1]; static void make_ungamma(double *Gamma, double *Midgamma, unsigned char *Ungamma, int kgamma, int cnt) { int i, j, k = 0; Midgamma[0] = 0.0; for (i = 1; i < cnt; i++) { Midgamma[i] = (Gamma[i - 1] + Gamma[i]) / 2.0; j = Midgamma[i] * kgamma; for (; k < j; k++) Ungamma[k] = i - 1; } for (; k <= kgamma; k++) Ungamma[k] = cnt - 1; } /* 16-bit gamma correction */ static double gamma64K[255 * 4 + 2]; static double gammaslope64K[255 * 4 + 1]; static unsigned short ungamma64K[KGAMMA64K + 1]; #if 0 /* Disable while not in use */ double gamma65536(int idx) { int n; idx *= 4; n = idx / 257; return ((idx % 257) * (1.0 / 257.0) * (gamma64K[n + 1] - gamma64K[n]) + gamma64K[n]); } int ungamma65536(double v) { int n = ungamma64K[(int)(v * KGAMMA64K)]; n -= v < gamma64K[n]; return ((int)((n + (v - gamma64K[n]) * gammaslope64K[n]) * 64.25 + 0.5)); } #endif double gamma65281(int idx) { int n; n = idx >> 6; return ((idx & 0x3F) * (1.0 / 64.0) * (gamma64K[n + 1] - gamma64K[n]) + gamma64K[n]); } int ungamma65281(double v) { int n = ungamma64K[(int)(v * KGAMMA64K)]; n -= v < gamma64K[n]; return ((int)((n + (v - gamma64K[n]) * gammaslope64K[n]) * 64.0 + 0.5)); } static void make_ungamma64K() { int i, j, k = 0; for (i = 1; i < 255 * 4 + 1; i++) { gammaslope64K[i - 1] = 1.0 / (gamma64K[i] - gamma64K[i - 1]); j = gamma64K[i] * KGAMMA64K; for (; k < j; k++) ungamma64K[k] = i - 1; } gammaslope64K[255 * 4] = 0.0; for (; k <= KGAMMA64K; k++) ungamma64K[k] = 255 * 4; } static void make_CIE(void) { int i; for (i = 0; i < CIENUM; i++) { CIE[i] = CIEpow(i * (1.0 / CIENUM)) * 116.0 - 16.0; } CIE[CIENUM] = CIE[CIENUM + 1] = 100.0; } static void make_EXP(void) { int i; for (i = 0; i < EXPNUM; i++) { EXP[i] = exp(M_LN10 * (i * (0.5 / EXPNUM) + EXPLOW)); } } void init_cols(void) { make_gamma(gamma64K, 255 * 4 + 1); gamma64K[255 * 4 + 1] = 1.0; make_gamma(gamma256, 256); make_gamma(gamma64, 64); make_ungamma64K(); make_ungamma(gamma256, midgamma256, ungamma256, kgamma256, 256); make_CIE(); make_EXP(); make_rgb_xyz(); #ifndef NATIVE_DOUBLES /* Fill reduced-precision gamma table */ { int i; for (i = 0; i < 256; i++) Fgamma256[i] = gamma256[i]; } #endif } /* Get L*X*N* triple */ void get_lxn(double *lxn, int col) { rgb2LXN(lxn, gamma256[INT_2_R(col)], gamma256[INT_2_G(col)], gamma256[INT_2_B(col)]); } /* Get hue vector (0..1529) */ static double get_vect(int col) { static int ixx[5] = {0, 1, 2, 0, 1}; int rgb[3] = {INT_2_R(col), INT_2_G(col), INT_2_B(col)}; int c1, c2, minc, midc, maxc; if (!((rgb[0] ^ rgb[1]) | (rgb[0] ^ rgb[2]))) return (0.0); c2 = rgb[2] < rgb[0] ? (rgb[1] < rgb[2] ? 2 : 0) : (rgb[0] < rgb[1] ? 1 : 2); minc = rgb[ixx[c2 + 2]]; midc = rgb[ixx[c2 + 1]]; c1 = midc > rgb[c2]; midc -= c1 ? rgb[c2] : minc; maxc = rgb[ixx[c2 + c1]] - minc; return ((c2 + c2 + c1) * 255 + midc * 255 / (double)maxc); } #if defined(U_THREADS) && defined(HAVE__SFA) /* Hope this and __sync_fetch_and_add() always come as a package */ #define SETBIT(A,B) __sync_fetch_and_or(&(A), (B)) #else #define SETBIT(A,B) (A) |= (B) #endif /* Answer which pixels are masked through selectivity */ int csel_scan(int start, int step, int cnt, unsigned char *mask, unsigned char *img, csel_info *info) { unsigned char res = 0; double d, dist = 0.0, lxn[3]; int i, j, k, l, jj, st3 = step * 3; #ifndef HAVE__SFA DEF_MUTEX(csel_lock); // To prevent concurrent writes to *info LOCK_MUTEX(csel_lock); #endif cnt = start + step * (cnt - 1) + 1; if (!mask) { mask = &res - start; cnt = start + 1; } if (mem_img_bpp == 1) /* Indexed image */ { for (i = start; i < cnt; i += step) { j = img[i]; k = PNG_2_INT(mem_pal[j]); if (info->pcache[j] != k) { if (info->mode == 0) /* Sphere mode */ { get_lxn(lxn, k); dist = (lxn[0] - info->clxn[0]) * (lxn[0] - info->clxn[0]) + (lxn[1] - info->clxn[1]) * (lxn[1] - info->clxn[1]) + (lxn[2] - info->clxn[2]) * (lxn[2] - info->clxn[2]); } else if (info->mode == 1) /* Angle mode */ { dist = fabs(get_vect(k) - info->cvec); if (dist > 765.0) dist = 1530.0 - dist; } else if (info->mode == 2) /* Cube mode */ { l = abs(INT_2_R(info->center) - INT_2_R(k)); jj = abs(INT_2_G(info->center) - INT_2_G(k)); if (l < jj) l = jj; jj = abs(INT_2_B(info->center) - INT_2_B(k)); dist = l > jj ? l : jj; } if (dist <= info->range2) SETBIT(info->pmap[j >> 5], 1U << (j & 31)); info->pcache[j] = k; } if (((info->pmap[j >> 5] >> (j & 31)) ^ info->invert) & 1) mask[i] |= 255; } } else if (info->mode == 0) /* RGB image, sphere mode */ { img += start * 3; for (i = start; i < cnt; i += step , img += st3) { unsigned l; k = MEM_2_INT(img, 0) - info->cbase; if (k & 0xFFC0C0C0) /* Coarse map */ { j = ((img[0] & 0xFC) << 6) + (img[1] & 0xFC) + (img[2] >> 6); k = (img[2] >> 1) & 0x1E; } else /* Fine map */ { j = ((k & 0x3F0000) >> 8) + ((k & 0x3F00) >> 6) + ((k & 0x3F) >> 4) + CMAPSIZE; k = (k + k) & 0x1E; } l = (info->colormap[j] >> k) & 3; if (!l) /* Not mapped */ { if (j < CMAPSIZE) rgb2LXN(lxn, gamma64[img[0] >> 2], gamma64[img[1] >> 2], gamma64[img[2] >> 2]); else rgb2LXN(lxn, gamma256[img[0]], gamma256[img[1]], gamma256[img[2]]); dist = (lxn[0] - info->clxn[0]) * (lxn[0] - info->clxn[0]) + (lxn[1] - info->clxn[1]) * (lxn[1] - info->clxn[1]) + (lxn[2] - info->clxn[2]) * (lxn[2] - info->clxn[2]); l = dist <= info->range2 ? 3 : 2; SETBIT(info->colormap[j], l << k); } if ((l ^ info->invert) & 1) mask[i] |= 255; } } else if (info->mode == 1) /* RGB image, angle mode */ { static int ixx[5] = {0, 1, 2, 0, 1}; img += start * 3; for (i = start; i < cnt; i += step , img += st3) { unsigned l; k = img[2] < img[0] ? (img[1] < img[2] ? 2 : 0) : (img[0] < img[1] ? 1 : 2); j = (img[ixx[k]] << 8) + img[ixx[k + 1]] - img[ixx[k + 2]] * 257; l = (info->colormap[j >> 3] >> ((j & 7) << 2)) & 0xF; if (!l) /* Not mapped */ { /* Map 3 sectors at once */ d = get_vect(j << 8) - info->cvec; for (jj = 1; jj < 8; jj += jj) { dist = fabs(d); d += 510.0; if (dist > 765.0) dist = 1530.0 - dist; if (dist <= info->range2) l += jj; } SETBIT(info->colormap[j >> 3], (l + 8) << ((j & 7) << 2)); } if (((l >> k) ^ info->invert) & 1) mask[i] |= 255; } } else if (info->mode == 2) /* RGB image, cube mode */ { j = INT_2_R(info->center); k = INT_2_G(info->center); l = INT_2_B(info->center); jj = info->invert & 1; img += start * 3; for (i = start; i < cnt; i += step , img += st3) { if (((abs(j - img[0]) <= info->irange) && (abs(k - img[1]) <= info->irange) && (abs(l - img[2]) <= info->irange)) ^ jj) mask[i] |= 255; } } #ifndef HAVE__SFA UNLOCK_MUTEX(csel_lock); #endif return (res); } /* Evaluate range */ double csel_eval(int mode, int center, int limit) { double cw[3], lw[3], cwv, lwv, r2; int i, j, k, ir; switch (mode) { case 0: /* L*X*N* spherical */ get_lxn(cw, center); get_lxn(lw, limit); r2 = (lw[0] - cw[0]) * (lw[0] - cw[0]) + (lw[1] - cw[1]) * (lw[1] - cw[1]) + (lw[2] - cw[2]) * (lw[2] - cw[2]); return (sqrt(r2)); case 1: /* RGB angular */ cwv = get_vect(center); lwv = get_vect(limit); r2 = fabs(lwv - cwv); if (r2 > 765.0) r2 = 1530.0 - r2; return (r2); case 2: /* RGB cubic */ i = abs(INT_2_R(center) - INT_2_R(limit)); j = abs(INT_2_G(center) - INT_2_G(limit)); k = abs(INT_2_B(center) - INT_2_B(limit)); ir = i > j ? i : j; if (ir < k) ir = k; return ((double)ir); } return (0.0); } /* Clear bitmaps and setup extra vars */ void csel_reset(csel_info *info) { int i, j, k, l; memset(info->colormap, 0, sizeof(info->colormap)); memset(info->pmap, 0, sizeof(info->pmap)); memset(info->pcache, 255, sizeof(info->pcache)); switch (info->mode) { case 0: /* L*X*N* sphere */ get_lxn(info->clxn, info->center); info->range2 = info->range * info->range; /* Find fine-precision base */ l = info->center & 0xFCFCFC; i = INT_2_R(l); j = INT_2_G(l); k = INT_2_B(l); i = i > 32 ? i - 32 : 0; j = j > 32 ? j - 32 : 0; k = k > 32 ? k - 32 : 0; info->cbase = RGB_2_INT(i, j, k); break; case 1: /* RGB angular */ info->cvec = get_vect(info->center); info->range2 = info->range; break; case 2: /* RGB cubic */ info->irange = info->range2 = (int)(info->range); break; } if (info->center_a < info->limit_a) { info->amin = info->center_a; info->amax = info->limit_a; } else { info->amax = info->center_a; info->amin = info->limit_a; } } /* Set center at A, limit at B */ void csel_init() { csel_info *info; info = ALIGN(calloc(1, sizeof(csel_info) + sizeof(double))); if (!info) { memory_errors(1); return; } info->center = PNG_2_INT(mem_col_A24); info->limit = PNG_2_INT(mem_col_B24); info->center_a = channel_col_A[CHN_ALPHA]; info->limit_a = channel_col_B[CHN_ALPHA]; info->range = csel_eval(0, info->center, info->limit); csel_reset(info); csel_data = info; } mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/csel.h000066400000000000000000000043131471325446300220420ustar00rootroot00000000000000/* csel.h Copyright (C) 2006-2011 Dmitry Groshev This file is part of mtPaint. mtPaint 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. mtPaint 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 mtPaint in the file COPYING. */ #define CMAPSIZE (64 * 64 * 64 / 16) typedef struct { /* Input fields */ int center, limit, center_a, limit_a; int mode, invert; double range; /* Cache fields */ guint32 colormap[CMAPSIZE * 2]; guint32 pmap[256 / 32]; int pcache[256], cbase, irange, amin, amax; double clxn[3], cvec, range2; } csel_info; #define CSEL_SVSIZE offsetof(csel_info, colormap) csel_info *csel_data; int csel_preview, csel_preview_a, csel_overlay; double gamma256[256], gamma64[64]; double midgamma256[256]; int kgamma256; extern unsigned char ungamma256[]; /* This gamma table is for when we need numeric stability */ #ifdef NATIVE_DOUBLES #define Fgamma256 gamma256 #else float Fgamma256[256]; #endif static inline int UNGAMMA256(double x) { int j = (int)(x * kgamma256); return (ungamma256[j] - (x < midgamma256[ungamma256[j]])); } static inline int UNGAMMA256X(double x) { int j = (int)(x * kgamma256); return (j < 0 ? 0 : j >= kgamma256 ? 255 : ungamma256[j] - (x < midgamma256[ungamma256[j]])); } //double gamma65536(int idx); //int ungamma65536(double v); /* Used in and around gradient engine */ double gamma65281(int idx); int ungamma65281(double v); double rgb2B(double r, double g, double b); void rgb2LXN(double *tmp, double r, double g, double b); //void rgb2Lab(double *tmp, double r, double g, double b); void init_cols(); void get_lxn(double *lxn, int col); int csel_scan(int start, int step, int cnt, unsigned char *mask, unsigned char *img, csel_info *info); double csel_eval(int mode, int center, int limit); void csel_reset(csel_info *info); void csel_init(); mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/font.c000066400000000000000000001246351471325446300220670ustar00rootroot00000000000000/* font.c Copyright (C) 2007-2020 Mark Tyler and Dmitry Groshev This file is part of mtPaint. mtPaint 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. mtPaint 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 mtPaint in the file COPYING. */ #ifdef U_FREETYPE #include "global.h" #undef _ #define _(X) X #include "mygtk.h" #include "memory.h" #include "vcode.h" #include "png.h" #include "mainwindow.h" #include "viewer.h" #include "canvas.h" #include "inifile.h" #include "font.h" #include #include #include FT_FREETYPE_H #if (GTK_MAJOR_VERSION == 1) && defined(U_NLS) #include #endif /* ----------------------------------------------------------------- | Definitions & Structs | ----------------------------------------------------------------- */ #define MT_TEXT_MONO 1 /* Force mono rendering */ #define MT_TEXT_ROTATE_NN 2 /* Use nearest neighbour rotation on bitmap fonts */ #define MT_TEXT_OBLIQUE 4 /* Apply Oblique matrix transformation to scalable fonts */ #define FONT_INDEX_FILENAME ".mtpaint_fonts" #define TX_MAX_DIRS 100 /* Persistent settings */ int font_obl, font_bmsize, font_size; int font_dirs; int ft_setdpi; typedef struct filenameNODE filenameNODE; struct filenameNODE { char *filename; // Filename of font int face_index; // Face index within font file filenameNODE *next; // Pointer to next filename, NULL=no more }; typedef struct sizeNODE sizeNODE; struct sizeNODE { int size; // Font size. 0=Scalable filenameNODE *filename; // Pointer to first filename sizeNODE *next; // Pointer to next size, NULL=no more }; typedef struct styleNODE styleNODE; struct styleNODE { char *style_name; // Style name sizeNODE *size; // Pointer to first size of this font styleNODE *next; // Pointer to next style, NULL=no more }; typedef struct fontNODE fontNODE; struct fontNODE { char *font_name; // Font name int directory; // Which directory is this font in? styleNODE *style; // Pointer to first style of this font fontNODE *next; // Pointer to next font family, NULL=no more }; typedef struct { fontNODE *fn; int dir, bm, name; } fontname_cc; typedef struct { styleNODE *sn; int name; } fontstyle_cc; typedef struct { sizeNODE *zn; int what; int n; } fontsize_cc; typedef struct { filenameNODE *fn; int name, face; } fontfile_cc; typedef struct { int idx, dir; } dir_cc; typedef struct { char *text; // !!! widget-owned memory int img, idx, script; int fontname, nfontnames, fnsort; int fontstyle, nfontstyles; int lfontsize, nlfontsizes; int fontfile, nfontfiles; int dir, ndirs; int fontsize; int bkg[3], angle, dpi[3], spacing; int preview_whc[3]; int lock; unsigned char *preview_rgb; memx2 fnmmem, fstmem, fszmem, ffnmem, dirmem; fontname_cc *fontnames; fontstyle_cc *fontstyles; fontsize_cc *fontsizes; fontfile_cc *fontfiles; dir_cc *dirs; void **preview_area; void **obl_c, **size_spin, **add_b, **book; void **fname_l, **fstyle_l, **fsize_l, **ffile_l, **dir_l; char dirp[PATHBUF]; } font_dd; static wjmem *font_mem; static fontNODE *global_font_node; static char *font_text; /* ----------------------------------------------------------------- | FreeType Rendering Code | ----------------------------------------------------------------- */ static void ft_draw_bitmap( unsigned char *mem, int w, FT_Bitmap *bitmap, FT_Int x, FT_Int y, int ppb ) { unsigned char *dest = mem + y * w + x, *src = bitmap->buffer; int i, j; for (j = 0; j < bitmap->rows; j++) { if (ppb == 1) // 8 bits per pixel greyscale { // memcpy(dest, src, bitmap->width); for (i = 0; i < bitmap->width; i++) dest[i] |= src[i]; } else if (ppb == 8) // 1 bit per pixel mono { for (i = 0; i < bitmap->width; i++) dest[i] |= (((int)src[i >> 3] >> (~i & 7)) & 1) * 255; } dest += w; src += bitmap->pitch; } } static inline void extend(int *rxy, int x0, int y0, int x1, int y1) { if (x0 < rxy[0]) rxy[0] = x0; if (y0 < rxy[1]) rxy[1] = y0; if (x1 > rxy[2]) rxy[2] = x1; if (y1 > rxy[3]) rxy[3] = y1; } /* Render text to a new chunk of memory. NULL return = failure, otherwise points to memory. int characters required to print unicode strings correctly. */ static unsigned char *mt_text_render( char *text, int characters, char *filename, char *encoding, double size, int face_index, double angle, int flags, int *width, int *height ) { unsigned char *mem = NULL; #ifdef WIN32 const char *txtp1; #else char *txtp1; #endif char *txtp2; double ca, sa, angle_r = angle / 180 * M_PI; int bx, by, bw, bh, bits, ppb, fix_w, fix_h, scalable; int Y1, Y2, X1, X2, ll, line, xflag; int spc, spcx, spcy; int pass, lines = 0; #define MAX_LW 16 int tx0, tx1, lwa[MAX_LW * 2], *lw, *lw0 = lwa; int dpi = ft_setdpi ? font_dpi : sys_dpi; int minxy[4] = { MAX_WIDTH, MAX_HEIGHT, -MAX_WIDTH, -MAX_HEIGHT }; size_t s, ssize1 = characters, ssize2 = characters * 4 + 5; iconv_t cd; FT_Library library; FT_Face face; FT_Matrix matrix; FT_Vector pen, uninit_(pen0); FT_Error error; FT_UInt glyph_index; FT_Int32 unichar, *txt2, *tmp2; FT_Int32 load_flags = FT_LOAD_RENDER | FT_LOAD_FORCE_AUTOHINT; //printf("\n%s %i %s %s %f %i %f %i\n", text, characters, filename, encoding, size, face_index, angle, flags); if ( flags & MT_TEXT_MONO ) load_flags |= FT_LOAD_TARGET_MONO; if (characters < 1) return NULL; error = FT_Init_FreeType( &library ); if (error) return NULL; error = FT_New_Face( library, filename, face_index, &face ); if (error) goto fail2; scalable = FT_IS_SCALABLE(face); if (!scalable) { ca = 1.0; sa = 0.0; // Transform, if any, is for later /* !!! Linux .pcf fonts require requested height to match ppem rounded up; * Windows .fon fonts, conversely, require width & height. So we try both - WJ */ fix_w = face->available_sizes[0].width; fix_h = face->available_sizes[0].height; error = FT_Set_Pixel_Sizes(face, fix_w, fix_h); if (error) { fix_w = (face->available_sizes[0].x_ppem + 32) >> 6; fix_h = (face->available_sizes[0].y_ppem + 32) >> 6; error = FT_Set_Pixel_Sizes(face, fix_w, fix_h); } if (error) goto fail1; // !!! FNT fonts have special support in FreeType - maybe use it? Y1 = face->size->metrics.ascender; Y2 = face->size->metrics.descender; } else { ca = cos(angle_r); sa = sin(angle_r); /* Ignore embedded bitmaps if transforming the font */ if (angle_r) load_flags |= FT_LOAD_NO_BITMAP; matrix.yy = matrix.xx = (FT_Fixed)(ca * 0x10000L); matrix.xy = -(matrix.yx = (FT_Fixed)(sa * 0x10000L)); if (flags & MT_TEXT_OBLIQUE) { matrix.xy = (FT_Fixed)((0.25 * ca - sa) * 0x10000L); matrix.yy = (FT_Fixed)((0.25 * sa + ca) * 0x10000L); load_flags |= FT_LOAD_NO_BITMAP; } error = FT_Set_Char_Size(face, size * 64, 0, dpi, 0); if (error) goto fail1; Y1 = FT_MulFix(face->ascender, face->size->metrics.y_scale); Y2 = FT_MulFix(face->descender, face->size->metrics.y_scale); } spc = font_spacing * 0.64; spcx = font_spacing * 0.64 * ca; spcy = font_spacing * 0.64 * sa; txt2 = calloc(1, ssize2 + 4); if (!txt2) goto fail1; txtp1 = text; txtp2 = (char *)txt2; /* !!! To handle non-Unicode fonts properly, is just too costly; * instead we map 'em to ISO 8859-1 and hope for the best - WJ */ if (FT_Select_Charmap(face, FT_ENCODING_UNICODE)) FT_Set_Charmap(face, face->charmaps[0]); // Fallback /* Convert input string to UTF-32, using native byte order */ #if G_BYTE_ORDER == G_LITTLE_ENDIAN cd = iconv_open("UTF-32LE", encoding); #else /* G_BYTE_ORDER == G_BIG_ENDIAN */ cd = iconv_open("UTF-32BE", encoding); #endif if ( cd == (iconv_t)(-1) ) goto fail0; s = iconv(cd, &txtp1, &ssize1, &txtp2, &ssize2); iconv_close(cd); if (s == (size_t)(-1)) goto fail0; characters = (txtp2 - (char *)txt2) / sizeof(*txt2); // Converted length txt2[characters] = 0x0A; // Final newline txt2[characters + 1] = 0; // Terminate the line for (tmp2 = txt2; *tmp2; tmp2++) lines += *tmp2 == 0x0A; /* For line boundaries */ if (lines > MAX_LW) lw0 = malloc(lines * sizeof(int) * 2); memset(lw0, 0, lines * sizeof(int) * 2); xflag = X1 = X2 = 0; for (pass = -1; pass <= 1; pass++) { pen.x = pen.y = 0; ll = 0; line = -1; for (tmp2 = txt2 , unichar = 0x0A; unichar; unichar = *tmp2++) { if (unichar == 0x0A) // Newline { lw = lw0 + ++line * 2; tx0 = 0; ll = 0; // Reset horizontal index if (pass < 0) continue; tx1 = (Y1 - Y2) * line; pen.x = tx1 * sa + lw[0] * ca; pen.y = tx1 * -ca + lw[0] * sa; continue; } // Apply spacing if (ll) pen.x += spcx , pen.y += spcy; glyph_index = FT_Get_Char_Index(face, unichar); if (scalable) // Cannot rotate fixed fonts FT_Set_Transform(face, &matrix, &pen); error = FT_Load_Glyph( face, glyph_index, load_flags ); if ( error ) continue; if (pass < 0) // Calculating line bounds { if (lw[0] > tx0) lw[0] = tx0; tx0 += face->glyph->metrics.horiAdvance; if (lw[1] < tx0) lw[1] = tx0; tx0 += spc; continue; } // Remember boundaries tx0 = lw[0] + face->glyph->metrics.horiBearingX; if (!ll++) { if (!xflag++) X1 = X2 = tx0; // First glyph pen0 = pen; } tx0 += (pen.x - pen0.x) * ca + (pen.y - pen0.y) * sa; if (X1 > tx0) X1 = tx0; tx0 += face->glyph->metrics.width - 64; if (X2 < tx0) X2 = tx0; switch (face->glyph->bitmap.pixel_mode) { case FT_PIXEL_MODE_GRAY: ppb = 1; break; case FT_PIXEL_MODE_GRAY2: ppb = 2; break; case FT_PIXEL_MODE_GRAY4: ppb = 4; break; case FT_PIXEL_MODE_MONO: ppb = 8; break; default: continue; // Unsupported mode } bx = face->glyph->bitmap_left; by = -face->glyph->bitmap_top; bw = face->glyph->bitmap.width; bh = face->glyph->bitmap.rows; bits = bw && bh; // Bitmap glyphs don't get offset by FreeType if (!scalable || (bits && !face->glyph->outline.n_points)) { bx += pen.x >> 6; by -= pen.y >> 6; } pen.x += face->glyph->advance.x; pen.y += face->glyph->advance.y; // Remember bitmap bounds if (!mem && bits) extend(minxy, bx, by, bx + bw - 1, by + bh - 1); // Draw bitmap onto clipboard memory in pass 1 if (mem) ft_draw_bitmap(mem, *width, &face->glyph->bitmap, bx - minxy[0], by - minxy[1], ppb); } if (pass < 0) // Calculate line offsets { lw = lw0; for (tx0 = tx1 = 0 , line = lines; line-- > 0; ) { if (tx0 > lw[0]) tx0 = lw[0]; if (tx1 < lw[1]) tx1 = lw[1]; lw += 2; } lw = lw0; for (line = lines; line-- > 0; ) { lw[0] = !font_align ? tx0 - lw[0] : // Left font_align == 1 ? // Center (tx0 + tx1 - lw[0] - lw[1]) / 2 : tx1 - lw[1]; // Right lw += 2; } continue; } if (mem) break; // Done /* Adjust bounds for full-height rectangle; ignore possible * rounding issues, for their effect is purely visual - WJ */ by = Y1 + (Y2 - Y1) * line; while (TRUE) { bx = X1; while (TRUE) { int Ax, Ay; Ax = bx * ca - by * sa; if (Ax < 0) Ax = -(-Ax / 64); else Ax = (Ax + 63) / 64; if (Ax < minxy[0]) minxy[0] = Ax; if (Ax > minxy[2]) minxy[2] = Ax; Ay = by * ca + bx * sa; if (Ay < 0) Ay = (63 - Ay) / 64; else Ay = -(Ay / 64); if (Ay < minxy[1]) minxy[1] = Ay; if (Ay > minxy[3]) minxy[3] = Ay; if (bx == X2) break; bx = X2; } if (by == Y1) break; // Done by = Y1; } // Set up new clipboard mem = calloc(1, (*width = minxy[2] - minxy[0] + 1) * (*height = minxy[3] - minxy[1] + 1)); if (!mem) break; // Allocation failed so bail out } if (mem && !scalable && (angle!=0 || size>=2) ) // Rotate/Scale the bitmap font { chanlist old_img = {NULL, NULL, NULL, NULL}, new_img = {NULL, NULL, NULL, NULL}; int nw, nh, ow = *width, oh = *height, ch = CHN_MASK, smooth = FALSE, // FALSE=nearest neighbour, TRUE=smooth scale = size // Scale factor ; if ( scale >= 2 ) // Scale the bitmap up { nw = ow*scale; nh = oh*scale; old_img[ch] = mem; new_img[ch] = calloc( 1, nw*nh ); if ( new_img[ch] ) { if ( !mem_image_scale_real(old_img, ow, oh, 1, new_img, nw, nh, 0, FALSE, FALSE) ) { mem = new_img[ch]; free( old_img[ch] ); // Scaling succeeded *width = nw; *height = nh; ow = nw; oh = nh; } else { free( new_img[ch] ); // Scaling failed } } } if ( angle != 0 ) { mem_rotate_geometry(ow, oh, angle, &nw, &nh); if ( !(flags & MT_TEXT_ROTATE_NN) ) // Smooth rotation requested smooth = TRUE; old_img[ch] = mem; new_img[ch] = calloc( 1, nw*nh ); if ( new_img[ch] ) { //printf("old = %i,%i new = %i,%i\n", ow, oh, nw, nh); mem_rotate_free_real(old_img, new_img, ow, oh, nw, nh, 1, -angle, smooth, FALSE, FALSE, TRUE); mem = new_img[ch]; *width = nw; *height = nh; free( old_img[ch] ); } } } if (lw0 != lwa) free(lw0); fail0: free(txt2); fail1: FT_Done_Face(face); fail2: FT_Done_FreeType(library); return mem; } /* ----------------------------------------------------------------- | Font Indexing Code | ----------------------------------------------------------------- */ #define SIZE_SHIFT 10 #define MAXLEN 256 #define SLOT_FONT 0 #define SLOT_DIR 1 #define SLOT_STYLE 2 #define SLOT_SIZE 3 #define SLOT_FILENAME 4 #define SLOT_TOT 5 static void trim_tab( char *buf, char *txt) { char *st; buf[0] = 0; if (txt) strncpy0(buf, txt, MAXLEN); for ( st=buf; st[0]!=0; st++ ) if ( st[0]=='\t' ) st[0]=' '; if ( buf[0] == 0 ) snprintf(buf, MAXLEN, "_None"); } typedef struct statchain statchain; struct statchain { statchain *p; struct stat buf; }; static void font_dir_search(FT_Library *ft_lib, int dirnum, FILE *fp, char *dir, statchain *cc) { // Search given directory for font files - recursively traverse directories statchain sc = { cc }; FT_Face face; DIR *dp; struct dirent *ep; char full_name[PATHBUF], tmp[2][MAXLEN]; int face_index; dp = opendir(dir); if (!dp) return; while ( (ep = readdir(dp)) ) { file_in_dir(full_name, dir, ep->d_name, PATHBUF); if (stat(full_name, &sc.buf) < 0) continue; // Get file details #ifdef WIN32 if (S_ISDIR(sc.buf.st_mode)) #else if ((ep->d_type == DT_DIR) || S_ISDIR(sc.buf.st_mode)) #endif { // Subdirectory so recurse if (!strcmp(ep->d_name, ".") || !strcmp(ep->d_name, "..")) continue; /* If no inode number, assume it's Windows and just hope * for the best: symlink loops do exist in Windows 7+, but * I know of no simple approach for avoiding them - WJ */ if (sc.buf.st_ino) { for (cc = sc.p; cc; cc = cc->p) if ((sc.buf.st_dev == cc->buf.st_dev) && (sc.buf.st_ino == cc->buf.st_ino)) break; if (cc) continue; // Directory loop } font_dir_search( ft_lib, dirnum, fp, full_name, &sc ); continue; } // File so see if its a font for ( face_index = 0; !FT_New_Face( *ft_lib, full_name, face_index, &face ); face_index++ ) { int size_type = 0; if (!FT_IS_SCALABLE(face)) size_type = face->available_sizes[0].height + (face->available_sizes[0].width << SIZE_SHIFT) + (face_index << (SIZE_SHIFT * 2)); // I use a tab character as a field delimeter, so replace any in the strings with a space trim_tab( tmp[0], face->family_name ); trim_tab( tmp[1], face->style_name ); fprintf(fp, "%s\t%i\t%s\t%i\t%s\n", tmp[0], dirnum, tmp[1], size_type, full_name); if ( (face_index+1) >= face->num_faces ) { FT_Done_Face(face); break; } FT_Done_Face(face); } } closedir(dp); } static void font_index_create(char *filename, char **dir_in) { // dir_in points to NULL terminated sequence of directories to search for fonts statchain sc = { NULL }; FT_Library library; int i; FILE *fp; if (FT_Init_FreeType(&library)) return; if ((fp = fopen(filename, "w"))) { for (i = 0; dir_in[i]; i++) { #ifdef WIN32 /* With old MinGW, stat() fails if dirname has path * separator on end, so cut it off before call */ char *s; int l = strlen(dir_in[i]); if (!l--) continue; s = strdup(dir_in[i]); if ((s[l] == '\\') || (s[l] == '/')) s[l] = '\0'; l = stat(s, &sc.buf); free(s); if (l < 0) continue; #else if (stat(dir_in[i], &sc.buf) < 0) continue; #endif font_dir_search(&library, i, fp, dir_in[i], &sc); } fclose(fp); } FT_Done_FreeType(library); } static void font_mem_clear() // Empty whole structure from memory { free(font_text); font_text = NULL; wjmemfree(font_mem); font_mem = NULL; global_font_node = NULL; } #define newNODE(X) wjmalloc(font_mem, sizeof(X), ALIGNOF(X)) static int font_mem_add(char *font, int dirn, char *style, int fsize, char *filename) {// Add new font data to memory structure. Returns TRUE if successful. int bm_index; fontNODE *fo; styleNODE *st; sizeNODE *ze; filenameNODE *fl; bm_index = fsize >> SIZE_SHIFT * 2; fsize &= (1 << SIZE_SHIFT * 2) - 1; for (fo = global_font_node; fo; fo = fo->next) { if (!strcmp(fo->font_name, font) && (fo->directory == dirn)) break; // Font family+directory already exists } if (!fo) // Set up new structure as no match currently exists { fo = newNODE(fontNODE); if (!fo) return (FALSE); // Memory failure fo->next = global_font_node; global_font_node = fo; fo->directory = dirn; fo->font_name = font; /* Its more efficient to load the newest font family/style/size as the new head because when checking subsequent new items, its more likely that the next match will be the head (or near it). If you add the new item to the end of the list you are ensuring that wasted searches will happen as the more likely match will be at the end. MT 22-8-2007 */ } for (st = fo->style; st; st = st->next) { if (!strcmp(st->style_name, style)) break; // Font style already exists } if (!st) // Set up new structure as no match currently exists { st = newNODE(styleNODE); if (!st) return (FALSE); // Memory failure st->next = fo->style; fo->style = st; // New head style st->style_name = style; } for (ze = st->size; ze; ze = ze->next) { if ( ze->size == fsize ) break; // Font size already exists } if (!ze) // Set up new structure { ze = newNODE(sizeNODE); if (!ze) return (FALSE); // Memory failure ze->next = st->size; st->size = ze; // New head size ze->size = fsize; } /* Always create a new filename node. If any filenames are duplicates we don't care. If the user is stupid enough to pass dupicates then they must have their stupidity shown to them in glorious technicolour so they don't do it again! ;-) MT 24-8-2007 */ fl = newNODE(filenameNODE); if (!fl) return (FALSE); // Memory failure fl->next = ze->filename; // Old first filename (maybe NULL) ze->filename = fl; // This is the new first filename fl->filename = filename; fl->face_index = bm_index; return (TRUE); } static void font_index_load(char *filename) { char *buf, *tmp, *tail, *slots[SLOT_TOT]; int i, dir, size; font_mem = wjmemnew(0, 0); font_text = slurp_file(filename, 1); if (!font_mem || !font_text) { font_mem_clear(); return; } for (buf = font_text + 1; *buf; buf = tmp) { buf += strspn(buf, "\r\n"); if (!*buf) break; tmp = buf + strcspn(buf, "\r\n"); if (*tmp) *tmp++ = 0; for (i = 0; i < SLOT_TOT; i++) { slots[i] = buf; buf += strcspn(buf, "\t"); if (*buf) *buf++ = 0; } dir = strtol(slots[SLOT_DIR], &tail, 10); if (*tail) break; size = strtol(slots[SLOT_SIZE], &tail, 10); if (*tail) break; if (!font_mem_add(slots[0], dir, slots[2], size, slots[4])) { // Memory failure font_mem_clear(); return; } } } #if 0 static void font_index_display(struct fontNODE *head) { int families=0, styles=0, sizes=0, filenames=0; fontNODE *fo = head; styleNODE *st; sizeNODE *ze; filenameNODE *fl; size_t nspace = 0, sspace = 0; while (fo) { printf("%s (%i)\n", fo->font_name, fo->directory); nspace += strlen(fo->font_name) + 1; sspace += sizeof(*fo); families ++; st = fo->style; while (st) { printf("\t%s\n", st->style_name); nspace += strlen(st->style_name) + 1; sspace += sizeof(*st); styles ++; ze = st->size; while (ze) { printf("\t\t%i x %i\n", ze->size % (1<size >> SIZE_SHIFT) % (1<filename; while (fl) { printf("\t\t\t%3i %s\n", fl->face_index, fl->filename); nspace += strlen(fl->filename) + 1; sspace += sizeof(*fl); filenames++; fl = fl->next; } ze = ze->next; } st = st->next; } fo = fo->next; } printf("\nMemory Used\t%'zu + %'zu (%.1fK)\n" "Font Families\t%i\nFont Styles\t%i\nFont Sizes\t%i\nFont Filenames\t%i\n\n", nspace, sspace, (double)(nspace + sspace) / 1024, families, styles, sizes, filenames); } #endif /* ----------------------------------------------------------------- | GTK+ Front End Code | ----------------------------------------------------------------- */ static unsigned char *render_to_1bpp(int *w, int *h) { double angle = 0; unsigned char *text_1bpp; int flags = 0, size = 1; size = inifile_get_gboolean("fontTypeBitmap", TRUE) ? font_bmsize : font_size; if ((mem_img_bpp == 1) || !font_aa) { flags |= MT_TEXT_MONO; flags |= MT_TEXT_ROTATE_NN; // RGB image without AA = nearest neighbour rotation } if (font_obl) flags |= MT_TEXT_OBLIQUE; if (font_r) angle = font_angle / 100.0; text_1bpp = mt_text_render( inifile_get( "textString", "" ), strlen( inifile_get( "textString", "" ) ), inifile_get( "lastTextFilename", "" ), #if GTK_MAJOR_VERSION == 1 #ifdef U_NLS nl_langinfo(CODESET), // this only works on international version of mtPaint, as setlocale is needed #else "ISO-8859-1", // Non-international verson so it must be this #endif #else /* if GTK_MAJOR_VERSION >= 2 */ "UTF-8", #endif size, inifile_get_gint32( "lastTextFace", 0 ), angle, flags, w, h ); return text_1bpp; } /* Re-render the preview text and update it */ static void font_preview_update(font_dd *dt) { unsigned char *text_1bpp; int w=1, h=1; if (script_cmds) return; // Not visible anyway if (dt->preview_rgb) // Remove old rendering { free(dt->preview_rgb); dt->preview_rgb = NULL; } text_1bpp = render_to_1bpp(&w, &h); if ( text_1bpp ) { dt->preview_rgb = calloc( 1, 3*w*h ); if (dt->preview_rgb) { int i, j = w*h; unsigned char *src = text_1bpp, *dest = dt->preview_rgb; for ( i=0; ipreview_whc[0] = w; dt->preview_whc[1] = h; } free( text_1bpp ); //printf("font preview update %i x %i\n", w, h); } cmd_reset(dt->preview_area, dt); // Show the world the fruits of my hard labour! ;-) } static void font_gui_create_index(char *filename) // Create index file with settings from ~/.mtpaint { char buf[128], *dirs[TX_MAX_DIRS + 1]; int i; memset(dirs, 0, sizeof(dirs)); for (i = 0; i < font_dirs; i++) { snprintf(buf, 128, "font_dir%i", i); dirs[i] = inifile_get( buf, "" ); } progress_init(_("Creating Font Index"), 0); font_index_create( filename, dirs ); progress_end(); } void ft_render_text() // FreeType equivalent of render_text() { unsigned char *text_1bpp; int w=1, h=1; text_1bpp = render_to_1bpp(&w, &h); if (text_1bpp && make_text_clipboard(text_1bpp, w, h, 1)) text_paste = TEXT_PASTE_FT; else text_paste = TEXT_PASTE_NONE; } static void store_values(font_dd *dt) { inifile_set("textString", dt->text); if (inifile_get_gboolean( "fontTypeBitmap", TRUE)) font_bmsize = dt->fontsize; else font_size = dt->fontsize; if (mem_channel == CHN_IMAGE) { if (!script_cmds || (font_bk = dt->bkg[0] >= 0)) font_bkg = dt->bkg[0]; } if (!script_cmds || (font_r = !!dt->angle)) font_angle = dt->angle; if (!script_cmds || (ft_setdpi = !!dt->dpi[0])) font_dpi = dt->dpi[0]; font_spacing = dt->spacing; } static void paste_text_ok(font_dd *dt, void **wdata, int what, void **where) { run_query(wdata); store_values(dt); ft_render_text(); if (mem_clipboard) pressed_paste(TRUE); run_destroy(wdata); } static void collect_fontnames(font_dd *dt) { memx2 mem = dt->fnmmem; char buf2[256]; fontNODE *fn; fontname_cc *fc; char *last_font_name = inifile_get("lastFontName", ""); int last_font_name_dir = inifile_get_gint32("lastFontNameDir", 0), last_font_name_bitmap = inifile_get_gint32("lastFontNameBitmap", 0); int ofs, dir, cnt, b, strs[TX_MAX_DIRS]; /* Gather up nodes */ for (fn = global_font_node , cnt = 0; fn; fn = fn->next) cnt++; dt->fontname = -1; memset(strs, 0, sizeof(strs)); mem.here = 0; getmemx2(&mem, 8000); // default size b = mem.here += getmemx2(&mem, cnt * sizeof(fontname_cc)); // minimum size addstr(&mem, "B", 0); for (fn = global_font_node , cnt = 0; fn; fn = fn->next) { if ((fn->directory < 0) || (fn->directory >= TX_MAX_DIRS)) continue; /* Trying to remember start row */ if (!strcmp(fn->font_name, last_font_name) && (last_font_name_dir == fn->directory) && (last_font_name_bitmap == !!fn->style->size->size)) dt->fontname = cnt; /* Prepare dir index */ dir = fn->directory; if (!strs[dir]) { strs[dir] = mem.here; sprintf(buf2, "%3d", dir + 1); addstr(&mem, buf2, 0); } dir = strs[dir]; /* Convert name string (to UTF-8 in GTK+2) and store it */ ofs = mem.here; /* Label bitmap/scalable fonts for scripting */ if (script_cmds) addstr(&mem, fn->style->size->size ? "B " : "S ", 1); gtkuncpy(buf2, fn->font_name, sizeof(buf2)); addstr(&mem, buf2, 0); /* Add a row - with offsets for now */ fc = (fontname_cc *)mem.buf + cnt; fc->fn = fn; fc->dir = dir - ((char *)&fc->dir - mem.buf); // "B" if has size (is bitmap), "" otherwise fc->bm = (fn->style->size->size ? b : b + 1) - ((char *)&fc->bm - mem.buf); fc->name = ofs - ((char *)&fc->name - mem.buf); cnt++; } dt->nfontnames = cnt; /* Allocations done - now set up pointers */ dt->fontnames = (void *)mem.buf; // won't change now /* Save allocator data */ dt->fnmmem = mem; } static void collect_fontstyles(font_dd *dt) { static const char *default_styles[] = { "Regular", "Medium", "Book", "Roman", NULL }; char *last_font_style = inifile_get("lastFontStyle", ""); char buf2[256]; styleNODE *sn; fontstyle_cc *fc; memx2 mem = dt->fstmem; int i, ofs, cnt, default_row = -1; /* Gather up nodes */ sn = dt->fontnames[dt->fontname].fn->style; for (cnt = 0; sn; sn = sn->next) cnt++; dt->fontstyle = -1; mem.here = 0; getmemx2(&mem, 4000); // default size mem.here += getmemx2(&mem, cnt * sizeof(fontstyle_cc)); // minimum size sn = dt->fontnames[dt->fontname].fn->style; for (cnt = 0; sn; sn = sn->next) { /* Trying to remember start row */ if (!strcmp(sn->style_name, last_font_style)) dt->fontstyle = cnt; else for (i = 0; default_styles[i]; i++) { if (!strcmp(sn->style_name, default_styles[i])) default_row = cnt; } /* Convert name string (to UTF-8 in GTK+2) and store it */ ofs = mem.here; gtkuncpy(buf2, sn->style_name, sizeof(buf2)); addstr(&mem, buf2, 0); /* Add a row - with offset for now */ fc = (fontstyle_cc *)mem.buf + cnt; fc->sn = sn; fc->name = ofs - ((char *)&fc->name - mem.buf); cnt++; } /* Use default if last style not found */ if (dt->fontstyle < 0) dt->fontstyle = default_row; dt->nfontstyles = cnt; /* Allocations done - now set up pointers */ dt->fontstyles = (void *)mem.buf; // won't change now /* Save allocator data */ dt->fstmem = mem; } static void collect_fontsizes(font_dd *dt) { static const unsigned char sizes[] = { 8, 9, 10, 11, 12, 13, 14, 16, 18, 20, 22, 24, 26, 28, 32, 36, 40, 48, 56, 64, 72 }; char buf2[256]; sizeNODE *zn; fontsize_cc *fc; memx2 mem = dt->fszmem; int i, cnt; /* Gather up nodes */ zn = dt->fontstyles[dt->fontstyle].sn->size; dt->lfontsize = -1; mem.here = 0; getmemx2(&mem, sizeof(sizes) * sizeof(fontsize_cc) > 4000 ? sizeof(sizes) * sizeof(fontsize_cc) : 4000); // default size if (zn && !zn->size) { mem.here += sizeof(sizes) * sizeof(fontsize_cc); for (i = 0; i < sizeof(sizes); i++) { int ofs, n = sizes[i]; /* Trying to remember start row */ if (n == font_size) dt->lfontsize = i; /* Prepare text */ ofs = mem.here; sprintf(buf2, "%2d", n); addstr(&mem, buf2, 0); /* Add a row - with offset for now */ fc = (fontsize_cc *)mem.buf + i; fc->zn = zn; fc->n = n; fc->what = ofs - ((char *)&fc->what - mem.buf); } cnt = sizeof(sizes); } else { int geom = inifile_get_gint32("lastfontBitmapGeometry", 0); for (cnt = 0; zn; zn = zn->next) cnt++; mem.here += getmemx2(&mem, cnt * sizeof(fontsize_cc)); // minsize zn = dt->fontstyles[dt->fontstyle].sn->size; for (cnt = 0; zn; zn = zn->next) { int ofs, n = zn->size; /* Trying to remember start row */ if (geom == n) dt->lfontsize = cnt; /* Prepare text */ ofs = mem.here; snprintf(buf2, 32, "%2d x %2d", i = (n >> SIZE_SHIFT) & ((1 << SIZE_SHIFT) - 1), n & ((1 << SIZE_SHIFT) - 1)); addstr(&mem, buf2, 0); /* Add a row - with offset for now */ fc = (fontsize_cc *)mem.buf + cnt; fc->zn = zn; fc->n = 0; // !!! or maybe zn->size? fc->what = ofs - ((char *)&fc->what - mem.buf); cnt++; } } dt->nlfontsizes = cnt; /* Allocations done - now set up pointers */ dt->fontsizes = (void *)mem.buf; // won't change now /* Save allocator data */ dt->fszmem = mem; } static void collect_fontfiles(font_dd *dt) { char *last_filename = inifile_get("lastTextFilename", ""); char buf2[256]; filenameNODE *fn; fontfile_cc *fc; memx2 mem = dt->ffnmem; int cnt; /* Gather up nodes */ fn = dt->fontsizes[dt->lfontsize].zn->filename; for (cnt = 0; fn; fn = fn->next) cnt++; dt->fontfile = -1; mem.here = 0; getmemx2(&mem, 4000); // default size mem.here += getmemx2(&mem, cnt * sizeof(fontfile_cc)); // minimum size fn = dt->fontsizes[dt->lfontsize].zn->filename; for (cnt = 0; fn; fn = fn->next) { char *s, *nm = fn->filename; int ofs1, ofs2; /* Trying to remember start row */ if (!strcmp(nm, last_filename)) dt->fontfile = cnt; /* Convert name string (to UTF-8 in GTK+2) and store it */ s = strrchr(nm, DIR_SEP); s = s ? s + 1 : nm; ofs1 = mem.here; gtkuncpy(buf2, s, sizeof(buf2)); addstr(&mem, buf2, 0); /* Store index string */ sprintf(buf2, "%3d", fn->face_index); ofs2 = mem.here; addstr(&mem, buf2, 0); /* Add a row - with offsets for now */ fc = (fontfile_cc *)mem.buf + cnt; fc->fn = fn; fc->name = ofs1 - ((char *)&fc->name - mem.buf); fc->face = ofs2 - ((char *)&fc->face - mem.buf); cnt++; } dt->nfontfiles = cnt; /* Allocations done - now set up pointers */ dt->fontfiles = (void *)mem.buf; // won't change now /* Save allocator data */ dt->ffnmem = mem; } static void collect_dirnames(font_dd *dt) { memx2 mem = dt->dirmem; char buf2[256]; dir_cc *fc; int i; /* Gather up nodes */ mem.here = 0; getmemx2(&mem, 4000); // default size mem.here += getmemx2(&mem, font_dirs * sizeof(dir_cc)); // minimum size for (i = 0; i < font_dirs; i++) { int ofs1, ofs2; /* Prepare dir index */ ofs1 = mem.here; sprintf(buf2, "%3d", i + 1); addstr(&mem, buf2, 0); /* Convert name string (to UTF-8 in GTK+2) and store it */ ofs2 = mem.here; snprintf(buf2, 128, "font_dir%i", i); gtkuncpy(buf2, inifile_get(buf2, ""), sizeof(buf2)); addstr(&mem, buf2, 0); /* Add a row - with offsets for now */ fc = (dir_cc *)mem.buf + i; fc->idx = ofs1 - ((char *)&fc->idx - mem.buf); fc->dir = ofs2 - ((char *)&fc->dir - mem.buf); } dt->ndirs = font_dirs; /* Allocations done - now set up pointers */ dt->dirs = (void *)mem.buf; // won't change now /* Save allocator data */ dt->dirmem = mem; } static void click_font_dir_btn(font_dd *dt, void **wdata, int what, void **where) { int i, rows = font_dirs; char buf[32], buf2[32]; run_query(wdata); if (origin_slot(where) != dt->add_b) // Remove row { if (!rows) return; // Nothing to delete rows--; // Re-work inifile items for (i = dt->dir; i < rows; i++) { snprintf(buf, sizeof(buf), "font_dir%i", i); snprintf(buf2, sizeof(buf2), "font_dir%i", i + 1); inifile_set(buf, inifile_get(buf2, "")); } // !!! List is sorted by index, so selected row == selected index if (dt->dir >= rows) dt->dir--; } else // Add row { if (!dt->dirp[0] || (rows >= TX_MAX_DIRS)) return; // Cannot add snprintf(buf, sizeof(buf), "font_dir%i", rows++); inifile_set(buf, dt->dirp); } font_dirs = rows; collect_dirnames(dt); cmd_reset(dt->dir_l, dt); } static void select_font(font_dd *dt, void **wdata, int what, void **where); static void click_create_font_index(font_dd *dt, void **wdata) { if (font_dirs > 0) { char txt[PATHBUF]; file_in_homedir(txt, FONT_INDEX_FILENAME, PATHBUF); font_gui_create_index(txt); // Create new index file dt->lock = TRUE; // Paranoia font_mem_clear(); // Empty memory of current nodes font_index_load(txt); collect_fontnames(dt); cmd_reset(dt->fname_l, dt); dt->lock = FALSE; select_font(dt, wdata, op_EVT_SELECT, dt->fname_l); // reselect } else alert_box(_("Error"), _("You must select at least one directory to search for fonts."), NULL); } static void select_font(font_dd *dt, void **wdata, int what, void **where) { void *cause; fontNODE *fn; styleNODE *sn; fontsize_cc *fc; filenameNODE *nn; int bitmap_font, idx; cause = cmd_read(where, dt); if (dt->lock || !dt->nfontnames) return; dt->lock = TRUE; idx = cause == &dt->fontname ? 0 : cause == &dt->fontstyle ? 1 : cause == &dt->lfontsize ? 2 : 3; /* cause == &dt->fontfile */ switch (idx) { case 0: // Name list fn = dt->fontnames[dt->fontname].fn; bitmap_font = !!fn->style->size->size; inifile_set_gboolean("fontTypeBitmap", bitmap_font); cmd_sensitive(dt->obl_c, !bitmap_font); /* Update style list */ collect_fontstyles(dt); cmd_reset(dt->fstyle_l, dt); inifile_set("lastFontName", fn->font_name); inifile_set_gint32("lastFontNameDir", fn->directory); inifile_set_gint32("lastFontNameBitmap", bitmap_font); /* Fallthrough */ case 1: // Style list sn = dt->fontstyles[dt->fontstyle].sn; /* Update size list */ collect_fontsizes(dt); cmd_reset(dt->fsize_l, dt); inifile_set("lastFontStyle", sn->style_name); /* Fallthrough */ case 2: // Size list fc = dt->fontsizes + dt->lfontsize; // Scalable so remember size if (!fc->zn->size) { // Only if it really was reselected if (idx == 2) font_size = fc->n; } // Non-Scalable so remember index else inifile_set_gint32("lastfontBitmapGeometry", fc->zn->size); /* Update file list */ collect_fontfiles(dt); cmd_reset(dt->ffile_l, dt); /* Fallthrough */ case 3: // File list nn = dt->fontfiles[dt->fontfile].fn; inifile_set("lastTextFilename", nn->filename); inifile_set_gint32("lastTextFace", nn->face_index); break; } /* Update size */ dt->fontsize = dt->fontsizes[dt->lfontsize].zn->size ? // nonzero for bitmaps font_bmsize : font_size; cmd_reset(dt->size_spin, dt); dt->lock = FALSE; font_preview_update(dt); // Update the font preview area } static void init_font_lists() // LIST INITIALIZATION { char txt[PATHBUF]; /* Get font directories if we don't have any */ if (font_dirs <= 0) { #ifdef WIN32 int new_dirs = 1; char *windir = getenv("WINDIR"); file_in_dir(txt, windir && *windir ? windir : "C:\\WINDOWS", "Fonts", PATHBUF); inifile_set("font_dir0", txt); #else int new_dirs = 0; FILE *fp; char buf[4096], buf2[128], *s; if (!(fp = fopen("/etc/X11/xorg.conf", "r"))) fp = fopen("/etc/X11/XF86Config", "r"); // If these files are not found the user will have to manually enter directories if (fp) { while (fgets(buf, 4090, fp)) { s = strstr(buf, "FontPath"); if (!s) continue; s = strstr(buf, ":unscaled\""); if (!s) s = strrchr(buf, '"'); if (!s) continue; *s = '\0'; s = strchr(buf, '"'); if (!s) continue; snprintf(buf2, 128, "font_dir%i", new_dirs); inifile_set(buf2, s + 1); if (++new_dirs >= TX_MAX_DIRS) break; } fclose(fp); } if (!new_dirs && (fp = fopen("/etc/fonts/fonts.conf", "r"))) { char *s1, *s2; for (s1 = NULL; s1 || (s1 = fgets(buf, 4090, fp)); s1 = s2) { s2 = strstr(s1, ""); if (!s2) continue; *s2 = '\0'; s2 += 6; s = strstr(s1, ""); if (!s) continue; snprintf(buf2, 128, "font_dir%i", new_dirs); inifile_set(buf2, s + 5); if (++new_dirs >= TX_MAX_DIRS) break; } fclose(fp); } /* Add user's font directory */ file_in_homedir(txt, ".fonts", PATHBUF); snprintf(buf2, 128, "font_dir%i", new_dirs++); inifile_set(buf2, txt); #endif font_dirs = new_dirs; } file_in_homedir(txt, FONT_INDEX_FILENAME, PATHBUF); font_index_load(txt); // Does a valid ~/.mtpaint_fonts index exist? if (!global_font_node) // Index file not loaded { font_gui_create_index(txt); font_index_load(txt); // Try for second and last time } } static void font_entry_changed(font_dd *dt, void **wdata, int what, void **where) { if (cmd_read(where, dt) == &ft_setdpi) cmd_set(dt->book, ft_setdpi); if (dt->lock) return; store_values(dt); font_preview_update(dt); // Update the font preview area } #define WBbase font_dd static void *font_code[] = { WPWHEREVER, WINDOWm(_("Paste Text")), WXYWH("paste_text_window", 400, 450), BORDER(NBOOK, 0), NBOOK, // !!! Originally was in window directly // TAB 1 - TEXT PAGE(_("Text")), XHBOX, // !!! Originally the page was an hbox VBOXP, // !!! what for? XSCROLL(0, 1), // never/auto WLIST, OPNAME0, RTXTCOLUMND(fontname_cc, dir, 0, 0), RTXTCOLUMND(fontname_cc, bm, 0, 0), NRTXTCOLUMND(_("Font"), fontname_cc, name, 0, 0), COLUMNDATA(fontnames, sizeof(fontname_cc)), CLEANUP(fontnames), REF(fname_l), LISTCS(fontname, nfontnames, fnsort, select_font), TRIGGER, WDONE, // VBOXP XVBOXP, XHBOXP, XSCROLL(1, 1), // auto/auto WLIST, NRTXTCOLUMND(_("Style"), fontstyle_cc, name, 0, 0), COLUMNDATA(fontstyles, sizeof(fontstyle_cc)), CLEANUP(fontstyles), REF(fstyle_l), WIDTH(100), LISTC(fontstyle, nfontstyles, select_font), XVBOX, BORDER(SCROLL, 0), XSCROLL(1, 1), // auto/auto DEFBORDER(SCROLL), WLIST, NRTXTCOLUMND(_("Size"), fontsize_cc, what, 0, 1), // centered OPNAME("Bitmap size"), // scalable fonts use the spin COLUMNDATA(fontsizes, sizeof(fontsize_cc)), CLEANUP(fontsizes), REF(fsize_l), LISTC(lfontsize, nlfontsizes, select_font), BORDER(SPIN, 0), REF(size_spin), SPINc(fontsize, 1, 500), EVENT(CHANGE, font_entry_changed), DEFBORDER(SPIN), OPNAME("Size"), WDONE, // XVBOX XSCROLL(1, 1), // auto/auto WLIST, NRTXTCOLUMND(_("Filename"), fontfile_cc, name, 0, 0), NRTXTCOLUMND(_("Face"), fontfile_cc, face, 0, 0), COLUMNDATA(fontfiles, sizeof(fontfile_cc)), CLEANUP(fontfiles), REF(ffile_l), LISTC(fontfile, nfontfiles, select_font), WDONE, // XHBOXP // Text entry box FVBOXB(_("Text")), // !!! Originally was hbox BORDER(ENTRY, 0), MLENTRY(text), EVENT(CHANGE, font_entry_changed), FOCUS, WDONE, // PREVIEW AREA FXVBOXB(_("Preview")), // !!! Originally was hbox BORDER(SCROLL, 0), XSCROLL(1, 1), // auto/auto DEFBORDER(SCROLL), REF(preview_area), CANVASIMGB(preview_rgb, preview_whc), CLEANUP(preview_rgb), WDONE, // FXVBOXB // TOGGLES HBOX, UNLESSx(idx, 1), CHECKv(_("Antialias"), font_aa), EVENT(CHANGE, font_entry_changed), ENDIF(1), UNLESSx(img, 1), CHECKv(_("Invert"), font_bk), EVENT(CHANGE, font_entry_changed), ENDIF(1), IFx(img, 1), UNLESSx(script, 1), /* && */ CHECKv(_("Background colour ="), font_bk), EVENT(CHANGE, font_entry_changed), ENDIF(1), IFx(img, 1), SPINa(bkg), EVENT(CHANGE, font_entry_changed), OPNAME("Background colour ="), ENDIF(1), UNLESSx(script, 1), CHECKv(_("DPI ="), ft_setdpi), EVENT(CHANGE, font_entry_changed), TRIGGER, ENDIF(1), REF(book), PLAINBOOK, NOSPINv(sys_dpi), WDONE, // page 0 SPINa(dpi), EVENT(CHANGE, font_entry_changed), OPNAME("DPI ="), WDONE, // page 1 WDONE, // HBOX HBOX, REF(obl_c), CHECKv(_("Oblique"), font_obl), EVENT(CHANGE, font_entry_changed), UNLESSx(script, 1), CHECKv(_("Angle of rotation ="), font_r), EVENT(CHANGE, font_entry_changed), ENDIF(1), FSPIN(angle, -36000, 36000), EVENT(CHANGE, font_entry_changed), OPNAME("Angle of rotation ="), MLABEL(_("Align")), OPTve(align_txt, 3, font_align, font_entry_changed), WDONE, // HBOX HBOX, MLABEL(_("Spacing")), FSPIN(spacing, -MAX_WIDTH * 100, MAX_WIDTH * 100), EVENT(CHANGE, font_entry_changed), WDONE, // HBOX HSEPl(200), OKBOXP(_("Paste Text"), paste_text_ok, _("Close"), NULL), WDONE, WDONE, WDONE, WDONE, // XVBOXP, XHBOX, PAGE /* !!! PATH isn't scriptable, and not much use to add dirs from script */ ENDSCRIPT, // TAB 2 - DIRECTORIES PAGE(_("Font Directories")), // VBOX, // !!! utterly useless XSCROLL(1, 1), // auto/auto WLIST, RTXTCOLUMND(dir_cc, idx, 0, 0), NRTXTCOLUMND(_("Directory"), dir_cc, dir, 0, 0), COLUMNDATA(dirs, sizeof(dir_cc)), CLEANUP(dirs), REF(dir_l), LISTC(dir, ndirs, NULL), PATH(_("New Directory"), _("Select Directory"), FS_SELECT_DIR, dirp), HSEPl(200), HBOXP, /* !!! Keyboard shortcut doesn't work for invisible buttons in GTK+, and * doubled handlers of window close don't matter - destructor called by * the first one removes the other before it runs - WJ */ CANCELBTN(_("Close"), NULL), REF(add_b), BUTTON(_("Add"), click_font_dir_btn), BUTTON(_("Remove"), click_font_dir_btn), BUTTON(_("Create Index"), click_create_font_index), WSHOW }; #undef WBbase void pressed_mt_text() { font_dd tdata; if (!global_font_node) init_font_lists(); cmd_peekv(main_window_, &sys_dpi, sizeof(sys_dpi), WINDOW_DPI); memset(&tdata, 0, sizeof(tdata)); tdata.fontsize = font_size; // !!! is reset tdata.text = inifile_get("textString", __("Enter Text Here")); tdata.bkg[0] = font_bkg % mem_cols; tdata.bkg[1] = 0; tdata.bkg[2] = mem_cols - 1; tdata.angle = font_angle; tdata.preview_whc[0] = tdata.preview_whc[1] = 1; tdata.preview_whc[2] = mem_background * 0x010101; tdata.img = mem_channel == CHN_IMAGE; tdata.idx = tdata.img && (mem_img_bpp == 1); tdata.dpi[0] = font_dpi; tdata.dpi[1] = 1; tdata.dpi[2] = 65535; tdata.spacing = font_spacing; if (script_cmds) // Simplified controls - spins w/o toggles { tdata.script = TRUE; if (!font_bk) tdata.bkg[0] = -1; tdata.bkg[1] = -1; if (!font_r) tdata.angle = 0; if (!ft_setdpi) tdata.dpi[0] = 0; tdata.dpi[1] = 0; } collect_fontnames(&tdata); tdata.fnsort = 3; // By name column, ascending collect_dirnames(&tdata); tdata.dir = -1; // Top sorted run_create_(font_code, &tdata, sizeof(tdata), script_cmds); } #endif /* U_FREETYPE */ mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/font.h000066400000000000000000000021041471325446300220560ustar00rootroot00000000000000/* font.h Copyright (C) 2007-2016 Mark Tyler and Dmitry Groshev This file is part of mtPaint. mtPaint 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. mtPaint 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 mtPaint in the file COPYING. */ #define TEXT_PASTE_NONE 0 // Not using text paste in the clipboard #define TEXT_PASTE_GTK 1 // GTK+ text paste #define TEXT_PASTE_FT 2 // FreeType text paste #ifdef U_FREETYPE int font_obl, font_bmsize, font_size; int font_dirs; int ft_setdpi; void pressed_mt_text(); void ft_render_text(); // FreeType equivalent of render_text() #else #define pressed_mt_text() #define ft_render_text() #endif mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/fpick.c000066400000000000000000000663421471325446300222150ustar00rootroot00000000000000/* fpick.c Copyright (C) 2007-2020 Mark Tyler and Dmitry Groshev This file is part of mtPaint. mtPaint 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. mtPaint 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 mtPaint in the file COPYING. */ #include "global.h" #undef _ #define _(X) X #include "mygtk.h" #include "fpick.h" #include "vcode.h" #ifdef U_FPICK_MTPAINT /* mtPaint fpicker */ #include "inifile.h" #include "memory.h" #include "png.h" // Needed by canvas.h #include "canvas.h" #include "mainwindow.h" #include "icons.h" #define FP_KEY "mtPaint.fpick" #define FPICK_ICON_UP 0 #define FPICK_ICON_HOME 1 #define FPICK_ICON_DIR 2 #define FPICK_ICON_HIDDEN 3 #define FPICK_ICON_CASE 4 #define FPICK_ICON_TOT 5 #define FPICK_COMBO_ITEMS 16 enum { COL_FILE = 0, COL_NAME, COL_SIZE, COL_TYPE, COL_TIME, COL_NOCASE, COL_CASE, COL_MAX }; #define RELREF(X) ((char *)&X + X) // ------ Main Data Structure ------ typedef struct { char *title; int flags; int entry_f; int allow_files, allow_dirs; // Allow the user to select files/directories int show_hidden; int cnt, cntx, idx; int fsort; // Sort column/direction of list int *fcols, *fmap; char *cdir, **cpp, *cp[FPICK_COMBO_ITEMS + 1]; void **combo, **list; void **hbox, **entry; void **ok, **cancel; memx2 files; char fname[PATHBUF]; char txt_directory[PATHBUF]; // Current directory - Normal C string char txt_mask[PATHTXT]; // Filter mask - UTF8 in GTK+2 char combo_items[FPICK_COMBO_ITEMS][PATHTXT]; // UTF8 in GTK+2 } fpick_dd; static int case_insensitive; static void fpick_btn(fpick_dd *dt, void **wdata, int what, void **where); #if GTK_MAJOR_VERSION == 1 #include #define fpick_fnmatch(mask, str) !fnmatch(mask, str, FNM_PATHNAME) #elif (GTK_MAJOR_VERSION == 2) && (GTK2VERSION < 4) /* GTK+ 2.0/2.2 */ #define fpick_fnmatch(mask, str) wjfnmatch(mask, str, TRUE) #else #define HAVE_FILEFILTER #endif static void filter_dir(fpick_dd *dt, const char *pattern) { #ifdef HAVE_FILEFILTER GtkFileFilter *filt = gtk_file_filter_new(); GtkFileFilterInfo info; gtk_file_filter_add_pattern(filt, pattern); info.contains = GTK_FILE_FILTER_DISPLAY_NAME; #endif int *cols = dt->fcols, *map = dt->fmap; int i, cnt = dt->cnt; char *s; for (i = 0; i < cnt; i++ , cols += COL_MAX) { s = RELREF(cols[COL_NAME]); /* Filter files, let directories pass */ if (pattern[0] && (s[0] == 'F')) { #ifdef HAVE_FILEFILTER info.display_name = s + 1; if (!gtk_file_filter_filter(filt, &info)) continue; #else if (!fpick_fnmatch(pattern, s + 1)) continue; #endif } *map++ = i; } dt->cntx = map - dt->fmap; #if GTK_MAJOR_VERSION == 3 g_object_ref_sink(filt); g_object_unref(filt); #elif defined HAVE_FILEFILTER gtk_object_sink(GTK_OBJECT(filt)); #endif } static fpick_dd *mdt; static int cmp_rows(const void *f1, const void *f2); static void fpick_sort(fpick_dd *dt) { if (dt->cntx <= 0) return; // Nothing to do /* Sort row map */ mdt = dt; qsort(dt->fmap, dt->cntx, sizeof(dt->fmap[0]), cmp_rows); } /* *** A WORD OF WARNING *** * Collating string comparison functions consider letter case only *AFTER* * letter itself for any (usable) value of LC_COLLATE except LC_COLLATE=C, and * in that latter case, order by character codepoint which frequently is * unrelated to alphabetical ordering. And on GTK+1 with multibyte charset, * casefolding will break down horribly, too. * What this means in practice: don't expect anything sane out of alphabetical * sorting outside of strict ASCII, and don't expect anything sane out of * case-sensitive sorting at all. - WJ */ #if GTK_MAJOR_VERSION == 1 /* Returns a string which can be used as key for case-insensitive sort; * input string is in locale encoding in GTK+1, in UTF-8 in GTK+2 */ static char *isort_key(char *src) { char *s; s = g_strdup(src); g_strdown(s); // !!! Consider replicating g_utf8_collate_key(), based on strxfrm() return (s); } /* "strkeycmp" is for sort keys, "strcollcmp" for displayable strings */ #define strkeycmp strcoll #define strcollcmp strcoll #else /* if GTK_MAJOR_VERSION >= 2 */ static char *isort_key(char *src) { char *s; src = g_utf8_casefold(src, -1); s = g_utf8_collate_key(src, -1); g_free(src); return (s); } #define strkeycmp strcmp #define strcollcmp g_utf8_collate #endif /* !!! Expects that "txt" points to PATHBUF-sized buffer */ static void fpick_cleanse_path(char *txt) // Clean up null terminated path { char *src, *dest; #ifdef WIN32 // Unify path separators reseparate(txt); #endif // Expand home directory if ((txt[0] == '~') && (txt[1] == DIR_SEP)) { src = file_in_homedir(NULL, txt + 2, PATHBUF); strncpy0(txt, src, PATHBUF - 1); free(src); } // Remove multiple consecutive occurences of DIR_SEP if ((dest = src = strstr(txt, DIR_SEP_STR DIR_SEP_STR))) { while (*src) { if (*src == DIR_SEP) while (src[1] == DIR_SEP) src++; *dest++ = *src++; } *dest++ = '\0'; } } static int cmp_rows(const void *f1, const void *f2) { static const signed char sort_order[] = { COL_NAME, COL_TIME, COL_SIZE, -1 }; int *r1, *r2; char *s1, *s2; int d, c, bits, lvl; r1 = mdt->fcols + *(int *)f1 * COL_MAX; r2 = mdt->fcols + *(int *)f2 * COL_MAX; /* "/ .." Directory always goes first, other dirs next, files last; * and their type IDs are ordered to reflect that */ s1 = RELREF(r1[COL_NAME]); s2 = RELREF(r2[COL_NAME]); if ((d = s1[0] - s2[0])) return (d); bits = lvl = 0; c = abs(mdt->fsort) - 1 + COL_NAME; while (c >= 0) { if (bits & (1 << c)) { c = sort_order[lvl++]; continue; } bits |= 1 << c; s1 = RELREF(r1[c]); s2 = RELREF(r2[c]); switch (c) { case COL_TYPE: if ((d = strcollcmp(s1, s2))) break; continue; case COL_SIZE: if ((d = strcmp(s1, s2))) break; continue; case COL_TIME: if ((d = strcmp(s2, s1))) break; // Newest first continue; default: case COL_NAME: c = case_insensitive ? COL_NOCASE : COL_CASE; continue; case COL_NOCASE: case COL_CASE: if ((d = strkeycmp(s1, s2))) break; c = COL_CASE; continue; } break; } return (mdt->fsort < 0 ? -d : d); } /* Register directory in combo */ static void fpick_directory_new(fpick_dd *dt, char *name) { char *dest, **cpp, txt[PATHTXT]; int i; gtkuncpy(txt, name, PATHTXT); /* Does this text already exist in the list? */ cpp = dt->cpp; for (i = 0 ; i < FPICK_COMBO_ITEMS - 1; i++) if (!strcmp(txt, cpp[i])) break; dest = cpp[i]; memmove(cpp + 1, cpp, i * sizeof(*cpp)); // Shuffle items down as needed memcpy(cpp[0] = dest, txt, PATHTXT); // Add item to list dt->cdir = txt; cmd_reset(dt->combo, dt); } #ifdef WIN32 #include #define WIN32_LEAN_AND_MEAN #include static void scan_drives(fpick_dd *dt, int cdrive) { static const unsigned char dmap[COL_MAX] = { 1, 0, 4, 4, 4, 1, 1 }; memx2 mem = dt->files; char *cp, *dest, buf[PATHBUF]; // More than enough for 26 4-char strings int i, j, *tc; mem.here = 0; getmemx2(&mem, 8000); // default size mem.here += getmemx2(&mem, 26 * ((COL_MAX + 1) * sizeof(int) + 5)); // minimum size /* Get the current drive letter */ if (!cdrive) { if (GetCurrentDirectory(sizeof(buf), buf) && (buf[1] == ':')) cdrive = buf[0]; } cdrive = toupper(cdrive); /* Get all drives */ GetLogicalDriveStrings(sizeof(buf), buf); tc = dt->fcols = (void *)mem.buf; dest = (void *)(tc + 26 * (COL_MAX + 1)); dt->idx = -1; for (i = 0 , cp = buf; *cp; i++ , cp += strlen(cp) + 1) { for (j = 0; j < COL_MAX; j++) { *tc = dest + dmap[j] - (char *)tc; tc++; } strcpy(dest, "DC:\\"); // 'D' is type flag if ((dest[1] = toupper(cp[0])) == cdrive) dt->idx = i; dest += 5; } dt->cnt = i; // Setup mapping array dt->fmap = tc; for (j = 0; j < i; j++) *tc++ = j; dt->cntx = i; dt->files = mem; } static void fpick_scan_drives(fpick_dd *dt) // Scan drives, populate widgets { int cdrive = 0; /* Get the current drive letter */ if (dt->txt_directory[1] == ':') cdrive = dt->txt_directory[0]; dt->txt_directory[0] = '\0'; cmd_setv(dt->combo, "", ENTRY_VALUE); // Just clear it scan_drives(dt, cdrive); cmd_reset(dt->list, dt); } #endif #define MAX_DIR_FILES (16 * 1024 * 1024) /* 16+ million is when to say "Enough" */ static void scan_dir(fpick_dd *dt, DIR *dp, char *select) { char full_name[PATHBUF], txt_size[64], txt_date[64], tmp_txt[64]; char *nm, *src, *dest, *dir = dt->txt_directory; memx2 mem = dt->files; struct tm *lt; struct dirent *ep; struct stat buf; int *tc; int subdir, tf, n, l = strlen(dir), cnt = 0; mem.here = 0; getmemx2(&mem, 8000); // default size dt->idx = -1; if (strcmp(dir, DIR_SEP_STR)) // Have a parent dir to move to? { // Field #0 - original name addstr(&mem, "..", 0); // Field #1 - type flag (space) + name in GUI encoding addstr(&mem, " " DIR_SEP_STR " ..", 0); // Fields #2-4 empty for all dirs // Fields #5-6 are empty strings, to keep this sorted first addchars(&mem, 0, 3 + 2); cnt++; } while ((cnt < MAX_DIR_FILES) && (ep = readdir(dp))) { wjstrcat(full_name, PATHBUF, dir, l, ep->d_name, NULL); // Error getting file details if (stat(full_name, &buf) < 0) continue; if (!dt->show_hidden && (ep->d_name[0] == '.')) continue; #ifdef WIN32 subdir = S_ISDIR(buf.st_mode); #else subdir = (ep->d_type == DT_DIR) || S_ISDIR(buf.st_mode); #endif tf = 'F'; // Type flag: 'D' for dir, 'F' for file if (subdir) { if (!dt->allow_dirs) continue; // Don't look at '.' or '..' if (!strcmp(ep->d_name, ".") || !strcmp(ep->d_name, "..")) continue; tf = 'D'; } else if (!dt->allow_files) continue; /* Remember which row has matching name */ if (select && !strcmp(ep->d_name, select)) dt->idx = cnt; cnt++; // Field #0 - original name addstr(&mem, ep->d_name, 0); // Field #1 - type flag + name in GUI encoding addchars(&mem, tf, 1); nm = gtkuncpy(NULL, ep->d_name, 0); addstr(&mem, nm, 0); // Fields #2-4 empty for dirs if (subdir) addchars(&mem, 0, 3); else { // Field #2 - file size #ifdef WIN32 n = snprintf(tmp_txt, 64, "%I64u", (unsigned long long)buf.st_size); #else n = snprintf(tmp_txt, 64, "%llu", (unsigned long long)buf.st_size); #endif memset(txt_size, ' ', 20); dest = txt_size + 20; *dest-- = '\0'; for (src = tmp_txt + n - 1; src - tmp_txt > 2; ) { *dest-- = *src--; *dest-- = *src--; *dest-- = *src--; *dest-- = ','; } while (src - tmp_txt >= 0) *dest-- = *src--; addstr(&mem, txt_size, 0); // Field #3 - file type (extension) src = strrchr(nm, '.'); if (src && (src != nm) && src[1]) { #if GTK_MAJOR_VERSION == 1 g_strup(src = g_strdup(src + 1)); #else src = g_utf8_strup(src + 1, -1); #endif addstr(&mem, src, 0); g_free(src); } else addchars(&mem, 0, 1); // Field #4 - file modification time strcpy(txt_date, " "); // to sort failed files after dirs lt = localtime(&buf.st_mtime); /* !!! localtime() can fail and return NULL if given * "wrong" input value */ if (lt) strftime(txt_date, 60, "%Y-%m-%d %H:%M.%S", lt); addstr(&mem, txt_date, 0); } // Field #5 - case-insensitive sort key src = isort_key(nm); addstr(&mem, src, 0); g_free(src); // Field #6 - alphabetic (case-sensitive) sort key #if GTK_MAJOR_VERSION == 1 addstr(&mem, nm, 0); #else /* if GTK_MAJOR_VERSION >= 2 */ src = g_utf8_collate_key(nm, -1); addstr(&mem, src, 0); g_free(src); #endif g_free(nm); } dt->cnt = cnt; /* Now add index array and mapping arrays to all this */ l = (~(unsigned)mem.here + 1) & (sizeof(int) - 1); n = cnt * COL_MAX; getmemx2(&mem, l + (n + cnt) * sizeof(int)); // Fill index array tc = dt->fcols = (void *)(mem.buf + mem.here + l); src = mem.buf; while (n-- > 0) { *tc = src - (char *)tc; tc++; src += strlen(src) + 1; } // Setup mapping array dt->fmap = tc; dt->files = mem; } /* Scan directory, populate widgets; return 1 if success, 0 if total failure, * -1 if failed with original dir and scanned a different one */ static int fpick_scan_directory(fpick_dd *dt, char *name, char *select) { DIR *dp; char *cp, *parent = NULL; char full_name[PATHBUF]; int len, fail, res = 1; strncpy0(full_name, name, PATHBUF - 1); len = strlen(full_name); /* Ensure the invariant */ if (!len || (full_name[len - 1] != DIR_SEP)) full_name[len++] = DIR_SEP , full_name[len] = 0; /* Step up the path till a searchable dir is found */ fail = 0; while (!(dp = opendir(full_name))) { res = -1; // Remember that original path was invalid full_name[len - 1] = 0; cp = strrchr(full_name, DIR_SEP); // Try to go one level up if (cp) len = cp - full_name + 1; // No luck - restart with current dir else if (!fail++) { getcwd(full_name, PATHBUF - 1); len = strlen(full_name); full_name[len++] = DIR_SEP; } // If current dir hasn't helped either, give up else return (0); full_name[len] = 0; } /* If we're going up the path and want to show from where */ if (!select) { if (!strncmp(dt->txt_directory, full_name, len) && dt->txt_directory[len]) { cp = strchr(dt->txt_directory + len, DIR_SEP); // Guaranteed parent = dt->txt_directory + len; select = parent = g_strndup(parent, cp - parent); } } /* If we've nothing to show */ else if (!select[0]) select = NULL; strncpy(dt->txt_directory, full_name, PATHBUF); fpick_directory_new(dt, full_name); // Register directory in combo scan_dir(dt, dp, select); g_free(parent); closedir(dp); filter_dir(dt, dt->txt_mask); cmd_reset(dt->list, dt); return (res); } static void fpick_enter_dir_via_list(fpick_dd *dt, char *name) { char ndir[PATHBUF], *c; int l; strncpy(ndir, dt->txt_directory, PATHBUF); l = strlen(ndir); if (!strcmp(name, "..")) // Go to parent directory { if (l && (ndir[l - 1] == DIR_SEP)) ndir[--l] = '\0'; c = strrchr(ndir, DIR_SEP); if (c) *c = '\0'; else /* Already in root directory */ { #ifdef WIN32 fpick_scan_drives(dt); #endif return; } } else strnncat(ndir, name, PATHBUF); fpick_cleanse_path(ndir); fpick_scan_directory(dt, ndir, NULL); // Enter new directory } static void fpick_ok(fpick_dd *dt) { int *rp = dt->fcols + dt->idx * COL_MAX; char *txt_name = RELREF(rp[COL_FILE]), *txt_size = RELREF(rp[COL_SIZE]); /* Directory selected */ if (!txt_size[0]) fpick_enter_dir_via_list(dt, txt_name); /* File selected */ else fpick_btn(dt, NULL, op_EVT_OK, NULL); } static void fpick_select(fpick_dd *dt, void **wdata, int what, void **where) { int *rp = dt->fcols + dt->idx * COL_MAX; char *txt_name = RELREF(rp[COL_FILE]), *txt_size = RELREF(rp[COL_SIZE]); // File selected if (txt_size[0]) cmd_setv(dt->entry, txt_name, PATH_VALUE); } /* Return 1 if changed directory, 0 if directory was the same, -1 if tried * to change but failed */ static int fpick_enter_dirname(fpick_dd *dt, const char *name, int l) { char txt[PATHBUF], *ctxt; int res = 0; if (name) name = g_strndup(name, l); else { cmd_read(dt->combo, dt); name = g_strdup(dt->cdir); } gtkncpy(txt, name, PATHBUF); fpick_cleanse_path(txt); // Path might have been entered manually if (strcmp(txt, dt->txt_directory) && // Only do something if the directory is new ((res = fpick_scan_directory(dt, txt, NULL)) <= 0)) { // Directory doesn't exist so tell user ctxt = g_strdup_printf(__("Could not access directory %s"), name); alert_box(_("Error"), ctxt, NULL); g_free(ctxt); res = res < 0 ? 1 : -1; } g_free((char *)name); return (res); } static void fpick_combo_changed(fpick_dd *dt, void **wdata, int what, void **where) { fpick_enter_dirname(dt, NULL, 0); } typedef struct { char *title, *what; void **xw; // parent widget-map void **cancel, **delete, **rename, **create; void **res; int dir; char fname[PATHBUF]; } fdialog_dd; #define WBbase fdialog_dd static void *fdialog_code[] = { ONTOP(xw), DIALOGpm(title), BORDER(LABEL, 8), WLABELp(what), XPENTRY(fname, PATHBUF), FOCUS, WDONE, // vbox BORDER(BUTTON, 2), REF(cancel), CANCELBTN(_("Cancel"), dialog_event), UNLESSx(dir, 1), REF(delete), BUTTON(_("Delete"), dialog_event), REF(rename), OKBTN(_("Rename"), dialog_event), ENDIF(1), IFx(dir, 1), REF(create), OKBTN(_("Create"), dialog_event), ENDIF(1), RAISED, WDIALOG(res) }; #undef WBbase static void fpick_file_dialog(fpick_dd *dt, void **wdata, int what, void **where, void *xdata) { fdialog_dd tdata, *ddt; char fnm[PATHBUF], *tmp, *fname = NULL, *snm = NULL; void **dd; int uninit_(l), res, row = (int)xdata; memset(&tdata, 0, sizeof(tdata)); tdata.xw = wdata; if (row >= 0) /* Doing things to selected file */ { fname = RELREF(dt->fcols[COL_FILE + dt->idx * COL_MAX]); if (!strcmp(fname, "..")) return; // Up-dir #ifdef WIN32 if (fname[1] == ':') return; // Drive #endif snprintf(tdata.title = fnm, sizeof(fnm), "%s / %s", __("Delete"), __("Rename")); tdata.what = _("Enter the new filename"); strncpy0(tdata.fname, fname, PATHBUF); } else { tdata.title = _("Create Directory"); tdata.what = _("Enter the name of the new directory"); tdata.dir = TRUE; } dd = run_create(fdialog_code, &tdata, sizeof(tdata)); // run dialog /* Retrieve results */ run_query(dd); ddt = GET_DDATA(dd); where = origin_slot(ddt->res); res = where == ddt->delete ? 2 : where == ddt->rename ? 3 : where == ddt->create ? 4 : 1; if (res > 1) { l = strlen(dt->txt_directory); wjstrcat(fnm, PATHBUF, dt->txt_directory, l, ddt->fname, NULL); // The source name SHOULD NOT get truncated, ever if (fname) snm = g_strconcat(dt->txt_directory, fname, NULL); } run_destroy(dd); tmp = NULL; if (res == 2) // Delete file or directory { char *ts = g_strdup_printf(__("Do you really want to delete \"%s\" ?"), RELREF(dt->fcols[COL_NAME + dt->idx * COL_MAX]) + 1); int r = alert_box(_("Warning"), ts, _("No"), _("Yes"), NULL); g_free(ts); if (r == 2) { if (remove(snm)) tmp = _("Unable to delete"); } else res = 1; } else if (res == 3) // Rename file or directory { if (rename(snm, fnm)) tmp = _("Unable to rename"); } else if (res == 4) // Create directory { #ifdef WIN32 if (mkdir(fnm)) #else if (mkdir(fnm, 0777)) #endif tmp = _("Unable to create directory"); } g_free(snm); if (tmp) alert_box(_("Error"), tmp, NULL); else if (res > 1) { if (row >= 0) /* Deleted/renamed a file - move down */ { if (++row >= dt->cntx) row = dt->cntx - 2; row = dt->fmap[row]; row = COL_FILE + row * COL_MAX; // !!! "fcols" will get overwritten strncpy0(tmp = fnm, RELREF(dt->fcols[row]), PATHBUF); } else tmp = fnm + l; /* Created a directory - move to it */ fpick_scan_directory(dt, dt->txt_directory, tmp); } } static int fpick_wildcard(fpick_dd *dt, int button) { char ctxt[PATHTXT]; char *ds, *nm, *mask = dt->txt_mask; cmd_peekv(dt->entry, ctxt, PATHTXT, PATH_RAW); /* Presume filename if called by user pressing "OK", pattern otherwise */ if (button) { /* If user had changed directory in the combo */ if (fpick_enter_dirname(dt, NULL, 0)) return (FALSE); /* If file entry is hidden anyway */ if (!dt->allow_files) return (TRUE); /* Filename must have some chars and no wildcards in it */ if (ctxt[0] && !ctxt[strcspn(ctxt, "?*")]) return (TRUE); } /* Do we have directory in here? */ ds = strrchr(ctxt, DIR_SEP); #ifdef WIN32 /* Allow '/' separator too */ if ((nm = strrchr(ds ? ds : ctxt, '/'))) ds = nm; #endif /* Store filename pattern */ nm = ds ? ds + 1 : ctxt; strncpy0(mask, nm, PATHTXT - 1); if (mask[0] && !strchr(mask, '*')) { /* Add a '*' at end if one isn't present in string */ int l = strlen(mask); mask[l++] = '*'; mask[l] = '\0'; } /* Have directory - enter it */ if (ds && (fpick_enter_dirname(dt, ctxt, ds + 1 - ctxt) > 0)) { // Opened a new dir - skip redisplay cmd_setv(dt->entry, nm, PATH_RAW); // Cut dir off } else { /* Redisplay only files that match pattern */ filter_dir(dt, mask); cmd_reset(dt->list, dt); } /* Don't let pattern pass as filename */ return (FALSE); } /* "Tab completion" for entry field, like in GtkFileSelection */ static int fpick_entry_key(fpick_dd *dt, void **wdata, int what, void **where, key_ext *keydata) { if (keydata->key != KEY(Tab)) return (FALSE); fpick_wildcard(dt, FALSE); return (TRUE); } // !!! May get NULLs in "wdata" and "where" when called from other handlers static void fpick_btn(fpick_dd *dt, void **wdata, int what, void **where) { if (what == op_EVT_CANCEL) do_evt_1_d(dt->cancel); else if (fpick_wildcard(dt, TRUE)) do_evt_1_d(dt->ok); } static void set_fname(fpick_dd *dt, char *name, int raw) { char txt[PATHTXT]; if (!raw) { /* Ensure that path is absolute */ resolve_path(txt, PATHBUF, name); /* Separate the filename */ name = strrchr(txt, DIR_SEP); *name++ = '\0'; // Scan directory, populate boxes if successful if (!fpick_scan_directory(dt, txt, "")) return; } cmd_setv(dt->entry, name, raw ? PATH_RAW : PATH_VALUE); } /* Store things to inifile */ static void fpick_destroy(fpick_dd *dt, void **wdata) { char txt[64], buf[PATHBUF]; int i; /* Remember recently used directories */ for (i = 0; i < FPICK_COMBO_ITEMS; i++) { gtkncpy(buf, dt->cpp[i], PATHBUF); sprintf(txt, "fpick_dir_%i", i); inifile_set(txt, buf); } inifile_set_gboolean("fpick_case_insensitive", case_insensitive); inifile_set_gboolean("fpick_show_hidden", dt->show_hidden ); } static void fpick_iconbar_click(fpick_dd *dt, void **wdata, int what, void **where) { char fnm[PATHBUF]; int id = TOOL_ID(where); cmd_read(where, dt); switch (id) { case FPICK_ICON_UP: fpick_enter_dir_via_list(dt, ".."); break; case FPICK_ICON_HOME: cmd_read(dt->entry, dt); file_in_homedir(fnm, dt->fname, PATHBUF); set_fname(dt, fnm, FALSE); break; case FPICK_ICON_DIR: fpick_file_dialog(dt, wdata, 0, NULL, (void *)(-1)); break; case FPICK_ICON_HIDDEN: fpick_scan_directory(dt, dt->txt_directory, ""); break; case FPICK_ICON_CASE: cmd_setv(dt->list, (void *)dt->fsort, LISTC_SORT); break; } } void fpick_get_filename(GtkWidget *fp, char *buf, int len, int raw) { fpick_dd *dt = GET_DDATA(get_wdata(fp, FP_KEY)); if (raw) cmd_peekv(dt->entry, buf, len, PATH_RAW); else { cmd_read(dt->entry, dt); snprintf(buf, len, "%s%s", dt->txt_directory, dt->fname); } } void fpick_set_filename(GtkWidget *fp, char *name, int raw) { set_fname(GET_DDATA(get_wdata(fp, FP_KEY)), name, raw); } #define WBbase fpick_dd static void *fpick_code[] = { IDENT(FP_KEY), WPWHEREVER, WINDOWpm(title), EVENT(DESTROY, fpick_destroy), HBOXP, // ------- Combo Box ------- REF(combo), COMBOENTRY(cdir, cpp, fpick_combo_changed), // ------- Toolbar ------- TOOLBAR(fpick_iconbar_click), TBBUTTON(_("Up"), XPM_ICON(up), FPICK_ICON_UP), TBBUTTON(_("Home"), XPM_ICON(home), FPICK_ICON_HOME), TBBUTTON(_("Create New Directory"), XPM_ICON(newdir), FPICK_ICON_DIR), TBTOGGLE(_("Show Hidden Files"), XPM_ICON(hidden), FPICK_ICON_HIDDEN, show_hidden), TBTOGGLEv(_("Case Insensitive Sort"), XPM_ICON(case), FPICK_ICON_CASE, case_insensitive), WDONE, WDONE, // ------- File List ------- XHBOXP, XSCROLL(1, 2), // auto/always WLIST, NRFILECOLUMNDax(_("Name"), COL_NAME, 250, 0, "fpick_col1"), NRTXTCOLUMNDaxx(_("Size"), COL_SIZE, 64, 2, "fpick_col2", "8,888,888,888"), NRTXTCOLUMNDax(_("Type"), COL_TYPE, 80, 2, "fpick_col3"), NRTXTCOLUMNDax(_("Modified"), COL_TIME, 150, 1, "fpick_col4"), COLUMNDATA(fcols, COL_MAX * sizeof(int)), REF(list), LISTCX(idx, cntx, fsort, fmap, fpick_select, fpick_file_dialog), EVENT(OK, fpick_ok), EVENT(CHANGE, fpick_sort), UNLESS(entry_f), FOCUS, CLEANUP(files.buf), WDONE, // ------- Extra widget section ------- REF(hbox), HBOXPr, WDONE, // ------- Entry Box ------- HBOXP, REF(entry), XPENTRY(fname, PATHBUF), EVENT(KEY, fpick_entry_key), EVENT(OK, fpick_btn), UNLESS(allow_files), HIDDEN, IF(entry_f), FOCUS, WDONE, // ------- Buttons ------- HBOX, MINWIDTH(110), EBUTTON(_("OK"), fpick_btn), MINWIDTH(110), ECANCELBTN(_("Cancel"), fpick_btn), WEND }; #undef WBbase GtkWidget *fpick(GtkWidget **box, char *title, int flags, void **r) { fpick_dd tdata, *dt; void **res; int i; memset(&tdata, 0, sizeof(tdata)); tdata.title = title; tdata.flags = flags; tdata.ok = NEXT_SLOT(r); tdata.cancel = SLOT_N(r, 2); tdata.entry_f = tdata.flags & FPICK_ENTRY; tdata.fsort = 1; // By name column, ascending case_insensitive = inifile_get_gboolean("fpick_case_insensitive", TRUE ); tdata.show_hidden = inifile_get_gboolean("fpick_show_hidden", FALSE ); tdata.allow_files = !(tdata.flags & FPICK_DIRS_ONLY); tdata.allow_dirs = TRUE; // Pointers can't yet be properly prepared, so the combo is created empty tdata.cdir = ""; tdata.cpp = tdata.cp; res = run_create(fpick_code, &tdata, sizeof(tdata)); dt = GET_DDATA(res); for (i = 0; i < FPICK_COMBO_ITEMS; i++) { char txt[64]; sprintf(txt, "fpick_dir_%i", i); gtkuncpy(dt->cp[i] = dt->combo_items[i], inifile_get(txt, ""), PATHTXT); } dt->cpp = dt->cp; cmd_reset(dt->combo, dt); *box = dt->hbox[0]; return (GET_REAL_WINDOW(res)); } #endif /* mtPaint fpicker */ #ifdef U_FPICK_GTKFILESEL /* GtkFileSelection based dialog */ GtkWidget *fpick(GtkWidget **box, char *title, int flags, void **r) { #if GTK_MAJOR_VERSION == 1 GtkAccelGroup* ag = gtk_accel_group_new(); #endif GtkWidget *fp; GtkFileSelection *fs; fp = gtk_file_selection_new(__(title)); fs = GTK_FILE_SELECTION(fp); if ( flags & FPICK_DIRS_ONLY ) { gtk_widget_hide(GTK_WIDGET(fs->selection_entry)); gtk_widget_set_sensitive(GTK_WIDGET(fs->file_list), FALSE); // Don't let the user select files } gtk_signal_connect_object(GTK_OBJECT(fs->ok_button), "clicked", GTK_SIGNAL_FUNC(do_evt_1_d), (gpointer)NEXT_SLOT(r)); gtk_signal_connect_object(GTK_OBJECT(fs->cancel_button), "clicked", GTK_SIGNAL_FUNC(do_evt_1_d), (gpointer)SLOT_N(r, 2)); *box = pack(fs->main_vbox, gtk_hbox_new(FALSE, 0)); gtk_widget_show(*box); #if GTK_MAJOR_VERSION == 1 /* No builtin accelerators - add our own */ gtk_widget_add_accelerator(fs->cancel_button, "clicked", ag, KEY(Escape), 0, (GtkAccelFlags)0); gtk_window_add_accel_group(GTK_WINDOW(fp), ag); #endif return (fp); } void fpick_get_filename(GtkWidget *fp, char *buf, int len, int raw) { char *fname = (char *)gtk_entry_get_text(GTK_ENTRY( GTK_FILE_SELECTION(fp)->selection_entry)); if (raw) strncpy0(buf, fname, len); else { #ifdef WIN32 /* Widget returns filename in UTF8 */ gtkncpy(buf, gtk_file_selection_get_filename(GTK_FILE_SELECTION(fp)), len); #else strncpy0(buf, gtk_file_selection_get_filename(GTK_FILE_SELECTION(fp)), len); #endif /* Make sure directory paths end with DIR_SEP */ if (fname[0]) return; raw = strlen(buf); if (!raw || (buf[raw - 1] != DIR_SEP)) { if (raw > len - 2) raw = len - 2; buf[raw] = DIR_SEP; buf[raw + 1] = '\0'; } } } void fpick_set_filename(GtkWidget *fp, char *name, int raw) { if (raw) gtk_entry_set_text(GTK_ENTRY( GTK_FILE_SELECTION(fp)->selection_entry), name); #ifdef WIN32 /* Widget wants filename in UTF8 */ else { name = gtkuncpy(NULL, name, 0); gtk_file_selection_set_filename(GTK_FILE_SELECTION(fp), name); g_free(name); } #else else gtk_file_selection_set_filename(GTK_FILE_SELECTION(fp), name); #endif } #endif /* GtkFileSelection based dialog */ mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/fpick.h000066400000000000000000000016721471325446300222150ustar00rootroot00000000000000/* fpick.h Copyright (C) 2007-2014 Mark Tyler and Dmitry Groshev This file is part of mtPaint. mtPaint 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. mtPaint 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 mtPaint in the file COPYING. */ #define FPICK_ENTRY 1 #define FPICK_LOAD 2 #define FPICK_DIRS_ONLY 4 GtkWidget *fpick(GtkWidget **box, char *title, int flags, void **r); void fpick_get_filename(GtkWidget *fp, char *buf, int len, int raw); void fpick_set_filename(GtkWidget *fp, char *name, int raw); mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/global.h000066400000000000000000000014631471325446300223570ustar00rootroot00000000000000/* global.h Copyright (C) 2005 Mark Tyler This file is part of mtPaint. mtPaint 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. mtPaint 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 mtPaint in the file COPYING. */ #ifdef U_NLS #include #define _(text) gettext(text) #define __(text) gettext(text) #else #define _(text) text #define __(text) text #endif mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/help.c000066400000000000000000000253441471325446300220460ustar00rootroot00000000000000/* help.c Copyright (C) 2004-2021 Mark Tyler and Dmitry Groshev This file is part of mtPaint. mtPaint 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. mtPaint 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 mtPaint in the file COPYING. */ #undef _ #define _(X) X #define HELP_PAGE_COUNT 4 static char *help_titles[HELP_PAGE_COUNT] = { _("General"), _("Keyboard shortcuts"), _("Mouse shortcuts"), _("Credits"), }; static char *help_page0[] = { _("mtPaint 3.51 - Copyright (C) 2004-2021 The Authors\n"), _("See 'Credits' section for a list of the authors.\n"), _("mtPaint 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.\n"), _("mtPaint 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.\n"), _("mtPaint is a simple GTK+1/2/3 painting program designed for creating icons and pixel based artwork. It can edit indexed palette or 24 bit RGB images and offers basic painting and palette manipulation tools. It also has several other more powerful features such as channels, layers and animation. Due to its simplicity and lack of dependencies it runs well on GNU/Linux, Windows and older PC hardware.\n"), _("There is full documentation of mtPaint's features contained in a handbook. If you don't already have this, you can download it from the mtPaint website.\n"), _("If you like mtPaint and you want to keep up to date with new releases, or you want to give some feedback, then the mailing lists may be of interest to you:\n"), _("http://sourceforge.net/mail/?group_id=155874"), NULL }; static char *help_page1[] = { _(" Ctrl-N Create new image"), _(" Ctrl-O Open Image"), _(" Ctrl-S Save Image"), _(" Ctrl-Shift-S Save layers file"), _(" Ctrl-Q Quit program\n"), _(" Ctrl-A Select whole image"), _(" Escape Select nothing, cancel paste box"), _(" J Lasso selection\n"), _(" Ctrl-C Copy selection to clipboard"), _(" Ctrl-X Copy selection to clipboard, and then paint current pattern to selection area"), _(" Ctrl-V Paste clipboard to centre of current view"), _(" Ctrl-K Paste clipboard to location it was copied from"), _(" Ctrl-Shift-V Paste clipboard to new layer"), _(" Enter/Return Commit paste to canvas"), _(" Shift+Enter/Return Commit paste and swap canvas into the clipboard\n"), _(" Arrow keys Paint Mode - Move the mouse pointer"), _(" Arrow keys Selection Mode - Nudge selection box or paste box by one pixel"), _(" Shift+Arrow keys Nudge mouse pointer, selection box or paste box by x pixels - x is defined by the Preferences window"), _(" Ctrl+Arrows Move layer or resize selection box"), _(" Ctrl+Shift+Arrows Move layer or resize selection box by x pixels\n"), _(" Enter/Return Paint Mode - Simulate left click"), _(" Backspace Paint Mode - Simulate right click\n"), _(" [ or ] Change colour A to the next or previous palette item"), _(" Shift+[ or ] Change colour B to the next or previous palette item\n"), _(" Delete Crop image to selection"), _(" Insert Transform colours - i.e. Brightness, Contrast, Saturation, Posterize, Gamma"), _(" Ctrl-G Greyscale the image"), _(" Shift-Ctrl-G Greyscale the image (Gamma corrected)"), _(" Ctrl+M Mirror the image"), _(" Shift-Ctrl-I Invert the image\n"), _(" Ctrl-T Draw a rectangle around the selection area with the current fill"), _(" Ctrl-Shift-T Fill in the selection area with the current fill"), _(" Ctrl-L Draw an ellipse spanning the selection area"), _(" Ctrl-Shift-L Draw a filled ellipse spanning the selection area\n"), _(" Ctrl-E Edit the RGB values for colours A & B"), _(" Ctrl-W Edit all palette colours\n"), _(" Ctrl-P Preferences"), _(" Ctrl-I Information\n"), _(" Ctrl-Z Undo last action"), _(" Ctrl-R Redo an undone action\n"), _(" Shift-T Text Tool (GTK+)"), _(" T Text Tool (FreeType)\n"), _(" V View Window"), _(" L Layers Window\n"), _(" Ctrl-H Toggle Hide Image mode"), _(" B Toggle Snap to Tile Grid mode\n"), _(" X Swap Colours A & B"), _(" E Choose Colour\n"), _(" A Draw open arrow head when using the line tool (size set by flow setting)"), _(" S Draw closed arrow head when using the line tool (size set by flow setting)\n"), _(" D Line Tool"), _(" F Flood Fill Tool\n"), _(" +,= Main edit window - Zoom in"), _(" - Main edit window - Zoom out"), _(" Shift +,= View window - Zoom in"), _(" Shift - View window - Zoom out\n"), _(" 1 10% zoom"), _(" 2 25% zoom"), _(" 3 50% zoom"), _(" 4 100% zoom"), _(" 5 400% zoom"), _(" 6 800% zoom"), _(" 7 1200% zoom"), _(" 8 1600% zoom"), _(" 9 2000% zoom\n"), _(" Shift + 1 Edit image channel"), _(" Shift + 2 Edit alpha channel"), _(" Shift + 3 Edit selection channel"), _(" Shift + 4 Edit mask channel\n"), _(" F1 Help"), _(" F2 Choose Pattern"), _(" F3 Choose Brush"), _(" F4 Paint Tool"), _(" F5 Toggle Main Toolbar"), _(" F6 Toggle Tools Toolbar"), _(" F7 Toggle Settings Toolbar"), _(" F8 Toggle Palette"), _(" F9 Selection Tool"), _(" F12 Toggle Dock Area\n"), _(" Ctrl + F1 - F12 Save current clipboard to file 1-12"), _(" Shift + F1 - F12 Load clipboard from file 1-12\n"), _(" Ctrl + 1, 2, ... , 0 Set opacity to 10%, 20%, ... , 100% (main or keypad numbers)"), _(" Ctrl + + or = Increase opacity by 1"), _(" Ctrl + - Decrease opacity by 1\n"), _(" Home Show or hide main window menu/toolbar/status bar/palette"), _(" Page Up Scale Image"), _(" Page Down Resize Image canvas"), _(" End Pan Window"), NULL }; static char *help_page2[] = { _(" Left button Paint to canvas using the current tool"), _(" Middle button Selects the point which will be the centre of the image after the next zoom"), _(" Right button Commit paste to canvas / Stop drawing current line / Cancel selection\n"), _(" Scroll Wheel In GTK+2/3 the user can have the scroll wheel zoom in or out via the Preferences window\n"), _(" Ctrl+Left button Choose colour A from under mouse pointer"), _(" Ctrl+Left button Clone tool - Select source"), _(" Ctrl+Middle button Create colour A/B and pattern based on the RGB colour in A (RGB images only)"), _(" Ctrl+Right button Choose colour B from under mouse pointer"), _(" Ctrl+Right button Polygon tool - Delete last point / Delete nearest point"), _(" Ctrl+Scroll Wheel Scroll the main edit window left or right\n"), _(" Ctrl+Double click Set colour A or B to average colour under brush square or selection marquee (RGB only)\n"), _(" Shift+Right button Selects the point which will be the centre of the image after the next zoom\n\n"), _("You can fixate the X/Y co-ordinates while moving the mouse:\n"), _(" Shift Constrain mouse movements to vertical line"), _(" Shift+Ctrl Constrain mouse movements to horizontal line"), NULL }; static char *help_page3[] = { _("mtPaint is maintained by Dmitry Groshev.\n"), _("wjaguar@users.sourceforge.net"), _("http://mtpaint.sourceforge.net/\n"), _("The following people (in alphabetical order) have contributed directly to the project, and are therefore worthy of gracious thanks for their generosity and hard work:\n\n"), _("Authors\n"), _("Dmitry Groshev - Contributing developer for version 2.30. Lead developer and maintainer from version 3.00 to the present."), _("Mark Tyler - Original author and maintainer up to version 3.00, occasional contributor thereafter."), _("Xiaolin Wu - Wrote the Wu quantizing method - see wu.c for more information.\n\n"), _("General Contributions (Feedback and Ideas for improvements unless otherwise stated)\n"), _("Abdulla Al Muhairi - Website redesign April 2005"), _("Alan Horkan"), _("Alexandre Prokoudine"), _("Antonio Andrea Bianco"), _("Charlie Ledocq"), _("Dennis Lee"), _("Donald White"), _("Ed Jason"), _("Eddie Kohler - Created Gifsicle which is needed for the creation and viewing of animated GIF files http://www.lcdf.org/gifsicle/"), _("Guadalinex Team (Junta de Andalucia) - man page, Launchpad/Rosetta registration"), _("Lou Afonso"), _("Magnus Hjorth"), _("Martin Zelaia"), _("Pasi Kallinen"), _("Pavel Ruzicka"), _("Puppy Linux (Barry Kauler)"), _("Victor Copovi"), _("Vlastimil Krejcir"), _("William Kern\n\n"), _("Translations\n"), _("Brazilian Portuguese - Paulo Trevizan, Valter Nazianzeno"), _("Czech - Pavel Ruzicka, Martin Petricek, Roman Hornik, Pavel Fric"), _("Dutch - Hans Strijards, Pjotr"), _("French - Nicolas Velin, Pascal Billard, Sylvain Cresto, Johan Serre, Philippe Etienne, Victor Copovi"), _("Galician - Miguel Anxo Bouzada"), _("German - Oliver Frommel, B. Clausius, Ulrich Ringel, Simon Brixel"), _("Hungarian - Ur Balazs"), _("Italian - Angelo Gemmi"), _("Japanese - Norihiro YONEDA"), _("Kabyle - Yacine Bouklif"), _("Polish - Bartosz Kaszubowski, LucaS"), _("Portuguese - Israel G. Lugo, Tiago Silva"), _("Russian - Sergey Irupin, Dmitry Groshev"), _("Simplified Chinese - Cecc"), _("Slovak - Jozef Riha"), _("Spanish - Guadalinex Team (Junta de Andalucia), Antonio Sanchez Leon, Miguel Anxo Bouzada, Francisco Jose Rey, Adolfo Jayme"), _("Swedish - Daniel Nylander, Daniel Eriksson"), _("Tagalog - Anjelo delCarmen"), _("Taiwanese Chinese - Wei-Lun Chao"), _("Turkish - Muhammet Kara, Tutku Dalmaz"), NULL }; #define HELP_PAGE_MAX 89 static char **help_pages[HELP_PAGE_COUNT] = { help_page0, help_page1, help_page2, help_page3, }; #undef _ #define _(X) __(X) mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons.c000066400000000000000000000073421471325446300222270ustar00rootroot00000000000000/* icons.c Copyright (C) 2007-2010 Mark Tyler This file is part of mtPaint. mtPaint 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. mtPaint 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 mtPaint in the file COPYING. */ #include "mygtk.h" #define static #include "graphics/icon.xpm" #include "graphics/xbm_backslash.xbm" #include "graphics/xbm_backslash_mask.xbm" #include "graphics/xbm_circle.xbm" #include "graphics/xbm_circle_mask.xbm" #include "graphics/xbm_clone.xbm" #include "graphics/xbm_clone_mask.xbm" #include "graphics/xbm_flood.xbm" #include "graphics/xbm_flood_mask.xbm" #include "graphics/xbm_grad.xbm" #include "graphics/xbm_grad_mask.xbm" #include "graphics/xbm_horizontal.xbm" #include "graphics/xbm_horizontal_mask.xbm" #include "graphics/xbm_line.xbm" #include "graphics/xbm_line_mask.xbm" #include "graphics/xbm_picker.xbm" #include "graphics/xbm_picker_mask.xbm" #include "graphics/xbm_polygon.xbm" #include "graphics/xbm_polygon_mask.xbm" #include "graphics/xbm_ring4.xbm" #include "graphics/xbm_ring4_mask.xbm" #include "graphics/xbm_select.xbm" #include "graphics/xbm_select_mask.xbm" #include "graphics/xbm_shuffle.xbm" #include "graphics/xbm_shuffle_mask.xbm" #include "graphics/xbm_slash.xbm" #include "graphics/xbm_slash_mask.xbm" #include "graphics/xbm_smudge.xbm" #include "graphics/xbm_smudge_mask.xbm" #include "graphics/xbm_spray.xbm" #include "graphics/xbm_spray_mask.xbm" #include "graphics/xbm_square.xbm" #include "graphics/xbm_square_mask.xbm" #include "graphics/xbm_vertical.xbm" #include "graphics/xbm_vertical_mask.xbm" #include "graphics/xpm_brcosa.xpm" #include "graphics/xpm_case.xpm" #include "graphics/xpm_centre.xpm" #include "graphics/xpm_clone.xpm" #include "graphics/xpm_close.xpm" #include "graphics/xpm_copy.xpm" #include "graphics/xpm_cut.xpm" #include "graphics/xpm_down.xpm" #include "graphics/xpm_ellipse.xpm" #include "graphics/xpm_ellipse2.xpm" #include "graphics/xpm_flip_hs.xpm" #include "graphics/xpm_flip_vs.xpm" #include "graphics/xpm_flood.xpm" #include "graphics/xpm_grad_place.xpm" #include "graphics/xpm_hidden.xpm" #include "graphics/xpm_home.xpm" #include "graphics/xpm_lasso.xpm" #include "graphics/xpm_line.xpm" #include "graphics/xpm_mode_blend.xpm" #include "graphics/xpm_mode_cont.xpm" #include "graphics/xpm_mode_csel.xpm" #include "graphics/xpm_mode_mask.xpm" #include "graphics/xpm_mode_opac.xpm" #include "graphics/xpm_mode_tint.xpm" #include "graphics/xpm_mode_tint2.xpm" #include "graphics/xpm_new.xpm" #include "graphics/xpm_newdir.xpm" #include "graphics/xpm_open.xpm" #include "graphics/xpm_paint.xpm" #include "graphics/xpm_pan.xpm" #include "graphics/xpm_paste.xpm" #include "graphics/xpm_polygon.xpm" #include "graphics/xpm_rect1.xpm" #include "graphics/xpm_rect2.xpm" #include "graphics/xpm_redo.xpm" #include "graphics/xpm_rotate_as.xpm" #include "graphics/xpm_rotate_cs.xpm" #include "graphics/xpm_save.xpm" #include "graphics/xpm_select.xpm" #include "graphics/xpm_shuffle.xpm" #include "graphics/xpm_smudge.xpm" #include "graphics/xpm_text.xpm" #include "graphics/xpm_undo.xpm" #include "graphics/xpm_up.xpm" #include "graphics/xpm_cline.xpm" #include "graphics/xpm_layers.xpm" #include "graphics/xpm_picker.xpm" //#include "graphics/xpm_config.xpm" #undef static #if GTK_MAJOR_VERSION >= 2 /* Create icon descriptors */ #define DEFINE_ICONS #include "icons.h" #endif mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons.h000066400000000000000000000062071471325446300222330ustar00rootroot00000000000000/* icons.h Copyright (C) 2007-2010 Mark Tyler and Dmitry Groshev This file is part of mtPaint. mtPaint 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. mtPaint 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 mtPaint in the file COPYING. */ #if GTK_MAJOR_VERSION == 1 #define XPM_ICON(X) xpm_##X##_xpm #define DEF_XPM_ICON(X) extern char *xpm_##X##_xpm[]; #else /* if GTK_MAJOR_VERSION >= 2 */ #define XPM_ICON(X) desc_##X##_xpm #ifdef DEFINE_ICONS #define DEF_XPM_ICON(X) xpm_icon_desc desc_##X##_xpm = { #X, xpm_##X##_xpm }; #else #define DEF_XPM_ICON(X) extern xpm_icon_desc desc_##X##_xpm; #endif extern char *xpm_open_xpm[]; extern char *xpm_new_xpm[]; #endif extern char *icon_xpm[]; DEF_XPM_ICON(brcosa); DEF_XPM_ICON(case); DEF_XPM_ICON(centre); DEF_XPM_ICON(clone); DEF_XPM_ICON(close); DEF_XPM_ICON(copy); DEF_XPM_ICON(cut); DEF_XPM_ICON(down); DEF_XPM_ICON(ellipse2); DEF_XPM_ICON(ellipse); DEF_XPM_ICON(flip_hs); DEF_XPM_ICON(flip_vs); DEF_XPM_ICON(flood); DEF_XPM_ICON(grad_place); DEF_XPM_ICON(hidden); DEF_XPM_ICON(home); DEF_XPM_ICON(lasso); DEF_XPM_ICON(line); DEF_XPM_ICON(mode_blend); DEF_XPM_ICON(mode_cont); DEF_XPM_ICON(mode_csel); DEF_XPM_ICON(mode_mask); DEF_XPM_ICON(mode_opac); DEF_XPM_ICON(mode_tint2); DEF_XPM_ICON(mode_tint); DEF_XPM_ICON(new); DEF_XPM_ICON(newdir); DEF_XPM_ICON(open); DEF_XPM_ICON(paint); DEF_XPM_ICON(pan); DEF_XPM_ICON(paste); DEF_XPM_ICON(polygon); DEF_XPM_ICON(rect1); DEF_XPM_ICON(rect2); DEF_XPM_ICON(redo); DEF_XPM_ICON(rotate_as); DEF_XPM_ICON(rotate_cs); DEF_XPM_ICON(save); DEF_XPM_ICON(select); DEF_XPM_ICON(shuffle); DEF_XPM_ICON(smudge); DEF_XPM_ICON(text); DEF_XPM_ICON(undo); DEF_XPM_ICON(up); DEF_XPM_ICON(cline); DEF_XPM_ICON(layers); DEF_XPM_ICON(picker); //DEF_XPM_ICON(config); extern unsigned char xbm_backslash_bits[], xbm_backslash_mask_bits[], xbm_circle_bits[], xbm_circle_mask_bits[], xbm_clone_bits[], xbm_clone_mask_bits[], xbm_flood_bits[], xbm_flood_mask_bits[], xbm_grad_bits[], xbm_grad_mask_bits[], xbm_horizontal_bits[], xbm_horizontal_mask_bits[], xbm_line_bits[], xbm_line_mask_bits[], xbm_picker_bits[], xbm_picker_mask_bits[], xbm_polygon_bits[], xbm_polygon_mask_bits[], xbm_ring4_bits[], xbm_ring4_mask_bits[], xbm_select_bits[], xbm_select_mask_bits[], xbm_shuffle_bits[], xbm_shuffle_mask_bits[], xbm_slash_bits[], xbm_slash_mask_bits[], xbm_smudge_bits[], xbm_smudge_mask_bits[], xbm_spray_bits[], xbm_spray_mask_bits[], xbm_square_bits[], xbm_square_mask_bits[], xbm_vertical_bits[], xbm_vertical_mask_bits[]; #define xbm_ring4_width 9 #define xbm_ring4_height 9 #define xbm_ring4_x_hot 4 #define xbm_ring4_y_hot 4 #define xbm_picker_width 17 #define xbm_picker_height 17 #define xbm_picker_x_hot 2 #define xbm_picker_y_hot 16 mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/000077500000000000000000000000001471325446300221365ustar00rootroot00000000000000mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/README000066400000000000000000000005011471325446300230120ustar00rootroot00000000000000This directory contains icons and mouse pointers that are compiled into mtPaint. It is possible to create custom icon sets to suit personal taste. For example in order to create and build a new set try: 1) cp -r icons1 icons-new 2) Edit the icons and pointers in icons-new as required 3) ./configure icons-new 4) make mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/icon.xpm000066400000000000000000000045461471325446300236250ustar00rootroot00000000000000/* XPM */ static char *icon_xpm[] = { "32 32 80 1", "A c #000000", "B c #0C0000", "C c #4A0000", "D c #7C0000", "E c #A10000", "F c #AD0000", "G c #C60000", "H c #FF0000", "I c #BB120E", "J c #F41408", "K c #B11A0B", "L c #CE5C42", "M c #9F421B", "N c #CE5623", "O c #FE6A2B", "P c #DE5D26", "Q c #5F2810", "R c #100703", "S c #8E5B44", "T c #F9773B", "U c #D8A980", "V c #E4AD7A", "W c #907255", "X c #090900", "Y c #101000", "Z c #373700", "a c #505040", "b c #5C5C00", "c c #606000", "d c #777700", "e c #818100", "f c #939300", "g c #9A9A00", "h c #9F9F00", "i c #BABA95", "j c #CFCF00", "k c #D0D000", "l c #D5D500", "m c #DFDF00", "n c #D5D5AA", "o c #E5E56A", "p c #FAFA15", "q c #FFFF00", "r c #8E930E", "s c #D3D77B", "t c #B9C742", "u c #BDC99A", "v c #7B9244", "w c #B3C393", "x c #859F55", "y c #A8BE8C", "z c #9EB985", "0 c #95B280", "1 c #8CAA7C", "2 c #82A377", "3 c #293729", "4 c #5F805F", "5 c #6D926D", "6 c #B9C4BB", "7 c #B5CDCA", "8 c #728C94", "9 c #8BC2F4", "+ c #080C10", "/ c #304860", "! c #80BFFF", "# c #70A7DF", "$ c #689BCF", "% c #50779F", "& c #6279A4", "' c #8F9CC2", "( c #5464BF", ") c #7783FF", "* c #5458ED", ", c #050510", "- c #1E1E60", ". c #32329F", ": c #4141CF", "; c #4646DF", "< c #5050FF", "= c #8080FF", "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", "AAAAAKAAAAAAAAAgAAAAAAAAA(AAAAAA", "AAAACJQAAAAAAAZkcAAAAAAA-)/AAAAA", "AAAAFHPAAAAAAAelmAAAAAAA;=#AAAAA", "AAA3WLUaAAAAA3xtsaAAAAA38'6aAAAA", "AAA42zuiAAAAA42zuiAAAAA42zuiAAAA", "AA351zwnaAAA351zwnaAAA351zwnaAAA", "AA450zyniAAA450zyniAAA450zyniAAA", "AAISzzzVTAAArvzzzopAAA*&zzz79AAA", "AAGGHHHOOAAAfflllqqAAA<<===!!AAA", "AAGGHHHOOAAAfflllqqAAA<<===!!AAA", "AAGGHHHOOAAAfflllqqAAA<<===!!AAA", "AAGGHHHOOAAAfflllqqAAA<<===!!AAA", "AAGGHHHOOAAAfflllqqAAA<<===!!AAA", "AAGGHHHOOAAAfflllqqAAA<<===!!AAA", "AAGGHHHOOAAAfflllqqAAA<<===!!AAA", "AAGGHHHOOAAAfflllqqAAA<<===!!AAA", "AAGGHHHOOAAAfflllqqAAA<<===!!AAA", "AAGGHHHOOAAAfflllqqAAA<<===!!AAA", "AAGGHHHOOAAAfflllqqAAA<<===!!AAA", "AAGGHHHOOAAAfflllqqAAA<<===!!AAA", "AAGGHHHOOAAAfflllqqAAA<<===!!AAA", "AAGGHHHOOAAAfflllqqAAA<<===!!AAA", "AAGGHHHOOAAAfflllqqAAA<<===!!AAA", "AAGGHHHOOAAAfflllqqAAA<<===!!AAA", "AAGGHHHOOAAAfflllqqAAA<<===!!AAA", "AAGGHHHOOAAAfflllqqAAA<<===!!AAA", "AAGGHHHOOAAAfflllqqAAA<<===!!AAA", "AAEGHHHONAAAdflllqjAAA:<===!$AAA", "AABDHHHMRAAAXblllhYAAA,.===%+AAA", "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xbm_backslash.xbm000066400000000000000000000007461471325446300254560ustar00rootroot00000000000000#define xbm_backslash_width 20 #define xbm_backslash_height 20 static unsigned char xbm_backslash_bits[] = { 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x06, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x7e, 0x00, 0x00, 0xfe, 0x08, 0x00, 0xfe, 0x11, 0x00, 0x3e, 0x20, 0x00, 0x36, 0x40, 0x00, 0x62, 0x80, 0x00, 0x60, 0x00, 0x01, 0xc0, 0x00, 0x02, 0xc0, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xbm_backslash_mask.xbm000066400000000000000000000007651471325446300264720ustar00rootroot00000000000000#define xbm_backslash_mask_width 20 #define xbm_backslash_mask_height 20 static unsigned char xbm_backslash_mask_bits[] = { 0x03, 0x00, 0x00, 0x07, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x0c, 0x00, 0xff, 0x1d, 0x00, 0xff, 0x3b, 0x00, 0xff, 0x73, 0x00, 0x7f, 0xe0, 0x00, 0xf7, 0xc0, 0x01, 0xf3, 0x80, 0x03, 0xe0, 0x01, 0x07, 0xe0, 0x01, 0x0e, 0xc0, 0x01, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xbm_circle.xbm000066400000000000000000000007351471325446300247620ustar00rootroot00000000000000#define xbm_circle_width 20 #define xbm_circle_height 20 static unsigned char xbm_circle_bits[] = { 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x06, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x7e, 0x00, 0x00, 0xfe, 0xc0, 0x00, 0xfe, 0x31, 0x03, 0x3e, 0x10, 0x02, 0x36, 0x08, 0x04, 0x62, 0x08, 0x04, 0x60, 0x10, 0x02, 0xc0, 0x30, 0x03, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xbm_circle_mask.xbm000066400000000000000000000007431471325446300257740ustar00rootroot00000000000000#define xbm_circle_mask_width 20 #define xbm_circle_mask_height 20 static unsigned char xbm_circle_mask_bits[] = { 0x02, 0x00, 0x00, 0x07, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x7F, 0x00, 0x00, 0xFF, 0xC0, 0x00, 0xFF, 0xF1, 0x03, 0xFF, 0xFB, 0x07, 0xFF, 0x3B, 0x07, 0x7F, 0x1C, 0x0E, 0xF7, 0x1C, 0x0E, 0xF3, 0x38, 0x07, 0xE0, 0xF9, 0x07, 0xE0, 0xF1, 0x03, 0xC0, 0xC1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xbm_clone.xbm000066400000000000000000000007211471325446300246140ustar00rootroot00000000000000#define xbm_clone_width 20 #define xbm_clone_height 20 static unsigned char xbm_clone_bits[] = { 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x06, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x7E, 0x00, 0x00, 0xFE, 0x00, 0x00, 0xFE, 0x71, 0x00, 0x3E, 0x70, 0x00, 0x36, 0x20, 0x00, 0x62, 0xF8, 0x00, 0x60, 0x20, 0x00, 0xC0, 0x50, 0x00, 0xC0, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xbm_clone_mask.xbm000066400000000000000000000007401471325446300256300ustar00rootroot00000000000000#define xbm_clone_mask_width 20 #define xbm_clone_mask_height 20 static unsigned char xbm_clone_mask_bits[] = { 0x03, 0x00, 0x00, 0x07, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x7F, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x71, 0x00, 0xFF, 0xFB, 0x00, 0xFF, 0xFB, 0x00, 0x7F, 0xF8, 0x00, 0xF7, 0xFC, 0x01, 0xF3, 0xF8, 0x00, 0xE0, 0xF9, 0x00, 0xE0, 0xDD, 0x01, 0xC0, 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xbm_flood.xbm000066400000000000000000000007321471325446300246210ustar00rootroot00000000000000#define xbm_flood_width 20 #define xbm_flood_height 20 static unsigned char xbm_flood_bits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x80, 0x29, 0x00, 0x40, 0x48, 0x00, 0x20, 0x84, 0x00, 0xf0, 0x03, 0x01, 0xf8, 0x01, 0x02, 0x7c, 0x00, 0x04, 0x3c, 0x00, 0x04, 0x5e, 0x00, 0x04, 0x8e, 0x00, 0x02, 0x0e, 0x01, 0x02, 0x0e, 0x02, 0x01, 0x0e, 0xc4, 0x00, 0x0e, 0x38, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00 }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xbm_flood_mask.xbm000066400000000000000000000007511471325446300256350ustar00rootroot00000000000000#define xbm_flood_mask_width 20 #define xbm_flood_mask_height 20 static unsigned char xbm_flood_mask_bits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x80, 0x3f, 0x00, 0xc0, 0x7f, 0x00, 0xe0, 0xff, 0x00, 0xf0, 0xff, 0x01, 0xf8, 0xff, 0x03, 0xfc, 0xff, 0x07, 0xfe, 0xff, 0x0f, 0xfe, 0xff, 0x0f, 0xff, 0xff, 0x0f, 0xdf, 0xff, 0x07, 0x9f, 0xff, 0x07, 0x1f, 0xff, 0x03, 0x1f, 0xfe, 0x01, 0x1f, 0xfc, 0x00, 0x0e, 0x38, 0x00, 0x0e, 0x00, 0x00, 0x04, 0x00, 0x00 }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xbm_grad.xbm000066400000000000000000000007151471325446300244340ustar00rootroot00000000000000#define xbm_grad_width 20 #define xbm_grad_height 20 static unsigned char xbm_grad_bits[] = { 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x06, 0x40, 0x00, 0x0E, 0x40, 0x00, 0x1E, 0xF0, 0x01, 0x3E, 0x40, 0x00, 0x7E, 0x40, 0x00, 0xFE, 0x00, 0x00, 0xFE, 0x41, 0x00, 0x3E, 0x00, 0x00, 0x36, 0x40, 0x00, 0x62, 0x00, 0x00, 0x60, 0x40, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0xF0, 0x01, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00 }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xbm_grad_mask.xbm000066400000000000000000000007341471325446300254500ustar00rootroot00000000000000#define xbm_grad_mask_width 20 #define xbm_grad_mask_height 20 static unsigned char xbm_grad_mask_bits[] = { 0x02, 0x00, 0x00, 0x07, 0xE0, 0x00, 0x0F, 0xE0, 0x00, 0x1F, 0xF8, 0x03, 0x3F, 0xF8, 0x03, 0x7F, 0xF8, 0x03, 0xFF, 0xE0, 0x00, 0xFF, 0xE1, 0x00, 0xFF, 0xE3, 0x00, 0xFF, 0xE3, 0x00, 0x7F, 0xE0, 0x00, 0xF7, 0xE0, 0x00, 0xF3, 0xE0, 0x00, 0xE0, 0xE1, 0x00, 0xE0, 0xE1, 0x00, 0xC0, 0xF8, 0x03, 0x00, 0xF8, 0x03, 0x00, 0xF8, 0x03, 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x00 }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xbm_horizontal.xbm000066400000000000000000000007511471325446300257100ustar00rootroot00000000000000#define xbm_horizontal_width 20 #define xbm_horizontal_height 20 static unsigned char xbm_horizontal_bits[] = { 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x06, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x7e, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x01, 0x00, 0x3e, 0x00, 0x00, 0x36, 0xf8, 0x07, 0x62, 0xf8, 0x07, 0x60, 0x00, 0x00, 0xc0, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xbm_horizontal_mask.xbm000066400000000000000000000007701471325446300267240ustar00rootroot00000000000000#define xbm_horizontal_mask_width 20 #define xbm_horizontal_mask_height 20 static unsigned char xbm_horizontal_mask_bits[] = { 0x03, 0x00, 0x00, 0x07, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x01, 0x00, 0xff, 0x03, 0x00, 0xff, 0xff, 0x0f, 0x7f, 0xfc, 0x0f, 0xf7, 0xfc, 0x0f, 0xf3, 0xfc, 0x0f, 0xe0, 0x01, 0x00, 0xe0, 0x01, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xbm_line.xbm000066400000000000000000000007161471325446300244470ustar00rootroot00000000000000#define xbm_line_width 20 #define xbm_line_height 20 static unsigned char xbm_line_bits[] = { 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x06, 0xF0, 0x03, 0x0E, 0xF0, 0x03, 0x1E, 0x80, 0x03, 0x3E, 0xF0, 0x03, 0x7E, 0xF0, 0x03, 0xFE, 0xC0, 0x03, 0xFE, 0xF1, 0x03, 0x3E, 0xF0, 0x03, 0x36, 0x80, 0x03, 0x62, 0xF0, 0x03, 0x60, 0xF0, 0x03, 0xC0, 0xC0, 0x03, 0xC0, 0xF0, 0x03, 0x00, 0xF0, 0x03, 0x00, 0x80, 0x03, 0x00, 0xF0, 0x03, 0x00, 0xF0, 0x03, 0x00, 0x00, 0x00 }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xbm_line_mask.xbm000066400000000000000000000007351471325446300254630ustar00rootroot00000000000000#define xbm_line_mask_width 20 #define xbm_line_mask_height 20 static unsigned char xbm_line_mask_bits[] = { 0x02, 0x00, 0x00, 0x07, 0xF8, 0x07, 0x0F, 0xF8, 0x07, 0x1F, 0xF8, 0x07, 0x3F, 0xF8, 0x07, 0x7F, 0xF8, 0x07, 0xFF, 0xF8, 0x07, 0xFF, 0xF9, 0x07, 0xFF, 0xFB, 0x07, 0xFF, 0xFB, 0x07, 0x7F, 0xF8, 0x07, 0xF7, 0xF8, 0x07, 0xF3, 0xF8, 0x07, 0xE0, 0xF9, 0x07, 0xE0, 0xF9, 0x07, 0xC0, 0xF8, 0x07, 0x00, 0xF8, 0x07, 0x00, 0xF8, 0x07, 0x00, 0xF8, 0x07, 0x00, 0xF8, 0x07 }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xbm_n7x7.xbm000066400000000000000000000010221471325446300243120ustar00rootroot00000000000000#define xbm_n7x7_width 7 #define xbm_n7x7_height 70 static unsigned char xbm_n7x7_bits[] = { 0x3C, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x1C, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x66, 0x60, 0x30, 0x18, 0x0C, 0x7E, 0x3C, 0x66, 0x60, 0x38, 0x60, 0x66, 0x3C, 0x30, 0x38, 0x3C, 0x36, 0x7E, 0x30, 0x30, 0x7E, 0x06, 0x3E, 0x60, 0x60, 0x66, 0x3C, 0x38, 0x0C, 0x06, 0x3E, 0x66, 0x66, 0x3C, 0x7E, 0x60, 0x30, 0x30, 0x18, 0x18, 0x18, 0x3C, 0x66, 0x66, 0x3C, 0x66, 0x66, 0x3C, 0x3C, 0x66, 0x66, 0x7C, 0x60, 0x30, 0x1C }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xbm_patterns.xbm000066400000000000000000000115571471325446300253650ustar00rootroot00000000000000#define xbm_patterns_width 80 #define xbm_patterns_height 80 static unsigned char xbm_patterns_bits[] = { 0x00, 0x11, 0x11, 0x55, 0x55, 0x55, 0x55, 0x55, 0xAA, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0xAA, 0x55, 0x33, 0x00, 0x00, 0x44, 0x44, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xCC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x88, 0x55, 0xCC, 0x00, 0x11, 0x11, 0x55, 0x55, 0x55, 0x55, 0x55, 0xAA, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0xAA, 0x55, 0x33, 0x00, 0x00, 0x44, 0x44, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xCC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x88, 0x55, 0xCC, 0xC3, 0xC0, 0x40, 0x44, 0xC1, 0xE3, 0x00, 0x30, 0x00, 0x33, 0xE1, 0x60, 0x20, 0x22, 0x63, 0xF7, 0x22, 0xCC, 0x66, 0x0C, 0xF0, 0x30, 0x10, 0x11, 0x36, 0x7F, 0x11, 0x03, 0x66, 0x33, 0x78, 0x18, 0x08, 0x88, 0x1C, 0x3E, 0x88, 0x00, 0x00, 0xC0, 0x3C, 0x0C, 0x04, 0x44, 0x1C, 0x3E, 0x00, 0x30, 0x00, 0x33, 0x1E, 0x06, 0x02, 0x22, 0x36, 0x7F, 0x22, 0xCC, 0x66, 0x0C, 0x0F, 0x03, 0x01, 0x11, 0x63, 0xF7, 0x11, 0x03, 0x66, 0x33, 0x87, 0x81, 0x80, 0x88, 0xC1, 0xE3, 0x08, 0x00, 0x00, 0xC0, 0x0F, 0x03, 0x01, 0x11, 0x41, 0x55, 0x00, 0x6C, 0x0F, 0x03, 0x1E, 0x06, 0x02, 0x22, 0x22, 0x22, 0x08, 0xC6, 0x0F, 0x0C, 0x3C, 0x0C, 0x04, 0x44, 0x14, 0x55, 0x11, 0x93, 0x0F, 0x30, 0x78, 0x18, 0x08, 0x88, 0x08, 0x88, 0x22, 0x39, 0x0F, 0xC0, 0xF0, 0x30, 0x10, 0x11, 0x14, 0x55, 0x00, 0x6C, 0xF0, 0x03, 0xE1, 0x60, 0x20, 0x22, 0x22, 0x22, 0x88, 0xC6, 0xF0, 0x0C, 0xC3, 0xC0, 0x40, 0x44, 0x41, 0x55, 0x11, 0x93, 0xF0, 0x30, 0x87, 0x81, 0x80, 0x88, 0x80, 0x88, 0x22, 0x39, 0xF0, 0xC0, 0x00, 0x00, 0x00, 0x02, 0x22, 0xFF, 0x11, 0x10, 0x00, 0x88, 0xFF, 0xFF, 0xFF, 0x02, 0x22, 0xFF, 0x00, 0x38, 0x00, 0x88, 0x00, 0x00, 0x00, 0x02, 0x22, 0x03, 0x10, 0x7C, 0x00, 0x44, 0x00, 0x00, 0xFF, 0x02, 0x22, 0x03, 0x00, 0xFE, 0x18, 0x44, 0x00, 0x00, 0x00, 0x02, 0x22, 0x03, 0x55, 0xEF, 0x18, 0x22, 0x00, 0xFF, 0xFF, 0x02, 0x22, 0x03, 0x00, 0xC7, 0x00, 0x22, 0x00, 0x00, 0x00, 0x02, 0x22, 0x03, 0x10, 0x83, 0x00, 0x11, 0x00, 0x00, 0xFF, 0x02, 0x22, 0x03, 0x00, 0x01, 0x00, 0x11, 0x00, 0x00, 0x22, 0x02, 0x22, 0x02, 0x22, 0x00, 0x08, 0x11, 0x55, 0x55, 0xDD, 0x00, 0x00, 0x55, 0x55, 0x55, 0x14, 0x11, 0x00, 0x00, 0x22, 0x02, 0x22, 0x02, 0x22, 0x00, 0x2A, 0x22, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x11, 0x55, 0x22, 0x00, 0x00, 0x22, 0x02, 0x22, 0x02, 0x22, 0x82, 0x2A, 0x44, 0x00, 0x55, 0xDD, 0x00, 0x00, 0x00, 0x55, 0x44, 0x14, 0x44, 0x00, 0x00, 0x22, 0x02, 0x22, 0x02, 0x22, 0x28, 0x08, 0x88, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x88, 0x00, 0x00, 0xAA, 0x06, 0x66, 0x02, 0x22, 0x08, 0x08, 0xC0, 0xFF, 0xFF, 0xAA, 0x06, 0x66, 0xFF, 0xFF, 0x1C, 0x1C, 0x30, 0xFF, 0xFF, 0xAA, 0x06, 0x66, 0x02, 0x22, 0x3E, 0x3E, 0x0C, 0x00, 0x00, 0xAA, 0x06, 0x66, 0x02, 0x22, 0xFF, 0x7F, 0x03, 0x00, 0x00, 0xAA, 0x06, 0x66, 0x02, 0x22, 0x3E, 0x3E, 0xC0, 0x00, 0xFF, 0xAA, 0x06, 0x66, 0x02, 0xFF, 0x1C, 0x1C, 0x30, 0x00, 0xFF, 0xAA, 0x06, 0x66, 0x02, 0x22, 0x08, 0x08, 0x0C, 0x00, 0x00, 0xAA, 0x06, 0x66, 0x02, 0x22, 0x08, 0x00, 0x03, 0x71, 0x18, 0x00, 0x00, 0x80, 0x11, 0xEE, 0x08, 0x08, 0x38, 0xBB, 0x0C, 0x10, 0x00, 0x80, 0x11, 0x19, 0x14, 0x14, 0x22, 0x17, 0x06, 0x20, 0x20, 0xAA, 0x11, 0x1F, 0x22, 0x22, 0x0E, 0x0E, 0x13, 0x40, 0x50, 0x14, 0x11, 0x1F, 0xC1, 0xC9, 0x22, 0x1D, 0x30, 0x00, 0x00, 0x08, 0x0A, 0xEE, 0x22, 0x22, 0x38, 0xBB, 0x60, 0x04, 0x00, 0x08, 0x04, 0x91, 0x14, 0x14, 0x22, 0xD1, 0xC0, 0x02, 0x02, 0xAA, 0x40, 0xF1, 0x08, 0x08, 0x0E, 0xE0, 0x80, 0x01, 0x05, 0x41, 0xA0, 0xF1, 0x08, 0x08, 0x22, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xC7, 0x08, 0x08, 0x00, 0xFF, 0x0F, 0x10, 0x6C, 0x10, 0x38, 0x01, 0x14, 0x14, 0x77, 0xFF, 0x0F, 0x38, 0xFE, 0x38, 0x38, 0x01, 0x22, 0x22, 0x22, 0xFF, 0x0F, 0x7C, 0xFE, 0x7C, 0xD6, 0x82, 0x41, 0x49, 0xAA, 0x00, 0x0F, 0x7C, 0x7C, 0xFE, 0xFE, 0x7C, 0x22, 0x22, 0x88, 0x00, 0x0F, 0x38, 0x38, 0xD6, 0xD6, 0x10, 0x14, 0x14, 0xDD, 0x00, 0x0F, 0x10, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x10, 0x10, 0x28, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x21, 0x88, 0x10, 0x08, 0x88, 0x20, 0x04, 0x81, 0x7E, 0x7E, 0x12, 0x44, 0x20, 0x04, 0x88, 0x20, 0x24, 0xA5, 0x42, 0x42, 0x84, 0x22, 0x50, 0x0A, 0x8F, 0x20, 0xEE, 0x81, 0x5A, 0x42, 0x48, 0x11, 0x88, 0x11, 0x88, 0xFF, 0x20, 0x81, 0x5A, 0x42, 0x21, 0x44, 0x05, 0xA0, 0x88, 0x02, 0x04, 0xBD, 0x42, 0x42, 0x12, 0x88, 0x02, 0x40, 0x88, 0x02, 0x77, 0x81, 0x7E, 0x7E, 0x84, 0x11, 0x04, 0x20, 0xF8, 0x02, 0x24, 0xFF, 0x00, 0x00, 0x48, 0x22, 0x08, 0x10, 0x88, 0xFF, 0x20, 0x00, 0x00, 0x11, 0x80, 0x01, 0x77, 0x71, 0x14, 0x00, 0x22, 0x02, 0xAA, 0x44, 0x80, 0x01, 0x51, 0x33, 0x36, 0x00, 0x2E, 0x00, 0x00, 0x11, 0xC0, 0x03, 0x57, 0x17, 0x77, 0xFF, 0x22, 0x00, 0x55, 0x44, 0x21, 0x84, 0x00, 0x00, 0x00, 0x88, 0x3A, 0x00, 0x00, 0x11, 0x12, 0x48, 0x75, 0x74, 0x77, 0xAA, 0x22, 0x00, 0xAA, 0x44, 0x0C, 0x30, 0x45, 0x66, 0x36, 0x22, 0x2E, 0x00, 0x00, 0x11, 0x30, 0x0C, 0x77, 0x47, 0x14, 0xFF, 0x22, 0x00, 0x55, 0x44, 0x40, 0x02, 0x00, 0x00, 0x00, 0x00, 0x3A }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xbm_picker.xbm000066400000000000000000000007241471325446300247740ustar00rootroot00000000000000#define xbm_picker_width 17 #define xbm_picker_height 17 #define xbm_picker_x_hot 2 #define xbm_picker_y_hot 16 static unsigned char xbm_picker_bits[] = { 0x00, 0x70, 0x00, 0x00, 0x88, 0x00, 0x00, 0x04, 0x01, 0x00, 0x07, 0x01, 0x80, 0x00, 0x01, 0x00, 0x81, 0x00, 0x00, 0x62, 0x00, 0x00, 0x27, 0x00, 0x80, 0x2B, 0x00, 0xC0, 0x11, 0x00, 0xE0, 0x00, 0x00, 0x70, 0x00, 0x00, 0x38, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00 }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xbm_picker_mask.xbm000066400000000000000000000007631471325446300260120ustar00rootroot00000000000000#define xbm_picker_mask_width 17 #define xbm_picker_mask_height 17 #define xbm_picker_mask_x_hot 2 #define xbm_picker_mask_y_hot 16 static unsigned char xbm_picker_mask_bits[] = { 0x00, 0x70, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xfc, 0x01, 0x00, 0xff, 0x01, 0x80, 0xff, 0x01, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x80, 0x3f, 0x00, 0xc0, 0x3f, 0x00, 0xe0, 0x13, 0x00, 0xf0, 0x01, 0x00, 0xf8, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x02, 0x00, 0x00, }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xbm_polygon.xbm000066400000000000000000000007271471325446300252110ustar00rootroot00000000000000#define xbm_polygon_width 20 #define xbm_polygon_height 20 static unsigned char xbm_polygon_bits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xE0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x00, 0x04, 0x06, 0x00, 0x04, 0x05, 0x00, 0x84, 0x04, 0x00, 0x40, 0x04, 0x00, 0xE0, 0x07, 0x00, 0x00, 0x00 }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xbm_polygon_mask.xbm000066400000000000000000000007461471325446300262250ustar00rootroot00000000000000#define xbm_polygon_mask_width 20 #define xbm_polygon_mask_height 20 static unsigned char xbm_polygon_mask_bits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x04, 0x00, 0xF0, 0xE0, 0x01, 0xF8, 0xF1, 0x03, 0xF0, 0xE0, 0x01, 0x00, 0x04, 0x04, 0x00, 0x0E, 0x0E, 0x00, 0x0E, 0x0F, 0x00, 0x8E, 0x0F, 0x00, 0xCE, 0x0F, 0x00, 0xE4, 0x0F, 0x00, 0xF0, 0x0F, 0x00, 0xE0, 0x0F }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xbm_ring4.xbm000066400000000000000000000004121471325446300245340ustar00rootroot00000000000000#define xbm_ring4_width 9 #define xbm_ring4_height 9 #define xbm_ring4_x_hot 4 #define xbm_ring4_y_hot 4 static unsigned char xbm_ring4_bits[] = { 0x00, 0x00, 0x38, 0x00, 0x44, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x44, 0x00, 0x38, 0x00, 0x00, 0x00 }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xbm_ring4_mask.xbm000066400000000000000000000004431471325446300255530ustar00rootroot00000000000000#define xbm_ring4_mask_width 9 #define xbm_ring4_mask_height 9 #define xbm_ring4_mask_x_hot 4 #define xbm_ring4_mask_y_hot 4 static unsigned char xbm_ring4_mask_bits[] = { 0x38, 0x00, 0x7C, 0x00, 0xFE, 0x00, 0xC7, 0x01, 0xC7, 0x01, 0xC7, 0x01, 0xFE, 0x00, 0x7C, 0x00, 0x38, 0x00 }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xbm_select.xbm000066400000000000000000000007351471325446300250000ustar00rootroot00000000000000#define xbm_select_width 20 #define xbm_select_height 20 static unsigned char xbm_select_bits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xbm_select_mask.xbm000066400000000000000000000007541471325446300260140ustar00rootroot00000000000000#define xbm_select_mask_width 20 #define xbm_select_mask_height 20 static unsigned char xbm_select_mask_bits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x0e, 0x00, 0xf8, 0xf1, 0x03, 0xf8, 0xf1, 0x03, 0xf8, 0xf1, 0x03, 0x00, 0x0e, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xbm_shuffle.xbm000066400000000000000000000010211471325446300251420ustar00rootroot00000000000000#define xbm_shuffle_width 20 #define xbm_shuffle_height 20 #define xbm_shuffle_x_hot 10 #define xbm_shuffle_y_hot 10 static unsigned char xbm_shuffle_bits[] = { 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x06, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x7E, 0x00, 0x00, 0xFE, 0x78, 0x06, 0xFE, 0x09, 0x06, 0x3E, 0x08, 0x00, 0x36, 0x08, 0x00, 0x62, 0x00, 0x00, 0x60, 0x00, 0x04, 0xC0, 0x18, 0x04, 0xC0, 0x98, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xbm_shuffle_mask.xbm000066400000000000000000000007461471325446300261720ustar00rootroot00000000000000#define xbm_shuffle_mask_width 20 #define xbm_shuffle_mask_height 20 static unsigned char xbm_shuffle_mask_bits[] = { 0x03, 0x00, 0x00, 0x07, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x7F, 0x00, 0x00, 0xFF, 0xFC, 0x0F, 0xFF, 0xFD, 0x0F, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0x0F, 0x7F, 0x3C, 0x0F, 0xF7, 0x3C, 0x0F, 0xF3, 0xFC, 0x0F, 0xE0, 0xFD, 0x0F, 0xE0, 0xFD, 0x0F, 0xC0, 0xFD, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xbm_slash.xbm000066400000000000000000000007321471325446300246300ustar00rootroot00000000000000#define xbm_slash_width 20 #define xbm_slash_height 20 static unsigned char xbm_slash_bits[] = { 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x06, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x7e, 0x00, 0x00, 0xfe, 0x00, 0x04, 0xfe, 0x01, 0x02, 0x3e, 0x00, 0x01, 0x36, 0x80, 0x00, 0x62, 0x40, 0x00, 0x60, 0x20, 0x00, 0xc0, 0x10, 0x00, 0xc0, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xbm_slash_mask.xbm000066400000000000000000000007511471325446300256440ustar00rootroot00000000000000#define xbm_slash_mask_width 20 #define xbm_slash_mask_height 20 static unsigned char xbm_slash_mask_bits[] = { 0x03, 0x00, 0x00, 0x07, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x0c, 0xff, 0x01, 0x0e, 0xff, 0x03, 0x07, 0xff, 0x83, 0x03, 0x7f, 0xc0, 0x01, 0xf7, 0xe0, 0x00, 0xf3, 0x70, 0x00, 0xe0, 0x39, 0x00, 0xe0, 0x1d, 0x00, 0xc0, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xbm_smudge.xbm000066400000000000000000000007241471325446300250030ustar00rootroot00000000000000#define xbm_smudge_width 20 #define xbm_smudge_height 20 static unsigned char xbm_smudge_bits[] = { 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x06, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x7E, 0x00, 0x00, 0xFE, 0x80, 0x07, 0xFE, 0xC1, 0x07, 0x3E, 0xA0, 0x07, 0x36, 0xD0, 0x07, 0x62, 0xA8, 0x02, 0x60, 0x50, 0x01, 0xC0, 0xA8, 0x00, 0xC0, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xbm_smudge_mask.xbm000066400000000000000000000007431471325446300260170ustar00rootroot00000000000000#define xbm_smudge_mask_width 20 #define xbm_smudge_mask_height 20 static unsigned char xbm_smudge_mask_bits[] = { 0x02, 0x00, 0x00, 0x07, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x7F, 0x00, 0x00, 0xFF, 0x80, 0x0F, 0xFF, 0xC1, 0x0F, 0xFF, 0xE3, 0x0F, 0xFF, 0xF3, 0x0F, 0x7F, 0xF8, 0x0F, 0xF7, 0xFC, 0x07, 0xF3, 0xFC, 0x03, 0xE0, 0xFD, 0x01, 0xE0, 0xF9, 0x00, 0xC0, 0x71, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xbm_spray.xbm000066400000000000000000000010071471325446300246500ustar00rootroot00000000000000#define xbm_spray_width 20 #define xbm_spray_height 20 #define xbm_spray_x_hot 10 #define xbm_spray_y_hot 10 static unsigned char xbm_spray_bits[] = { 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x06, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x7E, 0x00, 0x00, 0xFE, 0x88, 0x04, 0xFE, 0x21, 0x00, 0x3E, 0x00, 0x05, 0x36, 0x40, 0x00, 0x62, 0x28, 0x02, 0x60, 0x00, 0x00, 0xC0, 0x10, 0x01, 0xC0, 0x40, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xbm_spray_mask.xbm000066400000000000000000000007401471325446300256660ustar00rootroot00000000000000#define xbm_spray_mask_width 20 #define xbm_spray_mask_height 20 static unsigned char xbm_spray_mask_bits[] = { 0x03, 0x00, 0x00, 0x07, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x7F, 0x00, 0x00, 0xFF, 0xFC, 0x0F, 0xFF, 0xFD, 0x0F, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0x0F, 0x7F, 0xFC, 0x0F, 0xF7, 0xFC, 0x0F, 0xF3, 0xFC, 0x0F, 0xE0, 0xFD, 0x0F, 0xE0, 0xFD, 0x0F, 0xC0, 0xFD, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xbm_square.xbm000066400000000000000000000007351471325446300250210ustar00rootroot00000000000000#define xbm_square_width 20 #define xbm_square_height 20 static unsigned char xbm_square_bits[] = { 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x06, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x7e, 0x00, 0x00, 0xfe, 0xf8, 0x07, 0xfe, 0x09, 0x04, 0x3e, 0x08, 0x04, 0x36, 0x08, 0x04, 0x62, 0x08, 0x04, 0x60, 0x08, 0x04, 0xc0, 0x08, 0x04, 0xc0, 0xf8, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xbm_square_mask.xbm000066400000000000000000000007431471325446300260330ustar00rootroot00000000000000#define xbm_square_mask_width 20 #define xbm_square_mask_height 20 static unsigned char xbm_square_mask_bits[] = { 0x02, 0x00, 0x00, 0x07, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x7F, 0x00, 0x00, 0xFF, 0xFC, 0x0F, 0xFF, 0xFD, 0x0F, 0xFF, 0xFF, 0x0F, 0xFF, 0x1F, 0x0E, 0x7F, 0x1C, 0x0E, 0xF7, 0x1C, 0x0E, 0xF3, 0x1C, 0x0E, 0xE0, 0xFD, 0x0F, 0xE0, 0xFD, 0x0F, 0xC0, 0xFD, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xbm_vertical.xbm000066400000000000000000000007431471325446300253310ustar00rootroot00000000000000#define xbm_vertical_width 20 #define xbm_vertical_height 20 static unsigned char xbm_vertical_bits[] = { 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x06, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x7e, 0x00, 0x00, 0xfe, 0xc0, 0x00, 0xfe, 0xc1, 0x00, 0x3e, 0xc0, 0x00, 0x36, 0xc0, 0x00, 0x62, 0xc0, 0x00, 0x60, 0xc0, 0x00, 0xc0, 0xc0, 0x00, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xbm_vertical_mask.xbm000066400000000000000000000007621471325446300263450ustar00rootroot00000000000000#define xbm_vertical_mask_width 20 #define xbm_vertical_mask_height 20 static unsigned char xbm_vertical_mask_bits[] = { 0x03, 0x00, 0x00, 0x07, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0xe0, 0x01, 0xff, 0xe1, 0x01, 0xff, 0xe3, 0x01, 0xff, 0xe3, 0x01, 0x7f, 0xe0, 0x01, 0xf7, 0xe0, 0x01, 0xf3, 0xe0, 0x01, 0xe0, 0xe1, 0x01, 0xe0, 0xe1, 0x01, 0xc0, 0xe1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xpm_brcosa.xpm000066400000000000000000000013151471325446300250210ustar00rootroot00000000000000/* XPM */ static char *xpm_brcosa_xpm[] = { "20 20 12 1", " c None", "1 c #000000", "2 c #FFFF00", "3 c #FFE300", "4 c #FFC600", "5 c #FFAA00", "6 c #FF8E00", "7 c #FF7100", "8 c #FF5500", "9 c #FF3900", "A c #FF1C00", "B c #FF0000", " 11 ", " 11 11 11 ", " 111 11 111 ", " 111 111 ", " 11 1111 11 ", " 11876511 ", " 1A98765431 ", " 1A98765431 ", " 1BA987654321 ", "111 1BA987654321 111", "111 1BA987654321 111", " 1BA987654321 ", " 1A98765431 ", " 1A98765431 ", " 11876511 ", " 11 1111 11 ", " 111 111 ", " 111 11 111 ", " 11 11 11 ", " 11 " }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xpm_case.xpm000066400000000000000000000011221471325446300244570ustar00rootroot00000000000000/* XPM */ static char *xpm_case_xpm[] = { "20 20 4 1", " c None", "1 c #000000", "2 c #FF4949", "3 c #FFFFFF", " ", " ", " ", " 11111 ", " 1133311 ", " 1333331 ", " 1333331 ", " 113333311 ", " 133133331 ", " 1133133331 ", " 13311133311 ", " 13311133331 ", " 113333333331 ", " 1331111133311 ", " 1331 133331 ", " 1113111 11133311 ", " 1333331 13333331 ", " 1111111 11111111 ", " ", " " }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xpm_centre.xpm000066400000000000000000000011241471325446300250260ustar00rootroot00000000000000/* XPM */ static char *xpm_centre_xpm[] = { "20 20 4 1", " c None", "1 c #000000", "2 c #B4B4B4", "3 c #FFFF00", " ", " ", " 1111111111111111 ", " 1222222222222221 ", " 1222222222222221 ", " 1222222222222221 ", " 1222222222222221 ", " 1222211111122221 ", " 1222213333122221 ", " 1222213333122221 ", " 1222213333122221 ", " 1222213333122221 ", " 1222211111122221 ", " 1222222222222221 ", " 1222222222222221 ", " 1222222222222221 ", " 1222222222222221 ", " 1111111111111111 ", " ", " " }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xpm_cline.xpm000066400000000000000000000011041471325446300246360ustar00rootroot00000000000000/* XPM */ static char *xpm_cline_xpm[] = { "20 20 3 1", " c None", "1 c #000000", "2 c #FFFFFF", " ", " ", " ", " 11111111111111 ", " 12222222222221 ", " 12222222222221 ", " 12112222222221 ", " 12112111111121 ", " 12222222222221 ", " 12112222222221 ", " 12112111111121 ", " 12222222222221 ", " 12112222222221 ", " 12112111111121 ", " 12222222222221 ", " 12222222222221 ", " 11111111111111 ", " ", " ", " " }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xpm_clone.xpm000066400000000000000000000011041471325446300246440ustar00rootroot00000000000000/* XPM */ static char *xpm_clone_xpm[] = { "20 20 3 1", " c None", "1 c #000000", "2 c #FFFFFF", " ", " ", " 1111 1111 ", " 122221 122221 ", " 12222221 12222221 ", " 12222221 12222221 ", " 12222221 12222221 ", " 122221 122221 ", " 1221 1221 ", " 111221111111122111 ", "12222222222222222221", "12222222222222222221", " 111221111111122111 ", " 1221 1221 ", " 1221 1221 ", " 122221 122221 ", " 12211221 12211221 ", "1221 12211221 1221", " 11 11 11 11 ", " " }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xpm_close.xpm000066400000000000000000000011041471325446300246510ustar00rootroot00000000000000/* XPM */ static char *xpm_close_xpm[] = { "20 20 3 1", " c None", "1 c #000000", "2 c #FF0000", " ", " ", " ", " ", " 1 1 ", " 121 121 ", " 12221 12221 ", " 1222112221 ", " 12222221 ", " 122221 ", " 122221 ", " 12222221 ", " 1222112221 ", " 12221 12221 ", " 121 121 ", " 1 1 ", " ", " ", " ", " " }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xpm_config.xpm000066400000000000000000000011621471325446300250150ustar00rootroot00000000000000/* XPM */ static char *xpm_config_xpm[] = { "20 20 6 1", " c None", "1 c #000000", "2 c #FFFFFF", "3 c #929292", "4 c #2AB2B2", "5 c #1E7F7F", " ", " ", " 1 1 ", " 121 121 ", " 121 121 ", " 1 121 11 ", " 1211221 1 ", " 1222231 1 ", " 1111211 ", " 1111 ", " 11111231 ", " 14441 1231 ", " 144451 1231 ", " 1444551 1231 ", " 144551 121 ", " 14551 11 ", " 111 ", " ", " ", " " }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xpm_copy.xpm000066400000000000000000000011031471325446300245150ustar00rootroot00000000000000/* XPM */ static char *xpm_copy_xpm[] = { "20 20 3 1", " c None", "1 c #000000", "2 c #FFFFFF", " ", " ", " 1111111 ", " 12222221 ", " 12221111111 ", " 122212222221 ", " 1211122222221 ", " 12221222222221 ", " 12221211111121 ", " 12111222222221 ", " 12221222222221 ", " 12221211111121 ", " 12111222222221 ", " 12221222222221 ", " 12221211111121 ", " 11111222222221 ", " 1222222221 ", " 1111111111 ", " ", " " }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xpm_cut.xpm000066400000000000000000000010631471325446300243430ustar00rootroot00000000000000/* XPM */ static char *xpm_cut_xpm[] = { "20 20 2 1", " c None", "1 c #000000", " ", " ", " 1 1 ", " 11 11 ", " 11 11 ", " 11 11 ", " 11 11 ", " 11 11 ", " 11 11 ", " 1111 ", " 11 ", " 11 ", " 1111 ", " 11111 11111 ", " 11 11 11 11 ", " 1 1 1 1 ", " 11 11 11 11 ", " 111 111 ", " ", " " }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xpm_down.xpm000066400000000000000000000012161471325446300245170ustar00rootroot00000000000000/* XPM */ static char *xpm_down_xpm[] = { "20 20 8 1", " c None", "1 c #000000", "2 c #FFFF6D", "3 c #F0F066", "4 c #E2E25F", "5 c #D3D357", "6 c #C5C550", "7 c #B6B649", " ", " ", " ", " 111111 ", " 144551 ", " 134451 ", " 144551 ", " 134451 ", " 11111445511111 ", " 12223344556671 ", " 11233445566711 ", " 112334455611 ", " 1134455611 ", " 11344511 ", " 114511 ", " 1111 ", " 11 ", " ", " ", " " }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xpm_ellipse.xpm000066400000000000000000000011251471325446300252040ustar00rootroot00000000000000/* XPM */ static char *xpm_ellipse_xpm[] = { "20 20 4 1", " c None", "1 c #000000", "2 c #FF0000", "3 c #FFFF00", " 1 ", " 1111111 ", " 111111111 ", " 11111111211 ", " 111222222222222 ", " 12222222222222222 ", " 222222222222222222 ", "12222222222222222222", "22222222222222222222", "22222222222222222222", "12222222222222222222", "1222222222222222222 ", "112222222222222222 ", " 111222222222222 ", " 1111111112111 ", " 1111111111111 ", " 11111111111 ", " 111111111 ", " 1111111 ", " 1 " }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xpm_ellipse2.xpm000066400000000000000000000011261471325446300252670ustar00rootroot00000000000000/* XPM */ static char *xpm_ellipse2_xpm[] = { "20 20 4 1", " c None", "1 c #000000", "2 c #FF0000", "3 c #FFFF00", " 1 ", " 1111111 ", " 111111111 ", " 111 211 ", " 111222222222222 ", " 12222222222222222 ", " 222 11 222 ", "122 11 222", "222 11 22", "222 11 22", "122 11 222", "1222 11 222 ", "112222222222222222 ", " 1 222222222222 ", " 11 2 11 ", " 111 111 ", " 111 111 ", " 111111111 ", " 1111111 ", " 1 " }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xpm_flip_hs.xpm000066400000000000000000000011441471325446300251740ustar00rootroot00000000000000/* XPM */ static char *xpm_flip_hs_xpm[] = { "20 20 5 1", " c None", "1 c #000000", "2 c #FFFFFF", "3 c #B4B4B4", "4 c #FF0000", " 1 222111222", " 1 144444441", " 11 144444441", " 11 144444441", " 121 244444442", " 121 244444442", " 1221 244444442", " 1221 144444441", " 12221 111222111", " 12221 ", " 122221 133331 ", " 122221 133331 ", " 1222221 1333331 ", " 1111111 1111111 ", " ", " 1 1 ", " 11 11 ", " 1111111111111111 ", " 11 11 ", " 1 1 " }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xpm_flip_vs.xpm000066400000000000000000000011441471325446300252120ustar00rootroot00000000000000/* XPM */ static char *xpm_flip_vs_xpm[] = { "20 20 5 1", " c None", "1 c #000000", "2 c #FFFFFF", "3 c #B4B4B4", "4 c #FF0000", " 222111222", " 144444441", " 1 11 144444441", " 111 1211 144444441", "11111 1222 244444442", " 1 1222 244444442", " 1 1222 244444442", " 1 1222 144444441", " 1 1111 111222111", " 1 ", " 1 ", " 1 11111111111111", " 1 133333333311 ", " 1 1333333311 ", " 1 13333311 ", "11111 133311 ", " 111 1311 ", " 1 11 ", " ", " " }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xpm_flood.xpm000066400000000000000000000012171471325446300246540ustar00rootroot00000000000000/* XPM */ static char * xpm_flood_xpm[] = { "20 20 8 1", ". c None", "+ c #000000", "@ c #505050", "# c #A0A0A0", "$ c #C8C8C8", "% c #FF2200", "& c #FFFFFF", "* c #787878", "....................", "....................", "....................", ".........++++.......", ".......++@@+#+......", "......+@@@@+$#+.....", ".....+@@@@+$$$#+....", "....%%%%%+$$&&$#+...", "...%%%%++$$&&&&$#+..", "..%%%++#$$&&&&&&$#+.", "..%%%+*#$$&&&&&&&$+.", ".%%%%.+*#$$&&&&&&$+.", ".%%%...+*#$$&&&&$+..", ".%%%....+*#$$&&$#+..", ".%%%.....+*#$$$#+...", ".%%%......+*##++....", ".%%%.......+++......", "..%.................", "..%.................", "...................."}; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xpm_grad_place.xpm000066400000000000000000000016071471325446300256350ustar00rootroot00000000000000/* XPM */ static char *xpm_grad_place_xpm[] = { "22 22 18 1", " c None", "B c #000000", "C c #FF0000", "D c #FF8000", "E c #FFFF00", "F c #80FF00", "G c #00FF00", "H c #00FF55", "I c #00FFAA", "J c #00FFFF", "K c #00AAFF", "L c #0055FF", "M c #0000FF", "N c #8000FF", "O c #FF00FF", "P c #FF0080", "Q c #FF0000", "R c #FFFFFF", " ", " ", " B BBBBBBBBBB ", " BB BCCCCCCCCB ", " BRB BDDDDDDDDB ", " BRRB BEEEEEEEEB ", " BRRRB BFFFFFFFFB ", " BRRRRB BGGGGGGGGB ", " BRRRRRB BHHHHHHHHB ", " BRRRRRRB BIIIIIIIIB ", " BRRRRRRRB BJJJJJJJJB ", " BRRRRRRRRBBKKKKKKKKB ", " BRRRRRBBBBBLLLLLLLLB ", " BRRBRRB BMMMMMMMMB ", " BRB BRRB BNNNNNNNNB ", " BB BRRB BOOOOOOOOB ", " B BRRB BPPPPPPPPB ", " BRRB BQQQQQQQQB ", " BBB BBBBBBBBBB ", " ", " ", " " }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xpm_hidden.xpm000066400000000000000000000011051471325446300250000ustar00rootroot00000000000000/* XPM */ static char *xpm_hidden_xpm[] = { "20 20 3 1", " c None", "1 c #000000", "2 c #FFFFFF", " ", " ", " ", " 1111111 ", " 12222211 ", " 122222121 ", " 1222221221 ", " 122222122 1 ", " 12222211 1 1 ", " 1222222 2 2 ", " 122222 2 2 1 ", " 12222 2 2 2 ", " 1222 2 2 2 1 ", " 122 2 2 2 2 ", " 12 2 2 2 2 1 ", " 1 2 2 2 2 2 ", " 1 1 1 1 1 1 ", " ", " ", " " }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xpm_home.xpm000066400000000000000000000010151471325446300244750ustar00rootroot00000000000000/* XPM */ static char *xpm_home_xpm[] = { "18 18 5 1", " c None", "1 c #FFFFFF", "2 c #000000", "3 c #FFB650", "4 c #FF0000", " ", " 22 ", " 2332222 ", " 23443212 ", " 234444312 ", " 2344224432 ", " 234421124432 ", " 23442111124432 ", " 2344211111124432 ", "234421111111124432", " 2421111221111242 ", " 22111244211122 ", " 211124321112 ", " 211124321112 ", " 211124321112 ", " 211124321112 ", " 222222222222 ", " " }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xpm_lasso.xpm000066400000000000000000000011231471325446300246660ustar00rootroot00000000000000/* XPM */ static char *xpm_lasso_xpm[] = { "20 20 4 1", " c None", "1 c #000000", "2 c #FFFFFF", "3 c #FF0000", " ", " 11111111111 ", " 122222222222111 ", " 12211111111122221 ", " 121 111221 ", " 121 1221", " 1221 121", " 12211 1221", " 1222111 1221 ", " 11222211 11221 ", " 11122212221 ", " 1122221 ", " 111221 ", " 121 ", " 111221 ", " 111122221 ", " 111122222111 ", " 1222221111 ", " 11111 ", " " }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xpm_layers.xpm000066400000000000000000000011431471325446300250460ustar00rootroot00000000000000/* XPM */ static char *xpm_layers_xpm[] = { "20 20 5 1", " c None", "1 c #000000", "2 c #FFFFFF", "3 c #E6E6E2", "4 c #CDCDFF", " ", " ", " ", " 1111111111 ", " 12222222221 ", " 12222222221 ", " 12222222221 ", " 12222222221111 ", " 11111111113331 ", " 13333333331 ", " 13333333331 ", " 13333333331111 ", " 11111111114441 ", " 14444444441 ", " 14444444441 ", " 14444444441 ", " 1111111111 ", " ", " ", " " }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xpm_line.xpm000066400000000000000000000011031471325446300244720ustar00rootroot00000000000000/* XPM */ static char *xpm_line_xpm[] = { "20 20 3 1", " c None", "1 c #000000", "2 c #FFFFFF", " ", " 11111111 ", " 12222221 ", " 12222221 ", " 11112221 ", " 12222221 ", " 12222221 ", " 11122221 ", " 12222221 ", " 12222221 ", " 11112221 ", " 12222221 ", " 12222221 ", " 11122221 ", " 12222221 ", " 12222221 ", " 11112221 ", " 12222221 ", " 12222221 ", " 11111111 " }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xpm_mode_blend.xpm000066400000000000000000000013771471325446300256500ustar00rootroot00000000000000/* XPM */ static char *xpm_mode_blend_xpm[] = { "22 22 9 1", " c None", "1 c #000000", "2 c #FF0000", "3 c #FF00FF", "4 c #FFFF00", "5 c #0000FF", "6 c #FFFFFF", "7 c #00FF00", "8 c #00FFFF", " ", " 1111 ", " 11222211 ", " 1222222221 ", " 122222222221 ", " 122222222221 ", " 12222222222221 ", " 12333322444421 ", " 1533333664444471 ", " 155333366664444771 ", " 155533366664447771 ", " 15555336666664477771 ", " 15555536666664777771 ", " 15555558666687777771 ", " 15555558888887777771 ", " 155555588887777771 ", " 155555588887777771 ", " 1555555887777771 ", " 11555511777711 ", " 1111 1111 ", " ", " " }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xpm_mode_cont.xpm000066400000000000000000000012251471325446300255170ustar00rootroot00000000000000/* XPM */ static char *xpm_mode_cont_xpm[] = { "22 22 2 1", " c None", "1 c #000000", " ", " ", " ", " ", " 111 111 ", " 111 111 ", " 111 111 111 ", " 111 ", " 111 ", " ", " 111111 ", " 111111111 ", " 111111111111 ", " 1111111111 ", " 1111111 ", " 11111 ", " 11111 ", " 1111 ", " 1111 ", " ", " ", " " }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xpm_mode_csel.xpm000066400000000000000000000015671471325446300255130ustar00rootroot00000000000000/* XPM */ static char *xpm_mode_csel_xpm[] = { "22 22 17 1", " c None", "B c #000000", "C c #FFFF00", "D c #FFED00", "E c #FFDB00", "F c #FFC800", "G c #FFB600", "H c #FFA400", "I c #FF9200", "J c #FF7F00", "K c #FF6D00", "L c #FF5B00", "M c #FF4900", "N c #FF3700", "O c #FF2400", "P c #FF1200", "Q c #FF0000", " ", " ", " ", " B B ", " BBBBBBBBB ", " B B ", " ", " BBBBBBBBBBBBBBBBB ", " BCDEFGHIJKLMNOPQB ", " BCDEFGHIJKLMNOPQB ", " BCDEFGHIJKLMNOPQB ", " BCDEFGHIJKLMNOPQB ", " BCDEFGHIJKLMNOPQB ", " BCDEFGHIJKLMNOPQB ", " BCDEFGHIJKLMNOPQB ", " BCDEFGHIJKLMNOPQB ", " BBBBBBBBBBBBBBBBB ", " ", " ", " ", " ", " " }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xpm_mode_mask.xpm000066400000000000000000000012631471325446300255110ustar00rootroot00000000000000/* XPM */ static char *xpm_mode_mask_xpm[] = { "22 22 4 1", " c None", "1 c #FFFF00", "2 c #FF6D00", "3 c #000000", " ", " ", " 3333 3 3 ", " 3111333 3 3 1 3 ", " 311111133 3 1 1 1 ", " 3111111111 1 1 1 3 ", " 311331111 1 1 3 1 ", " 3113333111 3 3 1 3 ", " 311133331 3 3 1 1 ", " 3111133311 3 1 1 3 ", " 311111111 1 1 1 1 ", " 3111111111 1 1 1 3 ", " 311331111 1 1 3 1 ", " 3113333111 3 3 1 3 ", " 31133333 3 3 1 3 ", " 311133333 3 1 1 ", " 3111333 3 1 1 ", " 3111111 1 1 ", " 31111 1 1 ", " 33111 3 ", " 33 3 ", " " }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xpm_mode_opac.xpm000066400000000000000000000012631471325446300255000ustar00rootroot00000000000000/* XPM */ static char *xpm_mode_opac_xpm[] = { "22 22 4 1", " c None", "1 c #6D6D6D", "2 c #494949", "3 c #242424", " ", " ", " ", " 11111111 ", " 11111111 ", " 11111111 ", " 111122221111 ", " 111122221111 ", " 111122221111 ", " 111122221111 ", " 111122232222111 ", " 11122222111 ", " 11122222111 ", " 11122222111 ", " 11111111 ", " 11111111 ", " 11111111 ", " 11111111 ", " ", " ", " ", " " }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xpm_mode_tint.xpm000066400000000000000000000020721471325446300255330ustar00rootroot00000000000000/* XPM */ static char *xpm_mode_tint_xpm[] = { "22 22 30 1", " c None", "B c #FFFFFF", "C c #EDEDED", "D c #DBDBDB", "E c #C8C8C8", "F c #B6B6B6", "G c #A4A4A4", "H c #929292", "I c #7F7F7F", "J c #6D6D6D", "K c #5B5B5B", "L c #494949", "M c #373737", "N c #242424", "O c #121212", "P c #000000", "Q c #00FF00", "R c #00ED00", "S c #00DB00", "T c #00C800", "U c #00B600", "V c #00A400", "W c #009200", "X c #007F00", "Y c #006D00", "Z c #005B00", "a c #004900", "b c #003700", "c c #002400", "d c #001200", " ", " ", " ", " BCDEFGHIJKLMNOP ", " BCDEFGHIJKLMNOP ", " BCDEFGHIJKLMNOP ", " BCDEFGHIJKLMNOP ", " BCDEFGHIJKLMNOP ", " BCDEFGHIJKLMNOP ", " BCDEFGHIJKLMNOP ", " BCDEFGHIJKLMNOP ", " QRSTUVWXYZabcdP ", " QRSTUVWXYZabcdP ", " QRSTUVWXYZabcdP ", " QRSTUVWXYZabcdP ", " QRSTUVWXYZabcdP ", " QRSTUVWXYZabcdP ", " QRSTUVWXYZabcdP ", " ", " ", " ", " " }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xpm_mode_tint2.xpm000066400000000000000000000020731471325446300256160ustar00rootroot00000000000000/* XPM */ static char *xpm_mode_tint2_xpm[] = { "22 22 30 1", " c None", "B c #FFFFFF", "C c #EDEDED", "D c #DBDBDB", "E c #C8C8C8", "F c #B6B6B6", "G c #A4A4A4", "H c #929292", "I c #7F7F7F", "J c #6D6D6D", "K c #5B5B5B", "L c #494949", "M c #373737", "N c #242424", "O c #121212", "P c #000000", "Q c #00FF00", "R c #00ED00", "S c #00DB00", "T c #00C800", "U c #00B600", "V c #00A400", "W c #009200", "X c #007F00", "Y c #006D00", "Z c #005B00", "a c #004900", "b c #003700", "c c #002400", "d c #001200", " ", " ", " ", " P HIJKLMNOP ", " P HIJKLMNOP ", " PPPPP HIJKLMNOP ", " P HIJKLMNOP ", " P HIJKLMNOP ", " HIJKLMNOP ", " BCDEFGHIJKLMNOP ", " BCDEFGHIJKLMNOP ", " QRSTUVWXYZabcdP ", " QRSTUVWXYZabcdP ", " QRSTUVWXYZabcdP ", " QRSTUVWXY ", " QRSTUVWXY PPPPP ", " QRSTUVWXY ", " QRSTUVWXY ", " ", " ", " ", " " }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xpm_new.xpm000066400000000000000000000011021471325446300243330ustar00rootroot00000000000000/* XPM */ static char *xpm_new_xpm[] = { "20 20 3 1", " c None", "1 c #000000", "2 c #FFFFFF", " ", " ", " ", " 1111111 ", " 12222211 ", " 122222121 ", " 1222221221 ", " 12222212221 ", " 122222111111 ", " 122222222221 ", " 122222222221 ", " 122222222221 ", " 122222222221 ", " 122222222221 ", " 122222222221 ", " 122222222221 ", " 111111111111 ", " ", " ", " " }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xpm_newdir.xpm000066400000000000000000000012761471325446300250460ustar00rootroot00000000000000/* XPM */ static char *xpm_newdir_xpm[] = { "20 20 11 1", " c None", "1 c #000000", "2 c #FFFF92", "3 c #49DB00", "4 c #44D303", "5 c #40CC05", "6 c #3BC408", "7 c #36BD0B", "8 c #32B50D", "9 c #2DAE10", "A c #FFFF00", " 1A1 ", " 1 1A1 1 ", " 1A11A11A1 ", " 11111 1A1A1A1 ", " 12222211111AAA1111", " 12222221AAAAAAAAAAA", " 122222221111AAA1111", " 12222222221A1A1A1 ", " 1222111111A11A11A1 ", " 1222133333131A1311 ", " 1221444444441A141 ", " 12215555555551551 ", " 1216666666666661 ", " 1217777777777771 ", " 118888888888881 ", " 119999999999991 ", " 11111111111111 ", " ", " ", " " }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xpm_open.xpm000066400000000000000000000012551471325446300245140ustar00rootroot00000000000000/* XPM */ static char *xpm_open_xpm[] = { "20 20 10 1", " c None", "1 c #000000", "2 c #FFFF92", "3 c #49DB00", "4 c #44D303", "5 c #40CC05", "6 c #3BC408", "7 c #36BD0B", "8 c #32B50D", "9 c #2DAE10", " ", " ", " ", " 11111 ", " 1222221 ", " 12222222111111 ", " 12222222222221 ", " 12222222222221 ", " 122211111111111111 ", " 122213333333333331 ", " 12214444444444441 ", " 12215555555555551 ", " 1216666666666661 ", " 1217777777777771 ", " 118888888888881 ", " 119999999999991 ", " 11111111111111 ", " ", " ", " " }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xpm_paint.xpm000066400000000000000000000012171471325446300246640ustar00rootroot00000000000000/* XPM */ static char *xpm_paint_xpm[] = { "20 20 8 1", " c None", "1 c #C8C8FF", "2 c #7878FF", "3 c #0000FF", "4 c #000000", "5 c #B6B678", "6 c #DBDBB4", "7 c #FFFFC8", " ", " 44444 ", " 432124 ", " 4321224 ", " 43212224 ", " 432122234 ", " 4321222334 ", " 4321222334 ", " 4321222334 ", " 4321222334 ", " 4321222334 ", " 476222334 ", " 467652334 ", " 47655534 ", " 46755544 ", " 425544 ", " 42344 ", " 434 ", " 44 ", " " }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xpm_pan.xpm000066400000000000000000000011021471325446300243200ustar00rootroot00000000000000/* XPM */ static char *xpm_pan_xpm[] = { "20 20 3 1", " c None", "1 c #000000", "2 c #FFFF00", " 11 ", " 1111 ", " 111111 ", " 11 ", " 11 ", " 11 ", " 11111111 ", " 1 12222221 1 ", " 11 12222221 11 ", "11111112222221111111", "11111112222221111111", " 11 12222221 11 ", " 1 12222221 1 ", " 11111111 ", " 11 ", " 11 ", " 11 ", " 111111 ", " 1111 ", " 11 " }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xpm_paste.xpm000066400000000000000000000012561471325446300246700ustar00rootroot00000000000000/* XPM */ static char *xpm_paste_xpm[] = { "20 20 10 1", " c None", "1 c #000000", "2 c #FFFF92", "3 c #FFFFFF", "4 c #49DB00", "5 c #40CC05", "6 c #36BD0A", "7 c #2DAE10", "8 c #239F15", "9 c #1A901A", " ", " ", " 1111 ", " 111112211111 ", " 11441211214411 ", " 14412222221441 ", " 15411111111541 ", " 15555555555551 ", " 16565656565651 ", " 16666661111111 ", " 176767613333331 ", " 1777777133333331 ", " 18787871333333331 ", " 18888881311111131 ", " 19898981333333331 ", " 11999991333333331 ", " 1111111311111131 ", " 1333333331 ", " 1111111111 ", " " }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xpm_picker.xpm000066400000000000000000000007171471325446300250320ustar00rootroot00000000000000/* XPM */ static char *xpm_picker_xpm[] = { "17 17 3 1 2 16", "0 c #000000", "1 c #FFFFFF", " c None", " 111 ", " 10001 ", " 1000001", " 111000001", " 1000000001", " 10000001 ", " 0100011 ", " 0111001 ", " 01110101 ", " 01110 1 ", " 01110 ", " 01110 ", " 01110 ", " 01110 ", " 0110 ", "0 00 ", " 0 " }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xpm_polygon.xpm000066400000000000000000000011251471325446300252360ustar00rootroot00000000000000/* XPM */ static char *xpm_polygon_xpm[] = { "20 20 4 1", " c None", "1 c #000000", "2 c #FFFFFF", "3 c #FF0000", " ", " 1 ", " 11 ", " 2332 ", " 23332 ", " 233332 ", " 13333331 ", " 133333331 ", " 1333333331 ", " 233333333332 ", " 2333333333332 ", " 213333333333332 ", " 1133333333331 ", " 22333333331 ", " 2113333331 ", " 1133332 ", " 22332 ", " 2132 ", " 11 ", " " }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xpm_rect1.xpm000066400000000000000000000011231471325446300245630ustar00rootroot00000000000000/* XPM */ static char *xpm_rect1_xpm[] = { "20 20 4 1", " c None", "1 c #000000", "2 c #FF0000", "3 c #FFFF00", " ", " 1111111111111111", " 1111111111111111", " 11 11", " 11 11", "222222222222222 11", "222222222222222 11", "22 11 22 11", "22 11 22 11", "22 11 22 11", "22 11 22 11", "22 11 22 11", "22 11 22 11", "22 11 22 11", "22 1111111112211111", "22 1111111112211111", "22 22 ", "22 22 ", "222222222222222 ", "222222222222222 " }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xpm_rect2.xpm000066400000000000000000000011231471325446300245640ustar00rootroot00000000000000/* XPM */ static char *xpm_rect2_xpm[] = { "20 20 4 1", " c None", "1 c #000000", "2 c #FF0000", "3 c #FFFF00", " ", " 1111111111111111", " 1111111111111111", " 1111111111111111", " 1111111111111111", "22222222222222211111", "22222222222222211111", "22222222222222211111", "22222222222222211111", "22222222222222211111", "22222222222222211111", "22222222222222211111", "22222222222222211111", "22222222222222211111", "22222222222222211111", "22222222222222211111", "222222222222222 ", "222222222222222 ", "222222222222222 ", "222222222222222 " }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xpm_redo.xpm000066400000000000000000000012161471325446300245010ustar00rootroot00000000000000/* XPM */ static char *xpm_redo_xpm[] = { "20 20 8 1", " c None", "1 c #000000", "2 c #FFFF6D", "3 c #F0F066", "4 c #E2E25F", "5 c #D3D357", "6 c #C5C550", "7 c #B6B649", " ", " ", " ", " 111 ", " 1211 ", " 12211 ", " 123211 ", " 111111333311 ", " 1434343434311 ", " 14444444444411 ", " 15454545454511 ", " 1555555555511 ", " 111111565611 ", " 166611 ", " 16711 ", " 1711 ", " 111 ", " ", " ", " " }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xpm_rotate_as.xpm000066400000000000000000000011271471325446300255320ustar00rootroot00000000000000/* XPM */ static char *xpm_rotate_as_xpm[] = { "20 20 4 1", " c None", "1 c #000000", "2 c #FFFFFF", "3 c #FF0000", " ", " 222111222 ", " 133333331 ", " 133333331 ", " 133333331 ", " 233333332 ", " 233333332 11 ", " 233333332 1111 ", " 133333331 111111 ", " 111222111 11111111", " 11 11 ", " 11 11 ", " 11 11 ", " 11 11 ", " 111 111 ", " 11111111 ", " 1111 ", " ", " ", " " }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xpm_rotate_cs.xpm000066400000000000000000000011271471325446300255340ustar00rootroot00000000000000/* XPM */ static char *xpm_rotate_cs_xpm[] = { "20 20 4 1", " c None", "1 c #000000", "2 c #FFFFFF", "3 c #FF0000", " ", " 222111222 ", " 133333331 ", " 133333331 ", " 133333331 ", " 233333332 ", " 11 233333332 ", " 1111 233333332 ", " 111111 133333331 ", "11111111 111222111 ", " 11 11 ", " 11 11 ", " 11 11 ", " 11 11 ", " 111 111 ", " 11111111 ", " 1111 ", " ", " ", " " }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xpm_save.xpm000066400000000000000000000013131471325446300245040ustar00rootroot00000000000000/* XPM */ static char *xpm_save_xpm[] = { "20 20 12 1", " c None", "1 c #000000", "2 c #FFFFFF", "3 c #DBDBDB", "4 c #B6B6B6", "5 c #929292", "6 c #00B6FF", "7 c #00A4FB", "8 c #0092F8", "9 c #007FF4", "A c #006DF1", "B c #005BED", " ", " ", " 1111111111111111 ", " 1666666666666661 ", " 1662222222222661 ", " 1672222222222671 ", " 1772222222222771 ", " 1782222222222781 ", " 1882222222222881 ", " 1892222222222891 ", " 1999999999999991 ", " 1999999999999991 ", " 19A443323344A9A1 ", " 1AA431133444AAA1 ", " 1AB331B34445BAB1 ", " 1BB321B44455BBB1 ", " 1B233444555BBB1 ", " 11111111111111 ", " ", " " }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xpm_select.xpm000066400000000000000000000011241471325446300250250ustar00rootroot00000000000000/* XPM */ static char * xpm_select_xpm[] = { "20 20 4 1", " c None", ". c #000000", "+ c #FFFFFF", "@ c #FF0000", " ", " ", " ", " ...+++..+++... ", " +@@@@@@@@@@@@+ ", " +@@@@@@@@@@@@+ ", " +@@@@@@@@@@@@+ ", " .@@@@@@@@@@@@. ", " .@@@@@@@@@@@@. ", " .@@@@@@@@@@@@. ", " +@@@@@@@@@@@@+ ", " +@@@@@@@@@@@@+ ", " +@@@@@@@@@@@@+ ", " .@@@@@@@@@@@@. ", " .@@@@@@@@@@@@. ", " +@@@@@@@@@@@@+ ", " ++..+++++...++ ", " ", " ", " "}; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xpm_shuffle.xpm000066400000000000000000000010671471325446300252100ustar00rootroot00000000000000/* XPM */ static char * xpm_shuffle_xpm[] = { "20 20 2 1", ". c None", "+ c #000000", "....................", "....................", "....................", "...............++...", "....++++++++...++...", "....+...............", "....+...............", "....+...............", "....+..........+....", "..+++++.......+++...", "...+++.......+++++..", "....+..........+....", "...............+....", "...............+....", "...............+....", "...++...++++++++....", "...++...............", "....................", "....................", "...................."}; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xpm_smudge.xpm000066400000000000000000000013721471325446300250370ustar00rootroot00000000000000/* XPM */ static char *xpm_smudge_xpm[] = { "20 20 15 1", " c None", "1 c #000000", "2 c #151515", "3 c #2A2A2A", "4 c #404040", "5 c #555555", "6 c #6A6A6A", "7 c #7F7F7F", "8 c #959595", "9 c #AAAAAA", "A c #BFBFBF", "B c #D4D4D4", "C c #EAEAEA", "D c #FFFFFF", "E c #000000", " EEEEEEE", " E111111E", " E2222221E", " E33333321E", " E444444321E", " E5555554321E", " E66666654321E", " E77777765432E ", " E88888876543E ", " E99999987654E ", " EAAAAAA98765E ", " EBBBBBBA9876E ", " ECCCCCCBA987E ", "EDDDDDDCBA98E ", "EDDDDDDCBA9E ", "EDDDDDDCBAE ", "EDDDDDDCBE ", "EDDDDDDCE ", "EDDDDDDE ", "EEEEEEE " }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xpm_text.xpm000066400000000000000000000010641471325446300245350ustar00rootroot00000000000000/* XPM */ static char *xpm_text_xpm[] = { "20 20 2 1", " c None", "1 c #000000", " ", " 11111111111111111 ", " 11111111111111111 ", " 111 111 111 ", " 11 111 11 ", " 1 111 1 ", " 111 ", " 111 ", " 111 ", " 111 ", " 111 ", " 111 ", " 111 ", " 111 ", " 111 ", " 111 ", " 11111 ", " 1111111 ", " 111111111 ", " " }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xpm_undo.xpm000066400000000000000000000012161471325446300245150ustar00rootroot00000000000000/* XPM */ static char *xpm_undo_xpm[] = { "20 20 8 1", " c None", "1 c #000000", "2 c #FFFF6D", "3 c #F0F066", "4 c #E2E25F", "5 c #D3D357", "6 c #C5C550", "7 c #B6B649", " ", " ", " ", " 111 ", " 1121 ", " 11221 ", " 112321 ", " 113333111111 ", " 1134343434341 ", " 11444444444441 ", " 11545454545451 ", " 1155555555551 ", " 116565111111 ", " 116661 ", " 11761 ", " 1171 ", " 111 ", " ", " ", " " }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/icons1/xpm_up.xpm000066400000000000000000000012141471325446300241720ustar00rootroot00000000000000/* XPM */ static char *xpm_up_xpm[] = { "20 20 8 1", " c None", "1 c #000000", "2 c #FFFF6D", "3 c #F0F066", "4 c #E2E25F", "5 c #D3D357", "6 c #C5C550", "7 c #B6B649", " ", " ", " ", " 11 ", " 1111 ", " 114511 ", " 11344511 ", " 1134455611 ", " 112334455611 ", " 11233445566711 ", " 12223344556671 ", " 11111445511111 ", " 134451 ", " 144551 ", " 134451 ", " 144551 ", " 111111 ", " ", " ", " " }; mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/info.c000066400000000000000000000211721471325446300220440ustar00rootroot00000000000000/* info.c Copyright (C) 2005-2021 Mark Tyler and Dmitry Groshev This file is part of mtPaint. mtPaint 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. mtPaint 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 mtPaint in the file COPYING. */ #include "global.h" #include "mygtk.h" #include "memory.h" #include "vcode.h" #include "ani.h" #include "png.h" #include "mainwindow.h" #include "canvas.h" #include "layer.h" // Maximum median cuts to make #define MAX_CUTS 128 #define HS_GRAPH_W 256 #define HS_GRAPH_H 64 typedef struct { int indexed, clip, layers; int norm; int wh[3]; char *col_h, *col_d; unsigned char *rgb_mem; void **drawingarea; char mem_d[128], clip_d[256], rgb_d[64], lr_d[128]; int rgb[256][3]; // Raw frequencies int rgb_sorted[256][3]; // Sorted frequencies } info_dd; /* Plot RGB graphs */ static void hs_plot_graph(unsigned char *hs_rgb_mem, int hs_norm, int hs_rgb[256][3], int hs_rgb_sorted[256][3]) { unsigned char *im, col1[3] = { mem_pal_def[0].red, mem_pal_def[0].green, mem_pal_def[0].blue}, col2[3]; int i, j, k, t, /*min[3],*/ max[3], med[3], bars[256][3]; float f; for ( i=0; i<3; i++ ) col2[i] = 255 - col1[i]; im = hs_rgb_mem; if ( im != NULL ) { // Flush background to palette 0 colour j = HS_GRAPH_W * HS_GRAPH_H * mem_img_bpp; for ( i=0; i0; j=j-HS_GRAPH_H/2 ) { im = hs_rgb_mem + j*HS_GRAPH_W*3; for ( i=0; i0; j=j-HS_GRAPH_W/4 ) { im = hs_rgb_mem + j*3; for ( i=0; i 0 ) { t = j; break; } } // min[k] = hs_rgb_sorted[t][k]; med[k] = hs_rgb_sorted[(t+255)/2][k]; max[k] = hs_rgb_sorted[255][k]; } // Calculate bar values - either linear or normalized if ( hs_norm ) { for ( k=0; k63 ) t=63; im = hs_rgb_mem + i*3 + (k+1)*HS_GRAPH_H*HS_GRAPH_W*3; im = im - HS_GRAPH_W*3; for ( j=0; jrgb_mem, dt->norm, dt->rgb, dt->rgb_sorted); cmd_repaint(dt->drawingarea); } /* Populate RGB tables */ static void hs_populate_rgb(int hs_rgb[256][3], int hs_rgb_sorted[256][3]) { int i, j, k, t; unsigned char *im = mem_img[CHN_IMAGE]; memset(&hs_rgb[0][0], 0, 256 * 3 * sizeof(hs_rgb[0][0])); j = mem_width * mem_height; if ( mem_img_bpp == 3 ) { for ( i=0; i0; j-- ) // The venerable bubble sort { for ( i=0; i hs_rgb_sorted[i+1][k] ) { t = hs_rgb_sorted[i][k]; hs_rgb_sorted[i][k] = hs_rgb_sorted[i+1][k]; hs_rgb_sorted[i+1][k] = t; } } } } } //// INFORMATION WINDOW #undef _ #define _(X) X #define WBbase info_dd static void *info_code[] = { WINDOWm(_("Information")), IF(indexed), DEFH(400), FTABLE(_("Memory"), 2, 3), TLLABEL(_("Total memory for main + undo images"), 0, 0), TLTEXTf(mem_d, 1, 0), TLLABEL(_("Undo / Redo / Max levels used"), 0, 1), UNLESSx(clip, 1), TLLABEL(_("Clipboard"), 0, 2), TLLABEL(_("Unused"), 1, 2), ENDIF(1), IF(clip), TLTEXTf(clip_d, 0, 2), UNLESSx(indexed, 1), TLLABEL(_("Unique RGB pixels"), 0, 3), TLTEXTf(rgb_d, 1, 3), ENDIF(1), IFx(layers, 1), TLLABEL(_("Layers"), 0, 4), TLTEXTf(lr_d, 1, 4), TLLABEL(_("Total layer memory usage"), 0, 5), ENDIF(1), WDONE, BORDER(TABLE, 0), FTABLE(_("Colour Histogram"), 2, 2), TALLOC(rgb_mem, wh[2]), REF(drawingarea), TLRGBIMAGE(rgb_mem, wh, 0, 0), TLCHECK(_("Normalize"), norm, 0, 1), EVENT(CHANGE, hs_click_normalize), TRIGGER, WDONE, IFx(indexed, 1), /// Big index table BORDER(SCROLL, 0), XFRAMEp(col_h), VBOXbp(0, 4, 0), XSCROLL(1, 1), // auto/auto BORDER(TABLE, 0), TABLE(3, 256 + 3), TLLABEL(_("Index"), 0, 0), TLLABEL(_("Canvas pixels"), 1, 0), TLLABEL("%", 2, 0), BORDER(LABEL, 0), TLTEXTp(col_d, 0, 1), CLEANUP(col_d), WDONE, WDONE, // VBOXbp, TABLE ENDIF(1), HSEP, UDONEBTN(_("OK"), NULL), WSHOW }; #undef WBbase #undef _ #define _(X) __(X) void pressed_information() { info_dd tdata; char txt[256]; int i, j, maxi, orphans; memset(&tdata, 0, sizeof(tdata)); tdata.indexed = mem_img_bpp == 1; maxi = rint(((double)mem_undo_limit * 1024 * 1024) * (mem_undo_common * layers_total * 0.01 + 1) / (mem_width * mem_height * mem_img_bpp * (layers_total + 1)) - 1.25); maxi = maxi < 0 ? 0 : maxi >= mem_undo_max ? mem_undo_max - 1 : maxi; snprintf(tdata.mem_d, sizeof(tdata.mem_d), "%1.1f MB\n%d / %d / %d", mem_used() / (double)(1024 * 1024), mem_undo_done, mem_undo_redo, maxi); if (mem_clipboard) { tdata.clip = TRUE; snprintf(tdata.clip_d, sizeof(tdata.clip_d), mem_clip_bpp == 1 ? _("Clipboard = %i x %i") : _("Clipboard = %i x %i x RGB"), mem_clip_w, mem_clip_h); snprintf(txt, sizeof(txt), "\t%1.1f MB", ((size_t)mem_clip_w * mem_clip_h * mem_clip_bpp) / (double)(1024 * 1024)); strnncat(tdata.clip_d, txt, sizeof(tdata.clip_d)); } if (mem_img_bpp == 3) // RGB image so count different colours { i = mem_count_all_cols(); if (i < 0) // not enough memory { i = mem_cols_used(NULL); if (i > 256) i = -1; strcpy(tdata.rgb_d, ">256"); } if (i >= 0) snprintf(tdata.rgb_d, sizeof(tdata.rgb_d), "%d", i); } if ((tdata.layers = layers_total)) { snprintf(tdata.lr_d, sizeof(tdata.lr_d), "%d\n%1.1f MB", layers_total, mem_used_layers() / (double)(1024 * 1024)); } hs_populate_rgb(tdata.rgb, tdata.rgb_sorted); tdata.wh[0] = HS_GRAPH_W; tdata.wh[1] = HS_GRAPH_H * mem_img_bpp; tdata.wh[2] = tdata.wh[0] * tdata.wh[1] * 3; if (mem_img_bpp == 1) { memx2 mem; mem_get_histogram(CHN_IMAGE); memset(&mem, 0, sizeof(mem)); j = mem_width * mem_height; for (i = 0; i < mem_cols; i++) { snprintf(txt, sizeof(txt), "%d\t%d\t%1.1f\n", i, mem_histogram[i], (100.0 * mem_histogram[i]) / j); addstr(&mem, txt, 1); } for (orphans = 0 , i = mem_cols; i < 256; i++) orphans += mem_histogram[i]; snprintf(txt, sizeof(txt), "%s\t%d\t%1.1f", _("Orphans"), orphans, (100.0 * orphans) / j); addstr(&mem, txt, 0); tdata.col_d = mem.buf; for (j = i = 0; i < mem_cols; i++) if (mem_histogram[i]) j++; snprintf(tdata.col_h = txt, sizeof(txt), _("Colour index totals - %i of %i used"), j, mem_cols); } run_create(info_code, &tdata, sizeof(tdata)); } mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/info.h000066400000000000000000000012651471325446300220520ustar00rootroot00000000000000/* info.h Copyright (C) 2005-2008 Mark Tyler This file is part of mtPaint. mtPaint 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. mtPaint 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 mtPaint in the file COPYING. */ void pressed_information(); mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/inifile.c000066400000000000000000000603031471325446300225270ustar00rootroot00000000000000/* inifile.c Copyright (C) 2007-2019 Dmitry Groshev This file is part of mtPaint. mtPaint 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. mtPaint 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 mtPaint in the file COPYING. */ /* *** PREFACE *** * This implementation has no comment preservation, and has nested sections - * because this is how we like our inifiles. :-) * Allocations are done in slabs, because no slot is ever deallocated or * reordered; only modified string values are allocated singly, since it is * probable they will keep being modified. * Implementation uses one 32-bit hash function as two 16-bit ones while * possible, but with 40000 keys or more, has to evaluate two 32-bit functions * instead. But such loads are expected to be rare. - WJ */ #include #include #include #include #include #include "global.h" #include "memory.h" #include "inifile.h" /* Make code not compile where it cannot run */ typedef char Integers_Do_Not_Fit_Into_Pointers[2 * (sizeof(int) <= sizeof(char *)) - 1]; #define SLAB_INCREMENT 16384 #define SLAB_RESERVED 64 /* Reserved for allocator overhead */ #define INI_LIMIT 0x40000000 /* Limit imposed by hashing scheme */ #define HASHFILL(X) ((X) * 3) /* Hash occupancy no more than 1/3 */ #define HASHSEED 0x811C9DC5 #define HASH_RND(X) ((X) * 0x10450405 + 1) #define HASH_MIN 256 /* Minimum hash capacity, so that it won't be too tiny */ /* Slot types */ enum { INI_NONE = 0, INI_UNDEF, INI_STR, INI_INT, INI_BOOL, INI_REF }; // Negative types are section nesting levels /* Slot flags */ #define INI_SYSTEM 0x0001 /* Systemwide inifile */ #define INI_MALLOC 0x0002 /* Value is allocated singly (not in block) */ #define INI_DEFAULT 0x0004 /* Default value is defined */ #define INI_TEMP 0x0008 /* Transient - not written out */ /* Escaping is needed for leading tabs and spaces, for inline CR and LF, and * possibly for inline backslash */ static char *escape_string(char *src, int bs) { static const char *escaped = "\t \\\r\n"; const char *e = escaped; char c, *cp, *tmp, *t2; if ((src[0] != '\t') && (src[0] != ' ') && !src[strcspn(src, "\\\r\n" + !bs)]) return (NULL); t2 = tmp = calloc(1, strlen(src) * 2 + 1); if (tmp) { while ((c = *src++)) { if ((cp = strchr(e, c))) { *t2++ = '\\'; c = "t \\rn"[cp - escaped]; } *t2++ = c; e = escaped + 2; } *t2 = '\0'; } return (tmp); } #if GTK_MAJOR_VERSION == 1 /* GLib 1.2 doesn't provide g_strcompress() */ static void unescape_string(char *buf) { #define NUM_ESCAPES 5 static const char escapes[] = "bfnrt01234567"; static const char escaped[] = { 7, 12, 10, 13, 9, 0, 1, 2, 3, 4, 5, 6, 7 }; char c, cc, *tmp, *src = buf; int v; while ((c = *src++)) { if (c == '\\') { c = *src++; if (!c) break; while ((tmp = strchr(escapes, c))) { v = tmp - escapes; c = escaped[v]; if (v >= NUM_ESCAPES) { // Octal escape cc = *src - '0'; if (cc & ~7) break; c = c * 8 + cc; cc = *(++src) - '0'; if (cc & ~7) break; c = c * 8 + cc; ++src; } break; } } *buf++ = c; } *buf = '\0'; #undef NUM_ESCAPES } #else static void unescape_string(char *buf) { char *tmp = g_strcompress(buf); strcpy(buf, tmp); g_free(tmp); } #endif /* Thomas Wang's and "One at a time" hash functions */ static guint32 hashf(guint32 seed, int section, char *key) { seed += section; seed = (seed << 15) + ~seed; seed ^= (seed >> 12); seed += seed << 2; seed ^= seed >> 4; seed *= 2057; seed ^= seed >> 16; for (; *key; key++) { seed += *key; seed += seed << 10; seed ^= seed >> 6; } seed += seed << 3; seed ^= seed >> 11; seed += seed << 15; return (seed); } static int cuckoo_insert(inifile *inip, inislot *slotp) { gint32 idx, tmp; guint32 key; int i, j, d; /* Update section's chain */ i = slotp->sec; idx = slotp - inip->slots; if ((j = (int)inip->slots[i].value) < idx) { inip->slots[i].value = (char *)idx; if (j) inip->slots[j].chain = idx; else inip->slots[i].defv = (char *)idx; } /* Decide if using one-key mode */ d = inip->seed[0] == inip->seed[1]; /* Normal cuckoo process */ for (i = 0; i < inip->maxloop; i++) { key = hashf(inip->seed[i & 1], slotp->sec, slotp->key); key >>= (i & d) << 4; // Shift by 16 or don't j = (key & inip->hmask) * 2 + (i & 1); tmp = inip->hash[j]; inip->hash[j] = idx; idx = tmp; if (!idx) return (TRUE); slotp = inip->slots + idx; } return (FALSE); } static int resize_hash(inifile *inip, int cnt) { int len; if (!cnt) return (0); /* Degenerate case */ len = nextpow2(HASHFILL(cnt) - 1); if (len <= inip->hmask * 2 + 2) return (0); /* Large enough */ free(inip->hash); inip->hash = calloc(1, len * sizeof(gint32)); if (!inip->hash) return (-1); /* Failure */ inip->hmask = (len >> 1) - 1; inip->maxloop = ceil(3.0 * log(len / 2) / log((double)(len / 2) / cnt)); return (1); /* Resized */ } static int rehash(inifile *inip) { int i, flag; flag = resize_hash(inip, inip->count); if (flag < 0) return (FALSE); /* Failed */ while (TRUE) /* Until done */ { if (!flag) /* No size change */ { inip->seed[0] = inip->seed[1] = HASH_RND(inip->seed[0]); memset(inip->hash, 0, (inip->hmask + 1) * 2 * sizeof(gint32)); } /* Enter two-key mode */ if (inip->hmask > 0xFFFF) inip->seed[1] = HASH_RND(inip->seed[0]); /* Re-insert items */ for (i = 1; (i <= inip->count) && (flag = cuckoo_insert(inip, inip->slots + i)); i++); if (flag) return (TRUE); } } static inislot *cuckoo_find(inifile *inip, int section, char *name) { inislot *slotp; guint32 key; gint32 i; int j = 0; key = hashf(inip->seed[0], section, name); while (TRUE) { i = inip->hash[(key & inip->hmask) * 2 + j]; if (i) { slotp = inip->slots + i; if ((slotp->sec == section) && !strcmp(name, slotp->key)) return (slotp); } if (j++) return (NULL); if (inip->seed[0] == inip->seed[1]) key >>= 16; else key = hashf(inip->seed[1], section, name); } } static inislot *add_slot(inifile *inip) { inislot *ra; int i, j; if (inip->count >= INI_LIMIT) return (NULL); /* Too many entries */ /* Extend the slab if needed */ i = inip->count * sizeof(inislot) + sizeof(inislot) + SLAB_RESERVED + SLAB_INCREMENT - 1; j = (i + sizeof(inislot)) / SLAB_INCREMENT; if (i / SLAB_INCREMENT < j) { ra = realloc(inip->slots, j * SLAB_INCREMENT - SLAB_RESERVED); if (!ra) return (NULL); inip->slots = ra; } ra = inip->slots + ++inip->count; memset(ra, 0, sizeof(inislot)); return (ra); } static char *store_string(inifile *inip, char *str) { int i, l; char *ra; /* First byte of first block for zero length */ if (!str || !*str) return (*(char **)inip->sblocks + sizeof(char *)); /* Add new block if needed */ l = strlen(str) + 1; i = inip->slen + SLAB_RESERVED + SLAB_INCREMENT - 1; if (i / SLAB_INCREMENT < (i + l) / SLAB_INCREMENT) { i = l + sizeof(char *) + SLAB_RESERVED + SLAB_INCREMENT - 1; i -= i % SLAB_INCREMENT + SLAB_RESERVED; ra = calloc(1, i); if (!ra) return (NULL); /* Insert at tail of ring */ *(char **)ra = *(char **)inip->sblocks; *(char **)inip->sblocks = ra; inip->sblocks = ra; inip->slen = sizeof(char *); } ra = inip->sblocks + inip->slen; memcpy(ra, str, l); inip->slen += l; return (ra); } static inislot *key_slot(inifile *inip, int section, char *key, int type) { inislot *slot; if (type < 0) type = inip->slots[section].type - 1; slot = cuckoo_find(inip, section, key); if (slot) { if (type == INI_NONE) return (slot); if (slot->flags & INI_MALLOC) { free(slot->value); slot->flags ^= INI_MALLOC; } #if VALIDATE_TYPE if ((slot->type != type) && (slot->type > INI_UNDEF)) g_warning("INI key '%s' changed type\n", key); #endif } else { key = store_string(inip, key); if (!key) return (NULL); slot = add_slot(inip); if (!slot) return (NULL); slot->sec = section; slot->key = key; if (!cuckoo_insert(inip, slot) && !rehash(inip)) return (NULL); } slot->type = type; return (slot); } int new_ini(inifile *inip) { memset(inip, 0, sizeof(inifile)); inip->sblocks = calloc(1, SLAB_INCREMENT - SLAB_RESERVED); if (!inip->sblocks) return (FALSE); *(char **)inip->sblocks = inip->sblocks; inip->slen = sizeof(char *) + 1; inip->slots = calloc(1, SLAB_INCREMENT - SLAB_RESERVED); inip->seed[0] = inip->seed[1] = HASHSEED; return (inip->slots && (resize_hash(inip, HASH_MIN) > 0)); } void forget_ini(inifile *inip) { char *this, *next, *mem = inip->sblocks; int i; if (mem) for (this = *(char **)mem; this != mem; this = next) { next = *(char **)this; free(this); } free(mem); for (i = 1; i <= inip->count; i++) { if (inip->slots[i].flags & INI_MALLOC) free(inip->slots[i].value); } free(inip->slots); free(inip->hash); memset(inip, 0, sizeof(inifile)); } /* Load file whole into memory, with N zero bytes before and two after */ char *slurp_file_l(char *fname, int before, int *len) { FILE *fp; char *buf = NULL; int i, l; if (!fname || !(fp = fopen(fname, "rb"))) return (NULL); fseek(fp, 0, SEEK_END); l = ftell(fp); if ((l >= 0) && (l < INT_MAX - before - 2)) buf = calloc(1, l + before + 2); if (buf) { fseek(fp, 0, SEEK_SET); i = fread(buf + before, 1, l, fp); if (i != l) { free(buf); buf = NULL; } } fclose(fp); if (len) *len = l; return (buf); } int read_ini(inifile *inip, char *fname, int itype) { inifile ini; inislot *slot; char *tmp, *wrk, *w2, *str; int i, j, l, q, sec = 0; /* Read the file */ tmp = slurp_file(fname, sizeof(char *) + 1); if (!tmp) return (0); ini = *inip; /* Insert at head of ring */ *(char **)tmp = *(char **)inip->sblocks; *(char **)inip->sblocks = tmp; /* Parse the contents */ for (tmp += sizeof(char *) + 1; ; tmp = str) { tmp += strspn(tmp, "\r\n\t "); if (!*tmp) break; str = tmp + strcspn(tmp, "\r\n"); if (*str) *str++ = '\0'; if ((*tmp == ';') || (*tmp == '#')) continue; /* Comment */ if (*tmp == '[') /* Section */ { if (!(w2 = strchr(tmp + 1, ']'))) goto error; for (i = 0; tmp[i + 1] == '>'; i++); // Nesting level j = i + ini.slots[sec].type; if (j > 0) goto error; l = sec; while (j++) l = ini.slots[l].sec; *w2 = '\0'; /* Hash this */ tmp += ++i; slot = l || *tmp ? cuckoo_find(&ini, l, tmp) : ini.slots; if (!slot) /* New section */ { slot = add_slot(&ini); if (!slot) goto fail; slot->type = -i; slot->sec = l; slot->key = tmp; slot->flags = itype; if (!cuckoo_insert(&ini, slot) && !rehash(&ini)) goto fail; } sec = slot - ini.slots; /* Activate */ continue; } /* Variable (spaces in name allowed) */ w2 = strchr(tmp, '='); if (!w2) { error: g_printerr("Wrong INI line: '%s'\n", tmp); continue; } for (wrk = w2 - 1; wrk - tmp >= 0; wrk--) if ((*wrk != ' ') && (*wrk != '\t')) break; wrk[1] = '\0'; q = *(++w2) == '='; /* "==" means quoted value */ w2 += q + strspn(w2 + q, "\t "); // for (wrk = str - 1; *wrk && ((*wrk == '\t') || (*wrk == ' '); *wrk-- = '\0'); /* Hash this pair */ slot = cuckoo_find(&ini, sec, tmp); if (!slot) /* New key */ { slot = add_slot(&ini); if (!slot) goto fail; slot->sec = sec; slot->key = tmp; slot->flags = itype; if (!cuckoo_insert(&ini, slot) && !rehash(&ini)) goto fail; } if (q) unescape_string(w2); slot->type = INI_UNDEF; slot->value = w2; } /* Return the result */ *inip = ini; return (1); /* Catastrophic failure - unable to add key */ fail: forget_ini(&ini); *inip = ini; return (-1); } int write_ini(inifile *inip, char *fname, char *header) { FILE *fp; inislot *slotp, *secp = NULL; char *name, *sv, *xv; int i, j, sec, var, up, down, written = 0; if (!(fp = fopen(fname, "w"))) return (FALSE); if (header) fprintf(fp, "%s\n", header); sec = 0; var = -1; while (TRUE) { /* (Re)start scanning a new section */ if (var <= 0) i = (int)inip->slots[sec].defv , var = !var; else if (!sec) break; /* All done */ /* Return to scanning for parent's subsections */ else { i = inip->slots[sec].chain; sec = inip->slots[sec].sec; if (written > sec) written = sec; } for (; i; i = inip->slots[i].chain) { slotp = inip->slots + i; /* Transients are skipped with whole subtrees */ if (slotp->flags & INI_TEMP) continue; /* Variables first, subsections second */ if ((slotp->type < 0) ^ var) continue; if (var) /* Section */ { sec = i; var = -1; break; } sv = slotp->value ? slotp->value : ""; /* Keys from system inifile ignore defaults, because * they exist to override the defaults - WJ */ if (!(slotp->flags & INI_SYSTEM) && (slotp->flags & INI_DEFAULT) && (slotp->type == INI_STR ? !strcmp(slotp->defv, sv) : (slotp->type == INI_INT) || (slotp->type == INI_REF) ? (int)slotp->value == (int)slotp->defv : slotp->type == INI_BOOL ? !!slotp->value == !!slotp->defv : FALSE)) continue; /* Write out sections */ up = 0; while (written < sec) // Reverse chain to written level { down = inip->slots[sec].sec; inip->slots[sec].sec = up; up = sec; sec = down; } while (up) // Write out reversing back { down = sec; written = sec = up; secp = inip->slots + sec; up = secp->sec; secp->sec = down; fputc('[', fp); for (j = -1; j > secp->type; j--) fputc('>', fp); fprintf(fp, "%s]\n", secp->key); } /* Write out variable */ name = slotp->key; switch (slotp->type) { case INI_REF: fprintf(fp, "%s == ", name); j = (int)slotp->value; up = 0; while (j > 0) // Reverse chain to level 0 { down = inip->slots[j].sec; inip->slots[j].sec = up; up = j; j = down; } while (up) // Write out reversing back { down = j; j = up; secp = inip->slots + j; up = secp->sec; secp->sec = down; xv = escape_string(secp->key, TRUE); fprintf(fp, "%s%s", xv ? xv : secp->key, up ? "\\n" : ""); free(xv); } fputc('\n', fp); break; case INI_INT: fprintf(fp, "%s = %d\n", name, (int)slotp->value); break; case INI_BOOL: fprintf(fp, "%s = %s\n", name, slotp->value ? "true" : "false"); break; default: /* Escape value if needed */ if ((xv = escape_string(sv, FALSE))) { fprintf(fp, "%s == %s\n", name, xv); free(xv); } else fprintf(fp, "%s = %s\n", name, sv); break; } } } /* Return to main section if have sections */ if (secp) fputs("[]\n", fp); fclose(fp); return (TRUE); } int ini_setstr(inifile *inip, int section, char *key, char *value) { inislot *slot; /* NULLs are stored as empty strings, for less hazardous handling. * Value duplicated at once, for key_slot() might free it * (if it is the current one, being stored over itself) */ value = value && *value ? strdup(value) : NULL; if (!(slot = key_slot(inip, section, key, INI_STR))) { free(value); return (0); } slot->value = ""; if (value) { slot->value = value; slot->flags |= INI_MALLOC; } return (slot - inip->slots); } int ini_setint(inifile *inip, int section, char *key, int value) { inislot *slot; if (!(slot = key_slot(inip, section, key, INI_INT))) return (0); slot->value = (char *)value; return (slot - inip->slots); } int ini_setbool(inifile *inip, int section, char *key, int value) { inislot *slot; if (!(slot = key_slot(inip, section, key, INI_BOOL))) return (0); slot->value = (char *)!!value; return (slot - inip->slots); } int ini_setref(inifile *inip, int section, char *key, int value) { inislot *slot; if (!(slot = key_slot(inip, section, key, INI_REF))) return (0); slot->value = (char *)value; return (slot - inip->slots); } char *ini_getstr(inifile *inip, int section, char *key, char *defv) { inislot *slot; /* NULLs are stored as empty strings, for less hazardous handling */ if (!defv) defv = ""; /* Read existing */ slot = key_slot(inip, section, key, INI_NONE); if (!slot) return (defv); if (slot->type == INI_STR) { #if VALIDATE_DEF if ((slot->flags & INI_DEFAULT) && strcmp(defv ? defv : "", slot->defv)) g_warning("INI key '%s' new default\n", key); #endif if (slot->flags & INI_DEFAULT) return (slot->value); slot->type = INI_UNDEF; /* Fall through to storing default */ } /* Store default */ slot->flags &= ~INI_DEFAULT; if ((slot->defv = store_string(inip, defv))) slot->flags |= INI_DEFAULT; if (slot->type != INI_UNDEF) { #if VALIDATE_TYPE if (slot->type != INI_NONE) g_printerr("INI key '%s' wrong type\n", key); #endif if (!defv) slot->value = NULL; else if (!*defv) slot->value = ""; else { slot->value = strdup(defv); if (slot->value) slot->flags |= INI_MALLOC; } } slot->type = INI_STR; return (slot->value); } int ini_getint(inifile *inip, int section, char *key, int defv) { inislot *slot; char *tail; long l; /* Read existing */ slot = key_slot(inip, section, key, INI_NONE); if (!slot) return (defv); if (slot->type == INI_INT) { #if VALIDATE_DEF if ((slot->flags & INI_DEFAULT) && ((char *)defv != slot->defv)) g_warning("INI key '%s' new default\n", key); #endif if (slot->flags & INI_DEFAULT) return ((int)(slot->value)); /* Fall through to storing default */ } /* Store default */ slot->defv = (char *)defv; slot->flags |= INI_DEFAULT; while (slot->type != INI_INT) { if (slot->type == INI_UNDEF) { l = strtol(slot->value, &tail, 10); slot->value = (char *)l; if (!*tail) break; } else if (slot->flags & INI_MALLOC) { free(slot->value); slot->flags ^= INI_MALLOC; } #if VALIDATE_TYPE if (slot->type != INI_NONE) g_printerr("INI key '%s' wrong type\n", key); #endif slot->value = (char *)defv; break; } slot->type = INI_INT; return ((int)(slot->value)); } int str2bool(const char *s) { static const char *YN[] = { "n", "y", "0", "1", "no", "yes", "off", "on", "false", "true", "disabled", "enabled", NULL }; int i; for (i = 0; YN[i]; i++) if (!strcasecmp(YN[i], s)) return (i & 1); return (-1); } int ini_getbool(inifile *inip, int section, char *key, int defv) { inislot *slot; int i; defv = !!defv; /* Read existing */ slot = key_slot(inip, section, key, INI_NONE); if (!slot) return (defv); if (slot->type == INI_BOOL) { #if VALIDATE_DEF if ((slot->flags & INI_DEFAULT) && ((char *)defv != slot->defv)) g_warning("INI key '%s' new default\n", key); #endif if (slot->flags & INI_DEFAULT) return ((int)(slot->value)); /* Fall through to storing default */ } /* Store default */ slot->defv = (char *)defv; slot->flags |= INI_DEFAULT; while (slot->type != INI_BOOL) { if (slot->type == INI_UNDEF) { slot->value = (char *)(i = str2bool(slot->value)); if (i >= 0) break; } else if (slot->flags & INI_MALLOC) { free(slot->value); slot->flags ^= INI_MALLOC; } #if VALIDATE_TYPE if (slot->type != INI_NONE) g_printerr("INI key '%s' wrong type\n", key); #endif slot->value = (char *)defv; break; } slot->type = INI_BOOL; return ((int)(slot->value)); } int ini_getref(inifile *inip, int section, char *key, int defv) { inislot *slot; char *w, *tmp; /* Read existing */ slot = key_slot(inip, section, key, INI_NONE); if (!slot) return (defv); if (slot->type == INI_REF) { #if VALIDATE_DEF if ((slot->flags & INI_DEFAULT) && ((char *)defv != slot->defv)) g_warning("INI key '%s' new default\n", key); #endif if (slot->flags & INI_DEFAULT) return ((int)(slot->value)); /* Fall through to storing default */ } /* Store default */ slot->defv = (char *)defv; slot->flags |= INI_DEFAULT; while (slot->type != INI_REF) { if (slot->type == INI_UNDEF) { /* Parse a LF-separated path through sections */ section = 0; tmp = slot->value; while (tmp) { tmp = strchr(w = tmp, '\n'); if (tmp) { *tmp++ = '\0'; section = ini_getsection(inip, section, w); if (section <= 0) break; } else if (*w) { inislot *s = cuckoo_find(inip, section, w); section = s ? s - inip->slots : 0; } } /* Empty stays empty, broken goes to default */ if ((section <= 0) && slot->value[0]) section = defv; slot->value = (char *)section; break; } else if (slot->flags & INI_MALLOC) { free(slot->value); slot->flags ^= INI_MALLOC; } #if VALIDATE_TYPE if (slot->type != INI_NONE) g_printerr("INI key '%s' wrong type\n", key); #endif slot->value = (char *)defv; break; } slot->type = INI_REF; return ((int)(slot->value)); } int ini_setsection(inifile *inip, int section, char *key) { inislot *slot = key_slot(inip, section, key, -1); if (!slot) return (-1); return (slot - inip->slots); } int ini_getsection(inifile *inip, int section, char *key) { inislot *slot = cuckoo_find(inip, section, key); if (!slot || (slot->type != inip->slots[section].type - 1)) return (-1); return (slot - inip->slots); } int ini_transient(inifile *inip, int section, char *key) { inislot *slot = key ? cuckoo_find(inip, section, key) : section ? inip->slots + section : NULL; if (!slot) return (FALSE); slot->flags |= INI_TEMP; return (TRUE); } #ifdef WIN32 char *get_home_directory(void) { static char *homedir = NULL; if (homedir) return homedir; homedir = getenv("USERPROFILE"); // Gets the current users home directory in WinXP if (!homedir) homedir = ""; // And this, in Win9x :-) return homedir; } char *extend_path(const char *path) { char *dir, *name; if (path[0] == '~') return (g_strdup_printf("%s%s", get_home_directory(), path + 1)); if (path[0] && (path[1] == ':')) // Path w/drive letter is absolute return (g_strdup(path)); name = g_win32_get_package_installation_directory(NULL, NULL); dir = g_locale_from_utf8(name, -1, NULL, NULL, NULL); g_free(name); name = g_strdup_printf("%s%s", dir, path); g_free(dir); return (name); } #else #include #include /* * This function came from mhWaveEdit * by Magnus Hjorth, 2003. */ gchar *get_home_directory(void) { static char *homedir = NULL; struct passwd *p; if (homedir) return homedir; homedir = getenv("HOME"); if (!homedir) { p = getpwuid(getuid()); if (p) homedir = p->pw_dir; } if (!homedir) { g_warning(_("Could not find home directory. Using current directory as " "home directory.")); homedir = "."; } return homedir; } char *extend_path(const char *path) { if (path[0] == '~') return (g_strdup_printf("%s%s", get_home_directory(), path + 1)); return (g_strdup(path)); } #endif /* Compatibility functions */ inifile main_ini; static char *main_ininame; void inifile_init(char *system_ini, char *user_ini) { char *tmp, *ini = user_ini; int res, mask = 3; while (new_ini(&main_ini)) { if ((mask & 1) && system_ini) { tmp = extend_path(system_ini); res = read_ini(&main_ini, tmp, INI_SYSTEM); g_free(tmp); if (res <= 0) mask ^= 1; // Don't try again if failed if (res < 0) continue; // Restart if struct got deleted /* !!! Allow system inifile to relocate user inifile */ ini = inifile_get("userINI", user_ini); if (!ini[0]) ini = system_ini; } if ((mask & 2) && user_ini) { main_ininame = extend_path(ini); res = read_ini(&main_ini, main_ininame, 0); if (res <= 0) // Failed { mask ^= 2; if (res < 0) continue; } } break; } } void inifile_quit() { write_ini(&main_ini, main_ininame, "# Remove this file to restore default settings.\n"); forget_ini(&main_ini); g_free(main_ininame); } char *inifile_get(char *setting, char *defaultValue) { return (ini_getstr(&main_ini, 0, setting, defaultValue)); } int inifile_get_gint32(char *setting, int defaultValue) { return (ini_getint(&main_ini, 0, setting, defaultValue)); } int inifile_get_gboolean(char *setting, int defaultValue) { return (ini_getbool(&main_ini, 0, setting, defaultValue)); } int inifile_set(char *setting, char *value) { return (ini_setstr(&main_ini, 0, setting, value)); } int inifile_set_gint32(char *setting, int value) { return (ini_setint(&main_ini, 0, setting, value)); } int inifile_set_gboolean(char *setting, int value) { return (ini_setbool(&main_ini, 0, setting, value)); } mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/inifile.h000066400000000000000000000053311471325446300225340ustar00rootroot00000000000000/* inifile.h Copyright (C) 2007-2019 Dmitry Groshev This file is part of mtPaint. mtPaint 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. mtPaint 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 mtPaint in the file COPYING. */ typedef struct { char *key, *value, *defv; int sec, chain; short type, flags; } inislot; typedef struct { char *sblocks; inislot *slots; gint32 *hash; int count, slen, maxloop; guint32 hmask, seed[2]; } inifile; /* Access macros */ #define INI_KEY(P,N) ((P)->slots[(N)].key) #define INI_VALUE(P,N) ((P)->slots[(N)].value) #define INI_PARENT(P,N) ((P)->slots[(N)].sec) /* Iterator macros */ #define INI_FIRST(P,N) ((int)(P)->slots[(N)].defv) #define INI_NEXT(P,N) ((P)->slots[(N)].chain) /* Core functions */ int new_ini(inifile *inip); void forget_ini(inifile *inip); int read_ini(inifile *inip, char *fname, int itype); int write_ini(inifile *inip, char *fname, char *header); int ini_setstr(inifile *inip, int section, char *key, char *value); int ini_setint(inifile *inip, int section, char *key, int value); int ini_setbool(inifile *inip, int section, char *key, int value); int ini_setref(inifile *inip, int section, char *key, int value); char *ini_getstr(inifile *inip, int section, char *key, char *defv); int ini_getint(inifile *inip, int section, char *key, int defv); int ini_getbool(inifile *inip, int section, char *key, int defv); int ini_getref(inifile *inip, int section, char *key, int defv); int ini_setsection(inifile *inip, int section, char *key); int ini_getsection(inifile *inip, int section, char *key); int ini_transient(inifile *inip, int section, char *key); /* File functions */ char *slurp_file_l(char *fname, int before, int *len); #define slurp_file(A,B) slurp_file_l((A), (B), NULL) char *get_home_directory(void); char *extend_path(const char *path); /* Helper functions */ int str2bool(const char *s); /* Compatibility functions */ inifile main_ini; void inifile_init(char *system_ini, char *user_ini); void inifile_quit(); char *inifile_get(char *setting, char *defaultValue); int inifile_get_gint32(char *setting, int defaultValue); int inifile_get_gboolean(char *setting, int defaultValue); int inifile_set(char *setting, char *value); int inifile_set_gint32(char *setting, int value); int inifile_set_gboolean(char *setting, int value); mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/layer.c000066400000000000000000000725151471325446300222340ustar00rootroot00000000000000/* layer.c Copyright (C) 2005-2024 Mark Tyler and Dmitry Groshev This file is part of mtPaint. mtPaint 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. mtPaint 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 mtPaint in the file COPYING. */ #include "global.h" #undef _ #define _(X) X #include "mygtk.h" #include "memory.h" #include "vcode.h" #include "ani.h" #include "png.h" #include "layer.h" #include "mainwindow.h" #include "otherwindow.h" #include "canvas.h" #include "inifile.h" #include "viewer.h" #include "channels.h" #include "icons.h" int layers_total, // Layers currently being used layer_selected, // Layer currently selected in the layers window layers_changed; // 0=Unchanged char layers_filename[PATHBUF]; // Current filename for layers file int show_layers_main, // Show all layers in main window layer_overlay; // Toggle overlays per layer // !!! Always follow adding/changing layer's image_info by update_undo() layer_node layer_table[(MAX_LAYERS + 1) * 2]; // Table of layer info & its backup layer_node *layer_table_p = layer_table; // Unmodified layer table static void layer_clear_slot(int l, int visible) { memset(layer_table + l, 0, sizeof(layer_node)); layer_table[l].opacity = 100; layer_table[l].visible = visible; } void layers_init() { layer_clear_slot(0, TRUE); strncpy0(layer_table[0].name, __("Background"), LAYER_NAMELEN); layer_table[0].image = calloc(1, sizeof(layer_image)); } /* Allocate layer image, its channels and undo stack * !!! Must be followed by update_undo() after setting up image is done */ layer_image *alloc_layer(int w, int h, int bpp, int cmask, image_info *src) { layer_image *lim; lim = calloc(1, sizeof(layer_image)); if (!lim) return (NULL); if (init_undo(&lim->image_.undo_, mem_undo_depth) && mem_alloc_image(src ? AI_COPY : 0, &lim->image_, w, h, bpp, cmask, src)) return (lim); mem_free_image(&lim->image_, FREE_UNDO); free(lim); return (NULL); } /* Repaint layer in view/main window */ static void repaint_layer(int l) { image_info *image = l == layer_selected ? &mem_image : &layer_table[l].image->image_; lr_update_area(l, 0, 0, image->width, image->height); } static void repaint_layers() { update_stuff(show_layers_main ? UPD_ALLV : UPD_VIEW); } /// LAYERS WINDOW typedef struct { int lock; int x, y, opacity, trans; int nlayer, lnum; int vis; char *lname; void **llist, **nmentry, **xspin, **yspin, **opslider, **trspin; void **ltb_new, **ltb_raise, **ltb_lower, **ltb_dup, **ltb_center, **ltb_del, **ltb_close; } layers_dd; static void **layers_box_, **layers_window_; static void layers_update_titlebar() // Update filename in titlebar { char txt[300], txt2[PATHTXT]; if (!layers_window_) return; // Don't bother if window is not showing gtkuncpy(txt2, layers_filename, PATHTXT); snprintf(txt, 290, "%s %s %s", __("Layers"), layers_changed ? __("(Modified)") : "-", txt2[0] ? txt2 : __("Untitled")); cmd_setv(GET_WINDOW(layers_window_), txt, WINDOW_TITLE); } void layers_notify_changed() // Layers have just changed - update vars as needed { if ( layers_changed != 1 ) { layers_changed = 1; layers_update_titlebar(); } } static void layers_notify_unchanged() // Layers have just been unchanged (saved) - update vars as needed { if ( layers_changed != 0 ) { layers_changed = 0; layers_update_titlebar(); } } void layer_copy_from_main( int l ) // Copy info from main image to layer { layer_image *lp = layer_table[l].image; lp->image_ = mem_image; lp->state_ = mem_state; lp->image_.undo_.size = 0; // Invalidate update_undo(&lp->image_); // Safety net } void layer_copy_to_main( int l ) // Copy info from layer to main image { layer_image *lp = layer_table[l].image; if (!layer_overlay) { lp->state_.iover = mem_state.iover; lp->state_.aover = mem_state.aover; } mem_image = lp->image_; mem_state = lp->state_; } void shift_layer(int val) { layers_dd *dt = GET_DDATA(layers_box_); layer_node temp; int newbkg, lv = layer_selected + val; if ((lv < 0) || (lv > layers_total)) return; // Cannot move /* Update source layer */ if ((blend_src == SRC_LAYER + layer_selected) || (blend_src == SRC_LAYER + lv)) blend_src ^= (SRC_LAYER + layer_selected) ^ (SRC_LAYER + lv); layer_copy_from_main(layer_selected); temp = layer_table[layer_selected]; layer_table[layer_selected] = layer_table[lv]; layer_table[lv] = temp; newbkg = (layer_selected == 0) || (lv == 0); cmd_setv(dt->llist, (void *)layer_selected, LISTCC_RESET_ROW); cmd_setv(dt->llist, (void *)lv, LISTCC_RESET_ROW); cmd_set(dt->llist, layer_selected = lv); layers_notify_changed(); if (newbkg) // Background layer changed { vw_realign(); repaint_layers(); } else repaint_layer(layer_selected); // Regular layer shifted } void layer_show_new() { layer_refresh_list(layers_total); layers_notify_changed(); } int layer_add(int w, int h, int bpp, int cols, png_color *pal, int cmask) { layer_image *lim; if (layers_total >= MAX_LAYERS) return (FALSE); lim = alloc_layer(w, h, bpp, cmask, NULL); if (!lim) { memory_errors(1); return (FALSE); } lim->state_.xbm_hot_x = lim->state_.xbm_hot_y = -1; lim->state_.channel = lim->image_.img[mem_channel] ? mem_channel : CHN_IMAGE; lim->image_.trans = -1; lim->image_.cols = cols; if (pal) mem_pal_copy(lim->image_.pal, pal); else mem_bw_pal(lim->image_.pal, 0, cols - 1); init_istate(&lim->state_, &lim->image_); update_undo(&lim->image_); layers_total++; layer_clear_slot(layers_total, TRUE); layer_table[layers_total].image = lim; /* Start with fresh animation data if new */ if (layers_total == 1) ani_init(); return (TRUE); } void layer_new(int w, int h, int bpp, int cols, png_color *pal, int cmask) { if (layer_add(w, h, bpp, cols, pal, cmask)) layer_show_new(); } /* !!! Same as above: modify structures, *then* show results - WJ */ void layer_press_duplicate() { layer_image *lim, *ls; if (layers_total >= MAX_LAYERS) return; lim = alloc_layer(0, 0, 0, 0, &mem_image); if (!lim) { memory_errors(1); return; } // Copy layer info layer_copy_from_main(layer_selected); layers_total++; layer_table[layers_total] = layer_table[layer_selected]; layer_table[layers_total].image = lim; ls = layer_table[layer_selected].image; lim->state_ = ls->state_; mem_pal_copy(lim->image_.pal, ls->image_.pal); lim->image_.cols = ls->image_.cols; lim->image_.trans = ls->image_.trans; update_undo(&lim->image_); // Copy across position data lim->ani_ = ls->ani_; layer_show_new(); } void layer_delete(int item) { layer_image *lp = layer_table[item].image; int i; mem_free_image(&lp->image_, FREE_ALL); free(lp); // If deleted item is not at the end shuffle rest down for (i = item; i < layers_total; i++) layer_table[i] = layer_table[i + 1]; memset(layer_table + layers_total, 0, sizeof(layer_node)); layers_total--; } void layer_refresh_list(int slot) { layers_dd *dt = GET_DDATA(layers_box_); dt->nlayer = slot; dt->lnum = layers_total + 1; cmd_reset(dt->llist, dt); cmd_set(dt->llist, slot); // !!! For the rest of updates } void layer_press_delete() { char txt[256]; int i; if (!layer_selected) return; // Deleting background is forbidden snprintf(txt, 256, __("Do you really want to delete layer %i (%s) ?"), layer_selected, layer_table[layer_selected].name ); i = alert_box(_("Warning"), txt, _("No"), _("Yes"), NULL); if ((i != 2) || (check_for_changes() == 1)) return; if (blend_src == SRC_LAYER + layer_selected) blend_src = SRC_NORMAL; layer_copy_from_main(layer_selected); layer_copy_to_main(--layer_selected); update_main_with_new_layer(); layer_delete(layer_selected + 1); layer_refresh_list(layer_selected); layers_notify_changed(); } static void layer_show_position() { layers_dd *dt = GET_DDATA(layers_box_); layer_node *t = layer_table + layer_selected; dt->lock++; cmd_set(dt->xspin, t->x); cmd_set(dt->yspin, t->y); dt->lock--; } void layer_show_trans() { layers_dd *dt = GET_DDATA(layers_box_); if (dt->trans != mem_xpm_trans) { dt->lock++; cmd_set(dt->trspin, mem_xpm_trans); dt->lock--; } } void layer_press_centre() { if (!layer_selected) return; // Nothing to do layer_table[layer_selected].x = layer_table[0].x + layer_table[0].image->image_.width / 2 - mem_width / 2; layer_table[layer_selected].y = layer_table[0].y + layer_table[0].image->image_.height / 2 - mem_height / 2; layer_show_position(); layers_notify_changed(); repaint_layers(); } /* Return 1 if some layers are modified, 2 if some are nameless, 3 if both, * 0 if neither */ static int layers_changed_tot() { image_info *image; int j, k; for (j = k = 0; k <= layers_total; k++) // Check each layer for mem_changed { image = k == layer_selected ? &mem_image : &layer_table[k].image->image_; j |= !!image->changed + !image->filename * 2; } return (j); } int check_layers_for_changes() // 1=STOP, 2=IGNORE, -10=NOT CHANGED { if (!(layers_changed_tot() + layers_changed)) return (-10); return (alert_box(_("Warning"), _("One or more of the layers contains changes that have not been saved. Do you really want to lose these changes?"), _("Cancel Operation"), _("Lose Changes"), NULL)); } static void layer_update_filename( char *name ) { strncpy(layers_filename, name, PATHBUF); layers_changed = 1; // Forces update of titlebar layers_notify_unchanged(); } static void layers_free_all() { layer_node *t; if (blend_src > SRC_LAYER + 0) blend_src = SRC_NORMAL; if (layers_total && layer_selected) // Copy over layer 0 { layer_copy_from_main(layer_selected); layer_copy_to_main(0); layer_selected = 0; } for (t = layer_table + layers_total; t != layer_table; t--) { mem_free_image(&t->image->image_, FREE_ALL); free(t->image); } memset(layer_table + 1, 0, sizeof(layer_node) * MAX_LAYERS); layers_total = 0; layers_filename[0] = 0; layers_changed = 0; } void string_chop( char *txt ) { char *cp = txt + strlen(txt) - 1; // Chop off unwanted non ASCII characters at end while ((cp - txt >= 0) && ((unsigned char)*cp < 32)) *cp-- = 0; } int read_file_num(FILE *fp, char *txt) { int i; if (!fgets(txt, 32, fp)) return -987654321; sscanf(txt, "%i", &i); return i; } int load_layers( char *file_name ) { layer_node *t; layer_image *lim2; char tin[300], load_name[PATHBUF], *c; int i, j, k, kk; int layers_to_read = -1, /*layer_file_version = -1,*/ lfail = 0, lplen = 0; FILE *fp; c = strrchr(file_name, DIR_SEP); if (c) lplen = c - file_name + 1; // Try to save text file, return -1 if failure if ((fp = fopen(file_name, "r")) == NULL) goto fail; if (!fgets(tin, 32, fp)) goto fail2; string_chop( tin ); if ( strcmp( tin, LAYERS_HEADER ) != 0 ) goto fail2; // Bad header i = read_file_num(fp, tin); if ( i==-987654321 ) goto fail2; // layer_file_version = i; if ( i>LAYERS_VERSION ) goto fail2; // Version number must be compatible i = read_file_num(fp, tin); if ( i==-987654321 ) goto fail2; layers_to_read = i < MAX_LAYERS ? i : MAX_LAYERS; /* !!! Can use lock field instead, but this is the original way */ cmd_sensitive(GET_WINDOW(layers_box_), FALSE); if (layers_total) layers_free_all(); // Remove all current layers if any for ( i=0; i<=layers_to_read; i++ ) { // Read filename, strip end chars & try to load (if name length > 0) fgets(tin, 256, fp); string_chop(tin); wjstrcat(load_name, PATHBUF, file_name, lplen, tin, NULL); k = 1; j = detect_image_format(load_name); if ((j > 0) && (j != FT_NONE) && (j != FT_LAYERS1)) k = load_image(load_name, FS_LAYER_LOAD, j) != 1; if (k) /* Failure - skip this layer */ { for ( j=0; j<7; j++ ) read_file_num(fp, tin); lfail++; continue; } /* Update image variables after load */ t = layer_table + layers_total; lim2 = t->image; // !!! No old name so no fuss with saving it lim2->image_.filename = strdup(load_name); fgets(tin, 256, fp); string_chop(tin); strncpy0(t->name, tin, LAYER_NAMELEN); k = read_file_num(fp, tin); t->visible = k > 0; t->x = read_file_num(fp, tin); t->y = read_file_num(fp, tin); kk = read_file_num(fp, tin); k = read_file_num(fp, tin); lim2->image_.trans = kk <= 0 ? -1 : k < 0 ? 0 : k > 255 ? 255 : k; k = read_file_num(fp, tin); t->opacity = k < 1 ? 1 : k > 100 ? 100 : k; init_istate(&lim2->state_, &lim2->image_); if (!layers_total++) layer_copy_to_main(0); // Update mem_state } if (layers_total) layers_total--; /* Read in animation data - only if all layers loaded OK * (to do otherwise is likely to result in SIGSEGV) */ if (!lfail) ani_read_file(fp); fclose(fp); layer_refresh_list(layers_total); cmd_sensitive(GET_WINDOW(layers_box_), TRUE); layer_update_filename( file_name ); if (lfail) /* There were failures */ { snprintf(tin, 300, __("%d layers failed to load"), lfail); alert_box(_("Error"), tin, NULL); } return 1; // Success fail2: fclose(fp); fail: return -1; } int load_to_layers(char *file_name, int ftype, int ani_mode) { char tail[32], *buf; image_frame *frm; image_info *image; image_state *state; layer_node *t; layer_image *lim; frameset fset; int anim = ani_mode > ANM_PAGE; int i, j, l, res, res0; /* !!! Can use lock field instead, but this is the original way */ cmd_sensitive(GET_WINDOW(layers_box_), FALSE); /* Remove old layers, load new frames */ if (layers_total) layers_free_all(); // Remove all current layers res = res0 = load_frameset(&fset, ani_mode, file_name, FS_LAYER_LOAD, ftype); if (!fset.cnt) /* Failure - we have no image */ { if (res == FILE_LIB_ERROR) res = -1; // Failure is complete } else /* Got some frames - convert into layers */ { l = 0; // Start from layer 0 if (anim) /* Animation */ { int x0, y0, x1, y1, x, y; frm = fset.frames; /* Calculate a bounding box for the anim */ x1 = (x0 = frm->x) + frm->width; y1 = (y0 = frm->y) + frm->height; for (i = 1; i < fset.cnt; i++) { frm++; x = frm->x; if (x0 > x) x0 = x; x += frm->width; if (x1 < x) x1 = x; y = frm->y; if (y0 > y) y0 = y; y += frm->height; if (y1 < y) y1 = y; } /* Create an empty indexed background of that size */ do_new_one(x1 - x0, y1 - y0, 256, mem_pal_def, 1, FALSE); /* Remember the offsets */ layer_table[0].x = x0; layer_table[0].y = y0; l = 1; // Frames start from layer 1 } for (i = 0; i < fset.cnt; i++ , l++) { frm = fset.frames + i; t = layer_table + l; res = FILE_MEM_ERROR; if (!l) // Layer 0 aka current image { if (mem_new(frm->width, frm->height, frm->bpp, 0)) break; layer_copy_from_main(0); } else { if (!(t->image = alloc_layer(frm->width, frm->height, frm->bpp, 0, NULL))) break; } res = res0; lim = t->image; t->visible = !anim; t->opacity = 100; image = &lim->image_; state = &lim->state_; /* Move frame data to image */ memcpy(image->img, frm->img, sizeof(chanlist)); memset(frm->img, 0, sizeof(chanlist)); image->trans = frm->trans; mem_pal_copy(image->pal, frm->pal ? frm->pal : fset.pal ? fset.pal : mem_pal_def); image->cols = frm->cols; t->x = frm->x; t->y = frm->y; update_undo(image); /* Create a name for this frame */ sprintf(tail, ".%03d", i); // !!! No old name so no fuss with saving it image->filename = tailed_name(NULL, file_name, tail, PATHBUF); init_istate(state, image); if (!l) layer_copy_to_main(0); // Update everything } layers_total = l ? l - 1 : 0; if (anim) { // !!! These legacy things need be replaced by a per-layer field preserved_gif_delay = ani_gif_delay = fset.frames[0].delay; /* Clear stale cycles */ memset(ani_cycle_table, 0, sizeof(ani_cycle_table)); /* Build animation cycle for these layers */ ani_frame1 = ani_cycle_table[0].frame0 = 1; ani_frame2 = ani_cycle_table[0].frame1 = l - 1; ani_cycle_table[0].len = l - 1; for (j = 1; j < l; j++) { unsigned char *cp = layer_table[j].image->ani_.cycles; cp[0] = 1; // Cycle # + 1 cp[1] = j - 1; // Position } /* Display 1st layer in sequence */ layer_table[1].visible = TRUE; layer_copy_from_main(0); layer_copy_to_main(layer_selected = 1); } update_main_with_new_layer(); } mem_free_frames(&fset); layer_refresh_list(layer_selected); cmd_sensitive(GET_WINDOW(layers_box_), TRUE); /* Name change so that layers file would not overwrite the source */ buf = tailed_name(NULL, file_name, ".txt", PATHBUF); layer_update_filename(buf); free(buf); return (res); } /* Convert absolute filename 'file' into one relative to prefix */ static void parse_filename(char *dest, char *prefix, char *file, int len) { int i, k; /* # of chars that match at start */ for (i = 0; (i < len) && (prefix[i] == file[i]); i++); if (!i || (i == len)) /* Complete match, or no match at all */ strncpy(dest, file + i, PATHBUF); else /* Partial match */ { dest[0] = 0; /* Count number of DIR_SEP encountered on and after point i in * 'prefix', add a '../' for each found */ for (k = i; k < len; k++) { if (prefix[k] == DIR_SEP) strnncat(dest, ".." DIR_SEP_STR, PATHBUF); } /* nip backwards on 'file' from i to previous DIR_SEP or * beginning and ... */ for (k = i; (k >= 0) && (file[k] != DIR_SEP); k--); /* ... add rest of 'file' */ strnncat(dest, file + k + 1, PATHBUF); } } int layer_save_composite(char *fname, ls_settings *settings) { image_info *image; unsigned char *layer_rgb; int w, h, res = 0, tf = comp_need_alpha(settings->ftype); image = layer_selected ? &layer_table[0].image->image_ : &mem_image; w = image->width; h = image->height; layer_rgb = calloc(1, w * h * (3 + !!tf)); if (layer_rgb) { view_render_rgb(layer_rgb, 0, 0, w, h, 1); // Render layer if (tf) { unsigned char *alpha = layer_rgb + w * h * 3; collect_alpha(alpha, w, h); mem_demultiply(layer_rgb, alpha, w * h, 3); settings->img[CHN_ALPHA] = alpha; } settings->img[CHN_IMAGE] = layer_rgb; settings->width = w; settings->height = h; settings->bpp = 3; if (layers_total) /* Remember global offset */ { settings->x = layer_table[0].x; settings->y = layer_table[0].y; } /* Set up palette to go with transparency */ if (settings->xpm_trans >= 0) { settings->pal = image->pal; settings->colors = image->cols; } res = save_image(fname, settings); free( layer_rgb ); } else memory_errors(1); return res; } void layer_add_composite() { layer_image *lim; image_info *image = layer_selected ? &layer_table[0].image->image_ : &mem_image; unsigned char **img; int w = image->width, h = image->height; if (layers_total >= MAX_LAYERS) return; if (layer_add(w, h, 3, image->cols, image->pal, comp_need_alpha(FT_NONE) ? CMASK_RGBA : CMASK_IMAGE)) { /* Render to an invisible layer */ layer_table[layers_total].visible = FALSE; lim = layer_table[layers_total].image; img = lim->image_.img; view_render_rgb(img[CHN_IMAGE], 0, 0, w, h, 1); /* Add alpha if wanted */ if (img[CHN_ALPHA]) { collect_alpha(img[CHN_ALPHA], w, h); mem_demultiply(img[CHN_IMAGE], img[CHN_ALPHA], w * h, 3); } /* Copy background's transparency and position */ lim->image_.trans = image->trans; layer_table[layers_total].x = layer_table[0].x; layer_table[layers_total].y = layer_table[0].y; /* Activate the result */ layer_show_new(); } else memory_errors(1); } int save_layers( char *file_name ) { layer_node *t; char comp_name[PATHBUF], *c, *msg; int i, l = 0, xpm; FILE *fp; layer_copy_from_main(layer_selected); c = strrchr(file_name, DIR_SEP); if (c) l = c - file_name + 1; // Try to save text file, return -1 if failure if ((fp = fopen(file_name, "w")) == NULL) goto fail; fprintf( fp, "%s\n%i\n%i\n", LAYERS_HEADER, LAYERS_VERSION, layers_total ); for ( i=0; i<=layers_total; i++ ) { t = layer_table + i; parse_filename(comp_name, file_name, t->image->image_.filename, l); fprintf( fp, "%s\n", comp_name ); xpm = t->image->image_.trans; fprintf(fp, "%s\n%i\n%i\n%i\n%i\n%i\n%i\n", t->name, t->visible, t->x, t->y, xpm >= 0, xpm, t->opacity); } ani_write_file(fp); // Write animation data fclose(fp); layer_update_filename( file_name ); register_file( file_name ); // Recently used file list / last directory return 1; // Success fail: c = gtkuncpy(NULL, layers_filename, 0); msg = g_strdup_printf(__("Unable to save file: %s"), c); alert_box(_("Error"), msg, NULL); g_free(msg); g_free(c); return -1; } int check_layers_all_saved() { if (layers_changed_tot() < 2) return (0); alert_box(_("Warning"), _("One or more of the image layers has not been saved. You must save each image individually before saving the layers text file in order to load this composite image in the future."), NULL); return (1); } void layer_press_save() { if (!layers_filename[0]) file_selector(FS_LAYER_SAVE); else if (!check_layers_all_saved()) save_layers(layers_filename); } void layer_press_remove_all() { int i = check_layers_for_changes(); if (i < 0) i = alert_box(_("Warning"), _("Do you really want to delete all of the layers?"), _("No"), _("Yes"), NULL); if (i != 2) return; layers_free_all(); layer_refresh_list(0); update_main_with_new_layer(); } static void layer_tog_visible(layers_dd *dt, void **wdata, int what, void **where, void *xdata) { /* !!! Column is self-reading */ if (dt->lock) return; layers_notify_changed(); repaint_layer((int)xdata); // !!! row passed in there } static void layer_inputs_changed(layers_dd *dt, void **wdata, int what, void **where) { layer_node *t = layer_table + layer_selected; void *cause; int dx, dy; cause = cmd_read(where, dt); if (cause == &show_layers_main) { update_stuff(UPD_RENDER); return; } if (dt->lock) return; layers_notify_changed(); if (cause == &dt->lname) // Name entry { strncpy0(t->name, dt->lname, LAYER_NAMELEN); cmd_setv(dt->llist, (void *)layer_selected, LISTCC_RESET_ROW); } else if ((cause == &dt->x) || (cause == &dt->y)) // Position spin { dx = dt->x - t->x; dy = dt->y - t->y; if (dx | dy) move_layer_relative(layer_selected, dx, dy); } else if (cause == &dt->opacity) // Opacity slider { t->opacity = dt->opacity; repaint_layer(layer_selected); } else if (cause == &dt->vis) // Scripted visibility toggle { t->visible = dt->vis; cmd_setv(dt->llist, (void *)layer_selected, LISTCC_RESET_ROW); repaint_layer(layer_selected); } else /* if (cause == &dt->trans) */ // Transparency spin { mem_set_trans(dt->trans); } } void layer_choose(int l) // Select a new layer from the list { if ((l <= layers_total) && (l >= 0) && (l != layer_selected)) { layers_dd *dt = GET_DDATA(layers_box_); cmd_set(dt->llist, l); } } static void layer_select(layers_dd *dt, void **wdata, int what, void **where) { layer_node *t; int j; cmd_read(where, dt); if (dt->lock) return; // Paranoia j = dt->nlayer; if (j > layers_total) return; // Paranoia dt->lock++; if (j != layer_selected) /* Move data before doing anything else */ { layer_copy_from_main(layer_selected); layer_copy_to_main(layer_selected = j); update_main_with_new_layer(); } t = layer_table + j; cmd_setv(dt->nmentry, t->name, ENTRY_VALUE); cmd_sensitive(dt->ltb_raise, j < layers_total); cmd_sensitive(dt->ltb_lower, j); cmd_sensitive(dt->ltb_del, j); cmd_sensitive(dt->ltb_center, j); // Disable new/duplicate if we have max layers cmd_sensitive(dt->ltb_new, layers_total < MAX_LAYERS); cmd_sensitive(dt->ltb_dup, layers_total < MAX_LAYERS); cmd_set(dt->opslider, t->opacity); layer_show_position(); layer_show_trans(); dt->lock--; } void delete_layers_window() { void **wdata = layers_window_; // No deletion if no window if (!wdata) return; layers_window_ = NULL; cmd_set(menu_slots[MENU_LAYER], FALSE); // Ensure it's unchecked run_destroy(wdata); } void pressed_paste_layer() { layer_image *lim; unsigned char *dest; int i, j, k, chan = mem_channel, cmask = CMASK_IMAGE; if (layers_total >= MAX_LAYERS) { alert_box(_("Error"), _("You cannot add any more layers."), NULL); return; } /* No way to put RGB clipboard into utility channel */ if (mem_clip_bpp == 3) chan = CHN_IMAGE; if ((mem_clip_alpha || mem_clip_mask) && !channel_dis[CHN_ALPHA]) cmask = CMASK_RGBA; cmask |= CMASK_FOR(chan); if (!layer_add(mem_clip_w, mem_clip_h, mem_clip_bpp, mem_cols, mem_pal, cmask)) return; // Failed layer_table[layers_total].x = layer_table[layer_selected].x + mem_clip_x; layer_table[layers_total].y = layer_table[layer_selected].y + mem_clip_y; lim = layer_table[layers_total].image; lim->state_ = mem_state; lim->state_.channel = chan; j = mem_clip_w * mem_clip_h; memcpy(lim->image_.img[chan], mem_clipboard, j * mem_clip_bpp); /* Image channel with alpha */ dest = lim->image_.img[CHN_ALPHA]; if (dest && (chan == CHN_IMAGE)) { /* Fill alpha channel */ if (mem_clip_alpha) memcpy(dest, mem_clip_alpha, j); else memset(dest, 255, j); } /* Image channel with mask */ if (mem_clip_mask && (chan == CHN_IMAGE)) { /* Mask image - fill unselected part with color A */ dest = lim->image_.img[CHN_IMAGE]; k = mem_clip_bpp == 1 ? mem_col_A : mem_col_A24.red; for (i = 0; i < j; i++ , dest += mem_clip_bpp) { if (mem_clip_mask[i]) continue; dest[0] = k; if (mem_clip_bpp == 1) continue; dest[1] = mem_col_A24.green; dest[2] = mem_col_A24.blue; } } /* Utility channel with mask */ dest = lim->image_.img[CHN_ALPHA]; if (chan != CHN_IMAGE) dest = lim->image_.img[chan]; if (dest && mem_clip_mask) { /* Mask the channel */ for (i = 0; i < j; i++) { k = dest[i] * mem_clip_mask[i]; dest[i] = (k + (k >> 8) + 1) >> 8; } } set_new_filename(layers_total, NULL); layer_show_new(); view_show(); } /* Move a layer & update window labels */ void move_layer_relative(int l, int change_x, int change_y) { image_info *image = l == layer_selected ? &mem_image : &layer_table[l].image->image_; int upd = 0; layer_table[l].x += change_x; layer_table[l].y += change_y; layers_notify_changed(); if (l == layer_selected) { layer_show_position(); // All layers get moved while the current one stays still if (show_layers_main) upd |= UPD_RENDER; } // All layers get moved while the background stays still if (l == 0) upd |= UPD_VIEW; lr_update_area(l, change_x < 0 ? 0 : -change_x, change_y < 0 ? 0 : -change_y, image->width + abs(change_x), image->height + abs(change_y)); if (upd) update_stuff(upd); } static void layer_bar_click(layers_dd *dt, void **wdata, int what, void **where) { int act_m = TOOL_ID(where); action_dispatch(act_m >> 16, (act_m & 0xFFFF) - 0x8000, TRUE, FALSE); } #define WBbase layers_dd static void *layers_code[] = { TOPVBOX, SCRIPTED, BORDER(SCROLL, 0), BORDER(LISTCC, 0), XSCROLL(1, 1), // auto/auto WLIST, IDXCOLUMN(0, 1, 40, 1), // center XTXTCOLUMNv(layer_table[0].name, sizeof(layer_table[0]), 0, 0), // left CHKCOLUMNv(layer_table[0].visible, sizeof(layer_table[0]), 0, 0, layer_tog_visible), REF(llist), LISTCCHr(nlayer, lnum, MAX_LAYERS + 1, layer_select), TRIGGER, BORDER(TOOLBAR, 0), TOOLBAR(layer_bar_click), REF(ltb_new), TBBUTTON(_("New Layer"), XPM_ICON(new), ACTMOD(ACT_LR_ADD, LR_NEW)), REF(ltb_raise), TBBUTTON(_("Raise"), XPM_ICON(up), ACTMOD(ACT_LR_SHIFT, 1)), REF(ltb_lower), TBBUTTON(_("Lower"), XPM_ICON(down), ACTMOD(ACT_LR_SHIFT, -1)), REF(ltb_dup), TBBUTTON(_("Duplicate Layer"), XPM_ICON(copy), ACTMOD(ACT_LR_ADD, LR_DUP)), REF(ltb_center), TBBUTTON(_("Centralise Layer"), XPM_ICON(centre), ACTMOD(ACT_LR_CENTER, 0)), REF(ltb_del), TBBUTTON(_("Delete Layer"), XPM_ICON(cut), ACTMOD(ACT_LR_DEL, 0)), REF(ltb_close), TBBUTTON(_("Close Layers Window"), XPM_ICON(close), ACTMOD(DLG_LAYERS, 1)), UNNAME, WDONE, TABLEs(3, 4, 5), BORDER(LABEL, 0), BORDER(ENTRY, 0), BORDER(SPIN, 0), BORDER(SPINSLIDE, 0), TLABEL(_("Layer Name")), REF(nmentry), MINWIDTH(100), TLENTRY(lname, LAYER_NAMELEN - 1, 1, 0, 2), EVENT(CHANGE, layer_inputs_changed), TLABEL(_("Position")), REF(xspin), TLSPIN(x, -MAX_WIDTH, MAX_WIDTH, 1, 1), EVENT(CHANGE, layer_inputs_changed), OPNAME("X"), REF(yspin), TLSPIN(y, -MAX_HEIGHT, MAX_HEIGHT, 2, 1), EVENT(CHANGE, layer_inputs_changed), OPNAME("Y"), TLABEL(_("Opacity")), REF(opslider), TLSPINSLIDExl(opacity, 0, 100, 1, 2, 2), EVENT(CHANGE, layer_inputs_changed), TLLABELl(_("Transparent Colour"), 0, 3, 2), REF(trspin), TLSPIN(trans, -1, 255, 2, 3), EVENT(CHANGE, layer_inputs_changed), uCHECK("Visible", vis), EVENT(SCRIPT, layer_inputs_changed), WDONE, CHECKv(_("Show all layers in main window"), show_layers_main), EVENT(CHANGE, layer_inputs_changed), UNNAME, WEND }; #undef WBbase void **create_layers_box() { static char *noscript; layers_dd tdata; void **res; memset(&tdata, 0, sizeof(tdata)); tdata.nlayer = layer_selected; tdata.lnum = layers_total + 1; tdata.lname = ""; layers_box_ = res = run_create_(layers_code, &tdata, sizeof(tdata), cmd_mode ? &noscript : NULL); return (res); } static void *layersw_code[] = { WPWHEREVER, WINDOW(""), EVENT(CANCEL, delete_layers_window), WXYWH("layers", 400, 400), REMOUNTv(layers_dock), WSHOW }; void pressed_layers() { void **res; if (cmd_mode) return; if (layers_window_) return; // Already have it open layers_window_ = res = run_create(layersw_code, layersw_code, 0); layers_update_titlebar(); cmd_setv(GET_WINDOW(res), ((layers_dd *)GET_DDATA(layers_box_))->ltb_close, WINDOW_ESC_BTN); } mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/layer.h000066400000000000000000000063271471325446300222370ustar00rootroot00000000000000/* layer.h Copyright (C) 2005-2016 Mark Tyler and Dmitry Groshev This file is part of mtPaint. mtPaint 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. mtPaint 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 mtPaint in the file COPYING. */ #define MAX_LAYERS 100 #define LAYERS_HEADER "# mtPaint layers" #define LAYERS_VERSION 1 #define LAYER_NAMELEN 35 /// GLOBALS typedef struct { image_info image_; image_state state_; ani_info ani_; } layer_image; typedef struct { char name[LAYER_NAMELEN]; // Layer text name int x, y, opacity; // Position of layer, opacity % int visible; // Show layer layer_image *image; // Pointer to image data - malloc'd when created, free'd after } layer_node; layer_node layer_table[(MAX_LAYERS + 1) * 2]; // Table of layer info & its backup layer_node *layer_table_p; // Unmodified layer table int layers_total, // Layers currently in use layer_selected, // Layer currently selected in the layers window layers_changed; // 0=Unchanged char layers_filename[PATHBUF]; // Current filename for layers file int show_layers_main, // Show all layers in main window layer_overlay; // Toggle overlays per layer /// PROCEDURES void layers_init(); layer_image *alloc_layer(int w, int h, int bpp, int cmask, image_info *src); void pressed_layers(); void pressed_paste_layer(); void delete_layers_window(); void **create_layers_box(); int load_layers( char *file_name ); int save_layers( char *file_name ); void layer_press_save(); int layer_save_composite(char *fname, ls_settings *settings); int load_to_layers(char *file_name, int ftype, int ani_mode); #define update_main_with_new_layer() update_stuff(UPD_LAYER) void layers_notify_changed(); void layer_copy_from_main( int l ); // Copy info from main image to layer void layer_copy_to_main( int l ); // Copy info from layer to main image void layer_refresh_list(); void layer_press_remove_all(); int check_layers_for_changes(); int check_layers_all_saved(); void move_layer_relative(int l, int change_x, int change_y); // Move a layer & update window labels void layer_new(int w, int h, int bpp, int cols, png_color *pal, int cmask); // *Silently* add layer, return success int layer_add(int w, int h, int bpp, int cols, png_color *pal, int cmask); void layer_show_new(); // Show the last added layer void layer_delete(int item); // *Silently* delete layer void layer_choose( int l ); // Select a new layer from the list void layer_add_composite(); // Composite layers to new (invisible) layer void shift_layer(int val); // Move layer up or down void layer_press_duplicate(); void layer_press_centre(); // Center layer on background void layer_press_delete(); // Delete current layer void string_chop( char *txt ); int read_file_num(FILE *fp, char *txt); void layer_show_trans(); // Update transparency in layers window mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/main.c000066400000000000000000000360221471325446300220350ustar00rootroot00000000000000/* main.c Copyright (C) 2004-2021 Mark Tyler and Dmitry Groshev This file is part of mtPaint. mtPaint 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. mtPaint 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 mtPaint in the file COPYING. */ #include "global.h" #include "mygtk.h" #include "memory.h" #include "vcode.h" #include "ani.h" #include "png.h" #include "mainwindow.h" #include "otherwindow.h" #include "viewer.h" #include "inifile.h" #include "canvas.h" #include "layer.h" #include "prefs.h" #include "csel.h" #include "spawn.h" static int compare_names(const void *s1, const void *s2) { return (s1 == s2 ? 0 : strcoll(*(const char **)s1, *(const char **)s2)); } #ifndef WIN32 #include #define PATHC_TYPE size_t #else /* This is Windows only, as POSIX systems have glob() implemented */ /* Error returns from glob() */ #define GLOB_NOSPACE 1 /* No memory */ #define GLOB_NOMATCH 3 /* No files */ #define GLOB_APPEND 0x020 /* Append to existing array */ #define GLOB_MAGCHAR 0x100 /* Set if any wildcards in pattern */ typedef struct { int gl_pathc; char **gl_pathv; int gl_flags; } glob_t; #define PATHC_TYPE int static void globfree(glob_t *pglob) { int i; if (!pglob->gl_pathv) return; for (i = 0; i < pglob->gl_pathc; i++) free(pglob->gl_pathv[i]); free(pglob->gl_pathv); } typedef struct { DIR *dir; char *path, *mask; // Split up the string for them int lpath; } glob_dir_level; #define MAXDEPTH (PATHBUF / 2) /* A pattern with more cannot match anything */ static int split_pattern(glob_dir_level *dirs, char *pat) { char *tm2, *tmp, *lastpart; int ch, bracket = 0, cnt = 0; dirs[0].path = tmp = lastpart = pat; while (tmp) { if (cnt >= MAXDEPTH) return (0); tmp += strcspn(tmp, "?*[]"); ch = *tmp++; if (!ch) { dirs[cnt].path = lastpart; dirs[cnt++].mask = NULL; break; } if (ch == '[') bracket = TRUE; else if ((ch != ']') || bracket) { tmp = strchr(tmp, DIR_SEP); if (tmp) *tmp++ = '\0'; tm2 = strrchr(lastpart, DIR_SEP); /* 0th slot is special - path string is counted, * not terminated, and includes path separator */ if (!cnt) { if (!tm2) tm2 = strchr(lastpart, ':'); if (tm2) dirs[0].lpath = tm2 - lastpart + 1; } else if (tm2) dirs[cnt].path = lastpart; if (tm2) *tm2++ = '\0'; else tm2 = lastpart; dirs[cnt++].mask = tm2; lastpart = tmp; bracket = FALSE; } } return (cnt); } static int glob_add_file(glob_t *pglob, char *buf) { void *tmp; int l = pglob->gl_pathc; /* Use doubling array technique */ if (!pglob->gl_pathv || (((l + 1) & ~l) > l)) { tmp = realloc(pglob->gl_pathv, (l + 1) * 2 * sizeof(char *)); if (!tmp) return (-1); pglob->gl_pathv = tmp; } /* Add the name to array */ if (!(pglob->gl_pathv[l++] = strdup(buf))) return (-1); pglob->gl_pathv[pglob->gl_pathc = l] = NULL; return (0); } /* This implementation is strictly limited to mtPaint's needs, and tuned for * Win32 peculiarities; the only flag handled by it is GLOB_APPEND - WJ */ static int glob(const char *pattern, int flags, void *nothing, glob_t *pglob) { glob_dir_level dirs[MAXDEPTH + 1], *dp; struct dirent *ep; struct stat sbuf; char *pat, buf[PATHBUF]; int l, lv, maxdepth, prevcnt, memfail = 0; pglob->gl_flags = flags; if (!(flags & GLOB_APPEND)) { pglob->gl_pathc = 0; pglob->gl_pathv = NULL; } prevcnt = pglob->gl_pathc; /* Prepare the pattern */ if (!pattern[0]) return (GLOB_NOMATCH); pat = strdup(pattern); if (!pat) goto mfail; reseparate(pat); /* Split up the pattern */ memset(dirs, 0, sizeof(dirs)); if (!(maxdepth = split_pattern(dirs, pat))) { free(pat); return (GLOB_NOMATCH); } /* Scan through dir(s) */ maxdepth--; for (lv = 0; lv >= 0; ) { dp = dirs + lv--; // Step back a level in advance /* Start scanning directory */ if (!dp->dir) { l = dp->lpath; buf[l] = '\0'; if (lv < 0) memcpy(buf, dp->path, l); // Level 0 else if (!dp->path); // No extra path part else if (l + 1 + strlen(dp->path) >= PATHBUF) // Too long continue; else // Add path part { strcpy(buf + l + 1, dp->path); buf[l] = DIR_SEP; } dp->lpath = strlen(buf); if (!dp->mask) { if (!stat(buf, &sbuf)) memfail |= glob_add_file(pglob, buf); continue; } dp->dir = opendir(buf[0] ? buf : "."); if (!dp->dir) continue; } /* Finish scanning directory */ if (memfail || !(ep = readdir(dp->dir))) { closedir(dp->dir); dp->dir = NULL; continue; } lv++; // Undo step back /* Skip "." and ".." */ if (!strcmp(ep->d_name, ".") || !strcmp(ep->d_name, "..")) continue; /* Filter through mask */ if (!wjfnmatch(dp->mask, ep->d_name, FALSE)) continue; /* Combine names */ l = dp->lpath + !!lv; if (l + strlen(ep->d_name) >= PATHBUF) // Too long continue; // Should not happen, but let's make sure strcpy(buf + l, ep->d_name); if (lv) buf[l - 1] = DIR_SEP; // No forced separator on level 0 /* Filter files on lower levels */ if (stat(buf, &sbuf) || ((lv < maxdepth) && !S_ISDIR(sbuf.st_mode))) continue; /* Add to result set */ if (lv == maxdepth) memfail |= glob_add_file(pglob, buf); /* Enter into directory */ else { dp[1].lpath = strlen(buf); lv++; } } free(pat); /* Report the results */ if (memfail) { mfail: globfree(pglob); return (GLOB_NOSPACE); } if (pglob->gl_pathc == prevcnt) return (GLOB_NOMATCH); if (maxdepth) pglob->gl_flags |= GLOB_MAGCHAR; /* Sort the names */ qsort(pglob->gl_pathv + prevcnt, pglob->gl_pathc - prevcnt, sizeof(char *), compare_names); return (0); } #endif static char **flist; int flist_len, flist_top; int warnmax; static int extend_flist(int n, int ntoo) { char **tmp; /* Limit the sum & guard against overflow */ n = n > FILES_MAX - ntoo ? FILES_MAX : n + ntoo; n = n > FILES_MAX - flist_top ? FILES_MAX : n + flist_top; if (n > flist_len) { n = (n + 1023) & ~1023; // Align if ((tmp = realloc(flist, n * sizeof(char *)))) { flist = tmp; flist_len = n; } } return (flist_len - flist_top); } #ifdef WIN32 #define LSEP "\r\n" #else #define LSEP "\n" #endif static void add_filelist(char *name, int nf) { char *what, *t, *err; int i, l, lf = 0, a0 = 0; if (warnmax |= flist_top >= FILES_MAX) return; err = "Could not load list"; t = what = slurp_file_l(name, 0, &l); // Reads less than INT_MAX while (what) { /* Let file be LF or NUL separated */ for (i = 0; i < l; i++) { lf += what[i] == '\n'; a0 += !what[i]; } if (a0) lf = a0; // NUL has precedence if (!lf) a0 = 1; // Take all file as single name err = "Empty list"; if (lf >= l) break; err = "Ignored too long list"; if (lf > FILES_MAX) break; /* One extra as last name may be unterminated */ extend_flist(lf + 1, nf); if (!a0) /* LF separated */ { while (t - what < l) { t += strspn(t, LSEP); if (t - what >= l) break; if (warnmax |= flist_top >= flist_len) break; flist[flist_top++] = t; t += strcspn(t, LSEP); *t++ = '\0'; } } else /* NUL separated */ { while (t - what < l) { while (!*t && (++t - what < l)); if (t - what >= l) break; if (warnmax |= flist_top >= flist_len) break; flist[flist_top++] = t; t += strlen(t) + 1; } } return; } free(what); printf("%s: %s\n", err, name); } static gboolean run_init_script() { char **res = NULL, *env = getenv("MTPAINT_INIT"); if (env && *env) res = wj_parse_argv(env); if (res) { run_script(res); free(res); } return (FALSE); // Do not run again (if idle handler) } int main( int argc, char *argv[] ) { char *env; glob_t globdata; int file_arg_start = argc, new_empty = TRUE, get_screenshot = FALSE; int i, j, l, nf, nw, nl, w0, pass, fmode, dosort = FALSE; if (argc > 1) { if ( strcmp(argv[1], "--version") == 0 ) { printf("%s\n\n", MT_VERSION); exit(0); } if ( strcmp(argv[1], "--help") == 0 ) { printf("%s\n\n" "Usage: mtpaint [option] [imagefile ... ]\n\n" "Options:\n" " --help Output this help\n" " --version Output version information\n" " --flist Read a list of files\n" " --sort Sort files passed as arguments\n" " --cmd Commandline scripting mode, no GUI\n" " -s Grab screenshot\n" " -v Start in viewer mode\n" " -- End of options\n\n" , MT_VERSION); exit(0); } if (!strcmp(argv[1], "--cmd")) { cmd_mode = TRUE; script_cmds = argv + 2; } } putenv( "G_BROKEN_FILENAMES=1" ); // Needed to read non ASCII filenames in GTK+2 #if GTK_MAJOR_VERSION == 3 /* No floating random stuff over canvas */ putenv("GTK_OVERLAY_SCROLLING=0"); /* Prevent confusion */ #ifdef GDK_WINDOWING_X11 gdk_set_allowed_backends("x11"); #endif #else /* Disable bug-ridden eyecandy module that breaks sizing */ putenv("LIBOVERLAY_SCROLLBAR=0"); #endif #if GTK2VERSION >= 4 /* Tablet handling in GTK+ 2.18+ is broken beyond repair if this mode * is set; so unset it, if g_unsetenv() is present */ g_unsetenv("GDK_NATIVE_WINDOWS"); #endif #ifdef U_THREADS /* Enable threading for GLib, but NOT for GTK+ (at least, not yet) */ g_thread_init(NULL); #endif env = getenv("MTPAINT_INI"); inifile_init("/etc/mtpaint/mtpaintrc", env ? env : "~/.mtpaint"); #ifdef U_NLS #if GTK_MAJOR_VERSION == 1 /* !!! GTK+1 needs locale set up before gtk_init(); GTK+2, *QUITE* * the opposite - WJ */ setup_language(); #endif #endif #ifdef U_THREADS /* !!! Uncomment to allow GTK+ calls from other threads */ /* gdk_threads_init(); */ #endif if (!cmd_mode) { gtk_init(&argc, &argv); gtk_init_bugfixes(); } #if GTK_MAJOR_VERSION == 3 if (!cmd_mode) init_css(inifile_get(DEFAULT_CSS_INI, "")); #elif GTK_MAJOR_VERSION == 2 if (!cmd_mode) { char *theme = inifile_get(DEFAULT_THEME_INI, ""); if (theme[0]) gtk_rc_parse(theme); } else g_type_init(); #endif #ifdef U_NLS { char *locdir = extend_path(MT_LANG_DEST); #if GTK_MAJOR_VERSION >= 2 /* !!! GTK+2 starts acting up if this is before gtk_init() - WJ */ setup_language(); #endif bindtextdomain("mtpaint", locdir); g_free(locdir); textdomain("mtpaint"); #if GTK_MAJOR_VERSION >= 2 bind_textdomain_codeset("mtpaint", "UTF-8"); #endif } #endif nf = nw = nl = w0 = pass = fmode = 0; memset(&globdata, 0, sizeof(globdata)); for (i = 1 + cmd_mode; ; i++) { char *arg; if (i >= argc) // Pass is done { if (pass++) break; // Totally done file_args = argv + file_arg_start; files_passed = (warnmax = nf > FILES_MAX) ? FILES_MAX : nf; if (!(nw | nl)) break; // Regular filenames are good to go warnmax = 0; // Need to know WHEN limit gets hit if (nl | nf) // List not needed for wildcards alone extend_flist(nf, 1024); // Filenames and then some /* Go forth and stuff filenames into the list */ i = 1 + cmd_mode; fmode = 0; } arg = argv[i]; if (fmode); // Expect filename or wildcard else if (!strcmp(arg, "--")) // End of options { fmode |= 2; // Files only, no wildcards continue; } else if (cmd_mode) continue; // One more script command else if (!strcmp(arg, "-g")) // Loading GIF animation frames { if (++i >= argc) continue; sscanf(argv[i], "%i", &preserved_gif_delay); continue; } else if (!strcmp(arg, "-v")) // Viewer mode { viewer_mode = TRUE; continue; } else if (!strcmp(arg, "-s")) // Screenshot { get_screenshot = TRUE; continue; } else if (!strcmp(arg, "--flist")) // Filelist { if (++i >= argc) continue; nl++; if (!pass) continue; add_filelist(argv[i], nf); if (warnmax) break; continue; } else if (!strcmp(arg, "--sort")) // Sort names { dosort = TRUE; continue; } /* !!! I avoid GLOB_DOOFFS here, because glibc before version 2.2 mishandled it, * and quite a few copycats had cloned those buggy versions, some libc * implementors among them. So it is possible to encounter a broken function * in the wild, and playing it safe doesn't cost all that much - WJ */ if ((fmode < 2) && !strcmp(arg, "-w")) // Wildcard { if (++i >= argc) continue; nw++; if (!pass) continue; if (warnmax |= globdata.gl_pathc >= FILES_MAX) break; // Ignore errors - be glad for whatever gets returned glob(argv[i], (globdata.gl_pathc ? GLOB_APPEND : 0), NULL, &globdata); if (!flist) continue; // Use gl_pathv /* Add newfound filenames to flist */ if (globdata.gl_pathc <= (PATHC_TYPE)w0) continue; // Nothing new l = (globdata.gl_pathc > FILES_MAX ? FILES_MAX : (int)globdata.gl_pathc) - w0; j = extend_flist(l, nf); if (l > j) l = j; memcpy(flist + flist_top, globdata.gl_pathv + w0, l * sizeof(char *)); flist_top += l; w0 += l; if (warnmax |= globdata.gl_pathc > (PATHC_TYPE)w0) break; continue; } // Believe this is a filename fmode |= 1; // Only names and maybe wildcards past this point if (file_arg_start > i) file_arg_start = i; if (pass) { if (warnmax |= flist_top >= flist_len) break; flist[flist_top++] = argv[i]; } nf += 1 - pass * 2; // Counting back on second pass } /* Flist if exists, globs otherwise, commandline as default */ if (flist) file_args = flist , files_passed = flist_top; else if (globdata.gl_pathc) file_args = globdata.gl_pathv , files_passed = globdata.gl_pathc > FILES_MAX ? FILES_MAX : (int)globdata.gl_pathc; if (warnmax) printf("Too many files, limiting to %d\n", files_passed); /* Sort the list of names */ if (dosort && files_passed) qsort(file_args, files_passed, sizeof(char *), compare_names); if (strstr(argv[0], "mtv")) viewer_mode = TRUE; string_init(); // Translate static strings var_init(); // Load INI variables mem_init(); // Set up memory & back end layers_init(); init_cols(); if ( get_screenshot ) { if (load_image(NULL, FS_PNG_LOAD, FT_PIXMAP) == 1) new_empty = FALSE; // Successfully grabbed so no new empty else get_screenshot = FALSE; // Screenshot failed } main_init(); // Create main window if ( get_screenshot ) { do_new_chores(FALSE); notify_changed(); } else { if ((files_passed > 0) && !do_a_load(file_args[0], FALSE)) new_empty = FALSE; } if ( new_empty ) // If no file was loaded, start with a blank canvas { create_default_image(); } update_menus(); if (cmd_mode) // Console run_script(script_cmds); else // GUI { /* !!! GTK+1 hangs if error messagebox is displayed from idle * handler; GTK+3 has no gtk_init_add(); GTK+2 works OK with * both methods - WJ */ #if GTK_MAJOR_VERSION == 3 threads_idle_add_priority(G_PRIORITY_HIGH, (GtkFunction)run_init_script, NULL); #else /* if GTK_MAJOR_VERSION <= 2 */ gtk_init_add((GtkFunction)run_init_script, NULL); #endif THREADS_ENTER(); gtk_main(); THREADS_LEAVE(); inifile_quit(); } spawn_quit(); return (cmd_mode && user_break); } mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/mainwindow.c000066400000000000000000004773021471325446300232770ustar00rootroot00000000000000/* mainwindow.c Copyright (C) 2004-2021 Mark Tyler and Dmitry Groshev This file is part of mtPaint. mtPaint 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. mtPaint 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 mtPaint in the file COPYING. */ #include "global.h" #undef _ #define _(X) X #include "mygtk.h" #include "memory.h" #include "vcode.h" #include "ani.h" #include "png.h" #include "mainwindow.h" #include "viewer.h" #include "otherwindow.h" #include "inifile.h" #include "canvas.h" #include "polygon.h" #include "layer.h" #include "info.h" #include "prefs.h" #include "channels.h" #include "toolbar.h" #include "csel.h" #include "shifter.h" #include "spawn.h" #include "font.h" #include "icons.h" #include "thread.h" typedef struct { int idx_c, nidx_c, cnt_c; int cline_d, settings_d, layers_d; int impmode; int *strs_c; void **drop, **clip; void **clipboard; void **dockpage1; void **keyslot; } main_dd; #define GREY_W 153 #define GREY_B 102 const unsigned char greyz[2] = {GREY_W, GREY_B}; // For opacity squares char *channames[NUM_CHANNELS + 1], *allchannames[NUM_CHANNELS + 1]; char *cspnames[NUM_CSPACES]; char *channames_[NUM_CHANNELS + 1] = { _("Image"), _("Alpha"), _("Selection"), _("Mask"), NULL }; char *cspnames_[NUM_CSPACES] = { _("RGB"), _("sRGB"), "LXN" }; /// INIFILE ENTRY LISTS typedef struct { char *name; int *var; int defv; } inilist; static inilist ini_bool[] = { { "layermainToggle", &show_layers_main, FALSE }, { "sharperReduce", &sharper_reduce, FALSE }, { "tga565", &tga_565, FALSE }, { "tgaDefdir", &tga_defdir, FALSE }, { "tgaRLE", &tga_RLE, FALSE }, { "lbmPBM", &lbm_pbm, FALSE }, { "disableTransparency", &opaque_view, FALSE }, { "smudgeOpacity", &smudge_mode, FALSE }, { "showMenuIcons", &show_menu_icons, FALSE }, { "showTileGrid", &show_tile_grid, FALSE }, { "applyICC", &apply_icc, FALSE }, { "scrollwheelZOOM", &scroll_zoom, FALSE }, { "cursorZoom", &cursor_zoom, FALSE }, { "layerOverlay", &layer_overlay, FALSE }, { "paintGamma", &paint_gamma, FALSE }, { "patternB", &pattern_B, FALSE }, { "arrowScroll", &arrow_scroll, FALSE }, { "tablet_use_size", tablet_tool_use + 0, FALSE }, { "tablet_use_flow", tablet_tool_use + 1, FALSE }, { "tablet_use_opacity", tablet_tool_use + 2, FALSE }, { "pasteCommit", &paste_commit, TRUE }, { "couple_RGBA", &RGBA_mode, TRUE }, { "gridToggle", &mem_show_grid, TRUE }, { "optimizeChequers", &chequers_optimize, TRUE }, { "quitToggle", &q_quit, TRUE }, { "continuousPainting", &mem_continuous, TRUE }, { "opacityToggle", &mem_undo_opacity, TRUE }, { "imageCentre", &canvas_image_centre, TRUE }, { "view_focus", &vw_focus_on, TRUE }, { "pasteToggle", &show_paste, TRUE }, { "cursorToggle", &cursor_tool, TRUE }, { "autopreviewToggle", &brcosa_auto, TRUE }, { "colorGrid", &color_grid, TRUE }, { "defaultGamma", &use_gamma, TRUE }, { "undoableLoad", &undo_load, TRUE }, { "tiffPredictor", &tiff_predictor, TRUE }, { "lbmPack", &lbm_pack, TRUE }, { "lbmIgnoreTrans", &lbm_untrans, TRUE }, #if STATUS_ITEMS != 5 #error Wrong number of "status?Toggle" inifile items defined #endif { "status0Toggle", status_on + 0, TRUE }, { "status1Toggle", status_on + 1, TRUE }, { "status2Toggle", status_on + 2, TRUE }, { "status3Toggle", status_on + 3, TRUE }, { "status4Toggle", status_on + 4, TRUE }, #if TOOLBAR_MAX != 6 #error Wrong number of "toolbar?" inifile items defined #endif { "toolbar1", toolbar_status + 1, TRUE }, { "toolbar2", toolbar_status + 2, TRUE }, { "toolbar3", toolbar_status + 3, TRUE }, { "toolbar4", toolbar_status + 4, TRUE }, { "toolbar5", toolbar_status + 5, TRUE }, { "fontAntialias0", &font_aa, TRUE }, { "fontAntialias1", &font_bk, FALSE }, { "fontAntialias2", &font_r, FALSE }, #ifdef U_FREETYPE { "fontAntialias3", &font_obl, FALSE }, { "ftSetDPI", &ft_setdpi, TRUE }, #endif { "fontSetDPI", &font_setdpi, FALSE }, { NULL, NULL } }; static inilist ini_int[] = { { "jpegQuality", &jpeg_quality, 85 }, { "pngCompression", &png_compression, 9 }, { "jpeg2000Rate", &jp2_rate, 1 }, { "lzmaPreset", &lzma_preset, 9 }, { "zstdLevel", &zstd_level, 9 }, { "webpPreset", &webp_preset, 1 }, { "webpQuality", &webp_quality, 90 }, { "webpCompression", &webp_compression, 9 }, { "lbmMask", &lbm_mask, CHN_MASK }, { "silence_limit", &silence_limit, 18 }, { "gradientOpacity", &grad_opacity, 128 }, { "gridMin", &mem_grid_min, 8 }, { "undoMBlimit", &mem_undo_limit, 0 }, { "undoCommon", &mem_undo_common, 25 }, { "maxThreads", &maxthreads, 0 }, { "kpixThreads", &kpix_threads, 256 }, { "backgroundGrey", &mem_background, 180 }, { "pixelNudge", &mem_nudge, 8 }, { "recentFiles", &recent_files, 10 }, { "lastspalType", &spal_mode, 2 }, { "posterizeMode", &def_bcsp.pmode, 0 }, { "panSize", &max_pan, 128 }, { "undoDepth", &mem_undo_depth, DEF_UNDO }, { "tileWidth", &tgrid_dx, 32 }, { "tileHeight", &tgrid_dy, 32 }, { "gridRGB", grid_rgb + GRID_NORMAL, RGB_2_INT( 50, 50, 50) }, { "gridBorder", grid_rgb + GRID_BORDER, RGB_2_INT( 0, 219, 0) }, { "gridTrans", grid_rgb + GRID_TRANS, RGB_2_INT( 0, 109, 109) }, { "gridTile", grid_rgb + GRID_TILE, RGB_2_INT(170, 170, 170) }, { "gridSegment", grid_rgb + GRID_SEGMENT,RGB_2_INT(219, 219, 0) }, { "palAB", &mem_pal_ab_c, RGB_2_INT(53, 53, 162) }, { "palIndex", &mem_pal_id_c, RGB_2_INT(200, 200, 200) }, { "tablet_value_size", tablet_tool_factor + 0, MAX_TF }, { "tablet_value_flow", tablet_tool_factor + 1, MAX_TF }, { "tablet_value_opacity", tablet_tool_factor + 2,MAX_TF }, { "fontBackground", &font_bkg, 0 }, { "fontAngle", &font_angle, 0 }, { "fontAlign", &font_align, 0 }, { "fontDPI", &font_dpi, 72 }, { "fontSpacing", &font_spacing, 0 }, #ifdef U_FREETYPE { "fontSizeBitmap", &font_bmsize, 1 }, { "fontSize", &font_size, 12 }, { "font_dirs", &font_dirs, 0 }, #endif { NULL, NULL } }; void **main_window_, **main_keys, **settings_dock, **layers_dock, **main_split, **drawing_canvas, **scrolledwindow_canvas, **menu_slots[TOTAL_MENU_IDS]; static void **dock_area, **dock_book, **main_menubar; int view_image_only, viewer_mode, drag_index, q_quit, cursor_tool; int show_menu_icons, paste_commit, scroll_zoom, arrow_scroll; int drag_index_vals[2], cursor_corner, use_gamma, view_vsplit; int files_passed, cmd_mode, tablet_working; char **file_args, **script_cmds; static int show_dock; static int mouse_left_canvas, is_tracking; static int cvxy[2]; // canvas window position typedef struct { int mode; // (tool_type + 1) if drawn, 0 if not int x, y, s; // Top left corner and size int cx, cy; // Clone perimeter offset } perim_info; static perim_info perim_state; // Tool perimeter int perim_wx, perim_wy; // Cursor position #define perim_status perim_state.mode #define perim_x perim_state.x #define perim_y perim_state.y #define perim_s perim_state.s #define perim_cx perim_state.cx #define perim_cy perim_state.cy static void repaint_perim(rgbcontext *ctx); // Redraw perimeter around mouse cursor static void clear_perim(perim_info *p); // Clear perimeter around mouse cursor static void move_perim(int x, int y); // Move perimeter to a new location static void clear_perim_real(int x0, int y0, int s) { int x1, y1, zoom = 1, scale = 1; /* !!! This uses the fact that zoom factor is either N or 1/N !!! */ if (can_zoom < 1.0) zoom = rint(1.0 / can_zoom); else scale = rint(can_zoom); x1 = margin_main_x + ((x0 + s - 1) * scale) / zoom + scale - 1; y1 = margin_main_y + ((y0 + s - 1) * scale) / zoom + scale - 1; x0 = margin_main_x + (x0 * scale) / zoom; y0 = margin_main_y + (y0 * scale) / zoom; repaint_canvas(x0, y0, 1, y1 - y0 + 1); repaint_canvas(x1, y0, 1, y1 - y0 + 1); repaint_canvas(x0 + 1, y0, x1 - x0 - 1, 1); repaint_canvas(x0 + 1, y1, x1 - x0 - 1, 1); } static void pressed_load_recent(int item) { if ((layers_total ? check_layers_for_changes() : check_for_changes()) == 1) return; do_a_load(recent_filenames[item - 1], undo_load); // Load requested file } static void pressed_crop() { int res, rect[4]; if ( marq_status != MARQUEE_DONE ) return; marquee_at(rect); if ((rect[0] == 0) && (rect[2] >= mem_width) && (rect[1] == 0) && (rect[3] >= mem_height)) return; res = mem_image_resize(rect[2], rect[3], -rect[0], -rect[1], 0); if (!res) { pressed_select(FALSE); change_to_tool(DEFAULT_TOOL_ICON); update_stuff(UPD_GEOM); } else memory_errors(res); } static multi_ext *script_rect(int *rect); static void select_poly(multi_ext *mx); void pressed_select(int all) { int i = 0; /* Remove old selection */ if (marq_status != MARQUEE_NONE) { i = UPD_SEL; if (marq_status >= MARQUEE_PASTE) i = UPD_SEL | CF_DRAW; else paint_marquee(MARQ_HIDE, 0, 0, NULL); marq_status = MARQUEE_NONE; } if ((tool_type == TOOL_POLYGON) && (poly_status != POLY_NONE)) { poly_points = 0; poly_status = POLY_NONE; i = UPD_SEL | CF_DRAW; // Have to erase polygon } /* And deal with selection persistence too */ marq_x1 = marq_y1 = marq_x2 = marq_y2 = -1; while (all) /* Select entire canvas */ { multi_ext *mx; int rxy[4]; if ((mx = script_rect(rxy))) // Script wants a polygon { change_to_tool(TTB_POLY); select_poly(mx); free(mx); break; } clip(rxy, 0, 0, mem_width - 1, mem_height - 1, rxy); /* We are selecting an area, so block inside-out selections */ if ((rxy[0] > rxy[2]) || (rxy[1] > rxy[3])) break; i |= UPD_SEL; copy4(marq_xy, rxy); if (tool_type != TOOL_SELECT) { /* Switch tool, and let that & marquee persistence * do all the rest except full redraw */ change_to_tool(TTB_SELECT); i &= CF_DRAW; break; } marq_status = MARQUEE_DONE; if (i & CF_DRAW) break; // Full redraw will draw marquee too paint_marquee(MARQ_SHOW, 0, 0, NULL); break; } if (i) update_stuff(i); } static void pressed_remove_unused() { if (mem_remove_unused_check() <= 0) { if (!script_cmds) alert_box(_("Error"), _("There were no unused colours to remove!"), NULL); } else { spot_undo(UNDO_XPAL); mem_remove_unused(); mem_undo_prepare(); update_stuff(UPD_TPAL); } } static void pressed_default_pal() { spot_undo(UNDO_PAL); mem_pal_copy( mem_pal, mem_pal_def ); mem_cols = mem_pal_def_i; update_stuff(UPD_PAL); } static void pressed_remove_duplicates() { char *mess; int dups = scan_duplicates(); if (!dups) { if (!script_cmds) alert_box(_("Error"), _("The palette does not contain 2 colours that have identical RGB values"), NULL); return; } mess = g_strdup_printf(__("The palette contains %i colours that have identical RGB values. Do you really want to merge them into one index and realign the canvas?"), dups); if (script_cmds || (alert_box(_("Warning"), mess, _("Yes"), _("No"), NULL) == 1)) { spot_undo(UNDO_XPAL); remove_duplicates(); mem_undo_prepare(); update_stuff(UPD_PAL); } g_free(mess); } static void pressed_dither_A() { mem_find_dither(mem_col_A24.red, mem_col_A24.green, mem_col_A24.blue); update_stuff(UPD_ABP); } // System clipboard import static clipform_dd clip_formats[] = { { "application/x-mtpaint-pmm", (void *)(FT_PMM | FTM_EXTEND) }, { "application/x-mtpaint-clipboard", (void *)(FT_PNG | FTM_EXTEND) }, { "image/png", (void *)(FT_PNG) }, { "image/bmp", (void *)(FT_BMP) }, { "image/x-bmp", (void *)(FT_BMP) }, { "image/x-MS-bmp", (void *)(FT_BMP) }, #ifdef U_TIFF { "image/tiff", (void *)(FT_TIFF) }, #endif #ifdef HAVE_PIXMAPS /* These two don't make sense without X */ { "PIXMAP", (void *)(FT_PIXMAP), sizeof(XID_type), 32 }, { "BITMAP", (void *)(FT_PIXMAP), sizeof(XID_type), 32 }, /* !!! BITMAP requests are handled same as PIXMAP - because it is only * done to appease buggy XPaint which requests both and crashes if * receiving only one - WJ */ #endif }; #define CLIP_TARGETS (sizeof(clip_formats) / sizeof(clip_formats[0])) /* Seems it'll be better to prefer BMP when talking to the likes of GIMP - * they send PNGs really slowly (likely, compressed to the max); but not * everyone supports alpha in BMPs. */ static int clipboard_import_fn(main_dd *dt, void **wdata, int what, void **where, copy_ext *cdata) { int form = (int)cdata->format->id; if ((dt->impmode == FS_PNG_LOAD) && undo_load) form |= FTM_UNDO; return (load_mem_image(cdata->data, cdata->len, dt->impmode, form) == 1); } int import_clipboard(int mode) { main_dd *dt = GET_DDATA(main_window_); if (cmd_mode) return (FALSE); // !!! Needs active GTK+ to work dt->impmode = mode; return (cmd_checkv(dt->clipboard, CLIP_PROCESS)); } static void setup_clip_save(ls_settings *settings) { init_ls_settings(settings, NULL); memcpy(settings->img, mem_clip.img, sizeof(chanlist)); settings->pal = mem_pal; settings->width = mem_clip_w; settings->height = mem_clip_h; settings->bpp = mem_clip_bpp; settings->colors = mem_cols; } static void clipboard_export_fn(main_dd *dt, void **wdata, int what, void **where, copy_ext *cdata) { ls_settings settings; unsigned char *buf, *pp[2]; int res, len, type; if (!cdata->format) return; // Someone else stole system clipboard if (!mem_clipboard) return; // Our own clipboard got emptied /* Prepare settings */ setup_clip_save(&settings); settings.mode = FS_CLIPBOARD; settings.ftype = type = (int)cdata->format->id; settings.png_compression = 1; // Speed is of the essence res = save_mem_image(&buf, &len, &settings); if (res) return; // No luck creating in-memory image pp[1] = (pp[0] = buf) + len; cmd_setv(where, pp, COPY_DATA); free(buf); } static int export_clipboard() { main_dd *dt = GET_DDATA(main_window_); if (!mem_clipboard) return (FALSE); return (cmd_checkv(dt->clipboard, CLIP_OFFER)); } int gui_save(char *filename, ls_settings *settings) { int res = -2, fflags = file_formats[settings->ftype].flags; char *mess = NULL, *f8; /* Mismatched format - raise an error right here */ if ((fflags & FF_NOSAVE) || !(fflags & FF_SAVE_MASK)) { int maxc = 0; char *fform = NULL, *fname = file_formats[settings->ftype].name; /* RGB to indexed (or to unsaveable) */ if (mem_img_bpp == 3) fform = __("RGB"); /* Indexed to RGB, or to unsaveable format */ else if (!(fflags & FF_IDX) || (fflags & FF_NOSAVE)) fform = __("indexed"); /* More than 16 colors */ else if (fflags & FF_16) maxc = 16; /* More than 2 colors */ else maxc = 2; /* Build message */ if (fform) mess = g_strdup_printf(__("You are trying to save an %s image to an %s file which is not possible. I would suggest you save with a PNG extension."), fform, fname); else mess = g_strdup_printf(__("You are trying to save an %s file with a palette of more than %d colours. Either use another format or reduce the palette to %d colours."), fname, maxc, maxc); } else { /* Commit paste if required */ if (!script_cmds && paste_commit && (marq_status >= MARQUEE_PASTE)) { commit_paste(FALSE, NULL); pen_down = 0; mem_undo_prepare(); pressed_select(FALSE); } /* Prepare to save image */ memcpy(settings->img, mem_img, sizeof(chanlist)); settings->pal = mem_pal; settings->width = mem_width; settings->height = mem_height; settings->bpp = mem_img_bpp; settings->colors = mem_cols; res = save_image(filename, settings); } if (res < 0) { if (res == -1) { f8 = gtkuncpy(NULL, filename, 0); mess = g_strdup_printf(__("Unable to save file: %s"), f8); g_free(f8); } if (mess) { alert_box(_("Error"), mess, NULL); g_free(mess); } } else { notify_unchanged(filename); register_file(filename); } return res; } static void pressed_save_file() { ls_settings settings; while (mem_filename) { init_ls_settings(&settings, NULL); settings.ftype = file_type_by_ext(mem_filename, FF_IMAGE); if (settings.ftype == FT_NONE) break; settings.mode = FS_PNG_SAVE; if (gui_save(mem_filename, &settings) < 0) break; return; } file_selector(FS_PNG_SAVE); } char mem_clip_file[PATHBUF]; static void load_clip(int item) { char clip[PATHBUF]; int i; if (item == -1) // System clipboard i = import_clipboard(FS_CLIPBOARD); else // Disk file { snprintf(clip, PATHBUF, "%s%i", mem_clip_file, item); i = load_image(clip, FS_CLIP_FILE, FT_PNG) == 1; } if (!i) alert_box(_("Error"), _("Unable to load clipboard"), NULL); update_stuff(UPD_XCOPY); if (i && (MEM_BPP >= mem_clip_bpp)) pressed_paste(TRUE); } static void save_clip(int item) { ls_settings settings; char clip[PATHBUF]; int i; if (item == -1) // Exporting clipboard { export_clipboard(); return; } /* Prepare settings */ setup_clip_save(&settings); settings.mode = FS_CLIP_FILE; settings.ftype = FT_PNG; snprintf(clip, PATHBUF, "%s%i", mem_clip_file, item); i = save_image(clip, &settings); if (i) alert_box(_("Error"), _("Unable to save clipboard"), NULL); } void pressed_opacity(int opacity) { if (IS_INDEXED) opacity = 255; tool_opacity = opacity < 1 ? 1 : opacity > 255 ? 255 : opacity; update_stuff(UPD_OPAC); } static void toggle_view() { view_image_only = !view_image_only; cmd_showhide(main_menubar, !view_image_only); if (view_image_only) { int i; for (i = TOOLBAR_MAIN; i < TOOLBAR_MAX; i++) if (toolbar_boxes[i]) cmd_showhide(toolbar_boxes[i], FALSE); } else toolbar_showhide(); // Switch toolbar/status/palette on if needed } static void zoom_grid(int state) { mem_show_grid = state; update_stuff(UPD_RENDER); } static void delete_event(main_dd *dt, void **wdata); static void quit_all(int mode) { if (mode || q_quit) delete_event(GET_DDATA(main_window_), main_window_); } /* Scroll canvas under cursor instead of moving the cursor */ static int try_scroll(int *dxy) { int bx, by, mx[2]; if (!arrow_scroll || mouse_left_canvas) return (TRUE); // Let cursor go cmd_read(scrolledwindow_canvas, NULL); cmd_peekv(scrolledwindow_canvas, mx, sizeof(mx), CSCROLL_LIMITS); dxy[0] -= (bx = bounded(cvxy[0] + dxy[0], 0, mx[0])) - cvxy[0]; dxy[1] -= (by = bounded(cvxy[1] + dxy[1], 0, mx[1])) - cvxy[1]; if ((bx ^ cvxy[0]) | (by ^ cvxy[1])) { cvxy[0] = bx; cvxy[1] = by; cmd_reset(scrolledwindow_canvas, NULL); } return (dxy[0] | dxy[1]); } /* Forward declaration */ static void mouse_event(mouse_ext *m, int mflag, int dx, int dy); /* For "dual" mouse control */ static int unreal_move, lastdx, lastdy; static void move_mouse(int dx, int dy, int button) { static unsigned int bmasks[4] = { 0, _B1mask, _B2mask, _B3mask }; mouse_ext m; int dxy[2], zoom = 1, scale = 1; if (!unreal_move) lastdx = lastdy = 0; if (!mem_img[CHN_IMAGE]) return; dx += lastdx; dy += lastdy; cmd_peekv(drawing_canvas, &m, sizeof(m), CANVAS_FIND_MOUSE); if (button) /* Clicks simulated without extra movements */ { m.button = button; m.count = 1; // press mouse_event(&m, 1, dx, dy); m.state |= bmasks[button]; // Shows state _prior_ to event m.count = -1; // release mouse_event(&m, 1, dx, dy); return; } /* !!! This uses the fact that zoom factor is either N or 1/N !!! */ if (can_zoom < 1.0) zoom = rint(1.0 / can_zoom); else scale = rint(can_zoom); if (zoom > 1) /* Fine control required */ { lastdx = dx; lastdy = dy; mouse_event(&m, 1, dx, dy); // motion unreal_move = 2; /* Nudge cursor when needed */ if ((abs(lastdx) >= zoom) || (abs(lastdy) >= zoom)) { lastdx -= (dxy[0] = lastdx * can_zoom) * zoom; lastdy -= (dxy[1] = lastdy * can_zoom) * zoom; if (try_scroll(dxy)) { unreal_move = 3; /* Event can be delayed or lost */ cmd_setv(drawing_canvas, dxy, CANVAS_BMOVE_MOUSE); } } } else /* Real mouse is precise enough */ { unreal_move = 1; /* Simulate movement unless actually moved mouse */ dxy[0] = dx * scale; dxy[1] = dy * scale; while (TRUE) { if (try_scroll(dxy)) { cmd_setv(drawing_canvas, dxy, CANVAS_BMOVE_MOUSE); if (!(dxy[0] | dxy[1])) break; // Moved OK lastdx = dxy[0] / scale; lastdy = dxy[1] / scale; } mouse_event(&m, 1, dx, dy); // motion break; } } } void stop_line() { int i = line_status == LINE_LINE; line_status = LINE_NONE; if (i) repaint_line(NULL); } int check_zoom_keys_real(int act_m) { int action = act_m >> 16; if ((action == ACT_ZOOM) || (action == ACT_VIEW) || (action == ACT_VWZOOM)) { action_dispatch(action, (act_m & 0xFFFF) - 0x8000, 0, TRUE); return (TRUE); } return (FALSE); } int check_zoom_keys(int act_m) { int action = act_m >> 16; if (check_zoom_keys_real(act_m)) return (TRUE); if ((action == ACT_DOCK) || (action == ACT_QUIT) || (action == DLG_BRCOSA) || (action == ACT_PAN) || (action == ACT_CROP) || (action == ACT_SWAP_AB) || (action == DLG_CHOOSER) || (action == ACT_TOOL)) action_dispatch(action, (act_m & 0xFFFF) - 0x8000, 0, TRUE); else return (FALSE); return (TRUE); } static void menu_action(void *dt, void **wdata, int what, void **where); static void *keylist_code[] = { uMENUBAR(menu_action), uMENUITEM(_("Zoom in"), ACTMOD(ACT_ZOOM, 0)), SHORTCUT(plus, 0), SHORTCUT(KP_Add, 0), uMENUITEM(_("Zoom out"), ACTMOD(ACT_ZOOM, -1)), SHORTCUT(minus, 0), SHORTCUT(KP_Subtract, 0), uMENUITEM(_("10% zoom"), ACTMOD(ACT_ZOOM, -10)), SHORTCUT(1, 0), SHORTCUT(KP_1, 0), uMENUITEM(_("25% zoom"), ACTMOD(ACT_ZOOM, -4)), SHORTCUT(2, 0), SHORTCUT(KP_2, 0), uMENUITEM(_("50% zoom"), ACTMOD(ACT_ZOOM, -2)), SHORTCUT(3, 0), SHORTCUT(KP_3, 0), uMENUITEM(_("100% zoom"), ACTMOD(ACT_ZOOM, 1)), SHORTCUT(4, 0), SHORTCUT(KP_4, 0), uMENUITEM(_("400% zoom"), ACTMOD(ACT_ZOOM, 4)), SHORTCUT(5, 0), SHORTCUT(KP_5, 0), uMENUITEM(_("600% zoom"), ACTMOD(ACT_ZOOM, 6)), SHORTCUT0, uMENUITEM(_("800% zoom"), ACTMOD(ACT_ZOOM, 8)), SHORTCUT(6, 0), SHORTCUT(KP_6, 0), uMENUITEM(_("1000% zoom"), ACTMOD(ACT_ZOOM, 10)), SHORTCUT0, uMENUITEM(_("1200% zoom"), ACTMOD(ACT_ZOOM, 12)), SHORTCUT(7, 0), SHORTCUT(KP_7, 0), uMENUITEM(_("1600% zoom"), ACTMOD(ACT_ZOOM, 16)), SHORTCUT(8, 0), SHORTCUT(KP_8, 0), uMENUITEM(_("2000% zoom"), ACTMOD(ACT_ZOOM, 20)), SHORTCUT(9, 0), SHORTCUT(KP_9, 0), uMENUITEM(_("4000% zoom"), ACTMOD(ACT_ZOOM, 40)), SHORTCUT0, uMENUITEM(_("8000% zoom"), ACTMOD(ACT_ZOOM, 80)), SHORTCUT0, uMENUITEM(_("10% opacity"), ACTMOD(ACT_OPAC, 1)), SHORTCUT(1, C), SHORTCUT(KP_1, C), uMENUITEM(_("20% opacity"), ACTMOD(ACT_OPAC, 2)), SHORTCUT(2, C), SHORTCUT(KP_2, C), uMENUITEM(_("30% opacity"), ACTMOD(ACT_OPAC, 3)), SHORTCUT(3, C), SHORTCUT(KP_3, C), uMENUITEM(_("40% opacity"), ACTMOD(ACT_OPAC, 4)), SHORTCUT(4, C), SHORTCUT(KP_4, C), uMENUITEM(_("50% opacity"), ACTMOD(ACT_OPAC, 5)), SHORTCUT(5, C), SHORTCUT(KP_5, C), uMENUITEM(_("60% opacity"), ACTMOD(ACT_OPAC, 6)), SHORTCUT(6, C), SHORTCUT(KP_6, C), uMENUITEM(_("70% opacity"), ACTMOD(ACT_OPAC, 7)), SHORTCUT(7, C), SHORTCUT(KP_7, C), uMENUITEM(_("80% opacity"), ACTMOD(ACT_OPAC, 8)), SHORTCUT(8, C), SHORTCUT(KP_8, C), uMENUITEM(_("90% opacity"), ACTMOD(ACT_OPAC, 9)), SHORTCUT(9, C), SHORTCUT(KP_9, C), uMENUITEM(_("100% opacity"), ACTMOD(ACT_OPAC, 10)), SHORTCUT(0, C), SHORTCUT(KP_0, C), uMENUITEM(_("Increase opacity"), ACTMOD(ACT_OPAC, 0)), SHORTCUT(plus, C), SHORTCUT(KP_Add, C), uMENUITEM(_("Decrease opacity"), ACTMOD(ACT_OPAC, -1)), SHORTCUT(minus, C), SHORTCUT(KP_Subtract, C), uMENUITEM(_("Draw open arrow head"), ACTMOD(ACT_ARROW, 2)), SHORTCUT(a, 0), uMENUITEM(_("Draw closed arrow head"), ACTMOD(ACT_ARROW, 3)), SHORTCUT(s, 0), uMENUITEM(_("Previous colour A"), ACTMOD(ACT_A, -1)), SHORTCUT(bracketleft, 0), uMENUITEM(_("Next colour A"), ACTMOD(ACT_A, 1)), SHORTCUT(bracketright, 0), uMENUITEM(_("Previous colour B"), ACTMOD(ACT_B, -1)), SHORTCUT(bracketleft, S), SHORTCUT(braceleft, S), uMENUITEM(_("Next colour B"), ACTMOD(ACT_B, 1)), SHORTCUT(bracketright, S), SHORTCUT(braceright, S), uMENUITEM(_("Previous pattern"), ACTMOD(ACT_PAT, -1)), SHORTCUT0, uMENUITEM(_("Next pattern"), ACTMOD(ACT_PAT, 1)), SHORTCUT0, uMENUITEM(_("Larger brush"), ACTMOD(ACT_SIZE, 1)), SHORTCUT0, uMENUITEM(_("Smaller brush"), ACTMOD(ACT_SIZE, -1)), SHORTCUT0, uMENUITEM(_("View window - Zoom in"), ACTMOD(ACT_VWZOOM, 0)), SHORTCUT(plus, S), SHORTCUT(KP_Add, S), uMENUITEM(_("View window - Zoom out"), ACTMOD(ACT_VWZOOM, -1)), SHORTCUT(minus, S), SHORTCUT(KP_Subtract, S), /// FIXED KEYS uMENUITEM(NULL, ACTMOD(ACT_QUIT, 0)), SHORTCUT(q, 0), SHORTCUT(q, S), SHORTCUT(q, A), SHORTCUT(q, CS), SHORTCUT(q, CA), SHORTCUT(q, SA), SHORTCUT(q, CSA), uMENUITEM(NULL, ACTMOD(ACT_SEL_MOVE, 5)), SHORTCUT(Left, S), SHORTCUT(KP_Left, S), uMENUITEM(NULL, ACTMOD(ACT_SEL_MOVE, 7)), SHORTCUT(Right, S), SHORTCUT(KP_Right, S), uMENUITEM(NULL, ACTMOD(ACT_SEL_MOVE, 3)), SHORTCUT(Down, S), SHORTCUT(KP_Down, S), uMENUITEM(NULL, ACTMOD(ACT_SEL_MOVE, 9)), SHORTCUT(Up, S), SHORTCUT(KP_Up, S), uMENUITEM(NULL, ACTMOD(ACT_SEL_MOVE, 4)), SHORTCUT(Left, 0), SHORTCUT(KP_Left, 0), uMENUITEM(NULL, ACTMOD(ACT_SEL_MOVE, 6)), SHORTCUT(Right, 0), SHORTCUT(KP_Right, 0), uMENUITEM(NULL, ACTMOD(ACT_SEL_MOVE, 2)), SHORTCUT(Down, 0), SHORTCUT(KP_Down, 0), uMENUITEM(NULL, ACTMOD(ACT_SEL_MOVE, 8)), SHORTCUT(Up, 0), SHORTCUT(KP_Up, 0), uMENUITEM(NULL, ACTMOD(ACT_LR_MOVE, 5)), SHORTCUT(Left, CS), SHORTCUT(KP_Left, CS), uMENUITEM(NULL, ACTMOD(ACT_LR_MOVE, 7)), SHORTCUT(Right, CS), SHORTCUT(KP_Right, CS), uMENUITEM(NULL, ACTMOD(ACT_LR_MOVE, 3)), SHORTCUT(Down, CS), SHORTCUT(KP_Down, CS), uMENUITEM(NULL, ACTMOD(ACT_LR_MOVE, 9)), SHORTCUT(Up, CS), SHORTCUT(KP_Up, CS), uMENUITEM(NULL, ACTMOD(ACT_LR_MOVE, 4)), SHORTCUT(Left, C), SHORTCUT(KP_Left, C), uMENUITEM(NULL, ACTMOD(ACT_LR_MOVE, 6)), SHORTCUT(Right, C), SHORTCUT(KP_Right, C), uMENUITEM(NULL, ACTMOD(ACT_LR_MOVE, 2)), SHORTCUT(Down, C), SHORTCUT(KP_Down, C), uMENUITEM(NULL, ACTMOD(ACT_LR_MOVE, 8)), SHORTCUT(Up, C), SHORTCUT(KP_Up, C), uMENUITEM(NULL, ACTMOD(ACT_ESC, 0)), SHORTCUT(Escape, 0), SHORTCUT(Escape, A), uMENUITEM(NULL, ACTMOD(ACT_COMMIT, 0)), SHORTCUT(Return, 0), SHORTCUT(Return, C), SHORTCUT(Return, A), SHORTCUT(Return, CA), SHORTCUT(KP_Enter, 0), SHORTCUT(KP_Enter, C), SHORTCUT(KP_Enter, A), SHORTCUT(KP_Enter, CA), uMENUITEM(NULL, ACTMOD(ACT_COMMIT, 1)), SHORTCUT(Return, S), SHORTCUT(Return, CS), SHORTCUT(Return, SA), SHORTCUT(Return, CSA), SHORTCUT(KP_Enter, S), SHORTCUT(KP_Enter, CS), SHORTCUT(KP_Enter, SA), SHORTCUT(KP_Enter, CSA), uMENUITEM(NULL, ACTMOD(ACT_RCLICK, 0)), SHORTCUT(BackSpace, 0), SHORTCUT(BackSpace, C), SHORTCUT(BackSpace, S), SHORTCUT(BackSpace, A), SHORTCUT(BackSpace, CS), SHORTCUT(BackSpace, CA), SHORTCUT(BackSpace, SA), SHORTCUT(BackSpace, CSA), RET }; int key_action(key_ext *key, int toggle) { main_dd *dt = GET_DDATA(main_window_); void *v, **slot; int act_m; cmd_setv(main_keys, key, KEYMAP_KEY); slot = dt->keyslot; // Leave unmapped key to be handled elsewhere if (!slot) act_m = 0; // Do nothing if slot is insensitive else if (!cmd_checkv(slot, SLOT_SENSITIVE)) act_m = ACTMOD_DUMMY; // Activate toggleable widget if allowed else if (toggle && (v = slot_data(slot, dt))) { cmd_set(slot, cmd_checkv(slot, SLOT_RADIO) || !*(int *)v); act_m = ACTMOD_DUMMY; } else act_m = TOOL_ID(slot); return (act_m); } int dock_focused() { return (cmd_checkv(dock_book, SLOT_FOCUSED)); } static int handle_keypress(main_dd *dt, void **wdata, int what, void **where, key_ext *keydata) { int act_m = key_action(keydata, TRUE); if (!act_m) return (FALSE); if (act_m != ACTMOD_DUMMY) action_dispatch(act_m >> 16, (act_m & 0xFFFF) - 0x8000, 0, TRUE); return (TRUE); } static void draw_arrow(int mode) { int i, xa1, xa2, ya1, ya2, minx, maxx, miny, maxy, w, h; double uvx, uvy; // Line length & unit vector lengths int oldmode = mem_undo_opacity; grad_info svgrad; if (!((tool_type == TOOL_LINE) && (line_status != LINE_NONE) && ((line_x1 != line_x2) || (line_y1 != line_y2)))) return; svgrad = gradient[mem_channel]; line_to_gradient(); // Calculate 2 coords for arrow corners uvy = sqrt((line_x1 - line_x2) * (line_x1 - line_x2) + (line_y1 - line_y2) * (line_y1 - line_y2)); uvx = (line_x1 - line_x2) / uvy; uvy = (line_y1 - line_y2) / uvy; xa1 = rint(line_x2 + tool_flow * (uvx - uvy * 0.5)); xa2 = rint(line_x2 + tool_flow * (uvx + uvy * 0.5)); ya1 = rint(line_y2 + tool_flow * (uvy + uvx * 0.5)); ya2 = rint(line_y2 + tool_flow * (uvy - uvx * 0.5)); // !!! Call this, or let undo engine do it? // mem_undo_prepare(); pen_down = 0; do_tool_action(TC_LINE_ARROW, line_x2, line_y2, MAX_PRESSURE); line_status = LINE_LINE; // Draw arrow lines & circles mem_undo_opacity = TRUE; f_circle(xa1, ya1, tool_size); f_circle(xa2, ya2, tool_size); tline(xa1, ya1, line_x2, line_y2, tool_size); tline(xa2, ya2, line_x2, line_y2, tool_size); if (mode == 3) { // Draw 3rd line and fill arrowhead tline(xa1, ya1, xa2, ya2, tool_size ); poly_points = 0; poly_add(line_x2, line_y2); poly_add(xa1, ya1); poly_add(xa2, ya2); poly_paint(); poly_points = 0; } mem_undo_opacity = oldmode; gradient[mem_channel] = svgrad; mem_undo_prepare(); pen_down = 0; // Update screen areas minx = xa1 < xa2 ? xa1 : xa2; if (minx > line_x2) minx = line_x2; maxx = xa1 > xa2 ? xa1 : xa2; if (maxx < line_x2) maxx = line_x2; miny = ya1 < ya2 ? ya1 : ya2; if (miny > line_y2) miny = line_y2; maxy = ya1 > ya2 ? ya1 : ya2; if (maxy < line_y2) maxy = line_y2; i = (tool_size + 1) >> 1; minx -= i; miny -= i; maxx += i; maxy += i; w = maxx - minx + 1; h = maxy - miny + 1; update_stuff(UPD_IMGP); lr_update_area(layer_selected, minx, miny, w, h); } int check_for_changes() // 1=STOP, 2=IGNORE, -10=NOT CHANGED { if (!mem_changed) return (-10); return (alert_box(_("Warning"), _("This canvas/palette contains changes that have not been saved. Do you really want to lose these changes?"), _("Cancel Operation"), _("Lose Changes"), NULL)); } void var_init() { inilist *ilp; /* Load listed settings */ for (ilp = ini_bool; ilp->name; ilp++) *(ilp->var) = inifile_get_gboolean(ilp->name, ilp->defv); for (ilp = ini_int; ilp->name; ilp++) *(ilp->var) = inifile_get_gint32(ilp->name, ilp->defv); /* Initialize undo memory space */ if (mem_undo_limit <= 0) { unsigned mem = sys_mem_size(); /* Limit usable space to 2 Gb on 32-bit systems */ if ((sizeof(void *) <= 4) && (mem > 2048)) mem = 2048; /* Take 1/4 of memory space, rounded up to nearest 32 Mb */ mem_undo_limit = ((mem / 4) + 31) & ~31; /* But no less than 32 Mb */ if (!mem_undo_limit) mem_undo_limit = 32; } #ifdef U_TIFF /* Load TIFF types */ { int i, tr, ti, tb; tr = inifile_get_gint32("tiffTypeRGB", 1 /* COMPRESSION_NONE */); ti = inifile_get_gint32("tiffTypeI", 1 /* COMPRESSION_NONE */); tb = inifile_get_gint32("tiffTypeBW", 1 /* COMPRESSION_NONE */); init_tiff_formats(); for (i = 0; tiff_formats[i].name; i++) { if (tiff_formats[i].id == tr) tiff_rtype = i; if (tiff_formats[i].id == ti) tiff_itype = i; if (tiff_formats[i].id == tb) tiff_btype = i; } } #endif } void string_init() { int i; for (i = 0; i < NUM_CHANNELS + 1; i++) allchannames[i] = channames[i] = __(channames_[i]); channames[CHN_IMAGE] = ""; for (i = 0; i < NUM_CSPACES; i++) cspnames[i] = __(cspnames_[i]); } static void toggle_dock(int state); static void delete_event(main_dd *dt, void **wdata) { inilist *ilp; int i; i = layers_total ? check_layers_for_changes() : check_for_changes(); if (i == -10) { i = 2; if (inifile_get_gboolean("exitToggle", FALSE)) i = alert_box(MT_VERSION, _("Do you really want to quit?"), _("NO"), _("YES"), NULL); } if (i != 2) return; // Cancel quitting /* Store listed settings */ for (ilp = ini_bool; ilp->name; ilp++) inifile_set_gboolean(ilp->name, *(ilp->var)); for (ilp = ini_int; ilp->name; ilp++) inifile_set_gint32(ilp->name, *(ilp->var)); #ifdef U_TIFF /* Store TIFF types */ inifile_set_gint32("tiffTypeRGB", tiff_formats[tiff_rtype].id); inifile_set_gint32("tiffTypeI", tiff_formats[tiff_itype].id); inifile_set_gint32("tiffTypeBW", tiff_formats[tiff_btype].id); #endif update_recent_files(TRUE); // Store the list if (files_passed <= 1) inifile_set_gboolean("showDock", show_dock); toggle_dock(FALSE); // To remember dock size // Get rid of extra windows + remember positions delete_layers_window(); // Remember the toolbar settings toolbar_settings_exit(NULL, NULL); run_destroy(wdata); } static void canvas_scroll(main_dd *dt, void **wdata, int what, void **where, scroll_ext *scroll) { if (scroll_zoom) { action_dispatch(origin_slot(where) == drawing_canvas ? ACT_ZOOM : ACT_VWZOOM, scroll->yscroll > 0 ? -1 : 0, FALSE, TRUE); scroll->xscroll = scroll->yscroll = 0; } else if (scroll->state & _Cmask) /* Convert up-down into left-right */ { scroll->xscroll = scroll->yscroll; scroll->yscroll = 0; } } void grad_stroke(int x, int y) { grad_info *grad = gradient + mem_channel; double d, stroke; int i, j; /* No usable gradient */ if (grad->wmode == GRAD_MODE_NONE) return; if (!pen_down || (tool_type > TOOL_SPRAY)) /* Begin stroke */ { grad_path = grad->xv = grad->yv = 0.0; } else /* Continue stroke */ { i = x - tool_ox; j = y - tool_oy; stroke = sqrt(i * i + j * j); /* First step - anchor rear end */ if (grad_path == 0.0) { d = tool_size * 0.5 / stroke; grad_x0 = tool_ox - i * d; grad_y0 = tool_oy - j * d; } /* Scalar product */ d = (tool_ox - grad_x0) * (x - tool_ox) + (tool_oy - grad_y0) * (y - tool_oy); if (d < 0.0) /* Going backward - flip rear */ { d = tool_size * 0.5 / stroke; grad_x0 = x - i * d; grad_y0 = y - j * d; grad_path += tool_size + stroke; } else /* Going forward or sideways - drag rear */ { stroke = sqrt((x - grad_x0) * (x - grad_x0) + (y - grad_y0) * (y - grad_y0)); d = tool_size * 0.5 / stroke; grad_x0 = x + (grad_x0 - x) * d; grad_y0 = y + (grad_y0 - y) * d; grad_path += stroke - tool_size * 0.5; } d = 2.0 / (double)tool_size; grad->xv = (x - grad_x0) * d; grad->yv = (y - grad_y0) * d; } } #define GF_UPDATE 1 #define GF_REDRAW 2 #define GF_DRAW 4 static void do_grad_action(int cmd, int x, int y) { grad_info *grad = gradient + mem_channel; int old[4], prev = grad->status, upd = 0; copy4(old, grad->xy); switch (cmd) { case TC_GRAD_START: grad->xy[0] = grad->xy[2] = x; grad->xy[1] = grad->xy[3] = y; grad->status = GRAD_END; upd = GF_UPDATE | GF_DRAW; break; case TC_GRAD_PICK0: grad->status = GRAD_START; // Fallthrough case TC_GRAD_SET0: grad->xy[0] = x; grad->xy[1] = y; if (cmd == TC_GRAD_SET0) prev = grad->status = GRAD_DONE; upd = GF_UPDATE | GF_REDRAW; break; case TC_GRAD_PICK1: grad->status = GRAD_END; // Fallthrough case TC_GRAD_SET1: grad->xy[2] = x; grad->xy[3] = y; if (cmd == TC_GRAD_SET1) prev = grad->status = GRAD_DONE; upd = GF_UPDATE | GF_REDRAW; break; case TC_GRAD_DRAG0: case TC_GRAD_DRAG1: { int *xy = grad->xy + (cmd == TC_GRAD_DRAG0 ? 0 : 2); if ((xy[0] != x) || (xy[1] != y)) { xy[0] = x; xy[1] = y; upd = GF_UPDATE | GF_REDRAW; } break; } case TC_GRAD_CLEAR: grad->status = GRAD_NONE; upd = GF_UPDATE | GF_DRAW; break; } if (upd & GF_UPDATE) grad_update(grad); if (upd & (GF_REDRAW | GF_DRAW)) { if ((prev == GRAD_DONE) && grad_opacity) cmd_repaint(drawing_canvas); else repaint_grad(upd & GF_REDRAW ? old : NULL); } } static int grad_action(int count, int button, int x, int y) { grad_info *grad = gradient + mem_channel; int i, j, cmd = TC_NONE; /* Left click sets points and picks them up again */ if ((count == 1) && (button == 1)) { /* Start anew */ if (grad->status == GRAD_NONE) cmd = TC_GRAD_START; /* Place starting point */ else if (grad->status == GRAD_START) cmd = TC_GRAD_SET0; /* Place end point */ else if (grad->status == GRAD_END) cmd = TC_GRAD_SET1; /* Pick up nearest end */ else if (grad->status == GRAD_DONE) { i = (x - grad->xy[0]) * (x - grad->xy[0]) + (y - grad->xy[1]) * (y - grad->xy[1]); j = (x - grad->xy[2]) * (x - grad->xy[2]) + (y - grad->xy[3]) * (y - grad->xy[3]); cmd = i < j ? TC_GRAD_PICK0 : TC_GRAD_PICK1; } } /* Everything but left click is irrelevant when no gradient */ else if (grad->status == GRAD_NONE); /* Right click deletes the gradient */ else if (count == 1) cmd = TC_GRAD_CLEAR; /* button != 1 */ /* Motion is irrelevant with gradient in place */ else if (grad->status == GRAD_DONE); /* Motion drags points around */ else if (!count) cmd = grad->status == GRAD_START ? TC_GRAD_DRAG0 : TC_GRAD_DRAG1; return (cmd); } /* Pick color A/B from canvas, or use one given */ static int pick_color(int ox, int oy, int ab, int area[4], int pixel) { int rgba = RGBA_mode && (mem_channel == CHN_IMAGE); int upd = 0, alpha = 255; // opaque if (pixel < 0) // If no pixel value is given { /* Default alpha */ alpha = channel_col_[ab][CHN_ALPHA]; /* Average brush or selection area on double click */ while (area) { int rect[4]; /* Clip to image */ copy4(rect, area); rect[2] += rect[0]; rect[3] += rect[1]; if (!clip(rect, 0, 0, mem_width, mem_height, rect)) break; /* Average utility channel */ if (mem_channel != CHN_IMAGE) pixel = average_channel( mem_img[mem_channel], mem_width, rect); if (MEM_BPP != 3) break; /* Average alpha if needed */ if (rgba && mem_img[CHN_ALPHA]) alpha = average_channel( mem_img[CHN_ALPHA], mem_width, rect); /* Average image channel as RGBA or RGB */ pixel = average_pixels(mem_img[CHN_IMAGE], rgba && alpha && !channel_dis[CHN_ALPHA] ? mem_img[CHN_ALPHA] : NULL, mem_width, rect); break; } /* Failing that, just pick color from image */ if (pixel < 0) { pixel = get_pixel(ox, oy); if (mem_img[CHN_ALPHA]) alpha = mem_img[CHN_ALPHA][mem_width * oy + ox]; } } if (rgba) { upd = channel_col_[ab][CHN_ALPHA] ^ alpha; channel_col_[ab][CHN_ALPHA] = alpha; } if (mem_channel != CHN_IMAGE) { upd |= channel_col_[ab][mem_channel] ^ pixel; channel_col_[ab][mem_channel] = pixel; } else if (mem_img_bpp == 1) { upd |= mem_col_[ab] ^ pixel; mem_col_[ab] = pixel; mem_col_24[ab] = mem_pal[pixel]; } else { png_color *col = mem_col_24 + ab; upd |= PNG_2_INT(*col) ^ pixel; col->red = INT_2_R(pixel); col->green = INT_2_G(pixel); col->blue = INT_2_B(pixel); } return (upd); } static void tool_done() { tint_mode[2] = 0; // Paranoia clone_status &= CLONE_ABS; pen_down = 0; if (col_reverse) { col_reverse = FALSE; mem_swap_cols(FALSE); } mem_undo_prepare(); } static int get_bkg(int xc, int yc, int dclick); static inline int xmmod(int x, int y) { return (x - (x % y)); } /* Mouse event from button/motion on the canvas */ static void mouse_event(mouse_ext *m, int mflag, int dx, int dy) { static int tool_fix, tool_fixv; // Fixate on axis int new_cursor; int i, x0, y0, ox, oy; int x, y, cmd; int zoom = 1, scale = 1; /* !!! This uses the fact that zoom factor is either N or 1/N !!! */ if (can_zoom < 1.0) zoom = rint(1.0 / can_zoom); else scale = rint(can_zoom); x0 = floor_div((m->x - margin_main_x) * zoom, scale) + dx; y0 = floor_div((m->y - margin_main_y) * zoom, scale) + dy; ox = x0 < 0 ? 0 : x0 >= mem_width ? mem_width - 1 : x0; oy = y0 < 0 ? 0 : y0 >= mem_height ? mem_height - 1 : y0; if (!mflag) /* Coordinate fixation */ { if (!(m->state & _Smask)) tool_fix = 0; else if (!(m->state & _Cmask)) /* Shift */ { if (tool_fix != 1) tool_fixv = x0; tool_fix = 1; } else /* Ctrl+Shift */ { if (tool_fix != 2) tool_fixv = y0; tool_fix = 2; } } /* No use when moving cursor by keyboard */ else if (!m->count) tool_fix = 0; if (!tool_fix); /* For rectangular selection it makes sense to fix its width/height */ else if ((tool_type == TOOL_SELECT) && (m->button == 1) && ((marq_status == MARQUEE_DONE) || (marq_status == MARQUEE_SELECTING))) { if (tool_fix == 1) x0 = marq_x2; else y0 = marq_y2; } else if (tool_fix == 1) x0 = tool_fixv; else /* if (tool_fix == 2) */ y0 = tool_fixv; x = x0; y = y0; if (tgrid_snap) /* Snap to grid */ { int xy[2] = { x0, y0 }; /* For everything but rectangular selection, snap with rounding * feels more natural than with flooring - WJ */ if (tool_type != TOOL_SELECT) { xy[0] += tgrid_dx >> 1; xy[1] += tgrid_dy >> 1; } snap_xy(xy); if ((x = x0 = xy[0]) < 0) x += xmmod(tgrid_dx - x - 1, tgrid_dx); if (x >= mem_width) x -= xmmod(tgrid_dx + x - mem_width, tgrid_dx); if ((y = y0 = xy[1]) < 0) y += xmmod(tgrid_dy - y - 1, tgrid_dy); if (y >= mem_height) y -= xmmod(tgrid_dy + y - mem_height, tgrid_dy); } x = x < 0 ? 0 : x >= mem_width ? mem_width - 1 : x; y = y < 0 ? 0 : y >= mem_height ? mem_height - 1 : y; /* ****** Release-event-specific code ****** */ if (m->count < 0) { cmd = TC_NONE; if ((tool_type == TOOL_LINE) && (m->button == 1) && (line_status == LINE_START)) cmd = TC_LINE_NEXT; if (((tool_type == TOOL_SELECT) || (tool_type == TOOL_POLYGON)) && (m->button == 1) && ((marq_status == MARQUEE_SELECTING) || (marq_status == MARQUEE_PASTE_DRAG))) cmd = TC_SEL_STOP; // Finish off dragged polygon selection if ((tool_type == TOOL_POLYGON) && (poly_status == POLY_DRAGGING)) cmd = TC_POLY_CLOSE; if (cmd != TC_NONE) do_tool_action(cmd, x, y, 0); tool_done(); update_menus(); return; } /* ****** Common click/motion handling code ****** */ if ((m->state & _CSmask) == _Cmask) { /* Delete point from polygon */ if ((m->button == 3) && (tool_type == TOOL_POLYGON)) { if (m->count == 1) do_tool_action(TC_POLY_DEL, x, y, 0); } else if (m->button == 2) /* Auto-dither */ { if ((mem_channel == CHN_IMAGE) && (mem_img_bpp == 3)) pressed_dither_A(); } /* Snap clone source to point */ else if ((m->button == 1) && (tool_type == TOOL_CLONE)) { clone_x = x; clone_y = y; clone_dx = clone_dy = 0; move_perim(x, y); } /* Set colour A/B */ else if ((m->button == 1) || (m->button == 3)) { int pix, rect[4]; /* Pick color from tracing image when possible */ pix = get_bkg(m->x + dx * scale, m->y + dy * scale, m->count == 2); /* Double click averages an area */ rect[2] = 0; if (pix >= 0); // Got it from tracing image else if (m->count != 2); // No double click // Have brush square else if (!NO_PERIM(tool_type)) { int ts2 = tool_size >> 1; rect[0] = ox - ts2; rect[1] = oy - ts2; rect[2] = rect[3] = tool_size; } // Have selection marquee else if ((marq_status > MARQUEE_NONE) && (marq_status < MARQUEE_PASTE)) marquee_at(rect); if (pick_color(ox, oy, m->button == 3, // A for left, B for right rect[2] ? rect : NULL, // Area to average pix)) update_stuff(UPD_CAB); } } else if ((m->button == 2) || ((m->button == 3) && (m->state & _Smask))) set_zoom_centre(ox, oy); else if (tool_type == TOOL_GRADIENT) { cmd = grad_action(m->count, m->button, x0, y0); if (cmd != TC_NONE) do_grad_action(cmd, x0, y0); } /* Pure moves are handled elsewhere */ else if (m->button) { cmd = tool_action(m->count, m->button, x, y); if (cmd != TC_NONE) do_tool_action(cmd | TCF_ONCE, x, y, m->pressure); } /* ****** Now to mouse-move-specific part ****** */ /* A focus change caused by a click results in leave and enter events * immediately followed by a click event, so the task to restore the * tracking state then by necessity falls to that click - WJ */ if (!m->count || !is_tracking) { if ((poly_status == POLY_SELECTING) && !m->button) stretch_poly_line(x, y); if ((tool_type == TOOL_SELECT) || (tool_type == TOOL_POLYGON)) { if (marq_status == MARQUEE_DONE) { i = close_to(x, y); if (i != cursor_corner) // Stops excessive CPU/flickering set_cursor(corner_cursor[cursor_corner = i]); } if (marq_status >= MARQUEE_PASTE) { new_cursor = (x >= marq_x1) && (x <= marq_x2) && (y >= marq_y1) && (y <= marq_y2); // Normal/4way if (new_cursor != cursor_corner) // Stops flickering on slow hardware set_cursor((cursor_corner = new_cursor) ? move_cursor : NULL); } } update_xy_bar(x, y); /* TOOL PERIMETER BOX UPDATES */ if ((tool_type == TOOL_CLONE) && !(clone_status & CLONE_DRAG)) { if ((clone_status == CLONE_ABS) || (clone_status == (CLONE_REL | CLONE_TRACK))) { /* Source stays put */ clone_dx = clone_x - x; clone_dy = clone_y - y; } else { /* Source follows cursor */ clone_x = x + clone_dx; clone_y = y + clone_dy; } clone_status = (!m->button && (m->state & _Cmask) ? CLONE_TRACK : 0) | (clone_status & CLONE_ABS); } move_perim(x, y); /* LINE UPDATES */ if ((tool_type == TOOL_LINE) && (line_status == LINE_LINE) && ((line_x2 != x) || (line_y2 != y))) { int old[4]; copy4(old, line_xy); line_x2 = x; line_y2 = y; repaint_line(old); } is_tracking = TRUE; } update_sel_bar(FALSE); } static int canvas_mouse(main_dd *dt, void **wdata, int what, void **where, mouse_ext *mouse) { int rm = unreal_move; mouse_left_canvas = FALSE; /* Steal focus from dock window */ if ((mouse->count > 0) && dock_focused()) cmd_setv(main_window_, NULL, WINDOW_FOCUS); /* Skip synthetic mouse moves */ if (!mouse->count) { if (unreal_move == 3) { unreal_move = 2; return (TRUE); } unreal_move = 0; } /* Do nothing if no image */ if ((mouse->count >= 0) && !mem_img[CHN_IMAGE]) return (TRUE); /* If cursor got warped, will have another movement event to handle */ if (!mouse->count && mouse->button && (tool_type == TOOL_SELECT) && cmd_checkv(where, MOUSE_BOUND)) return (TRUE); mouse_event(mouse, rm & 1, 0, 0); return (mouse->count >= 0); } // Mouse enters/leaves the canvas static void canvas_enter_leave(main_dd *dt, void **wdata, int what, void **where, void *enter) { if (enter) { mouse_left_canvas = FALSE; return; } /* If leaving canvas */ /* Only do this if we have an image */ if (!mem_img[CHN_IMAGE]) return; mouse_left_canvas = TRUE; if (status_on[STATUS_CURSORXY]) cmd_setv(label_bar[STATUS_CURSORXY], "", LABEL_VALUE); if (status_on[STATUS_PIXELRGB]) cmd_setv(label_bar[STATUS_PIXELRGB], "", LABEL_VALUE); if (perim_status > 0) clear_perim(&perim_state); clone_status &= ~CLONE_TRACK; // No tracking w/o perimeter if (tool_type == TOOL_GRADIENT) { /* Let leave hide the dragged line */ grad_info *grad = gradient + mem_channel; if ((grad->status == GRAD_START) || (grad->status == GRAD_END)) repaint_grad(NULL); } if (((tool_type == TOOL_POLYGON) && (poly_status == POLY_SELECTING)) || ((tool_type == TOOL_LINE) && (line_status == LINE_LINE))) repaint_line(NULL); is_tracking = FALSE; } static int render_background(unsigned char *rgb, int x0, int y0, int wid, int hgt, int fwid) { int i, j, k, scale, dx, dy, step, ii, jj, ii0, px, py; int xwid = 0, xhgt = 0, wid3 = wid * 3; /* !!! This uses the fact that zoom factor is either N or 1/N !!! */ if (!chequers_optimize) step = 8; else if (can_zoom < 1.0) step = 6; else { scale = rint(can_zoom); step = scale < 4 ? 6 : scale == 4 ? 8 : scale; } dx = x0 % step; dy = y0 % step; py = (x0 / step + y0 / step) & 1; if (hgt + dy > step) { jj = step - dy; xhgt = (hgt + dy) % step; if (!xhgt) xhgt = step; hgt -= xhgt; xhgt -= step; } else jj = hgt--; if (wid + dx > step) { ii0 = step - dx; xwid = (wid + dx) % step; if (!xwid) xwid = step; wid -= xwid; xwid -= step; } else ii0 = wid--; for (j = 0; ; jj += step) { if (j >= hgt) { if (j > hgt) break; jj += xhgt; } px = py; ii = ii0; for (i = 0; ; ii += step) { if (i >= wid) { if (i > wid) break; ii += xwid; } k = (ii - i) * 3; memset(rgb, greyz[px], k); rgb += k; px ^= 1; i = ii; } rgb += fwid - wid3; for(j++; j < jj; j++) { memcpy(rgb, rgb - fwid, wid3); rgb += fwid; } py ^= 1; } return (!chequers_optimize); // Request async_bk } /// TRACING IMAGE unsigned char *bkg_rgb; int bkg_x, bkg_y, bkg_w, bkg_h, bkg_scale, bkg_flag; int config_bkg(int src) { image_info *img; int l; if (!src) return (TRUE); // No change // Remove old free(bkg_rgb); bkg_rgb = NULL; bkg_w = bkg_h = 0; img = src == 2 ? &mem_image : src == 3 ? &mem_clip : NULL; if (!img || !img->img[CHN_IMAGE]) return (TRUE); // No image l = img->width * img->height; bkg_rgb = malloc(l * 3); if (!bkg_rgb) return (FALSE); if (img->bpp == 1) do_convert_rgb(0, 1, l, bkg_rgb, img->img[CHN_IMAGE], mem_pal); else memcpy(bkg_rgb, img->img[CHN_IMAGE], l * 3); bkg_w = img->width; bkg_h = img->height; return (TRUE); } static int render_bkg(rgbcontext *ctx) { unsigned char *src, *dest; int i, x0, x, y, ty, w3, l3, d0, dd, adj, bs, rxy[4]; int zoom = 1, scale = 1; /* !!! This uses the fact that zoom factor is either N or 1/N !!! */ if (can_zoom < 1.0) zoom = rint(1.0 / can_zoom); else scale = rint(can_zoom); bs = bkg_scale * zoom; adj = bs - scale > 0 ? bs - scale : 0; if (!clip(rxy, floor_div(bkg_x * scale + adj, bs) + margin_main_x, floor_div(bkg_y * scale + adj, bs) + margin_main_y, floor_div((bkg_x + bkg_w) * scale + adj, bs) + margin_main_x, floor_div((bkg_y + bkg_h) * scale + adj, bs) + margin_main_y, ctx->xy)) return (FALSE); w3 = (ctx->xy[2] - ctx->xy[0]) * 3; dest = ctx->rgb + (rxy[1] - ctx->xy[1]) * w3 + (rxy[0] - ctx->xy[0]) * 3; l3 = (rxy[2] - rxy[0]) * 3; d0 = (rxy[0] - margin_main_x) * bs; x0 = floor_div(d0, scale); d0 -= x0 * scale; x0 -= bkg_x; for (ty = -1 , i = rxy[1]; i < rxy[3]; i++) { y = floor_div((i - margin_main_y) * bs, scale) - bkg_y; if (y != ty) { src = bkg_rgb + (y * bkg_w + x0) * 3; for (dd = d0 , x = rxy[0]; x < rxy[2]; x++ , dest += 3) { dest[0] = src[0]; dest[1] = src[1]; dest[2] = src[2]; for (dd += bs; dd >= scale; dd -= scale) src += 3; } ty = y; dest += w3 - l3; } else { memcpy(dest, dest - w3, l3); dest += w3; } } return (scale > 1); // Request async_bk } static int get_bkg(int xc, int yc, int dclick) { int xb, yb, xi, yi, x, scale; /* No background / not RGB / wrong scale */ if (!bkg_flag || (mem_channel != CHN_IMAGE) || (mem_img_bpp != 3) || (can_zoom < 1.0)) return (-1); scale = rint(can_zoom); xi = floor_div(xc - margin_main_x, scale); yi = floor_div(yc - margin_main_y, scale); /* Inside image */ if ((xi >= 0) && (xi < mem_width) && (yi >= 0) && (yi < mem_height)) { /* Pixel must be transparent */ x = mem_width * yi + xi; if (mem_img[CHN_ALPHA] && !channel_dis[CHN_ALPHA] && !mem_img[CHN_ALPHA][x]); // Alpha transparency else if (mem_xpm_trans < 0) return (-1); else if (x *= 3 , MEM_2_INT(mem_img[CHN_IMAGE], x) != PNG_2_INT(mem_pal[mem_xpm_trans])) return (-1); /* Double click averages background under image pixel */ if (dclick) { int vxy[4]; vxy[2] = (vxy[0] = xi * bkg_scale - bkg_x) + bkg_scale; vxy[3] = (vxy[1] = yi * bkg_scale - bkg_y) + bkg_scale; return (clip(vxy, 0, 0, bkg_w, bkg_h, vxy) ? average_pixels(bkg_rgb, NULL, bkg_w, vxy) : -1); } } xb = floor_div((xc - margin_main_x) * bkg_scale, scale) - bkg_x; yb = floor_div((yc - margin_main_y) * bkg_scale, scale) - bkg_y; /* Outside of background */ if ((xb < 0) || (xb >= bkg_w) || (yb < 0) || (yb >= bkg_h)) return (-1); x = (bkg_w * yb + xb) * 3; return (MEM_2_INT(bkg_rgb, x)); } /* This is set when background is at different scale than image */ int async_bk; void setup_row(renderstate *r, int x0, int width, int zoom, int scale, int mw, int xpm, int opac, int bpp, png_color *pal) { renderstate rr; /* Horizontal zoom */ rr.zoom = zoom; rr.scale = scale; x0 %= rr.scale; if (x0 < 0) x0 += rr.scale; if (width + x0 > rr.scale) { rr.dx = rr.scale - x0; x0 = (width + x0) % rr.scale; if (!x0) x0 = rr.scale; width -= x0; rr.xwid = x0 - rr.scale; } else { rr.dx = width--; rr.xwid = 0; } rr.width = width; rr.mw = mw; if ((xpm > -1) && (bpp == 3)) xpm = PNG_2_INT(pal[xpm]); rr.xpm = xpm; rr.opac = opac; rr.bpp = bpp; rr.pal = pal; rr.cmask = 0; *r = rr; } void render_row(renderstate *r, unsigned char *rgb, chanlist base_img, int x, int y, chanlist xtra_img) { renderstate rr = *r; int alpha_blend = !overlay_alpha; unsigned char *src = NULL, *dest, *alpha = NULL, px, beta = 255; int i, j, k, ii, ds = rr.zoom * 3, da = 0; int w_bpp = rr.bpp, w_xpm = rr.xpm; if (xtra_img) { src = xtra_img[CHN_IMAGE]; alpha = xtra_img[CHN_ALPHA]; } if (rr.cmask & CMASK_ALPHA) alpha = β /* Ignore alpha if disabled */ if (!src) src = base_img[CHN_IMAGE] + (rr.mw * y + x) * rr.bpp; if (!alpha) alpha = base_img[CHN_ALPHA] ? base_img[CHN_ALPHA] + rr.mw * y + x : β if (alpha != &beta) da = rr.zoom; dest = rgb; ii = rr.dx; /* Substitute non-transparent "image overlay" colour */ if (rr.cmask & CMASK_IMAGE) { w_bpp = 3; w_xpm = -1; ds = 0; src = channel_rgb[CHN_IMAGE]; } if (!da && (w_xpm < 0) && (rr.opac == 255)) alpha_blend = FALSE; /* Indexed fully opaque */ if ((w_bpp == 1) && !alpha_blend) { for (i = 0; ; ii += rr.scale) { if (i >= rr.width) { if (i > rr.width) break; ii += rr.xwid; } px = *src; src += rr.zoom; for(; i < ii; i++) { dest[0] = rr.pal[px].red; dest[1] = rr.pal[px].green; dest[2] = rr.pal[px].blue; dest += 3; } } } /* Indexed transparent */ else if (w_bpp == 1) { for (i = 0; ; ii += rr.scale , alpha += da) { if (i >= rr.width) { if (i > rr.width) break; ii += rr.xwid; } px = *src; src += rr.zoom; if (!*alpha || (px == w_xpm)) { dest += (ii - i) * 3; i = ii; continue; } rr2_as: if (rr.opac == 255) { dest[0] = rr.pal[px].red; dest[1] = rr.pal[px].green; dest[2] = rr.pal[px].blue; } else { j = 255 * dest[0] + rr.opac * (rr.pal[px].red - dest[0]); dest[0] = (j + (j >> 8) + 1) >> 8; j = 255 * dest[1] + rr.opac * (rr.pal[px].green - dest[1]); dest[1] = (j + (j >> 8) + 1) >> 8; j = 255 * dest[2] + rr.opac * (rr.pal[px].blue - dest[2]); dest[2] = (j + (j >> 8) + 1) >> 8; } rr2_s: dest += 3; if (++i >= ii) continue; if (async_bk) goto rr2_as; dest[0] = *(dest - 3); dest[1] = *(dest - 2); dest[2] = *(dest - 1); goto rr2_s; } } /* RGB fully opaque */ else if (!alpha_blend) { for (i = 0; ; ii += rr.scale , src += ds) { if (i >= rr.width) { if (i > rr.width) break; ii += rr.xwid; } for(; i < ii; i++) { dest[0] = src[0]; dest[1] = src[1]; dest[2] = src[2]; dest += 3; } } } /* RGB transparent */ else { for (i = 0; ; ii += rr.scale , src += ds , alpha += da) { if (i >= rr.width) { if (i > rr.width) break; ii += rr.xwid; } if (!*alpha || (MEM_2_INT(src, 0) == w_xpm)) { dest += (ii - i) * 3; i = ii; continue; } k = rr.opac * alpha[0]; k = (k + (k >> 8) + 1) >> 8; rr4_as: if (k == 255) { dest[0] = src[0]; dest[1] = src[1]; dest[2] = src[2]; } else { j = 255 * dest[0] + k * (src[0] - dest[0]); dest[0] = (j + (j >> 8) + 1) >> 8; j = 255 * dest[1] + k * (src[1] - dest[1]); dest[1] = (j + (j >> 8) + 1) >> 8; j = 255 * dest[2] + k * (src[2] - dest[2]); dest[2] = (j + (j >> 8) + 1) >> 8; } rr4_s: dest += 3; if (++i >= ii) continue; if (async_bk) goto rr4_as; dest[0] = *(dest - 3); dest[1] = *(dest - 2); dest[2] = *(dest - 1); goto rr4_s; } } } void overlay_row(renderstate *r, unsigned char *rgb, chanlist base_img, int x, int y, chanlist xtra_img) { renderstate rr = *r; unsigned char *alpha, *sel, *mask, *dest; int i, j, k, ii, dw, opA, opS, opM, t0, t1, t2, t3; if (xtra_img) { alpha = xtra_img[CHN_ALPHA]; sel = xtra_img[CHN_SEL]; mask = xtra_img[CHN_MASK]; } else alpha = sel = mask = NULL; j = rr.mw * y + x; if (!alpha && base_img[CHN_ALPHA]) alpha = base_img[CHN_ALPHA] + j; if (!sel && base_img[CHN_SEL]) sel = base_img[CHN_SEL] + j; if (!mask && base_img[CHN_MASK]) mask = base_img[CHN_MASK] + j; /* Prepare channel weights (256-based) */ k = rr.cmask & CMASK_IMAGE ? 256 : 256 - channel_opacity[CHN_IMAGE] - (channel_opacity[CHN_IMAGE] >> 7); opA = alpha && overlay_alpha && !(rr.cmask & CMASK_ALPHA) ? channel_opacity[CHN_ALPHA] : 0; opS = sel && !(rr.cmask & CMASK_SEL) ? channel_opacity[CHN_SEL] : 0; opM = mask && !(rr.cmask & CMASK_MASK) ? channel_opacity[CHN_MASK] : 0; /* Nothing to do - don't waste time then */ j = opA + opS + opM; if (!k || !j) return; opA = (k * opA) / j; opS = (k * opS) / j; opM = (k * opM) / j; if (!(opA + opS + opM)) return; dest = rgb; ii = rr.dx; for (i = dw = 0; ; ii += rr.scale , dw += rr.zoom) { if (i >= rr.width) { if (i > rr.width) break; ii += rr.xwid; } t0 = t1 = t2 = t3 = 0; if (opA) { j = opA * (alpha[dw] ^ channel_inv[CHN_ALPHA]); t0 += j; t1 += j * channel_rgb[CHN_ALPHA][0]; t2 += j * channel_rgb[CHN_ALPHA][1]; t3 += j * channel_rgb[CHN_ALPHA][2]; } if (opS) { j = opS * (sel[dw] ^ channel_inv[CHN_SEL]); t0 += j; t1 += j * channel_rgb[CHN_SEL][0]; t2 += j * channel_rgb[CHN_SEL][1]; t3 += j * channel_rgb[CHN_SEL][2]; } if (opM) { j = opM * (mask[dw] ^ channel_inv[CHN_MASK]); t0 += j; t1 += j * channel_rgb[CHN_MASK][0]; t2 += j * channel_rgb[CHN_MASK][1]; t3 += j * channel_rgb[CHN_MASK][2]; } j = (256 * 255) - t0; or_as: k = t1 + j * dest[0]; dest[0] = (k + (k >> 8) + 0x100) >> 16; k = t2 + j * dest[1]; dest[1] = (k + (k >> 8) + 0x100) >> 16; k = t3 + j * dest[2]; dest[2] = (k + (k >> 8) + 0x100) >> 16; or_s: dest += 3; if (++i >= ii) continue; if (async_bk) goto or_as; dest[0] = *(dest - 3); dest[1] = *(dest - 2); dest[2] = *(dest - 1); goto or_s; } } /* Specialized renderer for irregular overlays */ void overlay_preview(renderstate *r, unsigned char *rgb, unsigned char *map, int col, int opacity) { renderstate rr = *r; unsigned char *dest, crgb[3] = {INT_2_R(col), INT_2_G(col), INT_2_B(col)}; int i, j, k, ii, dw; dest = rgb; ii = rr.dx; for (i = dw = 0; ; ii += rr.scale , dw += rr.zoom) { if (i >= rr.width) { if (i > rr.width) break; ii += rr.xwid; } k = opacity * map[dw]; k = (k + (k >> 8) + 1) >> 8; op_as: j = 255 * dest[0] + k * (crgb[0] - dest[0]); dest[0] = (j + (j >> 8) + 1) >> 8; j = 255 * dest[1] + k * (crgb[1] - dest[1]); dest[1] = (j + (j >> 8) + 1) >> 8; j = 255 * dest[2] + k * (crgb[2] - dest[2]); dest[2] = (j + (j >> 8) + 1) >> 8; op_s: dest += 3; if (++i >= ii) continue; if (async_bk) goto op_as; dest[0] = *(dest - 3); dest[1] = *(dest - 2); dest[2] = *(dest - 1); goto op_s; } } typedef struct { int rgb_s; // For when need RGB with 1bpp channel int mask_s; // For most everything int overlay_s; // For extra overlay int channel_s; // For composited channel int alpha_s; // For composited alpha int n_channel_s; // For generated/transformed channel int n_alpha_s; // For generated alpha int n_opacity_s; // For generated opacity unsigned char *rgb, *mask, *overlay, *channel, *alpha, *n_channel, *n_alpha, *n_opacity; // Pointers to same } render_mem_req; typedef struct { unsigned char *wmask, *gmask, *walpha, *galpha; unsigned char *wimg, *gimg, *rgb; int opac, len, bpp; } grad_render_state; static int grad_render_req(render_mem_req *mr, int len) { int bpp; // !!! Only the "slow path" for now if (gradient[mem_channel].status != GRAD_DONE) return (FALSE); bpp = MEM_BPP; mr->mask_s = mr->n_opacity_s = len; mr->channel_s = mr->n_channel_s = len * bpp; if ((mem_channel == CHN_IMAGE) && RGBA_mode && mem_img[CHN_ALPHA]) mr->alpha_s = mr->n_alpha_s = len; if (IS_INDEXED && (grad_opacity < 255)) mr->rgb_s = len * 3; return (TRUE); } static void init_grad_render(render_mem_req *mr, grad_render_state *g, int len, chanlist tlist) { memset(g, 0, sizeof(grad_render_state)); g->wmask = mr->mask; /* Mask */ g->gmask = mr->n_opacity; /* Gradient opacity */ g->gimg = mr->n_channel; /* Gradient image */ g->wimg = mr->channel; /* Resulting image */ g->galpha = mr->n_alpha; /* Gradient alpha */ g->walpha = mr->alpha; /* Resulting alpha */ g->rgb = mr->rgb; /* Indexed to RGB */ tlist[CHN_ALPHA] = g->walpha; tlist[mem_channel] = g->wimg; if (g->rgb) tlist[CHN_IMAGE] = g->rgb; g->opac = IS_INDEXED ? 0 : grad_opacity; g->len = len; g->bpp = MEM_BPP; } static void grad_render(int start, int step, int cnt, int x, int y, unsigned char *mask0, grad_render_state *g) { int l = mem_width * y + x, li = l * mem_img_bpp; prep_mask(start, step, cnt, g->wmask, mask0, mem_img[CHN_IMAGE] + li); grad_pixels(start, step, cnt, x, y, g->wmask, g->gmask, g->gimg, g->galpha); if (g->walpha) memcpy(g->walpha, mem_img[CHN_ALPHA] + l, g->len); process_mask(start, step, cnt, g->wmask, g->walpha, mem_img[CHN_ALPHA] + l, g->galpha, g->gmask, g->opac, channel_dis[CHN_ALPHA]); memcpy(g->wimg, mem_img[mem_channel] + l * g->bpp, g->len * g->bpp); process_img(start, step, cnt, g->wmask, g->wimg, g->wimg, g->gimg, g->gimg, g->bpp, 0); if (g->rgb) blend_indexed(start, step, cnt, g->rgb, mem_img[CHN_IMAGE] + l, g->wimg, mem_img[CHN_ALPHA] + l, g->walpha, grad_opacity); } typedef struct { chanlist tlist; // Channel overrides unsigned char *mask0; // Active mask channel unsigned char *pvi; // Xform/xhold render: temp image row unsigned char *pvm; // Xform/xhold render: temp mask row int rxy[4]; // Clipped area int dx; // Image-space X offset int lx; // Allocated row length int pww; // Logical row length int zoom; // Decimation factor int scale; // Replication factor int lop; // Base opacity int xpm; // Transparent color } main_render_state; typedef struct { chanlist tlist; // Channel overrides for rendering clipboard unsigned char *clip_alpha; // Pasted into alpha channel unsigned char *t_alpha; // Fake pasted alpha unsigned char *pix, *alpha; // Destinations for the above unsigned char *mask, *wmask; // Temp mask: one we use, other we init unsigned char *mask0; // Image mask channel to use unsigned char *xbuf; // Extra buffer for process_img() int opacity, bpp; // Just that int pixf; // Flag: need current channel override filled int dx; // Memory-space X offset int lx; // Allocated row length int pww; // Logical row length int xform; // Flag: do color transform int maskf; // Flag: need mask filled } paste_render_state; /* !!! If ever combined with more than color transform, must not unconditionally * !!! assign potentially shorter (paste area sized) lengths to buffers */ static int paste_render_req(render_mem_req *mr, paste_render_state *p, main_render_state *r) { int rxy[4], bpp, scale = r->scale, zoom = r->zoom; /* Clip paste area to update area */ if (!clip(rxy, (marq_x1 * scale + zoom - 1) / zoom, (marq_y1 * scale + zoom - 1) / zoom, (marq_x2 * scale) / zoom + scale, (marq_y2 * scale) / zoom + scale, r->rxy)) return (FALSE); /* Setup row position and size */ p->dx = (rxy[0] * zoom) / scale; p->pww = xy_span(rxy, scale, 0); p->lx = (p->pww - 1) * zoom + 1; if ((mem_channel == CHN_IMAGE) && mem_img[CHN_ALPHA] && !channel_dis[CHN_ALPHA]) { // Need temp alpha if (mem_clip_alpha || RGBA_mode) mr->alpha_s = r->lx; // Need fake alpha if (!mem_clip_alpha && RGBA_mode) mr->n_alpha_s = p->lx; } bpp = p->bpp = MEM_BPP; // Need temp mask if ((p->maskf = !mr->mask_s)) mr->mask_s = p->lx; // Need temp image p->pixf = !mr->channel_s; /* Need it prefilled if no override data incoming */ mr->channel_s = r->lx * bpp; // Need xform buffer p->xform = mem_preview_clip && (bpp == 3) && (mem_clip_bpp == 3); if (p->xform || NEED_XBUF_PASTE) mr->n_channel_s = p->lx * bpp; /* Setup opacity mode */ if (!IS_INDEXED) p->opacity = tool_opacity; return (TRUE); } /* !!! This function copies existing override set to build its own modified * !!! one, so override set must not be changed after calling it */ static void init_paste_render(render_mem_req *mr, paste_render_state *p, main_render_state *r) { int ddx = p->dx - r->dx; memcpy(p->tlist, r->tlist, sizeof(chanlist)); if ((mem_channel == CHN_IMAGE) && !channel_dis[CHN_ALPHA]) p->clip_alpha = mem_clip_alpha; p->tlist[CHN_ALPHA] = mr->alpha; p->tlist[mem_channel] = mr->channel; p->mask = mr->mask; p->t_alpha = mr->n_alpha; p->xbuf = mr->n_channel; /* Setup "image" (current) channel override */ p->pix = p->tlist[mem_channel] + ddx * p->bpp; /* Setup alpha channel override */ if (mr->alpha) p->alpha = p->tlist[CHN_ALPHA] + ddx; /* Setup mask */ if (mem_channel <= CHN_ALPHA) p->mask0 = r->mask0; if (p->maskf) p->wmask = p->mask; else { p->mask += ddx; if (r->mask0 != p->mask0) /* Mask has wrong data - reuse memory but refill values */ p->wmask = p->mask; } /* Setup fake alpha */ if (p->t_alpha) memset(p->t_alpha, channel_col_A[CHN_ALPHA], p->lx); } static void paste_render(int start, int step, int y, paste_render_state *p) { int ld = mem_width * y + p->dx; int dc = mem_clip_w * (y - marq_y1) + p->dx - marq_x1; int bpp = p->bpp; int cnt = p->pww; unsigned char *clip_src = mem_clipboard + dc * mem_clip_bpp; if (p->wmask) prep_mask(start, step, cnt, p->wmask, p->mask0 ? p->mask0 + ld : NULL, mem_img[CHN_IMAGE] + ld * mem_img_bpp); process_mask(start, step, cnt, p->mask, p->alpha, mem_img[CHN_ALPHA] + ld, p->clip_alpha ? p->clip_alpha + dc : p->t_alpha, mem_clip_mask ? mem_clip_mask + dc : NULL, p->opacity, 0); if (p->xform) /* Apply color transform if preview requested */ { do_transform(start, step, cnt, p->mask, p->xbuf, clip_src, 0); clip_src = p->xbuf; } if (mem_clip_bpp < bpp) { /* Convert paletted clipboard to RGB */ do_convert_rgb(start, step, cnt, p->xbuf, clip_src, mem_clip_paletted ? mem_clip_pal : mem_pal); clip_src = p->xbuf; } process_img(start, step, cnt, p->mask, p->pix, p->pix, clip_src, p->xbuf, bpp, 0); } typedef struct { main_render_state r; paste_render_state p; render_mem_req m; int tflag, xflag, gflag, pflag, lr; int pw; int cxy[4]; unsigned char *rgb, *irgb; threaddata *tdata; // For simplicity } u_render_state; /* Filter preview modes */ #define XF_NONE 0 #define XF_XHOLD 1 #define XF_NOISE 2 static void main_render_req(u_render_state *u) { main_render_state r = u->r; if (!channel_dis[CHN_MASK]) r.mask0 = mem_img[CHN_MASK]; r.xpm = mem_xpm_trans; r.lop = 255; if (u->lr && layer_selected) r.lop = (layer_table_p[layer_selected].opacity * 255 + 50) / 100; /* Setup row position and size */ r.dx = (r.rxy[0] * r.zoom) / r.scale; r.pww = xy_span(r.rxy, r.scale, 0); r.lx = (r.pww - 1) * r.zoom + 1; /* ****** Memory request phase ****** */ /* Color transform preview */ if ((u->tflag = mem_preview && (mem_img_bpp == 3))) { u->m.mask_s = r.lx; if (mem_channel == CHN_IMAGE) u->m.channel_s = r.lx * 3; else u->m.rgb_s = r.lx * 3; } /* Filter preview */ else if ((u->xflag = xhold_preview ? XF_XHOLD : noise_preview ? XF_NOISE : 0)) { u->m.mask_s = r.lx; u->m.channel_s = r.lx * MEM_BPP; } /* Color selective mode preview */ else if (csel_overlay) u->m.overlay_s = r.lx; /* Gradient preview */ else if ((tool_type == TOOL_GRADIENT) && grad_opacity) u->gflag = grad_render_req(&u->m, r.lx); /* Paste preview - can only coexist with transform */ if (show_paste && (marq_status >= MARQUEE_PASTE) && !u->xflag && !u->m.overlay_s && !u->gflag) u->pflag = paste_render_req(&u->m, &u->p, &r); /* Pass the data */ u->r = r; } static void main_render(u_render_state *u, int py, int ph) { main_render_state r = u->r; grad_render_state grstate; renderstate rs; unsigned char *rgb, **tlist = r.tlist, *overlay = u->m.overlay; int j, jj, j0, l, pw2, pw; /* ****** Init phase ****** */ /* Color transform preview */ if (u->tflag) { r.pvm = u->m.mask; r.tlist[CHN_IMAGE] = r.pvi = u->m.rgb ? u->m.rgb : u->m.channel; } /* Threshold preview */ if (u->xflag) { if (mem_channel > CHN_ALPHA) r.mask0 = NULL; r.pvm = u->m.mask; r.tlist[mem_channel] = r.pvi = u->m.channel; } /* Gradient preview */ if (u->gflag) { if (mem_channel > CHN_ALPHA) r.mask0 = NULL; init_grad_render(&u->m, &grstate, r.lx, r.tlist); } /* Paste preview */ if (u->pflag) init_paste_render(&u->m, &u->p, &r); /* Start rendering */ pw2 = r.rxy[2] - r.rxy[0]; setup_row(&rs, r.rxy[0], pw2, r.zoom, r.scale, mem_width, r.xpm, r.lop, u->gflag && grstate.rgb ? 3 : mem_img_bpp, mem_pal); rs.cmask = (hide_image ? CMASK_IMAGE : 0) | (channel_dis[CHN_ALPHA] ? CMASK_ALPHA : 0) | (channel_dis[CHN_SEL] ? CMASK_SEL : 0) | (channel_dis[CHN_MASK] ? CMASK_MASK : 0); j0 = -1; pw2 *= 3; rgb = u->irgb + (py - r.rxy[1]) * (pw = u->pw); for (jj = 0; jj < ph; jj++ , rgb += pw) { j = ((py + jj) * r.zoom) / r.scale; if (j != j0) { j0 = j; l = mem_width * j + r.dx; tlist = r.tlist; /* Default override */ /* Color transform/threshold preview */ if (u->tflag | u->xflag) { unsigned char *src, *img; int bpp = mem_img_bpp; src = img = mem_img[CHN_IMAGE] + l * bpp; prep_mask(0, r.zoom, r.pww, r.pvm, r.mask0 ? r.mask0 + l : NULL, img); if (u->tflag) do_transform(0, r.zoom, r.pww, r.pvm, r.pvi, src, 255); else if (u->xflag == XF_XHOLD) { bpp = MEM_BPP; src = mem_img[mem_channel] + l * bpp; do_xhold(0, r.zoom, r.pww, r.pvm, r.pvi, src); } else /* if (u->xflag == XF_NOISE) */ do_perlin(0, r.zoom, r.pww, r.pvm, r.pvi, r.dx, j); process_img(0, r.zoom, r.pww, r.pvm, r.pvi, r.pvi, src, NULL, bpp, BLENDF_SET); } /* Color selective mode preview */ else if (overlay) { memset(overlay, 0, r.lx); csel_scan(0, r.zoom, r.pww, overlay, mem_img[CHN_IMAGE] + l * mem_img_bpp, csel_data); } /* Gradient preview */ else if (u->gflag) grad_render(0, r.zoom, r.pww, r.dx, j, r.mask0 ? r.mask0 + l : NULL, &grstate); /* Paste preview - should be after transform */ if (u->pflag && (j >= marq_y1) && (j <= marq_y2)) { tlist = u->p.tlist; /* Paste-area override */ if (u->p.alpha) memcpy(tlist[CHN_ALPHA], mem_img[CHN_ALPHA] + l, r.lx); if (u->p.pixf) memcpy(tlist[mem_channel], mem_img[mem_channel] + l * u->p.bpp, r.lx * u->p.bpp); paste_render(0, r.zoom, j, &u->p); } } else if (!async_bk) { memcpy(rgb, rgb - pw, pw2); continue; } render_row(&rs, rgb, mem_img, r.dx, j, tlist); if (!overlay) overlay_row(&rs, rgb, mem_img, r.dx, j, tlist); else overlay_preview(&rs, rgb, overlay, csel_preview, csel_preview_a); } } /// GRID int grid_rgb[GRID_MAX]; // Grid colors to use int mem_show_grid; // Boolean show toggle int mem_grid_min; // Minimum zoom to show it at int color_grid; // If to use grid coloring int show_tile_grid; // Tile grid toggle int tgrid_x0, tgrid_y0; // Tile grid origin int tgrid_dx, tgrid_dy; // Tile grid spacing int tgrid_snap; // Coordinates snap toggle /* Snap coordinate pair to tile grid (floored) */ void snap_xy(int *xy) { int dx, dy; dx = (xy[0] - tgrid_x0) % tgrid_dx; xy[0] -= dx + (dx < 0 ? tgrid_dx : 0); dy = (xy[1] - tgrid_y0) % tgrid_dy; xy[1] -= dy + (dy < 0 ? tgrid_dy : 0); } /* Buffer stores interleaved transparency bits for two pixel rows; current * row in bits 0, 2, etc., previous one in bits 1, 3, etc. */ static void scan_trans(unsigned char *dest, int delta, int y, int x, int w) { static unsigned char beta = 255; unsigned char *src, *srca = β int i, ofs, bit, buf, xpm, da = 0, bpp = mem_img_bpp; delta += delta; dest += delta >> 3; delta &= 7; if (y >= mem_height) // Clear { for (i = 0; i < w; i++ , dest++) *dest = (*dest & 0x55) << 1; return; } xpm = mem_xpm_trans < 0 ? -1 : bpp == 1 ? mem_xpm_trans : PNG_2_INT(mem_pal[mem_xpm_trans]); ofs = y * mem_width + x; src = mem_img[CHN_IMAGE] + ofs * bpp; if (mem_img[CHN_ALPHA]) srca = mem_img[CHN_ALPHA] + ofs , da = 1; bit = 1 << delta; buf = (*dest & 0x55) << 1; for (i = 0; i < w; i++ , src += bpp , srca += da) { if (*srca && ((bpp == 1 ? *src : MEM_2_INT(src, 0)) != xpm)) buf |= bit; if ((bit <<= 2) < 0x100) continue; *dest++ = buf; buf = (*dest & 0x55) << 1; bit = 1; } *dest = buf; } /* Draw grid on rgb memory */ static void draw_grid(unsigned char *rgb, int x, int y, int w, int h, int l) { /* !!! This limit IN THEORY can be violated by a sufficiently huge screen, if * clipping to image isn't enforced in some fashion; this code can be made to * detect the violation and do the clipping (on X axis) for itself - really * colored is only the image proper + 1 pixel to bottom & right of it */ unsigned char lbuf[(MAX_WIDTH * 2 + 2 + 7) / 8 + 2]; int dx, dy, step = can_zoom; int i, j, k, yy, wx, ww, x0, xw; l *= 3; dx = (x - margin_main_x) % step; if (dx <= 0) dx += step; dy = (y - margin_main_y) % step; if (dy <= 0) dy += step; /* Use dumb code for uncolored grid */ if (!color_grid || (x + w <= margin_main_x) || (y + h <= margin_main_y) || (x > margin_main_x + mem_width * step) || (y > margin_main_y + mem_height * step)) { unsigned char *tmp; int i, j, k, step3, tc; tc = grid_rgb[color_grid ? GRID_TRANS : GRID_NORMAL]; dx = (step - dx) * 3; w *= 3; for (k = dy , i = 0; i < h; i++ , k++) { tmp = rgb + i * l; if (k == step) /* Filled line */ { j = k = 0; step3 = 3; } else /* Spaced dots */ { j = dx; step3 = step * 3; } for (tmp += j; j < w; j += step3 , tmp += step3) { tmp[0] = INT_2_R(tc); tmp[1] = INT_2_G(tc); tmp[2] = INT_2_B(tc); } } return; } wx = floor_div(x - margin_main_x - 1, step); ww = (w + dx + step - 1) / step + 1; memset(lbuf, 0, (ww + ww + 7 + 16) >> 3); // Init to transparent x0 = wx < 0 ? 0 : wx; xw = (wx + ww < mem_width ? wx + ww : mem_width) - x0; wx = x0 - wx; yy = floor_div(y - margin_main_y, step); /* Initial row fill */ if (dy == step) yy--; if ((yy >= 0) && (yy < mem_height)) // Else it stays cleared scan_trans(lbuf, wx, yy, x0, xw); for (k = dy , i = 0; i < h; i++ , k++) { unsigned char *tmp = rgb + i * l, *buf = lbuf + 2; // Horizontal span if (k == step) { int nv, tc, kk; yy++; k = 0; // Fill one more row if ((yy >= 0) && (yy <= mem_height + 1)) scan_trans(lbuf, wx, yy, x0, xw); nv = (lbuf[0] + (lbuf[1] << 8)) ^ 0x2FFFF; // Invert tc = grid_rgb[((nv & 3) + 1) >> 1]; for (kk = dx , j = 0; j < w; j++ , kk++ , tmp += 3) { if (kk != step) // Span { tmp[0] = INT_2_R(tc); tmp[1] = INT_2_G(tc); tmp[2] = INT_2_B(tc); continue; } // Intersection /* 0->0, 15->2, in-between remains between */ tc = grid_rgb[((nv & 0xF) * 9 + 0x79) >> 7]; tmp[0] = INT_2_R(tc); tmp[1] = INT_2_G(tc); tmp[2] = INT_2_B(tc); nv >>= 2; if (nv < 0x400) nv ^= (*buf++ << 8) ^ 0x2FD00; // Invert tc = grid_rgb[((nv & 3) + 1) >> 1]; kk = 0; } } // Vertical spans else { int nv = (lbuf[0] + (lbuf[1] << 8)) ^ 0x2FFFF; // Invert j = step - dx; tmp += j * 3; for (; j < w; j += step , tmp += step * 3) { /* 0->0, 5->2, in-between remains between */ int tc = grid_rgb[((nv & 5) + 3) >> 2]; tmp[0] = INT_2_R(tc); tmp[1] = INT_2_G(tc); tmp[2] = INT_2_B(tc); nv >>= 2; if (nv < 0x400) nv ^= (*buf++ << 8) ^ 0x2FD00; // Invert } } } } /* Draw tile grid on rgb memory */ static void draw_tgrid(unsigned char *rgb, int x, int y, int w, int h, int l) { unsigned char *tmp, *tm2; int i, j, k, dx, dy, nx, ny, xx, yy, tc, zoom = 1, scale = 1; /* !!! This uses the fact that zoom factor is either N or 1/N !!! */ if (can_zoom < 1.0) zoom = rint(1.0 / can_zoom); else scale = rint(can_zoom); if ((tgrid_dx < zoom * 2) || (tgrid_dy < zoom * 2)) return; // Too dense dx = tgrid_x0 ? tgrid_dx - tgrid_x0 : 0; nx = (x * zoom - dx) / (tgrid_dx * scale); if (nx < 0) nx = 0; nx++; dx++; dy = tgrid_y0 ? tgrid_dy - tgrid_y0 : 0; ny = (y * zoom - dy) / (tgrid_dy * scale); if (ny < 0) ny = 0; ny++; dy++; xx = ((nx * tgrid_dx - dx) * scale) / zoom + scale - 1; yy = ((ny * tgrid_dy - dy) * scale) / zoom + scale - 1; if ((xx >= x + w) && (yy >= y + h)) return; // Entirely inside grid cell l *= 3; tc = grid_rgb[GRID_TILE]; for (i = 0; i < h; i++) { tmp = rgb + l * i; if (y + i == yy) /* Filled line */ { for (j = 0; j < w; j++ , tmp += 3) { tmp[0] = INT_2_R(tc); tmp[1] = INT_2_G(tc); tmp[2] = INT_2_B(tc); } yy = ((++ny * tgrid_dy - dy) * scale) / zoom + scale - 1; continue; } /* Spaced dots */ for (k = xx , j = nx + 1; k < x + w; j++) { tm2 = tmp + (k - x) * 3; tm2[0] = INT_2_R(tc); tm2[1] = INT_2_G(tc); tm2[2] = INT_2_B(tc); k = ((j * tgrid_dx - dx) * scale) / zoom + scale - 1; } } } /* Draw segmentation contours on rgb memory */ static void draw_segments(unsigned char *rgb, int x, int y, int w, int h, int l) { unsigned char lbuf[(MAX_WIDTH * 2 + 7) / 8]; int i, j, k, j0, kk, dx, dy, wx, ww, yy, vf, tc, zoom = 1, scale = 1; /* !!! This uses the fact that zoom factor is either N or 1/N !!! */ if (can_zoom < 1.0) zoom = rint(1.0 / can_zoom); else scale = rint(can_zoom); l *= 3; dx = x % scale; wx = x / scale; ww = (w + dx + scale - 1) / scale; dy = y % scale; yy = y / scale; /* Initial row fill */ mem_seg_scan(lbuf, yy, wx, ww, zoom, seg_preview); tc = grid_rgb[GRID_SEGMENT]; j0 = !!dx; vf = (scale == 1) | 2; // Draw both edges in one pixel if no zoom for (k = dy , i = 0; i < h; i++ , k++) { unsigned char *tmp, *buf; int nv; if (k == scale) { mem_seg_scan(lbuf, ++yy, wx, ww, zoom, seg_preview); k = 0; } /* Horizontal lines */ if (!k && (scale > 1)) { tmp = rgb + i * l; buf = lbuf; nv = *buf++ + 0x100; for (kk = dx, j = 0; j < w; j++ , tmp += 3) { if (nv & 1) // Draw grid line { tmp[0] = INT_2_R(tc); tmp[1] = INT_2_G(tc); tmp[2] = INT_2_B(tc); } if (++kk == scale) { if ((nv >>= 2) == 1) nv = *buf++ + 0x100; kk = 0; } } } /* Vertical/mixed lines */ tmp = rgb + i * l + (j0 * scale - dx) * 3; buf = lbuf; nv = (*buf++ + 0x100) >> (j0 * 2); for (j = j0; j < ww; j++ , tmp += scale * 3) { if (nv & vf) { tmp[0] = INT_2_R(tc); tmp[1] = INT_2_G(tc); tmp[2] = INT_2_B(tc); } if ((nv >>= 2) == 1) nv = *buf++ + 0x100; } } } /* Draw dashed line to RGB memory or straight to canvas */ void draw_dash(int c0, int c1, int ofs, int x, int y, int w, int h, rgbcontext *ctx) { rgbcontext cw; unsigned char *dest; int i, k, l, ww, step, cc[2] = { c0, c1 }; if (!ctx) { cw.xy[2] = (cw.xy[0] = x) + w; cw.xy[3] = (cw.xy[1] = y) + h; cw.rgb = NULL; cmd_setv(drawing_canvas, ctx = &cw, CANVAS_PAINT); if (!cw.rgb) return; } else if (!clip(cw.xy, x, y, x + w, y + h, ctx->xy)) return; ofs += cw.xy[0] + cw.xy[1] - x - y; // offset in pattern ww = (ctx->xy[2] - ctx->xy[0]) * 3; if (w == 1) // Vertical { step = ww; l = cw.xy[3] - cw.xy[1]; } else // Horizontal { step = 3; l = cw.xy[2] - cw.xy[0]; } dest = ctx->rgb + (cw.xy[1] - ctx->xy[1]) * ww + (cw.xy[0] - ctx->xy[0]) * 3; for (i = 0; i < l; i++) { k = cc[((i + ofs) / 3) & 1]; dest[0] = INT_2_R(k); dest[1] = INT_2_G(k); dest[2] = INT_2_B(k); dest += step; } if (ctx == &cw) cmd_setv(drawing_canvas, ctx, CANVAS_PAINT); } /* Polygon drawing to RGB memory */ void draw_poly(int *xy, int cnt, int shift, int x00, int y00, rgbcontext *ctx) { linedata line; unsigned char *rgb; int i, x0, y0, x1, y1, dx, dy, a0, a, w, vxy[4]; copy4(vxy, ctx->xy); w = vxy[2] - vxy[0]; --vxy[2]; --vxy[3]; x1 = x00 + *xy++; y1 = y00 + *xy++; a = x1 < vxy[0] ? 1 : x1 > vxy[2] ? 2: y1 < vxy[1] ? 3 : y1 > vxy[3] ? 4 : 5; for (i = 1; i < cnt; i++) { x0 = x1; y0 = y1; a0 = a; x1 = x00 + *xy++; y1 = y00 + *xy++; dx = abs(x1 - x0); dy = abs(y1 - y0); if (dx < dy) dx = dy; shift += dx; switch (a0) // Basic clipping { // Already visible - skip if same point case 0: if (!dx) continue; break; // Left of window - skip if still there case 1: if (x1 < vxy[0]) continue; break; // Right of window case 2: if (x1 > vxy[2]) continue; break; // Top of window case 3: if (y1 < vxy[1]) continue; break; // Bottom of window case 4: if (y1 > vxy[3]) continue; break; // First point - never skip case 5: a0 = 0; break; } // May be visible - find where the other end goes a = x1 < vxy[0] ? 1 : x1 > vxy[2] ? 2 : y1 < vxy[1] ? 3 : y1 > vxy[3] ? 4 : 0; line_init(line, x0, y0, x1, y1); if (a0 + a) // If both ends inside area, no clipping needed { if (line_clip(line, vxy, &a0) < 0) continue; dx -= a0; } // Draw to RGB for (dx = shift - dx; line[2] >= 0; line_step(line) , dx++) { rgb = ctx->rgb + ((line[1] - ctx->xy[1]) * w + (line[0] - ctx->xy[0])) * 3; rgb[0] = rgb[1] = rgb[2] = ((~dx >> 2) & 1) * 255; } } } /* Clip area to image & align rgb pointer with it */ static unsigned char *clip_to_image(int *rect, unsigned char *rgb, int *vxy) { int rxy[4], mw, mh; /* Clip update area to image bounds */ xy_origin(rxy, vxy, margin_main_x, margin_main_y); canvas_size(&mw, &mh); if (!clip(rect, 0, 0, mw, mh, rxy)) return (NULL); /* Align buffer with image */ rgb += ((rxy[2] - rxy[0]) * (rect[1] - rxy[1]) + (rect[0] - rxy[0])) * 3; return (rgb); } /* Map clipping rectangle to line-space, for use with line_clip() */ void prepare_line_clip(int *lxy, int *vxy, int scale) { int i; for (i = 0; i < 4; i++) lxy[i] = floor_div(vxy[i] - margin_main_xy[i & 1] - (i >> 1), scale); } static void canvas_render(u_render_state *u, int py, int ph) { int cxy[4], rxy[4], pw = u->pw; unsigned char *rgb = NULL; /* Render underlying layers */ if (u->lr) { copy4(cxy, u->cxy); rgb = u->rgb + (py - cxy[1]) * pw; cxy[3] = (cxy[1] = py) + ph; render_layers(rgb, cxy, pw, u->r.zoom, u->r.scale, 0, layer_selected - 1, FALSE); } /* Render canvas image */ if (u->irgb && clip(rxy, 0, py, INT_MAX, py + ph, u->r.rxy)) main_render(u, rxy[1], rxy[3] - rxy[1]); /* Render overlying layers */ if (u->lr) render_layers(rgb, cxy, pw, u->r.zoom, u->r.scale, layer_selected + 1, layers_total, FALSE); } #ifdef U_THREADS static void do_canvas_render(tcb *thread) { u_render_state *u = thread->data; int *rr = u->lr ? u->cxy : u->r.rxy; int y0 = rr[1], scale = u->r.scale, h = thread->nsteps * scale; int d = floor_mod(y0, scale); if (thread->step0) y0 += thread->step0 * scale - d; else h -= d; if (h > rr[3] - y0) h = rr[3] - y0; canvas_render(u, y0, h); } #endif int kpix_threads; // Min kpixels per render thread static int paint_canvas(void *dt, void **wdata, int what, void **where, rgbcontext *ctx) { u_render_state u; unsigned char *irgb, *rgb = ctx->rgb; int rect[4], vxy[4]; int i, px, py, pw, ph, zoom = 1, scale = 1, paste_f = FALSE; pw = ctx->xy[2] - (px = ctx->xy[0]); ph = ctx->xy[3] - (py = ctx->xy[1]); memset(rgb, mem_background, pw * ph * 3); /* Find out which part is image */ irgb = clip_to_image(rect, rgb, ctx->xy); /* !!! This uses the fact that zoom factor is either N or 1/N !!! */ if (can_zoom < 1.0) zoom = rint(1.0 / can_zoom); else scale = rint(can_zoom); /* Prepare data for renderer */ memset(&u, 0, sizeof(u)); u.r.zoom = zoom; u.r.scale = scale; u.rgb = rgb; u.irgb = irgb; u.pw = pw * 3; xy_origin(u.cxy, ctx->xy, margin_main_x, margin_main_y); u.lr = layers_total && show_layers_main; /* Set up image for renderer */ if (irgb) { copy4(u.r.rxy, rect); main_render_req(&u); paste_f = u.pflag; } if (bkg_flag && bkg_rgb) async_bk = render_bkg(ctx); /* Tracing image */ else if (!u.lr) /* Render default background if no layers shown */ { if (irgb && ((mem_xpm_trans >= 0) || (!overlay_alpha && mem_img[CHN_ALPHA] && !channel_dis[CHN_ALPHA]))) async_bk = render_background(irgb, rect[0], rect[1], rect[2] - rect[0], rect[3] - rect[1], pw * 3); } while (irgb || u.lr) { #ifdef U_THREADS int nt, nt2, pww = 0, wh = 0; size_t vpix = 0; /* Calculate amount of work for threads */ if (irgb) { wh = xy_span(rect, scale, 1); pww = xy_span(rect, scale, 0); vpix = pww * wh; } if (u.lr) { size_t vp2 = render_layers(NULL, u.cxy, 0, zoom, scale, 0, layers_total, FALSE); if (!vp2) break; // Nothing here, move along // !!! Heuristic weight; maybe 1/8 would be better? vpix += vp2 / 4 - vpix / 4; u.rgb += ((u.cxy[1] - py + margin_main_y) * pw + u.cxy[0] - px + margin_main_x) * 3; wh = xy_span(u.cxy, scale, 1); pww = xy_span(u.cxy, async_bk ? 1 : scale, 0); } nt = image_threads(pww, wh); nt2 = ceil_div(vpix, kpix_threads * 1024); if (nt2 > nt) nt2 = nt; #ifndef HAVE__SFA /* csel_scan() takes 50%+ of per-row time, so when it cannot share * its color cache, 2 threads can interleave calls to it but more * than 2 only waste even more time on lock contention - WJ */ if ((nt2 > 2) && (u.m.overlay_s || (mem_cselect && (u.tflag | u.xflag | u.gflag | u.pflag)))) nt2 = 2; #endif u.tdata = talloc(MA_SKIP_ZEROSIZE | MA_FLAG_NONE, nt2, &u, sizeof(u), NULL, #else /* ifndef U_THREADS */ u.tdata = multialloc(MA_SKIP_ZEROSIZE | MA_FLAG_NONE, #endif &u.m.rgb, u.m.rgb_s, &u.m.mask, u.m.mask_s, &u.m.overlay, u.m.overlay_s, &u.m.channel, u.m.channel_s, &u.m.alpha, u.m.alpha_s, &u.m.n_channel, u.m.n_channel_s, &u.m.n_alpha, u.m.n_alpha_s, &u.m.n_opacity, u.m.n_opacity_s, NULL); #ifdef U_THREADS if (u.tdata && (u.tdata != MEM_NONE)) // Threads w/allocation { /* !!! do_transform(), and any other preview code that * self-initializes global tables, should get an init * call here to avoid a thread clash - WJ */ if (u.tflag) do_transform(0, 0, 0, NULL, NULL, NULL, 255); nt /= u.tdata->count; if (nt > MAX_TH_STRIPS) nt = MAX_TH_STRIPS; u.tdata->chunks = nt; u.tdata->silent = TRUE; launch_threads(do_canvas_render, u.tdata, NULL, wh); } else #endif if (u.tdata) // Single thread { int *rr = u.lr ? u.cxy : rect; canvas_render(&u, rr[1], rr[3] - rr[1]); } if (u.tdata != MEM_NONE) free(u.tdata); break; } /* No grid at all */ if (!mem_show_grid || (scale < mem_grid_min)); /* No paste - single area */ else if (!paste_f) draw_grid(rgb, px, py, pw, ph, pw); /* With paste - zero to four areas */ else { int n, x0, y0, w0, h0, rect04[5 * 4], *p = rect04; unsigned char *r; w0 = (marq_x2 < mem_width ? marq_x2 + 1 : mem_width) * scale; x0 = marq_x1 > 0 ? marq_x1 * scale : 0; w0 -= x0; x0 += margin_main_x; h0 = (marq_y2 < mem_height ? marq_y2 + 1 : mem_height) * scale; y0 = marq_y1 > 0 ? marq_y1 * scale : 0; h0 -= y0; y0 += margin_main_y; n = clip4(rect04, px, py, pw, ph, x0, y0, w0, h0); while (n--) { p += 4; r = rgb + ((p[1] - py) * pw + (p[0] - px)) * 3; draw_grid(r, p[0], p[1], p[2], p[3], pw); } } /* Tile grid */ if (show_tile_grid && irgb) draw_tgrid(irgb, rect[0], rect[1], rect[2] - rect[0], rect[3] - rect[1], pw); /* Segmentation preview */ if (seg_preview && irgb) draw_segments(irgb, rect[0], rect[1], rect[2] - rect[0], rect[3] - rect[1], pw); async_bk = FALSE; /* !!! All other over-the-image things have to be redrawn here as well !!! */ prepare_line_clip(vxy, ctx->xy, scale); /* Redraw gradient line if needed */ i = gradient[mem_channel].status; if ((mem_gradient || (tool_type == TOOL_GRADIENT)) && (mouse_left_canvas ? (i == GRAD_DONE) : (i != GRAD_NONE))) refresh_line(3, vxy, ctx); /* Draw marquee as we may have drawn over it */ if ((marq_status != MARQUEE_NONE) && irgb) paint_marquee(MARQ_SHOW, 0, 0, ctx); if ((tool_type == TOOL_POLYGON) && poly_points) paint_poly_marquee(ctx); /* Redraw line if needed */ if ((((tool_type == TOOL_POLYGON) && (poly_status == POLY_SELECTING)) || ((tool_type == TOOL_LINE) && (line_status == LINE_LINE))) && !mouse_left_canvas) refresh_line(tool_type == TOOL_LINE ? 1 : 2, vxy, ctx); /* Redraw perimeter if needed */ if (perim_status) repaint_perim(ctx); return (TRUE); // now draw this } void repaint_canvas(int px, int py, int pw, int ph) { rgbcontext ctx = { { px, py, px + pw, py + ph }, NULL }; cmd_setv(drawing_canvas, &ctx, CANVAS_PAINT); if (!ctx.rgb) return; paint_canvas(NULL, NULL, 0, NULL, &ctx); cmd_setv(drawing_canvas, &ctx, CANVAS_PAINT); } /* Update x,y,w,h area of current image */ void main_update_area(int x, int y, int w, int h) { int zoom, scale, rxy[4]; if (can_zoom < 1.0) { zoom = rint(1.0 / can_zoom); w += x; h += y; x = floor_div(x + zoom - 1, zoom); y = floor_div(y + zoom - 1, zoom); w = (w - x * zoom + zoom - 1) / zoom; h = (h - y * zoom + zoom - 1) / zoom; if ((w <= 0) || (h <= 0)) return; } else { scale = rint(can_zoom); x *= scale; y *= scale; w *= scale; h *= scale; if (color_grid && mem_show_grid && (scale >= mem_grid_min)) w++ , h++; // Redraw grid lines bordering the area } rxy[2] = (rxy[0] = x + margin_main_x) + w; rxy[3] = (rxy[1] = y + margin_main_y) + h; cmd_setv(drawing_canvas, rxy, CANVAS_REPAINT); } /* Get zoomed canvas size */ void canvas_size(int *w, int *h) { int zoom = 1, scale = 1; /* !!! This uses the fact that zoom factor is either N or 1/N !!! */ if (can_zoom < 1.0) zoom = rint(1.0 / can_zoom); else scale = rint(can_zoom); *w = (mem_width * scale + zoom - 1) / zoom; *h = (mem_height * scale + zoom - 1) / zoom; } static void clear_perim(perim_info *p) { int ps = p->mode; p->mode = 0; /* Cleared */ clear_perim_real(p->x, p->y, p->s); if (ps == TOOL_CLONE + 1) clear_perim_real(p->x + p->cx, p->y + p->cy, p->s); } static void repaint_perim_real(int c, int ox, int oy, rgbcontext *ctx) { int w, h, x0, y0, x1, y1, zoom = 1, scale = 1; /* !!! This uses the fact that zoom factor is either N or 1/N !!! */ if (can_zoom < 1.0) zoom = rint(1.0 / can_zoom); else scale = rint(can_zoom); ox += perim_x; oy += perim_y; x0 = margin_main_x + (ox * scale) / zoom; y0 = margin_main_y + (oy * scale) / zoom; x1 = margin_main_x + ((ox + perim_s - 1) * scale) / zoom + scale - 1; y1 = margin_main_y + ((oy + perim_s - 1) * scale) / zoom + scale - 1; w = x1 - x0 + 1; h = y1 - y0 + 1; draw_dash(c, RGB_2_INT(0, 0, 0), 0, x0, y0, 1, h, ctx); draw_dash(c, RGB_2_INT(0, 0, 0), 0, x1, y0, 1, h, ctx); draw_dash(c, RGB_2_INT(0, 0, 0), 0, x0 + 1, y0, w - 2, 1, ctx); draw_dash(c, RGB_2_INT(0, 0, 0), 0, x0 + 1, y1, w - 2, 1, ctx); } static void repaint_perim(rgbcontext *ctx) { repaint_perim_real(RGB_2_INT(255, 255, 255), 0, 0, ctx); if (perim_status == TOOL_CLONE + 1) repaint_perim_real(RGB_2_INT(255, 0, 0), perim_cx, perim_cy, ctx); } static void move_perim(int x, int y) { perim_info p = perim_state; perim_status = 0; /* Clear */ perim_wx = x; /* Remember */ perim_wy = y; if ((tool_size * can_zoom > 4) && !NO_PERIM(tool_type) && !mouse_left_canvas) { perim_x = x - (tool_size >> 1); perim_y = y - (tool_size >> 1); perim_s = tool_size; perim_cx = clone_dx; perim_cy = clone_dy; perim_status = tool_type + 1; /* Draw */ } if (p.mode) clear_perim(&p); if (perim_status) repaint_perim(NULL); } static void configure_canvas() { int new_margin_x = 0, new_margin_y = 0; if (canvas_image_centre) { int w, h, wh[2]; cmd_peekv(drawing_canvas, wh, sizeof(wh), CANVAS_SIZE); canvas_size(&w, &h); if ((wh[0] -= w) > 0) new_margin_x = wh[0] >> 1; if ((wh[1] -= h) > 0) new_margin_y = wh[1] >> 1; } if ((new_margin_x != margin_main_x) || (new_margin_y != margin_main_y)) { margin_main_x = new_margin_x; margin_main_y = new_margin_y; cmd_repaint(drawing_canvas); // Force redraw of whole canvas as the margin has shifted } vw_realign(); // Update the view window as needed } void force_main_configure() { if (cmd_mode) return; if (drawing_canvas) configure_canvas(); if (view_showing && vw_drawing) vw_configure(); } void set_cursor(void **what) // Set mouse cursor { cmd_cursor(drawing_canvas, !cursor_tool ? NULL : what ? what : m_cursor[tool_type]); } void change_to_tool(int icon) { grad_info *grad; void *var, **slot = icon_buttons[icon]; int i, t, update = UPD_SEL; if (!cmd_checkv(slot, SLOT_SENSITIVE)) return; // Blocked // !!! Unnecessarily complicated approach - better add a peek operation var = cmd_read(slot, NULL); if (*(int *)var != TOOL_ID(slot)) cmd_set(slot, TRUE); switch (icon) { case TTB_PAINT: t = brush_type; break; case TTB_SHUFFLE: t = TOOL_SHUFFLE; break; case TTB_FLOOD: t = TOOL_FLOOD; break; case TTB_LINE: t = TOOL_LINE; break; case TTB_SMUDGE: t = TOOL_SMUDGE; break; case TTB_CLONE: t = TOOL_CLONE; break; case TTB_SELECT: t = TOOL_SELECT; break; case TTB_POLY: t = TOOL_POLYGON; break; case TTB_GRAD: t = TOOL_GRADIENT; break; default: return; } /* Tool hasn't changed (likely, recursion changed it from under us) */ if (t == tool_type) return; /* Make sure tool release actions are done */ tool_done(); if (perim_status) clear_perim(&perim_state); i = tool_type; tool_type = t; grad = gradient + mem_channel; if (i == TOOL_LINE) stop_line(); if ((i == TOOL_GRADIENT) && (grad->status != GRAD_NONE)) { if (grad->status != GRAD_DONE) grad->status = GRAD_NONE; else if (grad_opacity) update |= CF_DRAW; else if (!mem_gradient) repaint_grad(NULL); } if ( marq_status != MARQUEE_NONE) { if (!script_cmds && paste_commit && (marq_status >= MARQUEE_PASTE)) { commit_paste(FALSE, NULL); pen_down = 0; mem_undo_prepare(); } marq_status = MARQUEE_NONE; // Marquee is on so lose it! update |= CF_DRAW; // Needed to clear selection } if ( poly_status != POLY_NONE) { poly_status = POLY_NONE; // Marquee is on so lose it! poly_points = 0; update |= CF_DRAW; // Needed to clear selection } if (tool_type == TOOL_CLONE) init_clone(); /* Persistent selection frame */ // !!! To NOT show selection frame while placing gradient // if ((tool_type == TOOL_SELECT) if (((tool_type == TOOL_SELECT) || (tool_type == TOOL_GRADIENT)) && (marq_x1 >= 0) && (marq_y1 >= 0) && (marq_x2 >= 0) && (marq_y2 >= 0)) { marq_status = MARQUEE_DONE; paint_marquee(MARQ_SHOW, 0, 0, NULL); } if ((tool_type == TOOL_GRADIENT) && (grad->status != GRAD_NONE)) { if (grad_opacity) update |= CF_DRAW; else repaint_grad(NULL); } update_stuff(update); move_perim(perim_wx, perim_wy); // New perimeter in old location } static void pressed_view_hori(int state) { view_vsplit = !!state; if (view_showing) view_show(); // rearrange } void set_image(int state) { static int depth = 0; if (state ? --depth : depth++) return; cmd_showhide(main_split, state); } static char read_hex_dub(char *in) // Read hex double { static const char chars[] = "0123456789abcdef0123456789ABCDEF"; const char *p1, *p2; p1 = strchr(chars, in[0]); p2 = strchr(chars, in[1]); return (p1 && p2 ? (((p1 - chars) & 15) << 4) + ((p2 - chars) & 15) : '?'); } static void parse_drag(main_dd *dt, void **wdata, int what, void **where, drag_ext *drag) { #ifdef WIN32 char fname[PATHTXT]; #else char fname[PATHBUF]; #endif char ch, *tp, *tp2, *txt = drag->data; int i, j, nlayer = TRUE; if (drag->len <= 0) return; set_image(FALSE); tp = txt; while ((layers_total < MAX_LAYERS) && (tp2 = strstr(tp, "file:"))) { tp = tp2 + 5; while (*tp == '/') tp++; #ifndef WIN32 // If not windows keep a leading slash tp--; // If windows strip away all leading slashes #endif i = 0; while ((ch = *tp++) > 31) // Copy filename { if (ch == '%') // Weed out those ghastly % substitutions { ch = read_hex_dub(tp); tp += 2; } fname[i++] = ch; if (i >= sizeof(fname) - 1) break; } fname[i] = 0; tp--; #ifdef WIN32 /* !!! GTK+ uses UTF-8 encoding for URIs on Windows */ gtkncpy(fname, fname, PATHBUF); reseparate(fname); #endif j = detect_image_format(fname); if ((j > 0) && (j != FT_NONE) && (j != FT_LAYERS1)) { if (!nlayer || layer_add(0, 0, 1, 0, mem_pal_def, 0)) nlayer = load_image(fname, FS_LAYER_LOAD, j) == 1; if (nlayer) set_new_filename(layers_total, fname); } } if (!nlayer) layer_delete(layers_total); layer_refresh_list(); layer_choose(layers_total); layers_notify_changed(); if (layers_total) view_show(); set_image(TRUE); } static clipform_dd uri_list = { "text/uri-list" }; static void pressed_pal_copy(); static void pressed_pal_paste(); static void pressed_sel_ramp(int vert); static const signed char arrow_dx[4] = { 0, -1, 1, 0 }, arrow_dy[4] = { 1, 0, 0, -1 }; static void move_marquee(int action, int *xy, int change, int dir) { int dx = tgrid_dx, dy = tgrid_dy; if (!tgrid_snap) dx = dy = change; paint_marquee(action, xy[0] + dx * arrow_dx[dir], xy[1] + dy * arrow_dy[dir], NULL); update_stuff(UPD_SGEOM); } /// SCRIPTING /* Number of args is ((char **)res[0] - res - 1); res[] is NULL-terminated */ char **wj_parse_argv(char *src) { char c, q, q0, *dest, *tmp, **v; int n = 0, l = strlen(src); dest = tmp = malloc(l + 1); q0 = q = ' '; // Start outside word while ((c = *src++)) { /* Various quoted states */ if (q == '#') { if (c == '\n') q = ' '; } else if (q == '\\') { q = q0; if (q == '"') { if ((c != '"') && (c != '\\') && (c != '`') && (c != '$') && (c != '\n')) *dest++ = '\\'; *dest++ = c; } else if (c != '\n') { *dest++ = c; q = 0; } } else if (q == '"') { if (c == '\\') q0 = q , q = c; else if (c == '"') q = 0; else *dest++ = c; } else if (q == '\'') { if (c == '\'') q = 0; else *dest++ = c; } /* Unquoted state - in a word or in between */ else if ((c == '\n') || (c == ' ') || (c == '\t')) { if (!q) *dest++ = 0 , n++; q = ' '; } else if (c == '\\') q0 = q , q = c; else if ((c == '#') && q) q = c; else if ((c == '"') || (c == '\'')) q = c; else { *dest++ = c; q = 0; } } /* Final state */ if (!q) *dest++ = 0 , n++; else if ((q == '\\') || (q == '"') || (q == '\'')) n = -1; // Error l = dest - tmp; if ((n > 0) && (v = realloc(tmp, sizeof(*v) * (n + 1) + l))) { tmp = (void *)(v + n + 1); memmove(tmp, v, l); for (l = 0; l < n; l++) { v[l] = tmp; tmp += strlen(tmp) + 1; } v[n] = NULL; return (v); } /* Syntax error, or empty string */ free(tmp); return (NULL); } static void **command_slot(char *cmd) { void **slot; int l, m; l = strspn(++cmd, "/"); l += strcspn(cmd + l, "=/"); slot = find_slot(NEXT_SLOT(main_menubar), cmd, l, (cmd[0] != '/') && (cmd[l] == '/')); m = 2; while (slot && (cmd[l] == '/')) { cmd += l + 1; l = strcspn(cmd, "=/"); slot = find_slot(NEXT_SLOT(slot), cmd, l, m++); } return (slot); } #define MAX_NESTING 16 /* Defuse recursion bombs */ int run_script(char **res) { static int level; void **slot; char **cur, *str = NULL, *err = NULL; int n; level++; if (!res || !res[0]) err = _("Empty string or broken quoting"); else if (res[0][0] != '-') err = _("Script must begin with a command"); else if (level > MAX_NESTING) err = _("Script nesting limit exceeded"); else { user_break = 0; for (cur = res; cur[0]; cur++) { if (cur[0][0] != '-') continue; // Skip to next command if (!strcmp(cur[0], "--")) break; // End marker slot = command_slot(cur[0]); if (!slot) str = _("'%s' does not match any item"); else if (!cmd_checkv(slot, SLOT_SCRIPTABLE)) str = _("'%s' matches a non-scriptable item"); else if (!cmd_checkv(slot, SLOT_SENSITIVE)) str = _("'%s' matches a disabled item"); else { char *chain[3], *tmp = strchr(cur[0], '='); script_cmds = cur + 1; /* Send default value on, if no toggle-item */ if (tmp && !slot_data(slot, NULL)) { chain[0] = tmp; chain[1] = (void *)&chain[1]; chain[2] = (void *)script_cmds; script_cmds = chain; } /* Activate the item */ n = cmd_setstr(slot, tmp + !!tmp); // skip "=" script_cmds = NULL; if (n < 0) str = _("'%s' value does not fit item"); else if (!user_break) continue; } break; // Terminate on error } if (str) err = str = g_strdup_printf(__(str), cur[0]); update_stuff(CF_NOW); // Do cumulative update } level--; if (err) alert_box(_("Error"), err, NULL); if (str) g_free(str); return (!err ? 1 : str ? -1 : 0); // 1 = clean, -1 = buggy, 0 = wrong } #define SCRIPT_ITEMS 10 #define SCRIPTS_MAX FACTION_ROWS_TOTAL #define MAXNAMELEN 2048 #define SCRIPT1_NAME "# Resharpen image" #define SCRIPT1_CODE "# Resharpen image after rescaling\n" \ "-effect/unsharp r=1 am=0.4 -effect/unsharp r=30 am=0.1" static char *script_ini[2] = { "scriptName%d", "script%d" }; static void launch_script(int n) { char txt[64], **res; sprintf(txt, script_ini[1], n); res = wj_parse_argv(inifile_get(txt, "")); run_script(res); free(res); } static void update_script_menu() // Populate menu { int i, v, items = 0; char txt[64], *nm, *sm, *ns = SCRIPT1_NAME, *ss = SCRIPT1_CODE; void **slot; /* Show valid slots in menu */ for (i = 1; i <= SCRIPT_ITEMS; i++) { sprintf(txt, script_ini[0], i); nm = inifile_get(txt, ns); sprintf(txt, script_ini[1], i); sm = inifile_get(txt, ss); slot = menu_slots[MENU_SCRIPT1 - 1 + i]; if ((v = nm && nm[0] && (nm[0] != '#') && sm && sm[0])) cmd_setv(slot, nm, LABEL_VALUE); cmd_showhide(slot, v); // Hide by default cmd_sensitive(slot, v); // Make insensitive for shortcuts items += v; ns = ss = ""; } /* Hide submenu if no valid slots */ cmd_showhide(menu_slots[MENU_SCRIPT_M], items); cmd_showhide(menu_slots[MENU_SCRIPT], !items); } typedef struct { char *rows[SCRIPTS_MAX][4]; char *script, *name; void **list, **nm, **tx, **exec; int nidx, idx, cnt, lock, changed; } script_dd; static void update_text(script_dd *dt) { if (dt->changed) { char **rp = dt->rows[dt->idx]; cmd_read(dt->tx, dt); if (rp[1] != rp[3]) free(rp[1]); rp[1] = strdup(dt->script); dt->changed = FALSE; } } static void script_click(script_dd *dt, void **wdata, int what, void **where) { char txt[64], **rp; int i, idx[SCRIPTS_MAX]; if (what == op_EVT_DESTROY) // Finalize { cmd_sensitive(menu_slots[MENU_SCRIPT], TRUE); cmd_sensitive(menu_slots[MENU_SCRIPTC], TRUE); return; } if (what != op_EVT_CANCEL) update_text(dt); if (origin_slot(where) == dt->exec) // Run script { char **res = wj_parse_argv(dt->rows[dt->idx][1]); run_script(res); free(res); return; } cmd_showhide(wdata, FALSE); if (what != op_EVT_CANCEL) // Store scripts { cmd_peekv(dt->list, idx, sizeof(idx), LISTC_ORDER); /* Copy out reordered strings */ for (i = 0; i < SCRIPTS_MAX; i++) { if (idx[i] == i) continue; rp = dt->rows[i]; if (rp[0] == rp[2]) rp[0] = strdup(rp[0]); if (rp[1] == rp[3]) rp[1] = strdup(rp[1]); } /* Store into inifile */ for (i = 0; i < SCRIPTS_MAX; i++) { rp = dt->rows[i]; sprintf(txt, script_ini[0], idx[i] + 1); if (rp[0] != rp[2]) inifile_set(txt, rp[0]); sprintf(txt, script_ini[1], idx[i] + 1); if (rp[1] != rp[3]) inifile_set(txt, rp[1]); } /* Display in menu */ update_script_menu(); } for (i = 0; i < SCRIPTS_MAX; i++) // Release string memory { rp = dt->rows[i]; if (rp[0] != rp[2]) free(rp[0]); if (rp[1] != rp[3]) free(rp[1]); } run_destroy(wdata); } static void script_changed(script_dd *dt, void **wdata, int what, void **where) { char **rp; if (dt->lock) return; if (origin_slot(where) == dt->tx) // Text entry { dt->changed = TRUE; // Read it later return; } cmd_read(where, dt); // Name entry rp = dt->rows[dt->idx]; if (rp[0] == rp[2]) rp[0] = malloc(MAXNAMELEN); strncpy0(rp[0], dt->name, MAXNAMELEN); cmd_setv(dt->list, (void *)dt->idx, LISTC_RESET_ROW); } static void script_select_row(script_dd *dt, void **wdata, int what, void **where) { char **rp; cmd_read(where, dt); if (dt->nidx == dt->idx) return; // no change dt->lock = TRUE; /* Update outgoing row */ update_text(dt); /* Get fields from array for incoming row */ rp = dt->rows[dt->idx = dt->nidx]; cmd_setv(dt->nm, rp[0], ENTRY_VALUE); cmd_setv(dt->tx, rp[1], TEXT_VALUE); dt->lock = FALSE; } #define WBbase script_dd static void *script_code[] = { WINDOW(_("Script")), // nonmodal // WXYWH("script", 400, 400), DEFSIZE(400, 400), EVENT(DESTROY, script_click), HSEP, XVBOXB, BORDER(SCROLL, 0), BORDER(FRAME, 0), BORDER(ENTRY, 0), VSPLIT, XSCROLL(1, 1), // auto/auto; 1st page WLIST, PTXTCOLUMN(rows[0][0], WBsizeof(rows[0]), 200, 0), REF(list), LISTCd(nidx, cnt, script_select_row), TRIGGER, VBOXS, // 2nd page FHBOXB(_("Action")), REF(nm), XENTRY(name), EVENT(CHANGE, script_changed), WDONE, // FHBOX REF(tx), TEXT(script), EVENT(CHANGE, script_changed), WDONE, // VBOX WDONE, // VSPLIT WDONE, // XVBOX HSEP, EQBOX, CANCELBTN(_("Cancel"), script_click), REF(exec), BUTTON(_("Execute"), script_click), BUTTON(_("OK"), script_click), FOCUS, WSHOW }; #undef WBbase static void pressed_script() { script_dd tdata; char txt[64], *ns = SCRIPT1_NAME, *ss = SCRIPT1_CODE; int i; // Make sure the user can only open 1 script window cmd_sensitive(menu_slots[MENU_SCRIPT], FALSE); cmd_sensitive(menu_slots[MENU_SCRIPTC], FALSE); memset(&tdata, 0, sizeof(tdata)); for (i = 0; i < SCRIPTS_MAX; i++) { sprintf(txt, script_ini[0], i + 1); tdata.rows[i][0] = tdata.rows[i][2] = inifile_get(txt, ns); sprintf(txt, script_ini[1], i + 1); tdata.rows[i][1] = tdata.rows[i][3] = inifile_get(txt, ss); ns = ss = ""; } tdata.idx = 1; tdata.cnt = SCRIPTS_MAX; run_create(script_code, &tdata, sizeof(tdata)); } typedef struct { char *name; } name_dd; #define WBbase name_dd static void *name_code[] = { TOPVBOX, uPATHSTR(name), WSHOW }; #undef WBbase static void load_script() { name_dd *dt, tdata = { NULL }; char *txt, *tx2 = NULL, **res = NULL; void **wdata; wdata = run_create_(name_code, &tdata, sizeof(tdata), script_cmds); run_query(wdata); dt = GET_DDATA(wdata); txt = slurp_file(dt->name, 0); run_destroy(wdata); if (!txt) { alert_box(_("Error"), _("Unable to load script"), NULL); return; } /* Stepping through arguments is done within run_create_(), so here * script_cmds is done with and free for overloading - WJ */ if (!cmd_mode) tx2 = gtkuncpy(NULL, txt, 0); // Files are in system encoding res = wj_parse_argv(tx2 ? tx2 : txt); run_script(res); free(res); free(tx2); free(txt); } static void do_script(int what) { void **where = what == TOOLBAR_LAYERS ? layers_dock : what == TOOLBAR_SETTINGS ? settings_dock : /* what == TOOLBAR_TOOLS */ toolbar_boxes[TOOLBAR_TOOLS]; cmd_run_script(where, script_cmds); } /* Script mode image info */ typedef struct { char *str; int dest; } sinf_dd; static char *info_dest[] = { "stdout", "standard output", "stderr", "standard error", "clipboard" }; #define DEST_STDERR 2 #define DEST_CLIP 4 #define WBbase sinf_dd static void *sinf_code[] = { TOPVBOX, XENTRY(str), UNLESSv(cmd_mode), OPT(info_dest, DEST_CLIP + 1, dest), IFv(cmd_mode), OPT(info_dest, DEST_CLIP, dest), FLATTEN, WSHOW }; #undef WBbase static void interpolate_info() { static sinf_dd tdata = { "", 0 }; sinf_dd *dt; void **res; if (!script_cmds) return; res = run_create_(sinf_code, &tdata, sizeof(tdata), script_cmds); run_query(res); dt = GET_DDATA(res); if (dt->str[0]) // Do nothing for empty string { char *s = interpolate_line(dt->str, FALSE); if (!s); // Do nothing if could not interpolate else if (dt->dest < DEST_CLIP) { FILE *f = dt->dest < DEST_STDERR ? stdout : stderr; fputs(s, f); fflush(f); // In case no LF at end of line } else cmd_setv(((main_dd *)GET_DDATA(main_window_))->clipboard, s, CLIP_TEXT); free(s); } run_destroy(res); } /* Script mode color picker */ static int pick_pixel(multi_ext *mx, void **where, int ab) { int area[4], *row = mx->rows[0] + 1; /* Sanity check */ if ((mx->mincols < 2) || (mx->fractcol >= 0) || (mx->nrows > 2)) return (0); /* 2 corners */ if ((mx->nrows == 2) && (mx->ncols == 2)) { area[0] = row[0]; area[1] = row[1]; row = mx->rows[1] + 1; area[2] = row[0] + 1; area[3] = row[1] + 1; } /* 1 point */ else if (mx->ncols == 2) { area[2] = (area[0] = row[0]) + 1; area[3] = (area[1] = row[1]) + 1; } /* Area with size */ else if (mx->ncols == 4) { area[2] = (area[0] = row[0]) + row[2]; area[3] = (area[1] = row[1]) + row[3]; } /* Error */ else return (0); /* Drop previous regular value */ cmd_set(origin_slot(where), -1); if (clip(area, 0, 0, mem_width, mem_height, area)) { int sz = (area[2] -= area[0]) | (area[3] -= area[1]); pick_color(area[0], area[1], ab, sz != 1 ? area : NULL, -1); } return (1); } typedef struct { int n, mode; } idx_dd; static int idx_multi_evt(idx_dd *dt, void **wdata, int what, void **where, multi_ext *mx) { /* A/B mode */ if (dt->mode < 0x100) return (pick_pixel(mx, where, dt->mode)); /* Unmask/mask mode */ if ((mx->fractcol >= 0) || (mx->nrows > 1)) return (0); // Error cmd_set(origin_slot(where), 256); // Drop previous regular value mem_mask_setv(mx->rows[0] + 1, mx->rows[0][0], dt->mode - 0x100); return (1); } #define WBbase idx_dd static void *idx_code[] = { TOPVBOX, SPIN(n, -1, 256), EVENT(MULTI, idx_multi_evt), WSHOW }; #undef WBbase static int script_idx(int mode) { idx_dd tdata; void **res; int n; if (!script_cmds) return (-1); tdata.n = -1; tdata.mode = mode; res = run_create_(idx_code, &tdata, sizeof(tdata), script_cmds); run_query(res); n = ((idx_dd *)GET_DDATA(res))->n; run_destroy(res); return (n); } typedef struct { int a, b; } ab_dd; static int ab_pick_pixel(ab_dd *dt, void **wdata, int what, void **where, multi_ext *mx) { return (pick_pixel(mx, where, cmd_read(where, dt) == &dt->b)); } #define WBbase ab_dd static void *ab_code[] = { TOPVBOX, SPIN(a, -1, 256), ALTNAME("A"), EVENT(MULTI, ab_pick_pixel), SPIN(b, -1, 256), OPNAME("B"), EVENT(MULTI, ab_pick_pixel), WSHOW }; #undef WBbase static void script_ab() { static ab_dd tdata = { -1, -1 }; ab_dd *dt; void **res; res = run_create_(ab_code, &tdata, sizeof(tdata), script_cmds); run_query(res); dt = GET_DDATA(res); if ((dt->a >= 0) && (dt->a < mem_cols)) mem_col_A24 = mem_pal[mem_col_A = dt->a]; if ((dt->b >= 0) && (dt->b < mem_cols)) mem_col_B24 = mem_pal[mem_col_B = dt->b]; run_destroy(res); update_stuff(UPD_AB); } typedef struct { int x[3], y[3], n[3], b[3], brush; void **nspin; } nxy_dd; static void bp_evt(nxy_dd *dt, void **wdata, int what, void **where) { void *var = cmd_read(where, dt); int w = dt->x[2] + 1; if (var == dt->n) { int n = dt->n[0]; dt->x[0] = n % w; dt->y[0] = n / w; if (dt->brush) mem_set_brush(n); else mem_tool_pat = n; } else if (var == dt->b) mem_tool_pat_B = dt->b[0]; else if ((what == op_EVT_SCRIPT) && (dt->x[0] >= 0) && (dt->y[0] >= 0)) cmd_set(dt->nspin, dt->y[0] * w + dt->x[0]); } static int bp_pick(nxy_dd *dt, void **wdata, int what, void **where, multi_ext *mx) { /* Sanity check */ if (mx->fractcol >= 0) return (0); // Error /* Grid position */ if ((mx->nrows == 1) && (mx->ncols == 2)) { int *row = mx->rows[0] + 1, x = row[0], y = row[1]; cmd_set(where, bounded(y, 0, dt->y[2]) * (dt->x[2] + 1) + bounded(x, 0, dt->x[2])); return (1); } return (0); // Error } static char *brush_txt[TOOL_SPRAY + 1] = { "Square", "Circle", "Horizontal", "Vertical", "Slash", "Backslash", "Spray" }; #define WBbase nxy_dd static void *bp_code[] = { TOPVBOX, REF(nspin), SPINa(n), EVENT(CHANGE, bp_evt), EVENT(MULTI, bp_pick), UNLESSx(brush, 1), ALTNAME("A"), IFvx(pattern_B, 1), /* && */ SPINa(b), EVENT(CHANGE, bp_evt), EVENT(MULTI, bp_pick), OPNAME("B"), ENDIF(1), SPINa(x), EVENT(SCRIPT, bp_evt), OPNAME("X"), SPINa(y), EVENT(SCRIPT, bp_evt), OPNAME("Y"), IFx(brush, 1), RPACKv(brush_txt, TOOL_SPRAY + 1, 1, brush_type), EVENT(SELECT, bp_evt), OPNAME("Type"), SPINv(tool_size, 1, 255), EVENT(CHANGE, bp_evt), OPNAME("Size"), SPINv(tool_flow, 1, 255), EVENT(CHANGE, bp_evt), OPNAME("Flow"), ENDIF(1), WSHOW }; #undef WBbase static void script_bp(int mode) { nxy_dd tdata; memset(&tdata, 0, sizeof(tdata)); tdata.x[1] = tdata.y[1] = -1; if (mode == CHOOSE_BRUSH) { tdata.x[2] = BRUSH_GRID_W - 1; tdata.y[2] = BRUSH_GRID_H - 1; tdata.x[0] = tdata.y[0] = -1; tdata.brush = TRUE; } else { tdata.x[2] = patterns_grid_w - 1; tdata.y[2] = patterns_grid_h - 1; tdata.n[0] = mem_tool_pat; tdata.b[0] = mem_tool_pat_B; tdata.x[0] = mem_tool_pat % patterns_grid_w; tdata.y[0] = mem_tool_pat / patterns_grid_w; tdata.n[1] = tdata.b[1] = -DEF_PATTERNS; } tdata.n[2] = tdata.b[2] = (tdata.x[2] + 1) * (tdata.y[2] + 1) - 1; run_destroy(run_create_(bp_code, &tdata, sizeof(tdata), script_cmds)); if (mode == CHOOSE_BRUSH) { change_to_tool(TTB_PAINT); update_stuff(UPD_BRUSH); } else update_stuff(UPD_PAT); } typedef struct { int w, h, rxy[4]; multi_ext *mx; void **group; } rect_dd; static int make_select(rect_dd *dt, void **wdata, int what, void **where, multi_ext *mx) { /* Drop previous polygon if any */ free(dt->mx); dt->mx = NULL; /* Sanity check */ if ((mx->mincols < 2) || (mx->fractcol >= 0)) return (0); if ((mx->ncols != 2) && ((mx->nrows != 1) || (mx->ncols != 4))) return (0); /* Point/rectangle selection */ if (mx->nrows <= 2) { int *row = mx->rows[0] + 1; dt->rxy[0] = row[0]; dt->rxy[1] = row[1]; if (mx->nrows > 1) row = mx->rows[1] + 1; dt->rxy[2] = row[0]; dt->rxy[3] = row[1]; if (mx->ncols > 2) { dt->rxy[2] += row[2] - 1; dt->rxy[3] += row[3] - 1; } cmd_reset(dt->group, dt); // Update widgets return (1); } /* Polygon selection */ dt->mx = mx; return (-1); // Keep the data } #define WBbase rect_dd static void *rect_code[] = { TOPVBOX, EVENT(MULTI, make_select), OPNAME(""), REF(group), GROUPR, SPIN(rxy[0], 0, MAX_WIDTH - 1), OPNAME("x0"), SPIN(rxy[1], 0, MAX_HEIGHT - 1), OPNAME("y0"), SPIN(rxy[2], 0, MAX_WIDTH - 1), OPNAME("x1"), SPIN(rxy[3], 0, MAX_HEIGHT - 1), OPNAME("y1"), SPIN(w, 0, MAX_WIDTH), OPNAME("width"), SPIN(h, 0, MAX_HEIGHT), OPNAME("height"), WSHOW }; #undef WBbase static multi_ext *script_rect(int *rect) { static rect_dd tdata = { 0, 0, { 0, 0, MAX_WIDTH - 1, MAX_HEIGHT - 1 } }; rect_dd *dt; multi_ext *mx; void **res; copy4(rect, tdata.rxy); if (!script_cmds) return (NULL); res = run_create_(rect_code, &tdata, sizeof(tdata), script_cmds); run_query(res); dt = GET_DDATA(res); mx = dt->mx; if (dt->w) dt->rxy[2] = dt->rxy[0] + dt->w - 1; if (dt->h) dt->rxy[3] = dt->rxy[1] + dt->h - 1; copy4(rect, dt->rxy); run_destroy(res); return (mx); } typedef struct { int swap, mx, dx, dy, align, x, y; } paste_dd; static char *paste_align[] = { "Left", "Right", "Top", "Bottom", "Centre" }; static void align_evt(paste_dd *dt, void **wdata, int what, void **where) { cmd_read(where, dt); switch (dt->align) { case 0: // Left dt->dx = 0; break; case 1: // Right dt->dx = mem_clip_w - 1; break; case 2: // Top dt->dy = 0; break; case 3: // Bottom dt->dy = mem_clip_h - 1; break; case 4: // Center dt->dx = mem_clip_w / 2; dt->dy = mem_clip_h / 2; break; } } static int do_paste(paste_dd *dt, void **wdata, int what, void **where, multi_ext *mx) { int i, fr, mode, rows, dx = dt->dx, dy = dt->dy, p = MAX_PRESSURE; /* Sanity check */ if ((mx->ncols > 3) || (mx->mincols < 2) || ((mx->fractcol >= 0) && (mx->fractcol != 2))) return (0); // Error do_tool_action(TC_PASTE_DRAG, marq_x1, marq_y1, 0); mode = dt->swap ? TC_PASTE_PSWAP | TCF_PRES | TCF_ONCE : TC_PASTE_PAINT | TCF_PRES | TCF_ONCE; fr = mx->fractcol == 2; rows = mx->nrows; for (i = 0; i < rows; i++) { int *row = mx->rows[i]; if (row[0] > 2) p = bounded(fr ? row[3] : (row[3] * MAX_PRESSURE) / 100, 0, MAX_PRESSURE); do_tool_action(mode, row[1] - dx, row[2] - dy, p); } do_tool_action(TC_SEL_STOP, marq_x1, marq_y1, 0); tool_done(); dt->mx = TRUE; return (1); } #define WBbase paste_dd static void *paste_code[] = { TOPVBOX, OPT(paste_align, 5, align), EVENT(SCRIPT, align_evt), ALTNAME("Align"), FLATTEN, EVENT(MULTI, do_paste), CHECK("swap", swap), EVENT(CHANGE, align_evt), SPIN(x, -MAX_WIDTH, MAX_WIDTH), OPNAME("x0"), SPIN(y, -MAX_HEIGHT, MAX_HEIGHT), OPNAME("y0"), WSHOW }; #undef WBbase void script_paste(int centre) { paste_dd tdata, *dt; void **res; memset(&tdata, 0, sizeof(tdata)); tdata.x = marq_x1; tdata.y = marq_y1; if (centre) { tdata.x += tdata.dx = mem_clip_w / 2; tdata.y += tdata.dy = mem_clip_h / 2; tdata.align = 4; } res = run_create_(paste_code, &tdata, sizeof(tdata), script_cmds); run_query(res); dt = GET_DDATA(res); if (!dt->mx) // No commits yet - paste at x & y { int x = dt->x - dt->dx, y = dt->y - dt->dy; if ((marq_x1 ^ x) | (marq_y1 ^ y)) // Moved paint_marquee(MARQ_MOVE, x, y, NULL); commit_paste(dt->swap, NULL); tool_done(); } run_destroy(res); update_stuff(UPD_SGEOM); } typedef struct { int n[3]; } inrange_dd; #define WBbase inrange_dd static void *inrange_code[] = { TOPVBOX, SPINa(n), WSHOW }; #undef WBbase static int script_inrange(int n0, int nmin, int nmax) { if (script_cmds) { inrange_dd tdata = { { n0, nmin, nmax } }; void **res = run_create_(inrange_code, &tdata, sizeof(tdata), script_cmds); run_query(res); n0 = ((inrange_dd *)GET_DDATA(res))->n[0]; run_destroy(res); } return (n0); } static void do_act_esc() { if ((tool_type == TOOL_SELECT) || (tool_type == TOOL_POLYGON)) pressed_select(FALSE); else if (tool_type == TOOL_LINE) { stop_line(); update_sel_bar(FALSE); } else if ((tool_type == TOOL_GRADIENT) && (gradient[mem_channel].status != GRAD_NONE)) { do_grad_action(TC_GRAD_CLEAR, 0, 0); update_sel_bar(FALSE); } } static void select_poly(multi_ext *mx) { int i, rows = mx->nrows; for (i = 0; i < rows; i++) { int *row = mx->rows[i] + 1; do_tool_action(i ? TC_POLY_ADD | TCF_ONCE : TC_POLY_START, bounded(row[0], 0, mem_width - 1), bounded(row[1], 0, mem_height - 1), 0); } do_tool_action(TC_POLY_CLOSE, 0, 0, 0); } static int tool_command(main_dd *dt, void **wdata, int what, void **where, multi_ext *mx) { int *row; int i, p, fr, rows = mx->nrows, res = 0; do_act_esc(); switch (tool_type) { case TOOL_GRADIENT: if ((rows == 1) && (mx->ncols < 3)) res = 1; // Valid clear op if ((rows != 2) || (mx->ncols != 2) || (mx->mincols != 2) || (mx->fractcol >= 0)) break; // Error row = mx->rows[0] + 1; do_grad_action(TC_GRAD_START, bounded(row[0], -MAX_WIDTH, MAX_WIDTH), bounded(row[1], -MAX_HEIGHT, MAX_HEIGHT)); row = mx->rows[1] + 1; do_grad_action(TC_GRAD_SET1, bounded(row[0], -MAX_WIDTH, MAX_WIDTH), bounded(row[1], -MAX_HEIGHT, MAX_HEIGHT)); res = 1; break; case TOOL_LINE: if ((rows < 2) || (mx->ncols != 2) || (mx->mincols != 2) || (mx->fractcol >= 0)) break; // Error for (i = 0; i < rows; i++) { row = mx->rows[i] + 1; do_tool_action(TC_LINE_START, bounded(row[0], 0, mem_width - 1), bounded(row[1], 0, mem_height - 1), MAX_PRESSURE); line_status = LINE_LINE; } stop_line(); res = 1; break; case TOOL_SELECT: if ((rows > 2) || (mx->ncols != 2) || (mx->mincols != 2) || (mx->fractcol >= 0)) break; // Error row = mx->rows[0] + 1; do_tool_action(TC_SEL_START, bounded(row[0], 0, mem_width - 1), bounded(row[1], 0, mem_height - 1), 0); if (rows > 1) row = mx->rows[1] + 1; do_tool_action(TC_SEL_TO, bounded(row[0], 0, mem_width - 1), bounded(row[1], 0, mem_height - 1), 0); do_tool_action(TC_SEL_STOP, 0, 0, 0); res = 1; break; case TOOL_POLYGON: if ((mx->ncols != 2) || (mx->mincols != 2) || (mx->fractcol >= 0)) break; // Error select_poly(mx); res = 1; break; default: /* Regular painting tools */ if ((mx->ncols > 3) || (mx->mincols < 2) || ((mx->fractcol >= 0) && (mx->fractcol != 2))) break; // Error fr = mx->fractcol == 2; p = MAX_PRESSURE; for (i = 0; i < rows; i++) { row = mx->rows[i]; if (row[0] > 2) p = bounded(fr ? row[3] : (row[3] * MAX_PRESSURE) / 100, 0, MAX_PRESSURE); do_tool_action(TC_PAINT | TCF_PRES | TCF_ONCE, bounded(row[1], 0, mem_width - 1), bounded(row[2], 0, mem_height - 1), p); } res = 1; break; } if (res) /* Do as for button release */ { tool_done(); update_menus(); } return (res); } void *scriptbar_code[] = { EVENT(MULTI, tool_command), ALTNAME(""), // for tools toolbar RET }; static float new_zoom(int mode, float zoom) { return (!mode ? // Zoom in (zoom >= 1 ? zoom + 1 : 1.0 / (rint(1.0 / zoom) - 1)) : mode == -1 ? // Zoom out (zoom > 1 ? zoom - 1 : 1.0 / (rint(1.0 / zoom) + 1)) : mode > 0 ? mode : -1.0 / mode); // Zoom to given factor/divisor } void action_dispatch(int action, int mode, int state, int kbd) { int change = mode & 1 ? mem_nudge : 1, dir = (mode >> 1) - 1; switch (action) { case ACT_QUIT: quit_all(mode); break; case ACT_ZOOM: align_size(new_zoom(mode, can_zoom)); break; case ACT_VIEW: toggle_view(); break; case ACT_PAN: pressed_pan(); break; case ACT_CROP: pressed_crop(); break; case ACT_SWAP_AB: mem_swap_cols(TRUE); break; case ACT_TOOL: if (state || kbd) change_to_tool(mode); // Ignore DEactivating buttons break; case ACT_SEL_MOVE: /* Gradient tool has precedence over selection */ if ((tool_type != TOOL_GRADIENT) && (marq_status > MARQUEE_NONE)) move_marquee(MARQ_MOVE, marq_xy, change, dir); else move_mouse(change * arrow_dx[dir], change * arrow_dy[dir], 0); break; case ACT_OPAC: pressed_opacity(mode > 0 ? (255 * mode) / 10 : tool_opacity + 1 + mode + mode); break; case ACT_LR_MOVE: /* User is selecting so allow CTRL+arrow keys to resize the * marquee; for consistency, gradient tool blocks this */ if ((tool_type != TOOL_GRADIENT) && (marq_status == MARQUEE_DONE)) move_marquee(MARQ_SIZE, marq_xy + 2, change, dir); else if (bkg_flag && !layer_selected) { /* !!! Later, maybe localize redraw to the changed part */ bkg_x += change * arrow_dx[dir]; bkg_y += change * arrow_dy[dir]; update_stuff(UPD_RENDER); } else if (layers_total) move_layer_relative(layer_selected, change * arrow_dx[dir], change * arrow_dy[dir]); break; case ACT_ESC: do_act_esc(); break; case ACT_COMMIT: if (marq_status >= MARQUEE_PASTE) { commit_paste(mode, NULL); pen_down = 0; // Ensure each press of enter is a new undo level mem_undo_prepare(); } else move_mouse(0, 0, 1); break; case ACT_RCLICK: if (marq_status < MARQUEE_PASTE) move_mouse(0, 0, 3); break; case ACT_ARROW: draw_arrow(mode); break; case ACT_A: case ACT_B: action = action == ACT_B; dir = script_idx(action); if (!mode && (dir < 0)); // Nothing to do else if (mem_channel == CHN_IMAGE) { mode = mode ? mode + mem_col_[action] : dir; if ((mode >= 0) && (mode < mem_cols)) mem_col_[action] = mode; mem_col_24[action] = mem_pal[mem_col_[action]]; } else { mode = mode ? mode + channel_col_[action][mem_channel] : dir; if ((mode >= 0) && (mode <= 255)) channel_col_[action][mem_channel] = mode; } update_stuff(UPD_CAB); break; case ACT_SIZE: tool_size = bounded(tool_size + mode, 1, 255); update_stuff(UPD_BRUSH); break; case ACT_PAT: mem_tool_pat = bounded(mem_tool_pat + mode, -DEF_PATTERNS, patterns_grid_w * patterns_grid_h - 1); update_stuff(UPD_PAT); break; case ACT_CHANNEL: if (kbd) state = TRUE; if (mode < 0) pressed_channel_create(mode); else pressed_channel_edit(state, mode); break; case ACT_VWZOOM: vw_align_size(new_zoom(mode, vw_zoom)); break; case ACT_SAVE: pressed_save_file(); break; case ACT_FACTION: pressed_file_action(mode); break; case ACT_LOAD_RECENT: pressed_load_recent(mode); break; case ACT_DO_UNDO: pressed_do_undo(mode, script_inrange(1, 1, mode ? mem_undo_redo : mem_undo_done)); break; case ACT_COPY: pressed_copy(mode); break; case ACT_PASTE: pressed_paste(mode); if (script_cmds && (marq_status >= MARQUEE_PASTE)) script_paste(mode); // Move and commit break; case ACT_COPY_PAL: pressed_pal_copy(); break; case ACT_PASTE_PAL: pressed_pal_paste(); break; case ACT_LOAD_CLIP: load_clip(mode); break; case ACT_SAVE_CLIP: save_clip(mode); break; case ACT_TBAR: pressed_toolbar_toggle(state, mode); break; case ACT_DOCK: if (!kbd) toggle_dock(show_dock = state); else if (cmd_checkv(menu_slots[MENU_DOCK], SLOT_SENSITIVE)) cmd_set(menu_slots[MENU_DOCK], !show_dock); break; case ACT_CENTER: pressed_centralize(state); break; case ACT_GRID: zoom_grid(state); break; case ACT_SNAP: tgrid_snap = state; break; case ACT_VWWIN: if (state) view_show(); else view_hide(); break; case ACT_VWSPLIT: pressed_view_hori(state); break; case ACT_VWFOCUS: pressed_view_focus(state); break; case ACT_FLIP_V: pressed_flip_image_v(); break; case ACT_FLIP_H: pressed_flip_image_h(); break; case ACT_ROTATE: pressed_rotate_image(mode); break; case ACT_SELECT: pressed_select(mode); break; case ACT_LASSO: pressed_lasso(mode); break; case ACT_OUTLINE: pressed_rectangle(mode); break; case ACT_ELLIPSE: pressed_ellipse(mode); break; case ACT_SEL_FLIP_V: pressed_flip_sel_v(); break; case ACT_SEL_FLIP_H: pressed_flip_sel_h(); break; case ACT_SEL_ROT: pressed_rotate_sel(mode); break; case ACT_RAMP: pressed_sel_ramp(mode); break; case ACT_SEL_ALPHA_AB: pressed_clip_alpha_scale(); break; case ACT_SEL_ALPHAMASK: pressed_clip_alphamask(); break; case ACT_SEL_MASK_AB: pressed_clip_mask(mode); break; case ACT_SEL_MASK: if (!mode) pressed_clip_mask_all(); else pressed_clip_mask_clear(); break; case ACT_PAL_DEF: pressed_default_pal(); break; case ACT_PAL_MASK: mem_mask_setv(NULL, script_idx(mode + 0x100), mode); update_stuff(UPD_CMASK); break; case ACT_DITHER_A: pressed_dither_A(); break; case ACT_PAL_MERGE: pressed_remove_duplicates(); break; case ACT_PAL_CLEAN: pressed_remove_unused(); break; case ACT_ISOMETRY: iso_trans(mode); break; case ACT_CHN_DIS: pressed_channel_disable(state, mode); break; case ACT_SET_RGBA: pressed_RGBA_toggle(state); break; case ACT_SET_OVERLAY: pressed_channel_toggle(state, mode); break; case ACT_LR_SAVE: layer_press_save(); break; case ACT_LR_ADD: if (mode == LR_NEW) generic_new_window(1); else if (mode == LR_DUP) layer_press_duplicate(); else if (mode == LR_PASTE) pressed_paste_layer(); else /* if (mode == LR_COMP) */ layer_add_composite(); break; case ACT_LR_DEL: if (!mode) layer_press_delete(); else layer_press_remove_all(); break; case ACT_DOCS: show_html(inifile_get(HANDBOOK_BROWSER_INI, NULL), inifile_get(HANDBOOK_LOCATION_INI, NULL)); break; case ACT_REBIND_KEYS: /* "Tool of last resort" for when shortcuts don't work */ cmd_reset(main_keys, NULL); break; case ACT_MODE: mode_change(mode, state); break; case ACT_LR_SHIFT: shift_layer(mode); break; case ACT_LR_CENTER: layer_press_centre(); break; case ACT_SCRIPT: do_script(mode); break; case ACT_RUN_SCRIPT: if (!mode) load_script(); else launch_script(mode); break; case DLG_BRCOSA: pressed_brcosa(NULL); break; case DLG_CHOOSER: if (!script_cmds) choose_pattern(mode); else if (mode == CHOOSE_COLOR) script_ab(); else script_bp(mode); break; case DLG_SCALE: pressed_scale_size(TRUE); break; case DLG_SIZE: pressed_scale_size(FALSE); break; case DLG_NEW: generic_new_window(0); break; case DLG_FSEL: file_selector(mode); break; case DLG_FACTIONS: pressed_file_configure(); break; case DLG_TEXT: pressed_text(); break; case DLG_TEXT_FT: pressed_mt_text(); break; case DLG_LAYERS: if (mode) cmd_set(menu_slots[MENU_LAYER], FALSE); // Closed by toolbar else if (state) pressed_layers(); else delete_layers_window(); break; case DLG_INDEXED: pressed_quantize(mode); break; case DLG_ROTATE: pressed_rotate_free(); break; case DLG_INFO: if (script_cmds) interpolate_info(); else pressed_information(); break; case DLG_PREFS: pressed_preferences(); break; case DLG_COLORS: colour_selector(mode); break; case DLG_PAL_SIZE: pressed_add_cols(); break; case DLG_PAL_SORT: pressed_sort_pal(); break; case DLG_PAL_SHIFTER: pressed_shifter(); break; case DLG_CHN_DEL: pressed_channel_delete(); break; case DLG_ANI: pressed_animate_window(); break; case DLG_ANI_VIEW: ani_but_preview(NULL); break; case DLG_ANI_KEY: pressed_set_key_frame(); break; case DLG_ANI_KILLKEY: pressed_remove_key_frames(); break; case DLG_ABOUT: pressed_help(); break; case DLG_SKEW: pressed_skew(); break; case DLG_FLOOD: flood_settings(); break; case DLG_SMUDGE: smudge_settings(); break; case DLG_CLONE: clone_settings(); break; case DLG_GRAD: gradient_setup(mode); break; case DLG_STEP: step_settings(); break; case DLG_FILT: blend_settings(); break; case DLG_TRACE: bkg_setup(); break; case DLG_PICK_GRAD: pressed_pick_gradient(); break; case DLG_SEGMENT: pressed_segment(); break; case DLG_SCRIPT: pressed_script(); break; case DLG_LASSO: lasso_settings(); break; case DLG_KEYS: keys_selector(); break; case DLG_XHOLD: pressed_xhold(); break; case DLG_NOISE: pressed_noise(); break; case FILT_2RGB: if (mem_img_bpp == 1) pressed_convert_rgb(); // Allow a noop in script mode else if (script_cmds) spot_undo(UNDO_PAL); break; case FILT_INVERT: case FILT_NORM: pressed_inv(action); break; case FILT_GREY: pressed_greyscale(mode); break; case FILT_EDGE: pressed_edge_detect(); break; case FILT_DOG: pressed_dog(); break; case FILT_SHARPEN: pressed_sharpen(); break; case FILT_UNSHARP: pressed_unsharp(); break; case FILT_SOFTEN: pressed_soften(); break; case FILT_GAUSS: pressed_gauss(); break; case FILT_FX: pressed_fx(mode); break; case FILT_BACT: pressed_bacteria(); break; case FILT_MAP: pressed_map(); break; case FILT_THRES: pressed_threshold(); break; case FILT_UALPHA: pressed_unassociate(); break; case FILT_KUWAHARA: pressed_kuwahara(); break; } } static void menu_action(void *dt, void **wdata, int what, void **where) { int act_m = TOOL_ID(where), res = TRUE; void *cause = cmd_read(where, dt); // Good for radioitems too, as all action codes are nonzero if (cause) res = *(int *)cause; action_dispatch(act_m >> 16, (act_m & 0xFFFF) - 0x8000, res, FALSE); } static int do_pal_copy(png_color *tpal, unsigned char *img, unsigned char *alpha, unsigned char *mask, unsigned char *mask2, png_color *wpal, int w, int h, int bpp, int step) { int i, j, n; mem_pal_copy(tpal, mem_pal); for (n = i = 0; i < h; i++) { for (j = 0; j < w; j++ , img += bpp) { /* Skip empty parts */ if ((mask2 && !mask2[j]) || (mask && !mask[j]) || (alpha && !alpha[j])) continue; if (bpp == 1) tpal[n] = wpal[*img]; else { tpal[n].red = img[0]; tpal[n].green = img[1]; tpal[n].blue = img[2]; } if (++n >= 256) return (256); } img += (step - w) * bpp; if (alpha) alpha += step; if (mask) mask += step; if (mask2) mask2 += w; } return (n); } static void pressed_pal_copy() { png_color tpal[256]; int n = 0; /* Source is selection */ if ((marq_status == MARQUEE_DONE) || (poly_status == POLY_DONE)) { unsigned char *mask2 = NULL; int i, bpp, rect[4]; marquee_at(rect); if ((poly_status == POLY_DONE) && (mask2 = calloc(1, rect[2] * rect[3]))) poly_draw(TRUE, mask2, rect[2]); i = rect[1] * mem_width + rect[0]; bpp = MEM_BPP; n = do_pal_copy(tpal, mem_img[mem_channel] + i * bpp, (mem_channel == CHN_IMAGE) && mem_img[CHN_ALPHA] ? mem_img[CHN_ALPHA] + i : NULL, (mem_channel <= CHN_ALPHA) && mem_img[CHN_SEL] ? mem_img[CHN_SEL] + i : NULL, mask2, mem_pal, rect[2], rect[3], bpp, mem_width); if (mask2) free(mask2); } /* Source is clipboard */ else if (mem_clipboard) n = do_pal_copy(tpal, mem_clipboard, mem_clip_alpha, mem_clip_mask, NULL, mem_clip_paletted ? mem_clip_pal : mem_pal, mem_clip_w, mem_clip_h, mem_clip_bpp, mem_clip_w); if (!n) return; // Empty set - ignore spot_undo(UNDO_PAL); mem_pal_copy(mem_pal, tpal); mem_cols = n; update_stuff(UPD_PAL); } static void pressed_pal_paste() { unsigned char *dest; int i, h, w = mem_cols; // If selection exists, use it to set the width of the clipboard if ((tool_type == TOOL_SELECT) && (marq_status == MARQUEE_DONE)) { w = abs(marq_x1 - marq_x2) + 1; if (w > mem_cols) w = mem_cols; } h = (mem_cols + w - 1) / w; mem_clip_new(w, h, 1, CMASK_IMAGE, NULL); if (!mem_clipboard) { memory_errors(1); return; } mem_clip_paletted = 1; mem_pal_copy(mem_clip_pal, mem_pal); memset(dest = mem_clipboard, 0, w * h); for (i = 0; i < mem_cols; i++) dest[i] = i; pressed_paste(TRUE); } /// DOCK AREA static void toggle_dock(int state) { cmd_set(dock_area, state); } static void pressed_sel_ramp(int vert) { unsigned char *c0, *c1, *img, *dest, *buf, *mask; int i, j, k, a, b, v, w, h, ww, gcor, opacity, bpp = MEM_BPP, rect[4]; if (marq_status != MARQUEE_DONE) return; marquee_at(rect); w = rect[2]; h = rect[3]; k = (vert ? h : w) - 1; if (k < 2) return; // Nothing to do ww = w * bpp; buf = multialloc(MA_ALIGN_DEFAULT, &buf, ww, &mask, w, NULL); if (!buf) { memory_errors(1); return; } spot_undo(UNDO_FILT); opacity = IS_INDEXED ? 0 : tool_opacity; gcor = paint_gamma && (bpp == 3); img = mem_img[mem_channel] + (rect[1] * mem_width + rect[0]) * bpp; c0 = img; c1 = img + (h - 1) * mem_width * bpp; v = 0x3F; /* Vertical ramp: channel step 1, ramp step 0 */ vert = !!vert; /* Horizontal ramp: for 1bpp channel step 0, ramp step 1; * for 3 bpp channel step (1, 1, -2), ramp step (0, 0, 1) */ if (!vert) ww -= bpp , v = bpp == 3 ? 0x0F : 0x2A; /* Render the ramp row by row */ for (i = vert; i < h - vert; i++) { dest = img + i * mem_width * bpp; if (vert) j = 0 , b = i; else j = bpp , b = 1 , c0 = dest , c1 = dest + ww; for (a = 0; j < ww; j++) { buf[j] = gcor ? UNGAMMA256((gamma256[c0[a]] * (k - b) + gamma256[c1[a]] * b) / k) : (c0[a] * (k - b) + c1[a] * b) / k; a += (v & 3) - 2; // Step on channels b += 1 - (v & 1); // Step on ramp v = (v + ((v & 3) << 6)) >> 2; // Next step } row_protected(rect[0], rect[1] + i, w, mask); if (!vert) mask[0] = mask[k] = 255; // Leave source pixels alone process_mask(0, 1, w, mask, NULL, NULL, NULL, NULL, opacity, 0); process_img(0, 1, w, mask, dest, dest, buf, buf, bpp, 0); } free(buf); mem_undo_prepare(); update_stuff(UPD_IMG); } static int menu_view, menu_layer; static int menu_chan = ACTMOD(ACT_CHANNEL, CHN_IMAGE); // initial state static void *main_menu_code[] = { REFv(main_menubar), SMARTMENU(menu_action), SSUBMENU(_("/_File")), MENUTEAR, // MENUITEMis(_("//New"), ACTMOD(DLG_NEW, 0), XPM_ICON(new)), SHORTCUT(n, C), MENUITEMis(_("//Open ..."), ACTMOD(DLG_FSEL, FS_PNG_LOAD), XPM_ICON(open)), SHORTCUT(o, C), MENUITEMis(_("//Save"), ACTMOD(ACT_SAVE, 0), XPM_ICON(save)), SHORTCUT(s, C), MENUITEMs(_("//Save As ..."), ACTMOD(DLG_FSEL, FS_PNG_SAVE)), MENUSEP, // MENUITEMs(_("//Export Undo Images ..."), ACTMOD(DLG_FSEL, FS_EXPORT_UNDO)), ACTMAP(NEED_UNDO), MENUITEMs(_("//Export Undo Images (reversed) ..."), ACTMOD(DLG_FSEL, FS_EXPORT_UNDO2)), ACTMAP(NEED_UNDO), MENUITEMs(_("//Export ASCII Art ..."), ACTMOD(DLG_FSEL, FS_EXPORT_ASCII)), ACTMAP(NEED_IDX), MENUITEMs(_("//Export Animated GIF ..."), ACTMOD(DLG_FSEL, FS_EXPORT_GIF)), ACTMAP(NEED_IDX), MENUSEP, // SUBMENU(_("//Actions")), MENUTEAR, /// REFv(menu_slots[MENU_FACTION1]), MENUITEM("///1", ACTMOD(ACT_FACTION, 1)), REFv(menu_slots[MENU_FACTION2]), MENUITEM("///2", ACTMOD(ACT_FACTION, 2)), REFv(menu_slots[MENU_FACTION3]), MENUITEM("///3", ACTMOD(ACT_FACTION, 3)), REFv(menu_slots[MENU_FACTION4]), MENUITEM("///4", ACTMOD(ACT_FACTION, 4)), REFv(menu_slots[MENU_FACTION5]), MENUITEM("///5", ACTMOD(ACT_FACTION, 5)), REFv(menu_slots[MENU_FACTION6]), MENUITEM("///6", ACTMOD(ACT_FACTION, 6)), REFv(menu_slots[MENU_FACTION7]), MENUITEM("///7", ACTMOD(ACT_FACTION, 7)), REFv(menu_slots[MENU_FACTION8]), MENUITEM("///8", ACTMOD(ACT_FACTION, 8)), REFv(menu_slots[MENU_FACTION9]), MENUITEM("///9", ACTMOD(ACT_FACTION, 9)), REFv(menu_slots[MENU_FACTION10]), MENUITEM("///10", ACTMOD(ACT_FACTION, 10)), REFv(menu_slots[MENU_FACTION11]), MENUITEM("///11", ACTMOD(ACT_FACTION, 11)), REFv(menu_slots[MENU_FACTION12]), MENUITEM("///12", ACTMOD(ACT_FACTION, 12)), REFv(menu_slots[MENU_FACTION13]), MENUITEM("///13", ACTMOD(ACT_FACTION, 13)), REFv(menu_slots[MENU_FACTION14]), MENUITEM("///14", ACTMOD(ACT_FACTION, 14)), REFv(menu_slots[MENU_FACTION15]), MENUITEM("///15", ACTMOD(ACT_FACTION, 15)), REFv(menu_slots[MENU_FACTION_S]), MENUSEPr, /// MENUITEM(_("///Configure"), ACTMOD(DLG_FACTIONS, 0)), WDONE, REFv(menu_slots[MENU_RECENT_S]), MENUSEPr, // REFv(menu_slots[MENU_RECENT1]), MENUITEM("//1", ACTMOD(ACT_LOAD_RECENT, 1)), SHORTCUT(F1, CS), REFv(menu_slots[MENU_RECENT2]), MENUITEM("//2", ACTMOD(ACT_LOAD_RECENT, 2)), SHORTCUT(F2, CS), REFv(menu_slots[MENU_RECENT3]), MENUITEM("//3", ACTMOD(ACT_LOAD_RECENT, 3)), SHORTCUT(F3, CS), REFv(menu_slots[MENU_RECENT4]), MENUITEM("//4", ACTMOD(ACT_LOAD_RECENT, 4)), SHORTCUT(F4, CS), REFv(menu_slots[MENU_RECENT5]), MENUITEM("//5", ACTMOD(ACT_LOAD_RECENT, 5)), SHORTCUT(F5, CS), REFv(menu_slots[MENU_RECENT6]), MENUITEM("//6", ACTMOD(ACT_LOAD_RECENT, 6)), SHORTCUT(F6, CS), REFv(menu_slots[MENU_RECENT7]), MENUITEM("//7", ACTMOD(ACT_LOAD_RECENT, 7)), SHORTCUT(F7, CS), REFv(menu_slots[MENU_RECENT8]), MENUITEM("//8", ACTMOD(ACT_LOAD_RECENT, 8)), SHORTCUT(F8, CS), REFv(menu_slots[MENU_RECENT9]), MENUITEM("//9", ACTMOD(ACT_LOAD_RECENT, 9)), SHORTCUT(F9, CS), REFv(menu_slots[MENU_RECENT10]), MENUITEM("//10", ACTMOD(ACT_LOAD_RECENT, 10)), SHORTCUT(F10, CS), REFv(menu_slots[MENU_RECENT11]), MENUITEM("//11", ACTMOD(ACT_LOAD_RECENT, 11)), REFv(menu_slots[MENU_RECENT12]), MENUITEM("//12", ACTMOD(ACT_LOAD_RECENT, 12)), REFv(menu_slots[MENU_RECENT13]), MENUITEM("//13", ACTMOD(ACT_LOAD_RECENT, 13)), REFv(menu_slots[MENU_RECENT14]), MENUITEM("//14", ACTMOD(ACT_LOAD_RECENT, 14)), REFv(menu_slots[MENU_RECENT15]), MENUITEM("//15", ACTMOD(ACT_LOAD_RECENT, 15)), REFv(menu_slots[MENU_RECENT16]), MENUITEM("//16", ACTMOD(ACT_LOAD_RECENT, 16)), REFv(menu_slots[MENU_RECENT17]), MENUITEM("//17", ACTMOD(ACT_LOAD_RECENT, 17)), REFv(menu_slots[MENU_RECENT18]), MENUITEM("//18", ACTMOD(ACT_LOAD_RECENT, 18)), REFv(menu_slots[MENU_RECENT19]), MENUITEM("//19", ACTMOD(ACT_LOAD_RECENT, 19)), REFv(menu_slots[MENU_RECENT20]), MENUITEM("//20", ACTMOD(ACT_LOAD_RECENT, 20)), MENUSEP, // MENUITEMs(_("//Quit"), ACTMOD(ACT_QUIT, 1)), SHORTCUT(q, C), WDONE, SSUBMENU(_("/_Edit")), MENUTEAR, // MENUITEMis(_("//Undo"), ACTMOD(ACT_DO_UNDO, 0), XPM_ICON(undo)), ACTMAP(NEED_UNDO), SHORTCUT(z, C), MENUITEMis(_("//Redo"), ACTMOD(ACT_DO_UNDO, 1), XPM_ICON(redo)), ACTMAP(NEED_REDO), SHORTCUT(r, C), MENUSEP, // MENUITEMis(_("//Cut"), ACTMOD(ACT_COPY, 1), XPM_ICON(cut)), ACTMAP(NEED_SEL2), SHORTCUT(x, C), MENUITEMis(_("//Copy"), ACTMOD(ACT_COPY, 0), XPM_ICON(copy)), ACTMAP(NEED_SEL2), SHORTCUT(c, C), MENUITEMs(_("//Copy To Palette"), ACTMOD(ACT_COPY_PAL, 0)), ACTMAP(NEED_PSEL), MENUITEMis(_("//Paste To Centre"), ACTMOD(ACT_PASTE, 1), XPM_ICON(paste)), ACTMAP(NEED_CLIP), SHORTCUT(v, C), MENUITEMs(_("//Paste To New Layer"), ACTMOD(ACT_LR_ADD, LR_PASTE)), ACTMAP(NEED_PCLIP), SHORTCUT(v, CS), MENUITEMs(_("//Paste"), ACTMOD(ACT_PASTE, 0)), ACTMAP(NEED_CLIP), SHORTCUT(k, C), MENUITEMis(_("//Paste Text"), ACTMOD(DLG_TEXT, 0), XPM_ICON(text)), SHORTCUT(t, S), IFvx(cmd_mode, 1), // Disable GUI-only text renderer UNLESSv(texteng_con), ACTMAP(NEED_SKIP), ENDIF(1), #ifdef U_FREETYPE MENUITEMs(_("//Paste Text (FreeType)"), ACTMOD(DLG_TEXT_FT, 0)), SHORTCUT(t, 0), #endif MENUITEMs(_("//Paste Palette"), ACTMOD(ACT_PASTE_PAL, 0)), MENUSEP, // SUBMENU(_("//Load Clipboard")), MENUTEAR, /// MENUITEMs("///1", ACTMOD(ACT_LOAD_CLIP, 1)), SHORTCUT(F1, S), MENUITEMs("///2", ACTMOD(ACT_LOAD_CLIP, 2)), SHORTCUT(F2, S), MENUITEMs("///3", ACTMOD(ACT_LOAD_CLIP, 3)), SHORTCUT(F3, S), MENUITEMs("///4", ACTMOD(ACT_LOAD_CLIP, 4)), SHORTCUT(F4, S), MENUITEMs("///5", ACTMOD(ACT_LOAD_CLIP, 5)), SHORTCUT(F5, S), MENUITEMs("///6", ACTMOD(ACT_LOAD_CLIP, 6)), SHORTCUT(F6, S), MENUITEMs("///7", ACTMOD(ACT_LOAD_CLIP, 7)), SHORTCUT(F7, S), MENUITEMs("///8", ACTMOD(ACT_LOAD_CLIP, 8)), SHORTCUT(F8, S), MENUITEMs("///9", ACTMOD(ACT_LOAD_CLIP, 9)), SHORTCUT(F9, S), MENUITEMs("///10", ACTMOD(ACT_LOAD_CLIP, 10)), SHORTCUT(F10, S), MENUITEMs("///11", ACTMOD(ACT_LOAD_CLIP, 11)), SHORTCUT(F11, S), MENUITEMs("///12", ACTMOD(ACT_LOAD_CLIP, 12)), SHORTCUT(F12, S), WDONE, SUBMENU(_("//Save Clipboard")), MENUTEAR, /// MENUITEMs("///1", ACTMOD(ACT_SAVE_CLIP, 1)), ACTMAP(NEED_PCLIP), SHORTCUT(F1, C), MENUITEMs("///2", ACTMOD(ACT_SAVE_CLIP, 2)), ACTMAP(NEED_PCLIP), SHORTCUT(F2, C), MENUITEMs("///3", ACTMOD(ACT_SAVE_CLIP, 3)), ACTMAP(NEED_PCLIP), SHORTCUT(F3, C), MENUITEMs("///4", ACTMOD(ACT_SAVE_CLIP, 4)), ACTMAP(NEED_PCLIP), SHORTCUT(F4, C), MENUITEMs("///5", ACTMOD(ACT_SAVE_CLIP, 5)), ACTMAP(NEED_PCLIP), SHORTCUT(F5, C), MENUITEMs("///6", ACTMOD(ACT_SAVE_CLIP, 6)), ACTMAP(NEED_PCLIP), SHORTCUT(F6, C), MENUITEMs("///7", ACTMOD(ACT_SAVE_CLIP, 7)), ACTMAP(NEED_PCLIP), SHORTCUT(F7, C), MENUITEMs("///8", ACTMOD(ACT_SAVE_CLIP, 8)), ACTMAP(NEED_PCLIP), SHORTCUT(F8, C), MENUITEMs("///9", ACTMOD(ACT_SAVE_CLIP, 9)), ACTMAP(NEED_PCLIP), SHORTCUT(F9, C), MENUITEMs("///10", ACTMOD(ACT_SAVE_CLIP, 10)), ACTMAP(NEED_PCLIP), SHORTCUT(F10, C), MENUITEMs("///11", ACTMOD(ACT_SAVE_CLIP, 11)), ACTMAP(NEED_PCLIP), SHORTCUT(F11, C), MENUITEMs("///12", ACTMOD(ACT_SAVE_CLIP, 12)), ACTMAP(NEED_PCLIP), SHORTCUT(F12, C), WDONE, MENUITEM(_("//Import Clipboard from System"), ACTMOD(ACT_LOAD_CLIP, -1)), MENUITEM(_("//Export Clipboard to System"), ACTMOD(ACT_SAVE_CLIP, -1)), ACTMAP(NEED_PCLIP), MENUSEP, // MENUITEMs(_("//Choose Pattern ..."), ACTMOD(DLG_CHOOSER, CHOOSE_PATTERN)), SHORTCUT(F2, 0), MENUITEMs(_("//Choose Brush ..."), ACTMOD(DLG_CHOOSER, CHOOSE_BRUSH)), SHORTCUT(F3, 0), MENUITEMs(_("//Choose Colour ..."), ACTMOD(DLG_CHOOSER, CHOOSE_COLOR)), SHORTCUT(e, 0), // for scripting uMENUITEMs("//layers", ACTMOD(ACT_SCRIPT, TOOLBAR_LAYERS)), uMENUITEMs("//settings", ACTMOD(ACT_SCRIPT, TOOLBAR_SETTINGS)), uMENUITEMs("//tools", ACTMOD(ACT_SCRIPT, TOOLBAR_TOOLS)), WDONE, SSUBMENU(_("/_View")), MENUTEAR, // MENUCHECKv(_("//Show Main Toolbar"), ACTMOD(ACT_TBAR, TOOLBAR_MAIN), toolbar_status[TOOLBAR_MAIN]), SHORTCUT(F5, 0), MENUCHECKv(_("//Show Tools Toolbar"), ACTMOD(ACT_TBAR, TOOLBAR_TOOLS), toolbar_status[TOOLBAR_TOOLS]), SHORTCUT(F6, 0), REFv(menu_slots[MENU_TBSET]), MENUCHECKv(_("//Show Settings Toolbar"), ACTMOD(ACT_TBAR, TOOLBAR_SETTINGS), toolbar_status[TOOLBAR_SETTINGS]), SHORTCUT(F7, 0), REFv(menu_slots[MENU_DOCK]), MENUCHECKv(_("//Show Dock"), ACTMOD(ACT_DOCK, 0), show_dock), SHORTCUT(F12, 0), MTRIGGER(menu_action), // to show dock initially MENUCHECKv(_("//Show Palette"), ACTMOD(ACT_TBAR, TOOLBAR_PALETTE), toolbar_status[TOOLBAR_PALETTE]), SHORTCUT(F8, 0), MENUCHECKv(_("//Show Status Bar"), ACTMOD(ACT_TBAR, TOOLBAR_STATUS), toolbar_status[TOOLBAR_STATUS]), MENUSEP, // MENUITEM(_("//Toggle Image View"), ACTMOD(ACT_VIEW, 0)), SHORTCUT(Home, 0), SHORTCUT(Home, C), SHORTCUT(Home, S), SHORTCUT(Home, A), SHORTCUT(Home, CS), SHORTCUT(Home, CA), SHORTCUT(Home, SA), SHORTCUT(Home, CSA), MENUCHECKv(_("//Centralize Image"), ACTMOD(ACT_CENTER, 0), canvas_image_centre), MENUCHECKv(_("//Show Zoom Grid"), ACTMOD(ACT_GRID, 0), mem_show_grid), MENUCHECKvs(_("//Snap To Tile Grid"), ACTMOD(ACT_SNAP, 0), tgrid_snap), SHORTCUT(b, 0), MENUITEM(_("//Configure Grid ..."), ACTMOD(DLG_COLORS, COLSEL_GRID)), MENUITEM(_("//Tracing Image ..."), ACTMOD(DLG_TRACE, 0)), MENUSEP, // REFv(menu_slots[MENU_VIEW]), MENUCHECKv(_("//View Window"), ACTMOD(ACT_VWWIN, 0), menu_view), SHORTCUT(v, 0), MENUCHECKv(_("//Horizontal Split"), ACTMOD(ACT_VWSPLIT, 0), view_vsplit), SHORTCUT(h, 0), MENUCHECKv(_("//Focus View Window"), ACTMOD(ACT_VWFOCUS, 0), vw_focus_on), MENUSEP, // MENUITEMi(_("//Pan Window"), ACTMOD(ACT_PAN, 0), XPM_ICON(pan)), SHORTCUT(End, 0), REFv(menu_slots[MENU_LAYER]), MENUCHECKv(_("//Layers Window"), ACTMOD(DLG_LAYERS, 0), menu_layer), SHORTCUT(l, 0), WDONE, SSUBMENU(_("/_Image")), MENUTEAR, // uMENUITEMs("//Convert To RGB", ACTMOD(FILT_2RGB, 0)), // for scripting MENUITEM(_("//Convert To RGB"), ACTMOD(FILT_2RGB, 0)), ACTMAP(NEED_IDX), MENUITEMs(_("//Convert To Indexed ..."), ACTMOD(DLG_INDEXED, 0)), ACTMAP(NEED_24), MENUSEP, // MENUITEMs(_("//Scale Canvas ..."), ACTMOD(DLG_SCALE, 0)), SHORTCUT(Page_Up, 0), MENUITEMs(_("//Resize Canvas ..."), ACTMOD(DLG_SIZE, 0)), SHORTCUT(Page_Down, 0), MENUITEMs(_("//Crop"), ACTMOD(ACT_CROP, 0)), ACTMAP(NEED_CROP), SHORTCUT(x, CS), SHORTCUT(Delete, 0), MENUSEP, // MENUITEMs(_("//Flip Vertically"), ACTMOD(ACT_FLIP_V, 0)), MENUITEMs(_("//Flip Horizontally"), ACTMOD(ACT_FLIP_H, 0)), SHORTCUT(m, C), uMENUITEMs("//rotate", ACTMOD(DLG_ROTATE, 0)), // for scripting MENUITEMs(_("//Rotate Clockwise"), ACTMOD(ACT_ROTATE, 0)), MENUITEMs(_("//Rotate Anti-Clockwise"), ACTMOD(ACT_ROTATE, 1)), MENUITEMs(_("//Free Rotate ..."), ACTMOD(DLG_ROTATE, 0)), MENUITEMs(_("//Skew ..."), ACTMOD(DLG_SKEW, 0)), MENUSEP, // // !!! Maybe support indexed mode too, later MENUITEMs(_("//Segment ..."), ACTMOD(DLG_SEGMENT, 0)), ACTMAP(NEED_24), uMENUITEMs("//Script ...", ACTMOD(ACT_RUN_SCRIPT, 0)), // for scripting REFv(menu_slots[MENU_SCRIPT]), MENUITEM(_("//Script ..."), ACTMOD(DLG_SCRIPT, 0)), REFv(menu_slots[MENU_SCRIPT_M]), SUBMENU(_("//Scripts")), MENUTEAR, /// REFv(menu_slots[MENU_SCRIPT1]), MENUITEMs("///1", ACTMOD(ACT_RUN_SCRIPT, 1)), REFv(menu_slots[MENU_SCRIPT2]), MENUITEMs("///2", ACTMOD(ACT_RUN_SCRIPT, 2)), REFv(menu_slots[MENU_SCRIPT3]), MENUITEMs("///3", ACTMOD(ACT_RUN_SCRIPT, 3)), REFv(menu_slots[MENU_SCRIPT4]), MENUITEMs("///4", ACTMOD(ACT_RUN_SCRIPT, 4)), REFv(menu_slots[MENU_SCRIPT5]), MENUITEMs("///5", ACTMOD(ACT_RUN_SCRIPT, 5)), REFv(menu_slots[MENU_SCRIPT6]), MENUITEMs("///6", ACTMOD(ACT_RUN_SCRIPT, 6)), REFv(menu_slots[MENU_SCRIPT7]), MENUITEMs("///7", ACTMOD(ACT_RUN_SCRIPT, 7)), REFv(menu_slots[MENU_SCRIPT8]), MENUITEMs("///8", ACTMOD(ACT_RUN_SCRIPT, 8)), REFv(menu_slots[MENU_SCRIPT9]), MENUITEMs("///9", ACTMOD(ACT_RUN_SCRIPT, 9)), REFv(menu_slots[MENU_SCRIPT10]), MENUITEMs("///10", ACTMOD(ACT_RUN_SCRIPT, 10)), MENUSEP, /// REFv(menu_slots[MENU_SCRIPTC]), MENUITEM(_("///Configure"), ACTMOD(DLG_SCRIPT, 0)), WDONE, MENUSEP, // MENUITEMs(_("//Information ..."), ACTMOD(DLG_INFO, 0)), SHORTCUT(i, C), REFv(menu_slots[MENU_PREFS]), MENUITEMs(_("//Preferences ..."), ACTMOD(DLG_PREFS, 0)), SHORTCUT(p, C), WDONE, SSUBMENU(_("/_Selection")), MENUTEAR, // MENUITEMs(_("//Select All"), ACTMOD(ACT_SELECT, 1)), SHORTCUT(a, C), MENUITEMs(_("//Select None (Esc)"), ACTMOD(ACT_SELECT, 0)), ACTMAP(NEED_MARQ), SHORTCUT(a, CS), MENUITEMis(_("//Lasso Selection"), ACTMOD(ACT_LASSO, 0), XPM_ICON(lasso)), ACTMAP(NEED_LAS2), SHORTCUT(j, 0), MENUITEMs(_("//Lasso Selection Cut"), ACTMOD(ACT_LASSO, 1)), ACTMAP(NEED_LASSO), MENUSEP, // MENUITEMis(_("//Outline Selection"), ACTMOD(ACT_OUTLINE, 0), XPM_ICON(rect1)), ACTMAP(NEED_SEL2), SHORTCUT(t, C), MENUITEMis(_("//Fill Selection"), ACTMOD(ACT_OUTLINE, 1), XPM_ICON(rect2)), ACTMAP(NEED_SEL2), SHORTCUT(t, CS), MENUITEMis(_("//Outline Ellipse"), ACTMOD(ACT_ELLIPSE, 0), XPM_ICON(ellipse2)), ACTMAP(NEED_SEL), SHORTCUT(l, C), MENUITEMis(_("//Fill Ellipse"), ACTMOD(ACT_ELLIPSE, 1), XPM_ICON(ellipse)), ACTMAP(NEED_SEL), SHORTCUT(l, CS), MENUSEP, // MENUITEMis(_("//Flip Vertically"), ACTMOD(ACT_SEL_FLIP_V, 0), XPM_ICON(flip_vs)), ACTMAP(NEED_PCLIP), MENUITEMis(_("//Flip Horizontally"), ACTMOD(ACT_SEL_FLIP_H, 0), XPM_ICON(flip_hs)), ACTMAP(NEED_PCLIP), MENUITEMis(_("//Rotate Clockwise"), ACTMOD(ACT_SEL_ROT, 0), XPM_ICON(rotate_cs)), ACTMAP(NEED_PCLIP), MENUITEMis(_("//Rotate Anti-Clockwise"), ACTMOD(ACT_SEL_ROT, 1), XPM_ICON(rotate_as)), ACTMAP(NEED_PCLIP), MENUSEP, // MENUITEMs(_("//Horizontal Ramp"), ACTMOD(ACT_RAMP, 0)), ACTMAP(NEED_SEL), MENUITEMs(_("//Vertical Ramp"), ACTMOD(ACT_RAMP, 1)), ACTMAP(NEED_SEL), MENUSEP, // MENUITEMs(_("//Alpha Blend A,B"), ACTMOD(ACT_SEL_ALPHA_AB, 0)), ACTMAP(NEED_ACLIP), MENUITEMs(_("//Move Alpha to Mask"), ACTMOD(ACT_SEL_ALPHAMASK, 0)), ACTMAP(NEED_PCLIP), MENUITEMs(_("//Mask Colour A,B"), ACTMOD(ACT_SEL_MASK_AB, 0)), ACTMAP(NEED_CLIP), MENUITEMs(_("//Unmask Colour A,B"), ACTMOD(ACT_SEL_MASK_AB, 255)), ACTMAP(NEED_CLIP), MENUITEMs(_("//Mask All Colours"), ACTMOD(ACT_SEL_MASK, 0)), ACTMAP(NEED_PCLIP), MENUITEMs(_("//Clear Mask"), ACTMOD(ACT_SEL_MASK, 255)), ACTMAP(NEED_PCLIP), WDONE, SSUBMENU(_("/_Palette")), uMENUITEMs("//a", ACTMOD(ACT_A, 0)), // for scripting uMENUITEMs("//b", ACTMOD(ACT_B, 0)), // for scripting MENUTEAR, // MENUITEMis(_("//Load ..."), ACTMOD(DLG_FSEL, FS_PALETTE_LOAD), XPM_ICON(open)), MENUITEMis(_("//Save As ..."), ACTMOD(DLG_FSEL, FS_PALETTE_SAVE), XPM_ICON(save)), MENUITEMs(_("//Load Default"), ACTMOD(ACT_PAL_DEF, 0)), MENUSEP, // MENUITEMs(_("//Mask All"), ACTMOD(ACT_PAL_MASK, 1)), MENUITEMs(_("//Mask None"), ACTMOD(ACT_PAL_MASK, 0)), MENUSEP, // MENUITEMs(_("//Swap A & B"), ACTMOD(ACT_SWAP_AB, 0)), SHORTCUT(x, 0), MENUITEMs(_("//Edit Colour A & B ..."), ACTMOD(DLG_COLORS, COLSEL_EDIT_AB)), SHORTCUT(e, C), MENUITEMs(_("//Dither A"), ACTMOD(ACT_DITHER_A, 0)), ACTMAP(NEED_24), MENUITEMs(_("//Palette Editor ..."), ACTMOD(DLG_COLORS, COLSEL_EDIT_ALL)), SHORTCUT(w, C), MENUITEMs(_("//Set Palette Size ..."), ACTMOD(DLG_PAL_SIZE, 0)), MENUITEMs(_("//Merge Duplicate Colours"), ACTMOD(ACT_PAL_MERGE, 0)), ACTMAP(NEED_IDX), MENUITEMs(_("//Remove Unused Colours"), ACTMOD(ACT_PAL_CLEAN, 0)), ACTMAP(NEED_IDX), MENUSEP, // MENUITEMs(_("//Create Quantized ..."), ACTMOD(DLG_INDEXED, 1)), ACTMAP(NEED_24), MENUSEP, // MENUITEMs(_("//Sort Colours ..."), ACTMOD(DLG_PAL_SORT, 0)), MENUITEMs(_("//Palette Shifter ..."), ACTMOD(DLG_PAL_SHIFTER, 0)), MENUITEMs(_("//Pick Gradient ..."), ACTMOD(DLG_PICK_GRAD, 0)), WDONE, SSUBMENU(_("/Effe_cts")), MENUTEAR, // MENUITEMis(_("//Transform Colour ..."), ACTMOD(DLG_BRCOSA, 0), XPM_ICON(brcosa)), SHORTCUT(c, CS), SHORTCUT(Insert, 0), MENUITEMs(_("//Invert"), ACTMOD(FILT_INVERT, 0)), SHORTCUT(i, CS), MENUITEMs(_("//Greyscale"), ACTMOD(FILT_GREY, 0)), SHORTCUT(g, C), MENUITEMs(_("//Greyscale (Gamma corrected)"), ACTMOD(FILT_GREY, 1)), SHORTCUT(g, CS), MENUITEMs(_("//Normalize"), ACTMOD(FILT_NORM, 0)), MENUITEMs(_("//Threshold ..."), ACTMOD(DLG_XHOLD, 0)), MENUITEMs(_("//Map ..."), ACTMOD(FILT_MAP, 0)), ACTMAP(NEED_24), SUBMENU(_("//Isometric Transformation")), MENUTEAR, /// MENUITEMs(_("///Left Side Down"), ACTMOD(ACT_ISOMETRY, 0)), MENUITEMs(_("///Right Side Down"), ACTMOD(ACT_ISOMETRY, 1)), MENUITEMs(_("///Top Side Right"), ACTMOD(ACT_ISOMETRY, 2)), MENUITEMs(_("///Bottom Side Right"), ACTMOD(ACT_ISOMETRY, 3)), WDONE, MENUSEP, // MENUITEMs(_("//Edge Detect ..."), ACTMOD(FILT_EDGE, 0)), ACTMAP(NEED_NOIDX), MENUITEMs(_("//Difference of Gaussians ..."), ACTMOD(FILT_DOG, 0)), ACTMAP(NEED_NOIDX), MENUITEMs(_("//Sharpen ..."), ACTMOD(FILT_SHARPEN, 0)), ACTMAP(NEED_NOIDX), MENUITEMs(_("//Unsharp Mask ..."), ACTMOD(FILT_UNSHARP, 0)), ACTMAP(NEED_NOIDX), MENUITEMs(_("//Soften ..."), ACTMOD(FILT_SOFTEN, 0)), ACTMAP(NEED_NOIDX), MENUITEMs(_("//Gaussian Blur ..."), ACTMOD(FILT_GAUSS, 0)), ACTMAP(NEED_NOIDX), MENUITEMs(_("//Kuwahara-Nagao Blur ..."), ACTMOD(FILT_KUWAHARA, 0)), ACTMAP(NEED_24), MENUITEMs(_("//Emboss"), ACTMOD(FILT_FX, FX_EMBOSS)), ACTMAP(NEED_NOIDX), MENUITEMs(_("//Dilate"), ACTMOD(FILT_FX, FX_DILATE)), ACTMAP(NEED_NOIDX), MENUITEMs(_("//Erode"), ACTMOD(FILT_FX, FX_ERODE)), ACTMAP(NEED_NOIDX), MENUSEP, // MENUITEMs(_("//Solid Noise ..."), ACTMOD(DLG_NOISE, 0)), MENUITEMs(_("//Bacteria ..."), ACTMOD(FILT_BACT, 0)), ACTMAP(NEED_IDX), WDONE, SSUBMENU(_("/Cha_nnels")), MENUTEAR, // MENUITEMs(_("//New ..."), ACTMOD(ACT_CHANNEL, -1)), MENUITEMis(_("//Load ..."), ACTMOD(DLG_FSEL, FS_CHANNEL_LOAD), XPM_ICON(open)), MENUITEMis(_("//Save As ..."), ACTMOD(DLG_FSEL, FS_CHANNEL_SAVE), XPM_ICON(save)), MENUITEMs(_("//Delete ..."), ACTMOD(DLG_CHN_DEL, -1)), ACTMAP(NEED_CHAN), MENUSEP, // REFv(menu_slots[MENU_CHAN0]), MENURITEMvs(_("//Edit Image"), ACTMOD(ACT_CHANNEL, CHN_IMAGE), menu_chan), SHORTCUT(1, S), SHORTCUT(KP_1, S), REFv(menu_slots[MENU_CHAN1]), MENURITEMvs(_("//Edit Alpha"), ACTMOD(ACT_CHANNEL, CHN_ALPHA), menu_chan), SHORTCUT(2, S), SHORTCUT(KP_2, S), REFv(menu_slots[MENU_CHAN2]), MENURITEMvs(_("//Edit Selection"), ACTMOD(ACT_CHANNEL, CHN_SEL), menu_chan), SHORTCUT(3, S), SHORTCUT(KP_3, S), REFv(menu_slots[MENU_CHAN3]), MENURITEMvs(_("//Edit Mask"), ACTMOD(ACT_CHANNEL, CHN_MASK), menu_chan), SHORTCUT(4, S), SHORTCUT(KP_4, S), MENUSEP, // REFv(menu_slots[MENU_DCHAN0]), MENUCHECKv(_("//Hide Image"), ACTMOD(ACT_SET_OVERLAY, 1), hide_image), SHORTCUT(h, C), REFv(menu_slots[MENU_DCHAN1]), MENUCHECKvs(_("//Disable Alpha"), ACTMOD(ACT_CHN_DIS, CHN_ALPHA), channel_dis[CHN_ALPHA]), REFv(menu_slots[MENU_DCHAN2]), MENUCHECKvs(_("//Disable Selection"), ACTMOD(ACT_CHN_DIS, CHN_SEL), channel_dis[CHN_SEL]), REFv(menu_slots[MENU_DCHAN3]), MENUCHECKvs(_("//Disable Mask"), ACTMOD(ACT_CHN_DIS, CHN_MASK), channel_dis[CHN_MASK]), MENUSEP, // MENUCHECKvs(_("//Couple RGBA Operations"), ACTMOD(ACT_SET_RGBA, 0), RGBA_mode), MENUITEMs(_("//Threshold ..."), ACTMOD(FILT_THRES, 0)), MENUITEMs(_("//Unassociate Alpha"), ACTMOD(FILT_UALPHA, 0)), ACTMAP(NEED_RGBA), MENUSEP, // REFv(menu_slots[MENU_OALPHA]), MENUCHECKv(_("//View Alpha as an Overlay"), ACTMOD(ACT_SET_OVERLAY, 0), overlay_alpha), MENUITEM(_("//Configure Overlays ..."), ACTMOD(DLG_COLORS, COLSEL_OVERLAYS)), WDONE, SSUBMENU(_("/_Layers")), MENUTEAR, // MENUITEMis(_("//New Layer"), ACTMOD(ACT_LR_ADD, LR_NEW), XPM_ICON(new)), MENUITEMis(_("//Save"), ACTMOD(ACT_LR_SAVE, 0), XPM_ICON(save)), SHORTCUT(s, CS), MENUITEMs(_("//Save As ..."), ACTMOD(DLG_FSEL, FS_LAYER_SAVE)), MENUITEMs(_("//Save Composite Image ..."), ACTMOD(DLG_FSEL, FS_COMPOSITE_SAVE)), MENUITEMs(_("//Composite to New Layer"), ACTMOD(ACT_LR_ADD, LR_COMP)), MENUITEMs(_("//Remove All Layers"), ACTMOD(ACT_LR_DEL, 1)), MENUSEP, // MENUITEM(_("//Configure Animation ..."), ACTMOD(DLG_ANI, 0)), MENUITEM(_("//Preview Animation ..."), ACTMOD(DLG_ANI_VIEW, 0)), MENUITEM(_("//Set Key Frame ..."), ACTMOD(DLG_ANI_KEY, 0)), MENUITEM(_("//Remove All Key Frames ..."), ACTMOD(DLG_ANI_KILLKEY, 0)), WDONE, SSUBMENU(_("/More...")), WDONE, ESUBMENU(_("/_Help")), MENUITEM(_("//Documentation"), ACTMOD(ACT_DOCS, 0)), REFv(menu_slots[MENU_HELP]), MENUITEM(_("//About"), ACTMOD(DLG_ABOUT, 0)), SHORTCUT(F1, 0), MENUSEP, // MENUITEM(_("//Keyboard Shortcuts ..."), ACTMOD(DLG_KEYS, 0)), MENUITEM(_("//Rebind Shortcut Keycodes"), ACTMOD(ACT_REBIND_KEYS, 0)), WDONE, WDONE, // smartmenu ENDSCRIPT, RET }; static int dock_esc(main_dd *dt, void **wdata, int what, void **where, key_ext *keydata) { /* Pressing Escape moves focus out of dock - to nowhere */ if (keydata->key == KEY(Escape)) { cmd_setv(main_window_, NULL, WINDOW_FOCUS); return (TRUE); } return (FALSE); } static int cline_keypress(main_dd *dt, void **wdata, int what, void **where, key_ext *keydata) { return (check_zoom_keys(wtf_pressed(keydata))); // Check HOME/zoom keys } static void cline_select(main_dd *dt, void **wdata, int what, void **where) { cmd_read(where, dt); if (dt->idx_c == dt->nidx_c) return; // no change if ((layers_total ? check_layers_for_changes() : check_for_changes()) == 1) cmd_set(where, dt->idx_c); // Go back // Load requested file else do_a_load(file_args[dt->idx_c = dt->nidx_c], undo_load); } static void dock_undock_evt(main_dd *dt, void **wdata, int what, void **where) { int dstate; cmd_read(where, dt); dstate = dt->settings_d | dt->layers_d; /* Hide settings + layers page if it's empty */ cmd_showhide(dt->dockpage1, dstate); /* Show tabs only when it makes sense */ cmd_setv(dock_book, (void *)(dt->cline_d && dstate), NBOOK_TABS); /* Close dock if nothing left in it */ dstate |= dt->cline_d; if (!dstate) cmd_set(menu_slots[MENU_DOCK], FALSE); cmd_sensitive(menu_slots[MENU_DOCK], dstate); } #define REPAINT_CANVAS_COST 512 #define WBbase main_dd static void *main_code[] = { /// MAIN WINDOW MAINWINDOW(MT_VERSION, icon_xpm, 100, 100), EVENT(CANCEL, delete_event), EVENT(KEY, handle_keypress), REF(drop), CLIPFORM(uri_list, 1), /* !!! Konqueror needs GDK_ACTION_MOVE to do a drop; we never accept * move as a move, so have to do some non-default processing - WJ */ DRAGDROPm(drop, NULL, parse_drag), WXYWH("window", 630, 400), /// KEYMAP REFv(main_keys), KEYMAP(keyslot, "main"), CALL(keylist_code), REFv(dock_area), DOCK("dockSize"), /// MENU CALL(main_menu_code), /// TOOLBARS CALL(toolbar_code), XHBOX, /// PALETTE CALL(toolbar_palette_code), XVBOX, /// DRAWING AREA REFv(main_split), HVSPLIT, // MAIN WINDOW REFv(scrolledwindow_canvas), CSCROLLv(cvxy), EVENT(CHANGE, vw_focus_idle), REFv(drawing_canvas), CANVAS(48, 48, REPAINT_CANVAS_COST, paint_canvas), EVENT(CHANGE, configure_canvas), EVENT(XMOUSE, canvas_mouse), EVENT(RXMOUSE, canvas_mouse), EVENT(MXMOUSE, canvas_mouse), EVENT(CROSS, canvas_enter_leave), EVENT(SCROLL, canvas_scroll), // VIEW WINDOW CALL(init_view_code), EVENT(SCROLL, canvas_scroll), // for vw_drawing widget WDONE, // hvsplit //// STATUS BAR REFv(toolbar_boxes[TOOLBAR_STATUS]), STATUSBAR, UNLESSv(toolbar_status[TOOLBAR_STATUS]), HIDDEN, /* Labels visibility is set later by init_status_bar() */ REFv(label_bar[STATUS_GEOMETRY]), STLABEL(0, 0), REFv(label_bar[STATUS_CURSORXY]), STLABEL(90, 1), REFv(label_bar[STATUS_PIXELRGB]), STLABEL(0, 0), REFv(label_bar[STATUS_SELEGEOM]), STLABELe(0, 0), REFv(label_bar[STATUS_UNDOREDO]), STLABELe(70, 1), WDONE, // statusbar WDONE, // xvbox WDONE, // xhbox WDONE, // left pane BORDER(NBOOK, 0), REFv(dock_book), NBOOKr, KEEPWIDTH, WANTKEYS(dock_esc), IFx(cline_d, 1), PAGEi(XPM_ICON(cline), 0), BORDER(SCROLL, 0), XSCROLL(1, 1), // auto/auto WLIST, RTXTCOLUMNDi(0, 0), COLUMNDATA(strs_c, sizeof(int)), CLEANUP(strs_c), LISTCu(nidx_c, cnt_c, cline_select), FOCUS, EVENT(KEY, cline_keypress), WDONE, ENDIF(1), REF(dockpage1), PAGEir(XPM_ICON(layers), 5), REFv(settings_dock), MOUNT(settings_d, create_settings_box, dock_undock_evt), HSEPt, REFv(layers_dock), PMOUNT(layers_d, create_layers_box, dock_undock_evt, "layers_h", 400), TRIGGER, WDONE, // page WDONE, // nbook WDONE, // right pane REF(clip), CLIPFORM(clip_formats, CLIP_TARGETS), REF(clipboard), CLIPBOARD(clip, 3, clipboard_export_fn, clipboard_import_fn), RAISED, WEND }; #undef WBbase void main_init() { main_dd tdata; char *tdev, txt[PATHTXT]; memset(&tdata, 0, sizeof(tdata)); /* Prepare commandline list */ if ((show_dock = tdata.cline_d = files_passed > 1)) { memx2 mem; int i, *p; memset(&mem, 0, sizeof(mem)); getmemx2(&mem, 4000); // default size mem.here += getmemx2(&mem, files_passed * sizeof(int)); // minsize for (i = 0; i < files_passed; i++) { p = (int *)mem.buf + i; *p = mem.here - ((char *)p - mem.buf); /* Convert name string (to UTF-8 in GTK+2) and store it */ gtkuncpy(txt, file_args[i], sizeof(txt)); addstr(&mem, txt, 0); } tdata.cnt_c = files_passed; tdata.strs_c = (int *)mem.buf; } show_dock |= inifile_get_gboolean("showDock", FALSE); main_window_ = run_create_(main_code, &tdata, sizeof(tdata), script_cmds); recent_files = bounded(recent_files, 0, MAX_RECENT); update_recent_files(FALSE); if (!tdata.cline_d) // Stops first icon in toolbar being selected cmd_setv(main_window_, NULL, WINDOW_FOCUS); init_status_bar(); init_factions(); // Initialize file action menu update_script_menu(); file_in_homedir(txt, ".clipboard", PATHBUF); strncpy0(mem_clip_file, inifile_get("clipFilename", txt), PATHBUF); set_cursor(NULL); change_to_tool(DEFAULT_TOOL_ICON); /* Skip the GUI-specific updates in commandline mode */ if (cmd_mode) return; cmd_peekv(main_window_, &tdev, sizeof(tdev), WDATA_TABLET); // Check tablet state tablet_working = !!tdev; cmd_showhide(main_window_, TRUE); if (viewer_mode) toggle_view(); else toolbar_showhide(); } void spot_undo(int mode) { mem_undo_next(mode); // Do memory stuff for undo update_menus(); // Update menu undo issues } #ifdef U_NLS #include void setup_language() // Change language { char *txt = inifile_get( "languageSETTING", "system" ), txt2[64]; if (strcmp("system", txt)) { snprintf( txt2, 60, "LANGUAGE=%s", txt ); putenv( txt2 ); snprintf( txt2, 60, "LANG=%s", txt ); putenv( txt2 ); snprintf( txt2, 60, "LC_ALL=%s", txt ); putenv( txt2 ); } else txt = ""; #if GTK_MAJOR_VERSION > 1 if (cmd_mode) #endif setlocale(LC_ALL, txt); #if GTK_MAJOR_VERSION <= 2 /* !!! Slow or not, but NLS is *really* broken on GTK+1 without it - WJ */ // GTK+1 hates this - it really slows things down if (!cmd_mode) gtk_set_locale(); #endif } #endif void update_titlebar() // Update filename in titlebar { static int changed = -1; static char *name = ""; char txt[300], txt2[PATHTXT]; /* Don't send needless updates */ if (!main_window_ || ((mem_changed == changed) && (mem_filename == name))) return; changed = mem_changed; name = mem_filename; snprintf(txt, 290, "%s %s %s", MT_VERSION, changed ? __("(Modified)") : "-", name ? gtkuncpy(txt2, name, PATHTXT) : __("Untitled")); cmd_setv(main_window_, txt, WINDOW_TITLE); } void notify_changed() // Image/palette has just changed - update vars as needed { mem_tempfiles = NULL; if (!mem_changed) { mem_changed = TRUE; update_titlebar(); } } /* Image has just been unchanged: saved to file, or loaded if "filename" is NULL */ void notify_unchanged(char *filename) { if (mem_changed) { if (filename) mem_file_modified(filename); mem_changed = FALSE; update_titlebar(); } } mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/mainwindow.h000066400000000000000000000213461471325446300232750ustar00rootroot00000000000000/* mainwindow.h Copyright (C) 2004-2021 Mark Tyler and Dmitry Groshev This file is part of mtPaint. mtPaint 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. mtPaint 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 mtPaint in the file COPYING. */ /* Keyboard action codes */ #define ACTMOD_DUMMY -1 /* Means action is done already */ enum { // To let constants renumber themselves when adding new ones ACT_QUIT = 1, ACT_ZOOM, ACT_VIEW, ACT_PAN, ACT_CROP, ACT_SWAP_AB, ACT_TOOL, ACT_SEL_MOVE, ACT_OPAC, ACT_LR_MOVE, ACT_ESC, ACT_COMMIT, ACT_RCLICK, ACT_ARROW, ACT_A, ACT_B, ACT_CHANNEL, ACT_VWZOOM, ACT_SAVE, ACT_FACTION, ACT_LOAD_RECENT, ACT_DO_UNDO, ACT_COPY, ACT_PASTE, ACT_COPY_PAL, ACT_PASTE_PAL, ACT_LOAD_CLIP, ACT_SAVE_CLIP, ACT_TBAR, ACT_DOCK, ACT_CENTER, ACT_GRID, ACT_SNAP, ACT_VWWIN, ACT_VWSPLIT, ACT_VWFOCUS, ACT_FLIP_V, ACT_FLIP_H, ACT_ROTATE, ACT_SELECT, ACT_LASSO, ACT_OUTLINE, ACT_ELLIPSE, ACT_SEL_FLIP_V, ACT_SEL_FLIP_H, ACT_SEL_ROT, ACT_RAMP, ACT_SEL_ALPHA_AB, ACT_SEL_ALPHAMASK, ACT_SEL_MASK_AB, ACT_SEL_MASK, ACT_PAL_DEF, ACT_PAL_MASK, ACT_DITHER_A, ACT_PAL_MERGE, ACT_PAL_CLEAN, ACT_ISOMETRY, ACT_CHN_DIS, ACT_SET_RGBA, ACT_SET_OVERLAY, ACT_LR_SAVE, ACT_LR_ADD, ACT_LR_DEL, ACT_DOCS, ACT_REBIND_KEYS, ACT_MODE, ACT_LR_SHIFT, ACT_LR_CENTER, ACT_SCRIPT, ACT_RUN_SCRIPT, ACT_SIZE, ACT_PAT, DLG_BRCOSA, DLG_CHOOSER, DLG_SCALE, DLG_SIZE, DLG_NEW, DLG_FSEL, DLG_FACTIONS, DLG_TEXT, DLG_TEXT_FT, DLG_LAYERS, DLG_INDEXED, DLG_ROTATE, DLG_INFO, DLG_PREFS, DLG_COLORS, DLG_PAL_SIZE, DLG_PAL_SORT, DLG_PAL_SHIFTER, DLG_FILTER, DLG_CHN_DEL, DLG_ANI, DLG_ANI_VIEW, DLG_ANI_KEY, DLG_ANI_KILLKEY, DLG_ABOUT, DLG_SKEW, DLG_FLOOD, DLG_SMUDGE, DLG_CLONE, DLG_GRAD, DLG_STEP, DLG_FILT, DLG_TRACE, DLG_PICK_GRAD, DLG_SEGMENT, DLG_SCRIPT, DLG_LASSO, DLG_KEYS, DLG_XHOLD, DLG_NOISE, FILT_2RGB, FILT_INVERT, FILT_GREY, FILT_EDGE, FILT_DOG, FILT_SHARPEN, FILT_UNSHARP, FILT_SOFTEN, FILT_GAUSS, FILT_FX, FILT_BACT, FILT_THRES, FILT_UALPHA, FILT_KUWAHARA, FILT_NORM, FILT_MAP, ACT_TEST /* Reserved for testing things */ }; // New layer sources for ACT_LR_ADD #define LR_NEW 0 #define LR_DUP 1 #define LR_PASTE 2 #define LR_COMP 3 int key_action(key_ext *key, int toggle); #define wtf_pressed(X) key_action((X), FALSE) void action_dispatch(int action, int mode, int state, int kbd); /* Widget dependence flags */ #define NEED_UNDO 0x0001 #define NEED_REDO 0x0002 #define NEED_CROP 0x0004 #define NEED_MARQ 0x0008 #define NEED_SEL 0x0010 #define NEED_CLIP 0x0020 #define NEED_24 0x0040 #define NEED_NOIDX 0x0080 #define NEED_IDX 0x0100 #define NEED_LASSO 0x0200 #define NEED_ACLIP 0x0400 #define NEED_CHAN 0x0800 #define NEED_RGBA 0x1000 #define NEED_PCLIP 0x2000 #define NEED_SKIP 0x4000 /* Never activated at all */ #define NEED_SEL2 (NEED_SEL | NEED_LASSO) #define NEED_PSEL (NEED_MARQ | NEED_PCLIP) #define NEED_LAS2 (NEED_LASSO | NEED_PCLIP) /* Notable menu items */ enum { MENU_FACTION1 = 1, MENU_FACTION2, MENU_FACTION3, MENU_FACTION4, MENU_FACTION5, MENU_FACTION6, MENU_FACTION7, MENU_FACTION8, MENU_FACTION9, MENU_FACTION10, MENU_FACTION11, MENU_FACTION12, MENU_FACTION13, MENU_FACTION14, MENU_FACTION15, MENU_FACTION_S, MENU_RECENT_S, MENU_RECENT1, MENU_RECENT2, MENU_RECENT3, MENU_RECENT4, MENU_RECENT5, MENU_RECENT6, MENU_RECENT7, MENU_RECENT8, MENU_RECENT9, MENU_RECENT10, MENU_RECENT11, MENU_RECENT12, MENU_RECENT13, MENU_RECENT14, MENU_RECENT15, MENU_RECENT16, MENU_RECENT17, MENU_RECENT18, MENU_RECENT19, MENU_RECENT20, MENU_SCRIPT, MENU_SCRIPT_M, MENU_SCRIPT1, MENU_SCRIPT2, MENU_SCRIPT3, MENU_SCRIPT4, MENU_SCRIPT5, MENU_SCRIPT6, MENU_SCRIPT7, MENU_SCRIPT8, MENU_SCRIPT9, MENU_SCRIPT10, MENU_SCRIPTC, MENU_TBSET, MENU_VIEW, MENU_LAYER, MENU_PREFS, MENU_CHAN0, MENU_CHAN1, MENU_CHAN2, MENU_CHAN3, MENU_DCHAN0, MENU_DCHAN1, MENU_DCHAN2, MENU_DCHAN3, MENU_OALPHA, MENU_HELP, MENU_DOCK, TOTAL_MENU_IDS }; /// TRACING IMAGE unsigned char *bkg_rgb; int bkg_x, bkg_y, bkg_w, bkg_h, bkg_scale, bkg_flag; int config_bkg(int src); // 0 = unchanged, 1 = none, 2 = image, 3 = clipboard /// GRID /* !!! Indices 0-2 are hardcoded in draw_grid() */ #define GRID_NORMAL 0 /* Normal/image grid */ #define GRID_BORDER 1 #define GRID_TRANS 2 /* For transparency */ #define GRID_TILE 3 #define GRID_SEGMENT 4 #define GRID_MAX 5 int grid_rgb[GRID_MAX]; // Grid colors to use int mem_show_grid; // Boolean show toggle int mem_grid_min; // Minimum zoom to show it at int color_grid; // If to use grid coloring int show_tile_grid; // Tile grid toggle int tgrid_x0, tgrid_y0; // Tile grid origin int tgrid_dx, tgrid_dy; // Tile grid spacing int tgrid_snap; // Coordinates snap toggle /* Snap coordinate pair to tile grid (floored) */ void snap_xy(int *xy); const unsigned char greyz[2]; // For opacity squares char *channames[NUM_CHANNELS + 1], *allchannames[NUM_CHANNELS + 1]; char *cspnames[NUM_CSPACES]; char *channames_[NUM_CHANNELS + 1]; char *cspnames_[NUM_CSPACES]; void **main_window_, **main_keys, **settings_dock, **layers_dock, **main_split, **drawing_canvas, **scrolledwindow_canvas, **menu_slots[TOTAL_MENU_IDS]; int view_image_only, viewer_mode, drag_index, q_quit, cursor_tool; int show_menu_icons, paste_commit, scroll_zoom, arrow_scroll; int drag_index_vals[2], cursor_corner, use_gamma, view_vsplit; int files_passed, cmd_mode, tablet_working; char **file_args, **script_cmds; #define FILES_MAX (1024 * 1024) /* A million+ files should be enough */ int perim_wx, perim_wy; // Cursor position extern char mem_clip_file[]; extern void *scriptbar_code[]; // Set up scriptable items for tools toolbar int kpix_threads; // Min kpixels per render thread /* With 2 cores and uniform layers stack, no noticeable difference between * 1, 4 and 8 strips per thread; time jitter of about 10% is common, and spikes * of about 40% sometimes happen; with 1 strip, even 50% was observed once. * Still, with nonuniform layers, more strips can maybe balance better - WJ */ #define MAX_TH_STRIPS 8 void var_init(); // Load INI variables void string_init(); // Translate static strings void main_init(); // Initialise and display the main window char **wj_parse_argv(char *src); // Parse string into commands int run_script(char **res); // Interpret parsed sequence of commands void draw_dash(int c0, int c1, int ofs, int x, int y, int w, int h, rgbcontext *ctx); void draw_poly(int *xy, int cnt, int shift, int x00, int y00, rgbcontext *ctx); void canvas_size(int *w, int *h); // Get zoomed canvas size void prepare_line_clip(int *lxy, int *vxy, int scale); // Map clipping rectangle to line-space void main_update_area(int x, int y, int w, int h); // Update x,y,w,h area of current image void repaint_canvas( int px, int py, int pw, int ph ); // Redraw area of canvas void grad_stroke(int x, int y); // Update stroke gradient int async_bk; typedef struct { int dx; int width; int xwid; int zoom; int scale; int mw; int opac; int xpm; int bpp; int cmask; png_color *pal; } renderstate; void setup_row(renderstate *r, int x0, int width, int zoom, int scale, int mw, int xpm, int opac, int bpp, png_color *pal); void render_row(renderstate *r, unsigned char *rgb, chanlist base_img, int x, int y, chanlist xtra_img); void stop_line(); void change_to_tool(int icon); void spot_undo(int mode); // Take snapshot for undo void set_cursor(void **what); // Set mouse cursor int check_for_changes(); // 1=STOP, 2=IGNORE, 10=ESCAPE, -10=NOT CHECKED // Try to save file + warn if error + return < 0 if fail int gui_save(char *filename, ls_settings *settings); // Load system clipboard like a file, return TRUE if successful int import_clipboard(int mode); void pressed_select(int all); void pressed_opacity(int opacity); int check_zoom_keys(int act_m); int check_zoom_keys_real(int act_m); void setup_language(); // Change language // Image/palette has just changed - update vars as needed void notify_changed(); // Image has just been unchanged: saved to file, or loaded if "filename" is NULL void notify_unchanged(char *filename); void update_titlebar(); // Update filename in titlebar void force_main_configure(); // Force reconfigure of main drawing area - for centralizing code void set_image(int state); // Toggle image access (nestable) int dock_focused(); // Check if focus is inside dock window mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/memory.c000066400000000000000000010406311471325446300224230ustar00rootroot00000000000000/* memory.c Copyright (C) 2004-2021 Mark Tyler and Dmitry Groshev This file is part of mtPaint. mtPaint 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. mtPaint 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 mtPaint in the file COPYING. */ #include "global.h" #undef _ #define _(X) X #include "mygtk.h" #include "memory.h" #include "vcode.h" #include "ani.h" #include "png.h" #include "mainwindow.h" #include "otherwindow.h" #include "layer.h" #include "inifile.h" #include "canvas.h" #include "prefs.h" #include "channels.h" #include "toolbar.h" #include "viewer.h" #include "csel.h" #include "thread.h" grad_info gradient[NUM_CHANNELS]; // Per-channel gradients double grad_path, grad_x0, grad_y0; // Stroke gradient temporaries grad_map graddata[NUM_CHANNELS + 1]; // RGB + per-channel gradient data grad_store gradbytes; // Storage space for custom gradients int grad_opacity; // Preview opacity /// Vectorized low-level drawing functions void (*put_pixel)(int x, int y) = put_pixel_def; void (*put_pixel_row)(int x, int y, int len, unsigned char *xsel) = put_pixel_row_def; #define ROW_BUFLEN 2048 /* Preferred length of internal row buffer */ /// Bayer ordered dithering const unsigned char bayer[16] = { 0x00, 0x40, 0x10, 0x50, 0x04, 0x44, 0x14, 0x54, 0x01, 0x41, 0x11, 0x51, 0x05, 0x45, 0x15, 0x55 }; /// Tint tool - contributed by Dmitry Groshev, January 2006 int tint_mode[3]; // [0] = off/on, [1] = add/subtract, [2] = button (none, left, middle, right : 0-3) int mem_cselect; int mem_blend; int mem_unmask; int mem_gradient; int paint_gamma; /// BLEND MODE SETTINGS int blend_mode = BLEND_HUE; int blend_src; /// FLOOD FILL SETTINGS double flood_step; int flood_cube, flood_img, flood_slide; int smudge_mode; /// QUANTIZATION SETTINGS int quan_sqrt; // "Diameter based weighting" - use sqrt of pixel count /// IMAGE int mem_undo_depth = DEF_UNDO; // Current undo depth image_info mem_image; // Current image image_info mem_clip; // Current clipboard image_state mem_state; // Current edit settings int mem_background = 180; // Non paintable area unsigned char mem_brushes[PATCH_WIDTH * PATCH_HEIGHT * 3]; // Preset brushes screen memory int mem_clip_x = -1, mem_clip_y = -1; // Clipboard location on canvas int mem_nudge = -1; // Nudge pixels per SHIFT+Arrow key during selection/paste transform_state mem_bcsp[2]; /// UNDO ENGINE #define TILE_SIZE 64 #define TILE_SHIFT 6 #define MAX_TILEMAP ((((MAX_WIDTH + TILE_SIZE - 1) / TILE_SIZE + 7) / 8) * \ ((MAX_HEIGHT + TILE_SIZE - 1) / TILE_SIZE)) #define UF_TILED 0x01 #define UF_FLAT 0x02 #define UF_SIZED 0x04 #define UF_ORIG 0x08 /* Unmodified state */ #define UF_ACCUM 0x10 /* Cumulative */ int mem_undo_limit; // Max MB memory allocation limit int mem_undo_common; // Percent of undo space in common arena int mem_undo_opacity; // Use previous image for opacity calculations? int mem_undo_fail; // Undo space shortfall typedef struct { unsigned int n, size, freecnt; void *datastore, *freelist; } memchunks; #define UNDO_STORESIZE 1023 /* Leave space for memory block header */ static memchunks undo_datastore = { UNDO_STORESIZE, sizeof(undo_data) }; static memchunks undo_items = { DEF_UNDO, sizeof(undo_item) }; /// PATTERNS int pattern_B; // Let colour B have its own pattern unsigned char *mem_pattern; // Original 0-1 pattern unsigned char mem_col_pat[8 * 8]; // Indexed 8x8 colourised pattern using colours A & B unsigned char mem_col_pat24[8 * 8 * 3]; // RGB 8x8 colourised pattern using colours A & B /// TOOLS tool_info tool_state = { TOOL_SQUARE, TOOL_SQUARE, { 1, 1, 255 } }; // Type, brush, size/flow/opacity int pen_down; // Are we drawing? - Used to see if we need to do an UNDO int tool_ox, tool_oy; // Previous tool coords - used by continuous mode int mem_continuous; // Area we painting the static shapes continuously? /// PALETTE int mem_pal_id_c, mem_pal_ab_c; // Text & A/B highlight colors unsigned char mem_pals[PALETTE_WIDTH * PALETTE_HEIGHT * 3]; // RGB screen memory holding current palette int mem_brush_list[NUM_BRUSHES][3] = { // Preset brushes parameters { TOOL_SPRAY, 5, 1 }, { TOOL_SPRAY, 7, 1 }, { TOOL_SPRAY, 9, 2 }, { TOOL_SPRAY, 13, 2 }, { TOOL_SPRAY, 15, 3 }, { TOOL_SPRAY, 19, 3 }, { TOOL_SPRAY, 23, 4 }, { TOOL_SPRAY, 27, 5 }, { TOOL_SPRAY, 31, 6 }, { TOOL_SPRAY, 5, 5 }, { TOOL_SPRAY, 7, 7 }, { TOOL_SPRAY, 9, 9 }, { TOOL_SPRAY, 13, 13 }, { TOOL_SPRAY, 15, 15 }, { TOOL_SPRAY, 19, 19 }, { TOOL_SPRAY, 23, 23 }, { TOOL_SPRAY, 27, 27 }, { TOOL_SPRAY, 31, 31 }, { TOOL_SPRAY, 5, 15 }, { TOOL_SPRAY, 7, 21 }, { TOOL_SPRAY, 9, 27 }, { TOOL_SPRAY, 13, 39 }, { TOOL_SPRAY, 15, 45 }, { TOOL_SPRAY, 19, 57 }, { TOOL_SPRAY, 23, 69 }, { TOOL_SPRAY, 27, 81 }, { TOOL_SPRAY, 31, 93 }, { TOOL_CIRCLE, 3, -1 }, { TOOL_CIRCLE, 5, -1 }, { TOOL_CIRCLE, 7, -1 }, { TOOL_CIRCLE, 9, -1 }, { TOOL_CIRCLE, 13, -1 }, { TOOL_CIRCLE, 17, -1 }, { TOOL_CIRCLE, 21, -1 }, { TOOL_CIRCLE, 25, -1 }, { TOOL_CIRCLE, 31, -1 }, { TOOL_SQUARE, 1, -1 }, { TOOL_SQUARE, 2, -1 }, { TOOL_SQUARE, 3, -1 }, { TOOL_SQUARE, 4, -1 }, { TOOL_SQUARE, 8, -1 }, { TOOL_SQUARE, 12, -1 }, { TOOL_SQUARE, 16, -1 }, { TOOL_SQUARE, 24, -1 }, { TOOL_SQUARE, 32, -1 }, { TOOL_SLASH, 3, -1 }, { TOOL_SLASH, 5, -1 }, { TOOL_SLASH, 7, -1 }, { TOOL_SLASH, 9, -1 }, { TOOL_SLASH, 13, -1 }, { TOOL_SLASH, 17, -1 }, { TOOL_SLASH, 21, -1 }, { TOOL_SLASH, 25, -1 }, { TOOL_SLASH, 31, -1 }, { TOOL_BACKSLASH, 3, -1 }, { TOOL_BACKSLASH, 5, -1 }, { TOOL_BACKSLASH, 7, -1 }, { TOOL_BACKSLASH, 9, -1 }, { TOOL_BACKSLASH, 13, -1 }, { TOOL_BACKSLASH, 17, -1 }, { TOOL_BACKSLASH, 21, -1 }, { TOOL_BACKSLASH, 25, -1 }, { TOOL_BACKSLASH, 31, -1 }, { TOOL_VERTICAL, 3, -1 }, { TOOL_VERTICAL, 5, -1 }, { TOOL_VERTICAL, 7, -1 }, { TOOL_VERTICAL, 9, -1 }, { TOOL_VERTICAL, 13, -1 }, { TOOL_VERTICAL, 17, -1 }, { TOOL_VERTICAL, 21, -1 }, { TOOL_VERTICAL, 25, -1 }, { TOOL_VERTICAL, 31, -1 }, { TOOL_HORIZONTAL, 3, -1 }, { TOOL_HORIZONTAL, 5, -1 }, { TOOL_HORIZONTAL, 7, -1 }, { TOOL_HORIZONTAL, 9, -1 }, { TOOL_HORIZONTAL, 13, -1 }, { TOOL_HORIZONTAL, 17, -1 }, { TOOL_HORIZONTAL, 21, -1 }, { TOOL_HORIZONTAL, 25, -1 }, { TOOL_HORIZONTAL, 31, -1 }, }; int mem_pal_def_i = 256; // Items in default palette png_color mem_pal_def[256]={ // Default palette entries for new image /// All RGB in 3 bits per channel. i.e. 0..7 - multiply by 255/7 for full RGB .. /// .. or: int lookup[8] = {0, 36, 73, 109, 146, 182, 219, 255}; /// Primary colours = 8 {0,0,0}, {7,0,0}, {0,7,0}, {7,7,0}, {0,0,7}, {7,0,7}, {0,7,7}, {7,7,7}, /// Primary fades to black: 7 x 6 = 42 {6,6,6}, {5,5,5}, {4,4,4}, {3,3,3}, {2,2,2}, {1,1,1}, {6,0,0}, {5,0,0}, {4,0,0}, {3,0,0}, {2,0,0}, {1,0,0}, {0,6,0}, {0,5,0}, {0,4,0}, {0,3,0}, {0,2,0}, {0,1,0}, {6,6,0}, {5,5,0}, {4,4,0}, {3,3,0}, {2,2,0}, {1,1,0}, {0,0,6}, {0,0,5}, {0,0,4}, {0,0,3}, {0,0,2}, {0,0,1}, {6,0,6}, {5,0,5}, {4,0,4}, {3,0,3}, {2,0,2}, {1,0,1}, {0,6,6}, {0,5,5}, {0,4,4}, {0,3,3}, {0,2,2}, {0,1,1}, /// Shading triangles: 6 x 21 = 126 /// RED {7,6,6}, {6,5,5}, {5,4,4}, {4,3,3}, {3,2,2}, {2,1,1}, {7,5,5}, {6,4,4}, {5,3,3}, {4,2,2}, {3,1,1}, {7,4,4}, {6,3,3}, {5,2,2}, {4,1,1}, {7,3,3}, {6,2,2}, {5,1,1}, {7,2,2}, {6,1,1}, {7,1,1}, /// GREEN {6,7,6}, {5,6,5}, {4,5,4}, {3,4,3}, {2,3,2}, {1,2,1}, {5,7,5}, {4,6,4}, {3,5,3}, {2,4,2}, {1,3,1}, {4,7,4}, {3,6,3}, {2,5,2}, {1,4,1}, {3,7,3}, {2,6,2}, {1,5,1}, {2,7,2}, {1,6,1}, {1,7,1}, /// BLUE {6,6,7}, {5,5,6}, {4,4,5}, {3,3,4}, {2,2,3}, {1,1,2}, {5,5,7}, {4,4,6}, {3,3,5}, {2,2,4}, {1,1,3}, {4,4,7}, {3,3,6}, {2,2,5}, {1,1,4}, {3,3,7}, {2,2,6}, {1,1,5}, {2,2,7}, {1,1,6}, {1,1,7}, /// YELLOW (red + green) {7,7,6}, {6,6,5}, {5,5,4}, {4,4,3}, {3,3,2}, {2,2,1}, {7,7,5}, {6,6,4}, {5,5,3}, {4,4,2}, {3,3,1}, {7,7,4}, {6,6,3}, {5,5,2}, {4,4,1}, {7,7,3}, {6,6,2}, {5,5,1}, {7,7,2}, {6,6,1}, {7,7,1}, /// MAGENTA (red + blue) {7,6,7}, {6,5,6}, {5,4,5}, {4,3,4}, {3,2,3}, {2,1,2}, {7,5,7}, {6,4,6}, {5,3,5}, {4,2,4}, {3,1,3}, {7,4,7}, {6,3,6}, {5,2,5}, {4,1,4}, {7,3,7}, {6,2,6}, {5,1,5}, {7,2,7}, {6,1,6}, {7,1,7}, /// CYAN (blue + green) {6,7,7}, {5,6,6}, {4,5,5}, {3,4,4}, {2,3,3}, {1,2,2}, {5,7,7}, {4,6,6}, {3,5,5}, {2,4,4}, {1,3,3}, {4,7,7}, {3,6,6}, {2,5,5}, {1,4,4}, {3,7,7}, {2,6,6}, {1,5,5}, {2,7,7}, {1,6,6}, {1,7,7}, /// Scales: 11 x 6 = 66 /// RGB {7,6,5}, {6,5,4}, {5,4,3}, {4,3,2}, {3,2,1}, {2,1,0}, {7,5,4}, {6,4,3}, {5,3,2}, {4,2,1}, {3,1,0}, /// RBG {7,5,6}, {6,4,5}, {5,3,4}, {4,2,3}, {3,1,2}, {2,0,1}, {7,4,5}, {6,3,4}, {5,2,3}, {4,1,2}, {3,0,1}, /// BRG {6,5,7}, {5,4,6}, {4,3,5}, {3,2,4}, {2,1,3}, {1,0,2}, {5,4,7}, {4,3,6}, {3,2,5}, {2,1,4}, {1,0,3}, /// BGR {5,6,7}, {4,5,6}, {3,4,5}, {2,3,4}, {1,2,3}, {0,1,2}, {4,5,7}, {3,4,6}, {2,3,5}, {1,2,4}, {0,1,3}, /// GBR {5,7,6}, {4,6,5}, {3,5,4}, {2,4,3}, {1,3,2}, {0,2,1}, {4,7,5}, {3,6,4}, {2,5,3}, {1,4,2}, {0,3,1}, /// GRB {6,7,5}, {5,6,4}, {4,5,3}, {3,4,2}, {2,3,1}, {1,2,0}, {5,7,4}, {4,6,3}, {3,5,2}, {2,4,1}, {1,3,0}, /// Misc {7,5,0}, {6,4,0}, {5,3,0}, {4,2,0}, // Oranges {7,0,5}, {6,0,4}, {5,0,3}, {4,0,2}, // Red Pink {0,5,7}, {0,4,6}, {0,3,5}, {0,2,4}, // Blues {0,0,0}, {0,0,0} /// End: Primary (8) + Fades (42) + Shades (126) + Scales (66) + Misc (14) = 256 }; /// FONT FOR PALETTE WINDOW #define B8(A,B,C,D,E,F,G,H) (A|B<<1|C<<2|D<<3|E<<4|F<<5|G<<6|H<<7) static unsigned char mem_cross[PALETTE_CROSS_H] = { B8( 1,1,0,0,0,0,1,1 ), B8( 1,1,1,0,0,1,1,1 ), B8( 0,1,1,1,1,1,1,0 ), B8( 0,0,1,1,1,1,0,0 ), B8( 0,0,1,1,1,1,0,0 ), B8( 0,1,1,1,1,1,1,0 ), B8( 1,1,1,0,0,1,1,1 ), B8( 1,1,0,0,0,0,1,1 ) }; #include "graphics/xbm_n7x7.xbm" #if (PALETTE_DIGIT_W != xbm_n7x7_width) || (PALETTE_DIGIT_H * 10 != xbm_n7x7_height) #error "Mismatched palette-window font" #endif /* While a number of unwieldy allocation APIs is provided by GLib, it's better * to do it the right way once, than constantly invent workarounds - WJ */ #define WJMEM_DEFINCR 16384 #define WJMEM_RESERVED 64 #define WJMEM_DEFSIZE (WJMEM_DEFINCR - WJMEM_RESERVED) wjmem *wjmemnew(int minsize, int incr) { wjmem *mem; if (incr <= 0) incr = WJMEM_DEFINCR; if (minsize <= (int)sizeof(wjmem)) minsize = WJMEM_DEFSIZE; mem = calloc(1, minsize); if (mem) { mem->block = (char *)mem; mem->here = sizeof(wjmem); mem->size = mem->minsize = minsize; mem->incr = incr; } return (mem); } void wjmemfree(wjmem *mem) { char *this, *next; if (!mem) return; for (this = mem->block; this != (char *)mem; this = next) { next = *(char **)this; free(this); } free(mem); } void *wjmalloc(wjmem *mem, int size, int align) { char *dest; unsigned int sz, ds; align += !align; // 0 -> 1 dest = mem->block + mem->here; dest = ALIGNED(dest, align); ds = dest - mem->block + size; if (ds > mem->size) { sz = mem->minsize; ds = sizeof(char *) + align + size; if (sz < ds) { ds += WJMEM_RESERVED + mem->incr - 1; sz = ds - ds % mem->incr - WJMEM_RESERVED; } dest = calloc(1, sz); if (!dest) return (NULL); *(char **)dest = mem->block; mem->block = dest; mem->size = sz; dest += sizeof(char *); dest = ALIGNED(dest, align); ds = dest - mem->block + size; } mem->here = ds; return ((void *)dest); } /* Simple doubling allocator */ size_t getmemx2(memx2 *mem, size_t length) { size_t s = mem->size - mem->here; if (length > s) { size_t l = mem->here + length, l2 = mem->size * 2; unsigned char *tmp = NULL; if ((l2 > l) && (l2 <= MEMX2_MAX)) tmp = realloc(mem->buf, l2); if (!tmp && (l <= MEMX2_MAX)) tmp = realloc(mem->buf, l2 = l); if (!tmp) return (s); mem->buf = tmp; mem->size = l2; } return (length); } void addstr(memx2 *mem, char *s, int bk) { int l; if ((l = getmemx2(mem, strlen(s) + 1))) { memcpy(mem->buf + mem->here, s, l); mem->buf[(l += mem->here) - 1] = '\0'; mem->here = l - bk; } } void addchars(memx2 *mem, int c, int l) { l = getmemx2(mem, l); memset(mem->buf + mem->here, c, l); mem->here += l; } /* Calculate optimal number of objects in a memory chunk */ static inline unsigned int objcount(unsigned int n, unsigned int size, unsigned int hsize) { n = nextpow2(n * size + hsize + WJMEM_RESERVED); if (n < WJMEM_DEFINCR) n = WJMEM_DEFINCR; return ((n - hsize - WJMEM_RESERVED) / size); } static void *newchunk(memchunks *mem) { void *node; if ((node = mem->freelist)) { mem->freelist = *(void **)node; *(void **)node = NULL; // Clear } else { if (!mem->freecnt) { unsigned int n = objcount(mem->n, mem->size, 0); node = calloc(n, mem->size); if (!node) return (NULL); mem->datastore = node; mem->freecnt = n; } /* Datastores are never freed, so pointer is movable */ node = mem->datastore; mem->datastore += mem->size; mem->freecnt--; } return (node); } static inline void freechunk(memchunks *mem, void *chunk) { *(void **)chunk = mem->freelist; mem->freelist = chunk; } char MEM_NONE_[1]; /* Nothing is located here :-) */ /* This allocates several memory chunks in one block - making it one single * point of allocation failure, and needing just a single free() later on. * On Windows, allocations aren't guaranteed to be double-aligned, so * MA_ALIGN_DOUBLE flag is necessary there unless no chunks contain doubles. */ void *multialloc(int flags, void *ptr, int size, ...) { va_list args; void *res; char *tmp; size_t tsz, sz = size, align = 0; if ((flags & MA_ALIGN_MASK) == MA_ALIGN_DOUBLE) align = sizeof(double) - 1; va_start(args, size); while (va_arg(args, void *)) { sz = (sz + align) & ~align; sz += va_arg(args, int); } va_end(args); if (!sz && (flags & MA_FLAG_NONE)) return (MEM_NONE); if (align) sz += align + 1; tmp = res = calloc(1, sz); if (res) { tmp = ALIGNED(tmp, align + 1); sz = 0; tsz = size; va_start(args, size); while (TRUE) { if (tsz || !(flags & MA_SKIP_ZEROSIZE)) *(void **)ptr = (void *)(tmp + sz); if (!(ptr = va_arg(args, void *))) break; sz = (sz + tsz + align) & ~align; tsz = va_arg(args, int); } va_end(args); } return (res); } static int frameset_realloc(frameset *fset) { image_frame *tmp; int n; /* Next power of 2 */ n = nextpow2(fset->cnt); if (n < FRAMES_MIN) n = FRAMES_MIN; if (n == fset->max) return (TRUE); tmp = realloc(fset->frames, n * sizeof(image_frame)); if (!tmp) return (FALSE); fset->frames = tmp; fset->max = n; fset->size = 0; // Recalculate it later return (TRUE); } /* Add one more frame to a frameset */ int mem_add_frame(frameset *fset, int w, int h, int bpp, int cmask, png_color *pal) { image_frame *frm; unsigned char *res; size_t l, sz = (size_t)w * h; int i; /* Extend frames array if necessary */ if (fset->cnt >= fset->max) { if ((fset->cnt >= FRAMES_MAX) || !frameset_realloc(fset)) return (FALSE); } /* Initialize the frame */ frm = fset->frames + fset->cnt; memset(frm, 0, sizeof(image_frame)); frm->width = w; frm->height = h; frm->bpp = bpp; /* Allocate channels */ l = sz * bpp; res = MEM_NONE; for (i = CHN_IMAGE; res && (i < NUM_CHANNELS); i++) { if (cmask & CMASK_FOR(i)) res = frm->img[i] = malloc(l); l = sz; } /* Allocate palette if it differs from default */ if (res && pal && (!fset->pal || memcmp(fset->pal, pal, SIZEOF_PALETTE))) { res = malloc(SIZEOF_PALETTE); if (res) { /* Set as default if first frame and no default yet */ if (!fset->cnt && !fset->pal) fset->pal = (void *)res; else frm->pal = (void *)res; mem_pal_copy(res, pal); } } if (!res) /* Not enough memory */ { while (--i >= 0) free(frm->img[i]); return (FALSE); } fset->cnt++; fset->size = 0; // Recalculate it later return (TRUE); } /* Remove specified frame from a frameset */ void mem_remove_frame(frameset *fset, int frame) { image_frame *tmp; int l = fset->cnt; if (frame >= l) return; tmp = fset->frames + frame; mem_free_chanlist(tmp->img); free(tmp->pal); memmove(tmp, tmp + 1, (--l - frame) * sizeof(image_frame)); fset->cnt = l; // !!! Like with layers, you switch to another frame before deleting current one if (fset->cur > frame) fset->cur--; /* Reduce array size if 2/3+ empty */ if ((l * 3 <= fset->max) && (fset->max > FRAMES_MIN)) frameset_realloc(fset); fset->size = 0; // Recalculate it later } /* Empty a frameset */ void mem_free_frames(frameset *fset) { image_frame *frm; int i; if (fset->frames) { for (i = 0 , frm = fset->frames; i < fset->cnt; i++ , frm++) { mem_free_chanlist(frm->img); free(frm->pal); } free(fset->frames); } free(fset->pal); memset(fset, 0, sizeof(frameset)); } /* Set initial state of image variables */ void init_istate(image_state *state, image_info *image) { memset(state->prot_mask, 0, 256); /* Clear all mask info */ state->prot = 0; state->col_[0] = 1; state->col_[1] = 0; state->col_24[0] = image->pal[1]; state->col_24[1] = image->pal[0]; state->tool_pat = 0; state->tool_pat_B = 0; } /* Add a new undo data node */ static int undo_add_data(undo_item *undo, int type, void *ptr) { undo_data *node; unsigned int tmap = 1 << type; /* Reuse existing node */ if ((node = undo->dataptr)) { if (node->map & tmap) goto fail; // Prevent duplication tmap |= node->map; } /* Allocate a new node */ else if (!(node = newchunk(&undo_datastore))) goto fail; node->map = tmap; node->store[type] = ptr; undo->dataptr = node; return (TRUE); fail: /* Cannot store - delete the data right now */ if (tmap & UD_FREE_MASK) free(ptr); return (FALSE); } /* Free an undo data block, and delete its data */ static void undo_free_data(undo_item *undo) { undo_data *tmp; unsigned int tmap; int i; if (!(tmp = undo->dataptr)) return; for (tmap = tmp->map & UD_FREE_MASK, i = 0; tmap; tmap >>= 1 , i++) if (tmap & 1) free(tmp->store[i]); freechunk(&undo_datastore, tmp); undo->dataptr = NULL; } /* Swap undo data - move current set out, and replace by incoming set */ static void undo_swap_data(undo_item *outp) { undo_data *tmp = outp->dataptr; unsigned int tmap; outp->dataptr = NULL; if (mem_tempfiles) undo_add_data(outp, UD_TEMPFILES, mem_tempfiles); mem_tempfiles = NULL; // !!! Other unconditionally outgoing stuff goes here if (!tmp) return; tmap = tmp->map; if (tmap & (1 << UD_FILENAME)) { undo_add_data(outp, UD_FILENAME, mem_filename); mem_filename = tmp->store[UD_FILENAME]; } if (tmap & (1 << UD_TEMPFILES)) mem_tempfiles = tmp->store[UD_TEMPFILES]; // !!! All stuff (swappable or incoming) goes here /* Release the incoming node */ freechunk(&undo_datastore, tmp); } /* Change layer's filename * Note: calling this with non-empty redo, for example when saving to a new * name, will "reparent" its frames from the old filename to the new one - WJ */ void mem_replace_filename(int layer, char *fname) { image_info *image = &mem_image; undo_stack *undo; char *name; if (layer != layer_selected) image = &layer_table[layer].image->image_; name = image->filename; if (fname && !fname[0]) fname = NULL; // Empty name is no name /* Do nothing if "replacing" name by itself */ if (fname && name ? !strcmp(fname, name) : fname == name) return; /* !!! Make a copy of new filename while the old filename still exists, * because the new pointer must differ from the old one - WJ */ if (fname) fname = strdup(fname); /* Store the old filename in _previous_ undo frame if possible */ undo = &image->undo_; if (undo->done) undo_add_data(undo->items[(undo->pointer ? undo->pointer : undo->max) - 1], UD_FILENAME, name); else free(name); /* Replace filename, and clear tempfiles too while we're at it */ image->filename = fname; image->tempfiles = NULL; } /* Label file's frames in current layer as changed */ void mem_file_modified(char *fname) { char *name; undo_item *undo; int i, j, k, l, changed; l = mem_undo_done; for (k = -1; k <= 1; k += 2) { name = mem_filename; changed = name && !strcmp(name, fname) ? ~UF_ORIG : ~0; for (i = 1; i <= l; i++) { j = (mem_undo_max + mem_undo_pointer + i * k) % mem_undo_max; undo = mem_undo_im_[j]; if (undo->dataptr && (undo->dataptr->map & (1 << UD_FILENAME))) { name = undo->dataptr->store[UD_FILENAME]; changed = name && !strcmp(name, fname) ? ~UF_ORIG : ~0; } undo->flags &= changed; } l = mem_undo_redo; } } /* Create new undo stack of a given depth, and put default frame onto it */ int init_undo(undo_stack *ustack, int depth) { if ((ustack->items = calloc(depth, sizeof(undo_item *))) && (ustack->items[0] = newchunk(&undo_items))) { ustack->max = depth; ustack->pointer = ustack->done = ustack->redo = 0; ustack->size = 0; return (TRUE); } free(ustack->items); return (FALSE); } /* Copy image state into current undo frame */ void update_undo(image_info *image) { undo_item *undo = image->undo_.items[image->undo_.pointer]; /* !!! If system is unable to allocate 768 bytes, may as well die by SIGSEGV * !!! right here, and not hobble along till GUI does the dying - WJ */ if (!undo->pal_) undo->pal_ = malloc(SIZEOF_PALETTE); mem_pal_copy(undo->pal_, image->pal); memcpy(undo->img, image->img, sizeof(chanlist)); undo->dataptr = NULL; undo->cols = image->cols; undo->trans = image->trans; undo->bpp = image->bpp; undo->width = image->width; undo->height = image->height; undo->flags = image->changed ? 0 : UF_ORIG; } void mem_free_chanlist(chanlist img) { int i; for (i = 0; i < NUM_CHANNELS; i++) { if (!img[i]) continue; if (img[i] != MEM_NONE) free(img[i]); } } static size_t undo_free_x(undo_item **undo_) { undo_item *undo = *undo_; size_t j; if (!undo) return (0); j = undo->size; undo_free_data(undo); free(undo->pal_); mem_free_chanlist(undo->img); memset(undo, 0, sizeof(undo_item)); freechunk(&undo_items, undo); *undo_ = NULL; return (j); } /* This resizes an in-use undo stack * !!! Both old and new depths must be nonzero */ static int resize_undo(undo_stack *ustack, int depth) { undo_stack nstack; int i, j, k, undo, redo, ptr, uptr, udepth, trim; if (!init_undo(&nstack, depth)) return (FALSE); undo_free_x(nstack.items); // Drop default item undo = ustack->done; redo = ustack->redo; if ((trim = undo + redo + 1 > depth)) { i = (depth - 1) / 2; if (undo < i) redo = depth - undo - 1; else { if (redo > i) redo = i; undo = depth - redo - 1; } } uptr = ptr = ustack->pointer; if (ptr >= depth) ptr = 0; udepth = ustack->max; for (i = -undo; i <= redo; i++) { j = (uptr + i + udepth) % udepth; k = (ptr + i + depth) % depth; nstack.items[k] = ustack->items[j]; ustack->items[j] = NULL; } nstack.pointer = ptr; nstack.done = undo; nstack.redo = redo; if (trim) { for (i = 0; i < udepth; i++) undo_free_x(ustack->items + i); } free(ustack->items); *ustack = nstack; return (TRUE); } /* Resize all undo stacks */ void update_undo_depth() { image_info *image; int l; mem_undo_depth = mem_undo_depth <= MIN_UNDO ? MIN_UNDO : mem_undo_depth >= MAX_UNDO ? MAX_UNDO : mem_undo_depth | 1; for (l = 0; l <= layers_total; l++) { image = l == layer_selected ? &mem_image : &layer_table[l].image->image_; if (image->undo_.max == mem_undo_depth) continue; resize_undo(&image->undo_, mem_undo_depth); } } /* Clear/remove image data */ void mem_free_image(image_info *image, int mode) { int i, j = image->undo_.max, p = image->undo_.pointer; /* Delete current image (don't rely on undo frame being up to date) */ if (mode & FREE_IMAGE) { mem_free_chanlist(image->img); memset(image->img, 0, sizeof(chanlist)); image->width = image->height = 0; free(image->filename); image->filename = image->tempfiles = NULL; } /* Delete undo frames if any */ image->undo_.pointer = image->undo_.done = image->undo_.redo = 0; if (!image->undo_.items) return; memset(image->undo_.items[p]->img, 0, sizeof(chanlist)); // Already freed for (i = 0; i < j; i++) undo_free_x(image->undo_.items + i); /* Delete undo stack if finalizing */ if (mode & FREE_UNDO) { free(image->undo_.items); image->undo_.items = NULL; image->undo_.max = 0; } /* Otherwise, allocate default frame */ else image->undo_.items[0] = newchunk(&undo_items); } /* Allocate new image data */ // !!! Does NOT copy palette in copy mode, as it may be invalid int mem_alloc_image(int mode, image_info *image, int w, int h, int bpp, int cmask, image_info *src) { unsigned char *res; size_t l, sz; int i; if (mode & AI_CLEAR) memset(image, 0, sizeof(image_info)); else { memset(image->img, 0, sizeof(chanlist)); image->filename = image->tempfiles = NULL; /* Paranoia */ image->changed = 0; } if (mode & AI_COPY) { if (src->filename && !(image->filename = strdup(src->filename))) return (FALSE); image->tempfiles = src->tempfiles; image->changed = src->changed; w = src->width; h = src->height; bpp = src->bpp; cmask = cmask_from(src->img); } image->width = w; image->height = h; image->bpp = bpp; if (!cmask) return (TRUE); /* Empty block requested */ sz = (size_t)w * h; l = sz * bpp; res = MEM_NONE; for (i = CHN_IMAGE; res && (i < NUM_CHANNELS); i++) { if (cmask & CMASK_FOR(i)) res = image->img[i] = malloc(l); l = sz; } if (res && image->undo_.items) { undo_item *undo = image->undo_.items[image->undo_.pointer]; if (!undo->pal_) res = (void *)(undo->pal_ = malloc(SIZEOF_PALETTE)); } if (!res) /* Not enough memory */ { free(image->filename); image->filename = NULL; while (--i >= 0) free(image->img[i]); memset(image->img, 0, sizeof(chanlist)); return (FALSE); } l = sz * bpp; if (mode & AI_COPY) /* Clone */ { for (i = CHN_IMAGE; i < NUM_CHANNELS; i++) { if (image->img[i]) memcpy(image->img[i], src->img[i], l); l = sz; } } else if (!(mode & AI_NOINIT)) /* Init */ { for (i = CHN_IMAGE; i < NUM_CHANNELS; i++) { if (image->img[i]) memset(image->img[i], channel_fill[i], l); l = sz; } } return (TRUE); } /* Allocate space for new image, removing old if needed */ int mem_new( int width, int height, int bpp, int cmask ) { int res; mem_free_image(&mem_image, FREE_IMAGE); res = mem_alloc_image(0, &mem_image, width, height, bpp, cmask, NULL); if (!res) /* Not enough memory */ { // 8x8 is bound to work! mem_alloc_image(0, &mem_image, 8, 8, bpp, CMASK_IMAGE, NULL); } mem_image.trans = -1; // !!! If palette isn't set up before mem_new(), undo frame will get wrong one // !!! (not that it affects anything at this time) update_undo(&mem_image); mem_channel = CHN_IMAGE; mem_xbm_hot_x = mem_xbm_hot_y = -1; return (!res); } int cmask_from(chanlist img) { int i, j, k = 1; for (i = j = 0; i < NUM_CHANNELS; i++ , k += k) if (img[i]) j |= k; return (j); } /* Allocate new clipboard, removing or preserving old as needed */ int mem_clip_new(int width, int height, int bpp, int cmask, chanlist backup) { int res; /* Text flag defaults to cleared */ text_paste = 0; /* Clear everything if no backup needed */ if (!backup) { mem_free_image(&mem_clip, FREE_ALL); mem_clip_paletted = 0; } /* Backup current contents */ else memcpy(backup, mem_clip.img, sizeof(chanlist)); /* Allocate new frame */ res = mem_alloc_image(AI_NOINIT, &mem_clip, width, height, bpp, cmask, NULL); /* Remove backup if allocation failed */ if (!res && backup) { mem_free_chanlist(backup); mem_clip_paletted = 0; } return (!res); } /* Get address of previous channel data (or current if none) */ unsigned char *mem_undo_previous(int channel) { undo_item *undo; unsigned char *res; undo = mem_undo_im_[(mem_undo_pointer ? mem_undo_pointer : mem_undo_max) - 1]; if (!undo || !(res = undo->img[channel]) || (res == MEM_NONE) || (undo->flags & UF_TILED)) res = mem_img[channel]; // No usable undo so use current return (res); } static size_t lose_oldest(undo_stack *ustack) // Lose the oldest undo image { int idx; if (ustack->redo > ustack->done) idx = ustack->redo--; else if (ustack->done) idx = ustack->max - ustack->done--; else return (0); /* !!! mem_try_malloc() may call this on an unsized undo stack - but it * !!! doesn't need valid sizes anyway - WJ */ return (undo_free_x(ustack->items + (ustack->pointer + idx) % ustack->max)); } /* Convert tile bitmap row into a set of spans (skip/copy), terminated by * a zero-length copy span; return copied length */ static int mem_undo_spans(int *spans, unsigned char *tmap, int width, int bpp) { int bt = 0, bw = 0, tl = 0, l = 0, ll = bpp * TILE_SIZE; while (width > 0) { if ((bw >>= 1) < 2) bw = 0x100 + *tmap++; if (bt ^ (bw & 1)) { *spans++ = tl * ll; tl = 0; } tl++; l += (bt = bw & 1) * ll; width -= TILE_SIZE; } width *= bpp; *spans++ = tl * ll + width; l += bt * width; spans[0] = spans[bt] = 0; return (l); } /* Endianness-aware byte shifts */ #if G_BYTE_ORDER == G_LITTLE_ENDIAN #define SHIFTUP(X,N) (X) <<= ((N) << 3) #define SHIFTDN(X,N) (X) >>= ((N) << 3) #else /* G_BYTE_ORDER == G_BIG_ENDIAN */ #define SHIFTUP(X,N) (X) >>= ((N) << 3) #define SHIFTDN(X,N) (X) <<= ((N) << 3) #endif /* Register-sized unsigned integer - redefine if this isn't it */ #include #define R_INT uintptr_t /* Integer-at-a-time byte array comparison function; its efficiency depends on * both arrays aligned, or misaligned, the same - which is natural for channel * strips when geometry and position match - WJ */ static int tile_row_compare(unsigned char *src, unsigned char *dest, int w, int h, unsigned char *buf) { const int amask = sizeof(R_INT) - 1; int l = w * h, mc = (w + TILE_SIZE - 1) >> TILE_SHIFT, nc = 0; /* Long enough & identically aligned - use fast path */ if ((w > sizeof(R_INT)) && (l > sizeof(R_INT) * 4) && (((int)src & amask) == ((int)dest & amask))) { R_INT v, vm, vt1, vt2, *isrc, *idest; int i, k, t, x, d0, d1, il; /* Given that loose ends, if any, belong to tiles too, we * simply leave them for later - maybe there won't be need */ d0 = (((int)src ^ amask) + 1) & amask; d1 = (int)(src + l) & amask; isrc = (R_INT *)(src + d0); idest = (R_INT *)(dest + d0); il = (l - d0 - d1) / sizeof(v); i = 0; while (TRUE) { /* Fast comparison loop - damn GCC's guts for not * allocating it on registers without heavy wizardry */ { int wi = il - i; R_INT *wsrc = isrc + i, *wdest = idest + i; while (TRUE) { if (wi-- <= 0) goto done; if (*wsrc != *wdest) break; ++wsrc; ++wdest; } t = (unsigned char *)wsrc - src; } k = (unsigned int)t % w; x = TILE_SIZE - (k & (TILE_SIZE - 1)); if (k + x > w) x = w - k; k >>= TILE_SHIFT; /* Value overlaps two or three tiles */ while (x < sizeof(v)) { v = *(R_INT *)(src + t) ^ *(R_INT *)(dest + t); tile2: vm = ~0UL; SHIFTUP(vm, x); x += sizeof(v); if (!(vm &= v)) break; x -= sizeof(v); /* Farther tile(s) differ */ if ((v != vm) && !buf[k]) /* First one differs too */ { buf[k] = 1; if (++nc >= mc) x = l; /* Done is done */ } if (++k + 1 == mc) /* May be 3 tiles */ { x += w & (TILE_SIZE - 1); if (x >= sizeof(v)) break; v = vm; goto tile2; } x += TILE_SIZE; if (k == mc) k = 0; /* Row wrap */ break; } i = (t + x - d0) / sizeof(v); if (buf[k]) continue; buf[k] = 1; if (++nc >= mc) break; } done: /* Compare the ends - using the fact that memory blocks * *must* be aligned at least that much */ if (d1 && !buf[mc - 1]) { vt2 = isrc[il] ^ idest[il]; SHIFTUP(vt2, sizeof(vt2) - d1); if (vt2) ++nc , buf[mc - 1] = 1; } if (d0 && !buf[0]) { vt1 = *(isrc - 1) ^ *(idest - 1); SHIFTDN(vt1, d0); if (vt1) ++nc , buf[0] = 1; } } /* Misaligned - use slow path */ else { int i, k, x; for (i = 0; i < l; i++) { if (src[i] != dest[i]) { k = (unsigned int)i % w; x = TILE_SIZE - (k & (TILE_SIZE - 1)); if (k + x > w) x = w - k; i += x; k >>= TILE_SHIFT; if (buf[k]) continue; buf[k] = 1; if (++nc >= mc) break; } } } return (nc); } /* Convert undo frame to tiled representation */ static void mem_undo_tile(undo_item *undo) { unsigned char buf[((MAX_WIDTH + TILE_SIZE - 1) / TILE_SIZE) * 3]; unsigned char *tstrip, tmap[MAX_TILEMAP], *tmp = NULL; int spans[(MAX_WIDTH + TILE_SIZE - 1) / TILE_SIZE + 3]; size_t sz, area = 0, msize = 0; int i, j, k, nt, dw, cc, bpp; int h, nc, bw, tw, tsz, nstrips, ntiles = 0; undo->flags |= UF_FLAT; /* Not tiled by default */ /* Not tileable if too small */ if (mem_width + mem_height < TILE_SIZE * 3) return; /* Not tileable if different geometry */ if ((undo->width != mem_width) || (undo->height != mem_height) || (undo->bpp != mem_img_bpp)) return; for (i = nc = 0; i < NUM_CHANNELS; i++) { /* Not tileable if different set of channels */ if (!!undo->img[i] ^ !!mem_img[i]) return; if (undo->img[i] && mem_img[i] && (undo->img[i] != MEM_NONE)) nc |= 1 << i; } /* Not tileable if no matching channels */ if (!nc) return; /* Build tilemap */ nstrips = (mem_height + TILE_SIZE - 1) / TILE_SIZE; dw = (TILE_SIZE - 1) & ~(mem_width - 1); bw = (mem_width + TILE_SIZE - 1) / TILE_SIZE; tw = (bw + 7) >> 3; tsz = tw * nstrips; memset(tmap, 0, tsz); for (i = 0 , tstrip = tmap; i < mem_height; i += TILE_SIZE , tstrip += tw) { h = mem_height - i; if (h > TILE_SIZE) h = TILE_SIZE; /* Compare strip of image */ memset(buf, 0, bw * 3); for (cc = 0; nc >= 1 << cc; cc++) { unsigned char *src, *dest; int j, k, j2, w; if (!(nc & 1 << cc)) continue; bpp = BPP(cc); w = mem_width * bpp; k = i * w; src = undo->img[cc] + k; dest = mem_img[cc] + k; if (!tile_row_compare(src, dest, w, h, buf)) continue; if (bpp == 1) continue; /* 3 bpp happen only in image channel, which goes first; * so we can postprocess the results to match 1 bpp */ for (j = j2 = 0; j < bw; j++ , j2 += 3) buf[j] = buf[j2] | buf[j2 + 1] | buf[j2 + 2]; } /* Fill tilemap row */ for (j = nt = 0; j < bw; j++) { nt += (k = buf[j]); tstrip[j >> 3] |= k << (j & 7); } ntiles += nt; area += (nt * TILE_SIZE - buf[bw - 1] * dw) * h; } /* Not tileable if tilemap cannot fit in space gained */ sz = (size_t)mem_width * mem_height; bpp = (nc & CMASK_IMAGE ? mem_img_bpp : 1); if ((sz - area) * bpp <= tsz) return; /* Implement tiling */ sz = (size_t)mem_width * mem_height; for (cc = 0; nc >= 1 << cc; cc++) { unsigned char *src, *dest, *blk; size_t l; int i; if (!(nc & 1 << cc)) continue; if (!ntiles) /* Channels unchanged - free the memory */ { free(undo->img[cc]); undo->img[cc] = MEM_NONE; continue; } /* Try to reduce memory fragmentation - allocate small blocks * anew when possible, instead of carving up huge ones */ src = blk = undo->img[cc]; bpp = BPP(cc); l = area * bpp + (tmp ? 0 : tsz); if (l * 3 <= sz * bpp) /* Small enough */ { blk = malloc(l); /* Use original chunk if cannot get new one */ if (!blk) blk = src; } dest = blk; /* Compress channel */ for (i = 0; i < nstrips; i++) { int j, k, *span; mem_undo_spans(spans, tmap + tw * i, mem_width, bpp); k = mem_height - i * TILE_SIZE; if (k > TILE_SIZE) k = TILE_SIZE; for (j = 0; j < k; j++) { span = spans; while (TRUE) { src += *span++; if (!*span) break; if (dest != src) memmove(dest, src, *span); src += *span; dest += *span++; } } } /* Resize or free memory block */ if (blk == undo->img[cc]) /* Resize old */ { dest = realloc(undo->img[cc], l); /* Leave chunk alone if resizing failed */ if (!dest) l = sz * bpp; else undo->img[cc] = dest; } else /* Replace with new */ { free(undo->img[cc]); undo->img[cc] = blk; } msize += l + 32; /* Place tilemap in first chunk */ if (!tmp) tmp = undo->img[cc] + area * bpp; } /* Re-label as tiled and store tilemap, if there *are* tiles */ if (msize) { undo->flags ^= UF_FLAT | UF_TILED; undo->tileptr = tmp; memcpy(tmp, tmap, tsz); } if (undo->pal_) msize += SIZEOF_PALETTE + 32; undo->size = msize; undo->flags |= UF_SIZED; } /* Compress last undo frame */ void mem_undo_prepare() { undo_item *undo; if (!mem_undo_done) return; undo = mem_undo_im_[(mem_undo_pointer ? mem_undo_pointer : mem_undo_max) - 1]; /* Already processed? */ if (undo->flags & (UF_TILED | UF_FLAT)) return; /* Cull palette if unchanged */ if (undo->pal_ && !memcmp(undo->pal_, mem_pal, SIZEOF_PALETTE)) { /* Free new block, reuse old */ free(mem_undo_im_[mem_undo_pointer]->pal_); mem_undo_im_[mem_undo_pointer]->pal_ = undo->pal_; undo->pal_ = NULL; } /* Tile image */ mem_undo_tile(undo); } static size_t mem_undo_size(undo_stack *ustack) { undo_item *undo; size_t k, l, total = 0; int i, j, bpp, umax = ustack->max; for (i = 0; i < umax; i++) { /* Anything there? */ if (!(undo = ustack->items[i])) continue; /* Not empty and not yet scanned */ if (undo->width && !(undo->flags & UF_SIZED)) { k = (size_t)undo->width * undo->height; bpp = undo->bpp; for (j = l = 0; j < NUM_CHANNELS; j++) { if (undo->img[j] && (undo->img[j] != MEM_NONE)) l += k * bpp + 32; bpp = 1; } if (undo->pal_) l += SIZEOF_PALETTE + 32; undo->size = l; undo->flags |= UF_SIZED; } total += undo->size; } return (total); } /* Add up sizes of all layers other than current */ static size_t mem_undo_lsize() { undo_stack *ustack; size_t total = 0; int l; for (l = 0; l <= layers_total; l++) { if (l == layer_selected) continue; ustack = &layer_table[l].image->image_.undo_; // !!! This relies on layer_table items already processed by update_undo() if (!ustack->size) ustack->size = mem_undo_size(ustack); total += ustack->size; } return (total); } /* Free requested amount of undo space */ static int mem_undo_space(size_t mem_req) { undo_stack *heap[MAX_LAYERS + 2], *wp, *hp; size_t mem_lim, mem_max = (size_t)mem_undo_limit * (1024 * 1024); int i, l, l2, h, csz = mem_undo_common * layers_total; /* Layer mem limit including common area */ mem_lim = mem_max * (csz * 0.01 + 1) / (layers_total + 1); /* Fail if hopeless */ if (mem_req > mem_lim) return (mem_req - mem_lim); /* Layer mem limit exceeded - drop oldest */ mem_req += mem_undo_size(&mem_image.undo_); while (mem_req > mem_lim) { if (!mem_undo_done) return (mem_req - mem_lim); mem_req -= lose_oldest(&mem_image.undo_); } /* All done if no common area */ if (!csz) return (0); mem_req += mem_undo_lsize(); if (mem_req <= mem_max) return (0); // No need to trim other layers yet mem_lim -= mem_max * (mem_undo_common * 0.01); // Reserved space per layer /* Build heap of undo stacks */ for (i = h = 0; i <= layers_total; i++) { // Skip current layer if (i == layer_selected) continue; wp = &layer_table[i].image->image_.undo_; // Skip layers without extra frames if (!(wp->done + wp->redo)) continue; // Skip layers under the memory limit if (wp->size <= mem_lim) continue; // Put undo stack onto heap for (l = ++h; l > 1; l = l2) { l2 = l >> 1; if ((hp = heap[l2])->size >= wp->size) break; heap[l] = hp; } heap[l] = wp; } /* Drop frames of greediest layers */ while (h > 0) { size_t mem_nx = h > 1 ? heap[2]->size : 0; if ((h > 2) && (heap[3]->size > mem_nx)) mem_nx = heap[3]->size; /* Drop frames */ wp = heap[1]; while (TRUE) { size_t res = lose_oldest(wp); wp->size -= res; // Maintain undo stack size mem_req -= res; if (mem_req <= mem_max) return (0); if (!(wp->done + wp->redo) || (wp->size <= mem_lim)) wp = heap[h--]; else if (wp->size >= mem_nx) continue; break; } /* Reheap layer */ mem_nx = wp->size; for (l = 1; (l2 = l + l) <= h; l = l2) { if ((l2 < h) && (heap[l2]->size < heap[l2 + 1]->size)) l2++; if (mem_nx >= (hp = heap[l2])->size) break; heap[l] = hp; } heap[l] = wp; } return (0); } /* Try to allocate a memory block, releasing undo frames if needed */ void *mem_try_malloc(size_t size) { void *ptr; while (!((ptr = malloc(size)))) { // !!! Hardcoded to work with mem_image for now if (!mem_undo_done) return (NULL); lose_oldest(&mem_image.undo_); } return (ptr); } int undo_next_core(int mode, int new_width, int new_height, int new_bpp, int cmask) { png_color *newpal; undo_item *undo; unsigned char *img; void *tempfiles = mem_tempfiles; chanlist holder, frame; size_t mem_req, mem_lim, wh; int i, j, k, need_frame; if (pen_down && (mode & UC_PENDOWN)) return (0); pen_down = mode & UC_PENDOWN ? 1 : 0; /* Fill undo frame */ update_undo(&mem_image); /* Postpone change notify if nothing will be done without new frame */ need_frame = mode & (UC_CREATE | UC_NOCOPY | UC_GETMEM); if (!need_frame) notify_changed(); /* Release redo data */ if (mem_undo_redo) { k = mem_undo_pointer; for (i = 0; i < mem_undo_redo; i++) { k = (k + 1) % mem_undo_max; undo_free_x(mem_undo_im_ + k); } mem_undo_redo = 0; } /* Let cumulative updates stack */ if (mode & UC_ACCUM) { int i = (mem_undo_pointer ? mem_undo_pointer : mem_undo_max) - 1; if (mem_undo_done && (mem_undo_im_[i]->flags & UF_ACCUM)) return (0); mem_undo_im_[mem_undo_pointer]->flags |= UF_ACCUM; } /* Compress last undo frame */ mem_undo_prepare(); /* Calculate memory requirements */ mem_req = SIZEOF_PALETTE + 32; wh = (size_t)new_width * new_height; if (!(mode & UC_DELETE)) { for (i = j = 0; i < NUM_CHANNELS; i++) { if ((cmask & (1 << i)) && (mem_img[i] || (mode & (UC_CREATE | UC_RESET)))) j++; } if (cmask & CMASK_IMAGE) j += new_bpp - 1; mem_req += (wh + 32) * j; // !!! Must be after update_undo() to get used memory right if ((mem_undo_fail = mem_undo_space(mem_req))) return (2); } if (mode & UC_GETMEM) return (0); // Enough memory was freed /* Ensure a new frame */ undo = newchunk(&undo_items); if (!undo) return (1); freechunk(&undo_items, undo); // It'll be waiting in the freelist /* Prepare outgoing frame */ undo = mem_undo_im_[mem_undo_pointer]; memcpy(frame, undo->img, sizeof(chanlist)); if (!(mode & UC_RESET)) for (i = 0; i < NUM_CHANNELS; i++) if (frame[i] && !(cmask & (1 << i))) frame[i] = MEM_NONE; /* Allocate new palette */ newpal = mem_try_malloc(SIZEOF_PALETTE); if (!newpal) return (1); /* Duplicate affected channels */ for (i = 0; i < NUM_CHANNELS; i++) { holder[i] = img = mem_img[i]; if (!(cmask & (1 << i))) { if (mode & UC_RESET) holder[i] = NULL; continue; } if (mode & UC_DELETE) { holder[i] = NULL; continue; } if (!img && !(mode & (UC_CREATE | UC_RESET))) continue; mem_lim = i == CHN_IMAGE ? wh * new_bpp : wh; img = mem_try_malloc(mem_lim); if (!img) /* Release memory and fail */ { free(newpal); for (j = 0; j < i; j++) if (holder[j] != mem_img[j]) free(holder[j]); return (1); } holder[i] = img; /* Copy */ if (!frame[i] || (mode & UC_NOCOPY)) continue; memcpy(img, frame[i], mem_lim); } /* Next undo step */ mem_undo_pointer = (mem_undo_pointer + 1) % mem_undo_max; if (mem_undo_done >= mem_undo_max - 1) undo_free_x(mem_undo_im_ + mem_undo_pointer); else mem_undo_done++; mem_undo_im_[mem_undo_pointer] = newchunk(&undo_items); // Cannot fail /* Commit */ if (tempfiles) undo_add_data(undo, UD_TEMPFILES, tempfiles); memcpy(undo->img, frame, sizeof(chanlist)); mem_undo_im_[mem_undo_pointer]->pal_ = newpal; memcpy(mem_img, holder, sizeof(chanlist)); mem_width = new_width; mem_height = new_height; mem_img_bpp = new_bpp; /* Do postponed change notify, now that new frame is created */ if (need_frame) notify_changed(); update_undo(&mem_image); return (0); } // Call this after a draw event but before any changes to image void mem_undo_next(int mode) { int cmask = CMASK_ALL, wmode = 0; switch (mode) { case UNDO_TRANS: /* Transparent colour change (cumulative) */ wmode = UC_ACCUM; /* Fallthrough */ case UNDO_PAL: /* Palette changes */ cmask = CMASK_NONE; break; case UNDO_XPAL: /* Palette and indexed image changes */ cmask = mem_img_bpp == 1 ? CMASK_IMAGE : CMASK_NONE; break; case UNDO_COL: /* Palette and/or RGB image changes */ cmask = mem_img_bpp == 3 ? CMASK_IMAGE : CMASK_NONE; break; case UNDO_TOOL: /* Continuous drawing */ wmode = UC_PENDOWN; case UNDO_DRAW: /* Changes to current channel / RGBA */ cmask = (mem_channel == CHN_IMAGE) && RGBA_mode ? CMASK_RGBA : CMASK_CURR; break; case UNDO_INV: /* "Invert" operation */ if ((mem_channel == CHN_IMAGE) && (mem_img_bpp == 1)) cmask = CMASK_NONE; else cmask = CMASK_CURR; break; case UNDO_XFORM: /* Changes to all channels */ cmask = CMASK_ALL; break; case UNDO_FILT: /* Changes to current channel */ cmask = CMASK_CURR; break; case UNDO_PASTE: /* Paste to current channel / RGBA */ wmode = UC_PENDOWN; /* !!! Workaround for move-with-RMB-pressed */ cmask = (mem_channel == CHN_IMAGE) && !channel_dis[CHN_ALPHA] && (mem_clip_alpha || RGBA_mode) ? CMASK_RGBA : CMASK_CURR; break; } undo_next_core(wmode, mem_width, mem_height, mem_img_bpp, cmask); } /* Swap image & undo tiles; in process, normal order translates to reverse and * vice versa - in order to do it in same memory with minimum extra copies */ static void mem_undo_tile_swap(undo_item *undo, int redo) { unsigned char buf[MAX_WIDTH * 3], *tmap, *src, *dest; int spans[(MAX_WIDTH + TILE_SIZE - 1) / TILE_SIZE + 3]; int i, l, h, cc, nw, bpp, w; nw = ((mem_width + TILE_SIZE - 1) / TILE_SIZE + 7) >> 3; for (cc = 0; cc < NUM_CHANNELS; cc++) { if (!undo->img[cc] || (undo->img[cc] == MEM_NONE)) continue; tmap = undo->tileptr; bpp = BPP(cc); w = mem_width * bpp; src = undo->img[cc]; for (i = 0; i < mem_height; i += TILE_SIZE , tmap += nw) { int j, j1, dj; if (!(l = mem_undo_spans(spans, tmap, mem_width, bpp))) continue; dest = mem_img[cc] + w * i; h = mem_height - i; if (h > TILE_SIZE) h = TILE_SIZE; /* First row stored after last in redo frames */ if (!redo) j = 0 , j1 = h , dj = 1; else { j = h - 1; j1 = dj = -1; memcpy(buf, src + j * l, l); } /* Process undo normally, and redo backwards */ for (; j != j1; j += dj) { unsigned char *ts, *td, *tm; int *span = spans; td = dest + j * w; tm = ts = src + j * l; *(redo ? &ts : &tm) = j ? tm - l : buf; while (TRUE) { td += *span++; if (!*span) break; memcpy(tm, td, *span); memcpy(td, ts, *span); tm += *span; ts += *span; td += *span++; } } src += h * l; if (!redo) memcpy(src - l, buf, l); } } } static void mem_undo_swap(undo_item *prev, int redo) { undo_item tmp = *prev; png_color pal[256]; int i; if (prev->flags & UF_TILED) { mem_undo_tile_swap(prev, redo); prev->flags &= ~UF_ORIG; } else { for (i = 0; i < NUM_CHANNELS; i++) { if (prev->img[i] != MEM_NONE) { prev->img[i] = mem_img[i]; mem_img[i] = tmp.img[i]; } } /* !!! If more flags need preserving, add them to mask */ prev->flags = (prev->flags & UF_ACCUM) | UF_FLAT; } if (prev->pal_) { mem_pal_copy(pal, mem_pal); mem_pal_copy(mem_pal, prev->pal_); mem_pal_copy(prev->pal_, pal); } undo_swap_data(prev); prev->width = mem_width; prev->height = mem_height; prev->bpp = mem_img_bpp; prev->cols = mem_cols; prev->trans = mem_xpm_trans; if (!mem_changed) prev->flags |= UF_ORIG; mem_width = tmp.width; mem_height = tmp.height; mem_img_bpp = tmp.bpp; mem_cols = tmp.cols; mem_xpm_trans = tmp.trans; mem_changed = !(tmp.flags & UF_ORIG); } void mem_do_undo(int redo) { undo_item *curr, *prev; int i, j; /* Compress last undo frame */ mem_undo_prepare(); if ((redo ? mem_undo_redo : mem_undo_done) > 0 ) { j = redo ? 1 : -1; i = (mem_undo_pointer + j + mem_undo_max) % mem_undo_max; /* Swap data */ curr = mem_undo_im_[mem_undo_pointer]; prev = mem_undo_im_[i]; mem_undo_swap(prev, redo); /* Swap frames */ mem_undo_im_[mem_undo_pointer] = prev; mem_undo_im_[i] = curr; mem_undo_pointer = i; mem_undo_done += j; mem_undo_redo -= j; /* Update current */ update_undo(&mem_image); } pen_down = 0; } /* Return the number of bytes used in image + undo */ size_t mem_used() { update_undo(&mem_image); return mem_undo_size(&mem_image.undo_); } /* Return the number of bytes used in image + undo in all layers */ size_t mem_used_layers() { return (mem_used() + mem_undo_lsize()); } /* Fast approximate atan2() function, returning result in degrees. This code is * approximately 2x faster than using libm on P4/Linux, and 6x on Windows. * Absolute error is below 0.0003 degrees, which means 1/10 of a pixel in worst * possible case. - WJ */ #define ATANNUM 128 static float ATAN[2 * ATANNUM + 2]; double atan360(int x, int y) { double d; int xa, ya, n; if (!(x | y)) return (0.0); xa = abs(x); ya = abs(y); d = ya < xa ? (double)ya / (double)xa : 2.0 - (double)xa / (double)ya; d *= ATANNUM; n = d; d = ATAN[n] + (ATAN[n + 1] - ATAN[n]) * (d - n); if (x < 0) d = 180.0 - d; return (y >= 0 ? d : 360.0 - d); } static void make_ATAN() { int i; for (i = 0; i <= ATANNUM; i++) ATAN[2 * ATANNUM - i] = 90.0 - (ATAN[i] = atan(i * (1.0 / ATANNUM)) * (180.0 / M_PI)); ATAN[2 * ATANNUM + 1] = 90.0; } int load_def_palette(char *name) { int i; if (!name[0]) return (FALSE); // Useless i = detect_palette_format(name); if (i > FT_NONE) return (load_image(name, FS_PALETTE_DEF, i) == 1); return (FALSE); } int load_def_patterns(char *name) { int i; if (!name[0]) return (FALSE); // Useless i = detect_image_format(name); if ((i > FT_NONE) && (file_formats[i].flags & FF_IDX)) return (load_image(name, FS_PATTERN_LOAD, i) == 1); return (FALSE); } void mem_init() // Initialise memory { static const unsigned char lookup[8] = { 0, 36, 73, 109, 146, 182, 219, 255 }; unsigned char *dest; char txt[64]; int i, j, ix, iy, bs, bf, bt; make_ATAN(); for (i = 0; i < 256; i++) // Load up normal palette defaults { mem_pal_def[i].red = lookup[mem_pal_def[i].red]; mem_pal_def[i].green = lookup[mem_pal_def[i].green]; mem_pal_def[i].blue = lookup[mem_pal_def[i].blue]; } load_def_palette(inifile_get(DEFAULT_PAL_INI, "")); load_def_patterns(inifile_get(DEFAULT_PAT_INI, "")); /* Init editor settings */ mem_channel = CHN_IMAGE; mem_icx = mem_icy = 0.5; mem_xbm_hot_x = mem_xbm_hot_y = -1; mem_col_A = 1; mem_col_B = 0; /* Set up default undo stack */ mem_undo_depth = mem_undo_depth <= MIN_UNDO ? MIN_UNDO : mem_undo_depth >= MAX_UNDO ? MAX_UNDO : mem_undo_depth | 1; if (!init_undo(&mem_image.undo_, mem_undo_depth)) { memory_errors(1); exit(0); } // Create brush presets mem_cols = mem_pal_def_i; mem_pal_copy( mem_pal, mem_pal_def ); if (mem_new(PATCH_WIDTH, PATCH_HEIGHT, 3, CMASK_IMAGE)) // Not enough memory! { memory_errors(1); exit(0); } mem_mask_setv(NULL, -1, FALSE); mem_col_A24.red = 255; mem_col_A24.green = 255; mem_col_A24.blue = 255; mem_col_B24.red = 0; mem_col_B24.green = 0; mem_col_B24.blue = 0; j = mem_width * mem_height; dest = mem_img[CHN_IMAGE]; for (i = 0; i < j; i++) { *dest++ = mem_col_B24.red; *dest++ = mem_col_B24.green; *dest++ = mem_col_B24.blue; } mem_pat_update(); for (i = 0; i < NUM_BRUSHES; i++) // Draw each brush { ix = BRUSH_CELL / 2 + BRUSH_CELL * (i % BRUSH_GRID_W); iy = BRUSH_CELL / 2 + BRUSH_CELL * (i / BRUSH_GRID_W); bt = mem_brush_list[i][0]; bs = mem_brush_list[i][1]; bf = mem_brush_list[i][2]; switch (bt) { case TOOL_SQUARE: f_rectangle(ix - bs / 2, iy - bs / 2, bs, bs); break; case TOOL_CIRCLE: f_circle(ix, iy, bs); break; case TOOL_VERTICAL: f_rectangle(ix, iy - bs / 2, 1, bs); break; case TOOL_HORIZONTAL: f_rectangle(ix - bs / 2, iy, bs, 1); break; case TOOL_SLASH: for (j = 0; j < bs; j++) put_pixel(ix - bs / 2 + j, iy + bs / 2 - j); break; case TOOL_BACKSLASH: for (j = 0; j < bs; j++) put_pixel(ix + bs / 2 - j, iy + bs / 2 - j); break; case TOOL_SPRAY: for (j = 0; j < bf * 3; j++) put_pixel(ix - bs / 2 + rand() % bs, iy - bs / 2 + rand() % bs); break; } } j = PATCH_WIDTH * PATCH_HEIGHT * 3; memcpy(mem_brushes, mem_img[CHN_IMAGE], j); // Store image for later use memset(mem_img[CHN_IMAGE], 0, j); // Clear so user doesn't see it upon load fail mem_set_brush(36); // Initial brush for ( i=0; igmode = GRAD_MODE_LINEAR; grad->rmode = GRAD_BOUND_STOP; grad_update(grad); } for (i = 0; i <= NUM_CHANNELS; i++) { graddata[i].gtype = GRAD_TYPE_RGB; graddata[i].otype = GRAD_TYPE_CONST; } grad_def_update(-1); for (i = 0; i <= NUM_CHANNELS; i++) gmap_setup(graddata + i, gradbytes, i); } void mem_swap_cols(int redraw) { int oc, flags; png_color o24; if (pattern_B) { oc = mem_tool_pat; mem_tool_pat = mem_tool_pat_B; mem_tool_pat_B = oc; } if (mem_channel != CHN_IMAGE) { oc = channel_col_A[mem_channel]; channel_col_A[mem_channel] = channel_col_B[mem_channel]; channel_col_B[mem_channel] = oc; flags = redraw ? UPD_GRAD : CF_GRAD; } else { oc = mem_col_A; mem_col_A = mem_col_B; mem_col_B = oc; o24 = mem_col_A24; mem_col_A24 = mem_col_B24; mem_col_B24 = o24; if (RGBA_mode) { oc = channel_col_A[CHN_ALPHA]; channel_col_A[CHN_ALPHA] = channel_col_B[CHN_ALPHA]; channel_col_B[CHN_ALPHA] = oc; } flags = redraw ? UPD_AB : CF_AB | CF_GRAD; } update_stuff(flags); } void mem_set_trans(int trans) { if (trans == mem_xpm_trans) return; mem_undo_next(UNDO_TRANS); mem_xpm_trans = trans; update_stuff(UPD_TRANS); } static void repaint_swatch(int index) // Update a palette colour swatch { static const int ll[3] = { PALETTE_SWATCH_X, PALETTE_SWATCH_W, PALETTE_WIDTH - PALETTE_CROSS_X }; unsigned char *tr, *tmp; int i, j, k, n, d, c = PNG_2_INT(mem_pal[index]); int cc[4] = { mem_pal_ab_c, c, mem_pal_ab_c, mem_pal_id_c }; /* Unhighlight background if not A or B */ if ((index ^ mem_col_A) | (c ^ PNG_2_INT(mem_col_A24))) cc[0] = 0; if ((index ^ mem_col_B) | (c ^ PNG_2_INT(mem_col_B24))) cc[2] = 0; tr = mem_pals + index * PALETTE_SWATCH_H * PALETTE_W3 + PALETTE_SWATCH_Y * PALETTE_W3; /* Draw color & background */ tmp = tr; for (n = 0; n < 3; n++) { c = cc[n]; j = ll[n]; for (i = 0; i < j; i++ , tmp += 3) { tmp[0] = INT_2_R(c); tmp[1] = INT_2_G(c); tmp[2] = INT_2_B(c); } } for (i = 1; i < PALETTE_SWATCH_H; i++) memcpy(tr + i * PALETTE_W3, tr, PALETTE_W3); /* Draw index */ cc[1] = mem_pal_id_c; tmp = tr + PALETTE_INDEX_DY * PALETTE_W3 + PALETTE_INDEX_X * 3; for (d = 100; d; d /= 10 , tmp += (PALETTE_DIGIT_W + 1) * 3) { if ((index < d) && (d > 1)) continue; n = ((index / d) % 10) * PALETTE_DIGIT_H; for (i = 0; i < PALETTE_DIGIT_H; i++) { k = xbm_n7x7_bits[n + i]; for (j = 0; j < PALETTE_DIGIT_W; j++ , k >>= 1 , tmp += 3) { c = cc[k & 1]; tmp[0] = INT_2_R(c); tmp[1] = INT_2_G(c); tmp[2] = INT_2_B(c); } tmp += PALETTE_W3 - PALETTE_DIGIT_W * 3; } tmp -= PALETTE_DIGIT_H * PALETTE_W3; } /* Draw protection mask cross */ if (!mem_prot_mask[index]) return; tmp = tr + PALETTE_CROSS_DY * PALETTE_W3 + (PALETTE_CROSS_X + PALETTE_CROSS_DX) * 3; for (i = 0; i < PALETTE_CROSS_H; i++) { k = mem_cross[i]; for (j = 0; j < PALETTE_CROSS_W; j++ , k >>= 1 , tmp += 3) { c = cc[(k & 1) + 2]; tmp[0] = INT_2_R(c); tmp[1] = INT_2_G(c); tmp[2] = INT_2_B(c); } tmp += PALETTE_W3 - PALETTE_CROSS_W * 3; } } void mem_pal_init() // Redraw whole palette { int i; memset(mem_pals, 0, PALETTE_WIDTH * PALETTE_HEIGHT * 3); for (i = 0; i < mem_cols; i++) repaint_swatch(i); } void mem_pal_load_def() // Load default palette { mem_pal_copy( mem_pal, mem_pal_def ); mem_cols = mem_pal_def_i; } #define RGB_PROT_MAX 256 /* The 16:8 split is optimal for up to 768 colors, then 17:7 etc */ typedef struct { short nb[0x10000 / 32]; uint32_t rg[0x10000 / 32], b[RGB_PROT_MAX * 0x100 / 32]; } rgb_prot; static rgb_prot mem_prot_map; void mem_mask_init() // Initialise RGB protection bitmaps { int i, j, n, v, rgb[RGB_PROT_MAX]; memset(&mem_prot_map, 0, sizeof(mem_prot_map)); for (i = n = 0; i < mem_cols; i++) { if (!mem_prot_mask[i]) continue; rgb[n++] = v = PNG_2_INT(mem_pal[i]); v >>= 8; mem_prot_map.rg[v >> 5] |= 1U << (v & 0x1F); } mem_prot = n; if (!n) return; for (i = v = 0; i < 0x10000 / 32 - 1; i++) mem_prot_map.nb[i + 1] = v += bitcount(mem_prot_map.rg[i]); for (i = 0; i < n; i++) { unsigned u; v = rgb[i] >> 8; u = (1U << (v & 0x1F)) - 1; v >>= 5; j = mem_prot_map.nb[v] + bitcount(u & mem_prot_map.rg[v]); v = rgb[i] & 0xFF; mem_prot_map.b[j * (0x100 >> 5) + (v >> 5)] |= 1U << (v & 0x1F); } } static inline int mem_mask_test(int rgb) { int v = rgb >> 8; unsigned u = 1U << (v & 0x1F), w = mem_prot_map.rg[v >> 5]; if (u &= w) { v = mem_prot_map.nb[v >> 5] + bitcount((u - 1) & w); rgb &= 0xFF; u = mem_prot_map.b[v * (0x100 >> 5) + (rgb >> 5)] >> (rgb & 0x1F); } return (u & 1); } void mem_mask_setv(int *what, int n, int state) { state = state ? 255 : 0; if (what) { while (n-- > 0) { int i = *what++; if ((i >= 0) && (i < mem_cols)) mem_prot_mask[i] = state; } } else if (n < 0) memset(mem_prot_mask, state, 256); else if (n < mem_cols) mem_prot_mask[n] = state; mem_mask_init(); } void mem_get_histogram(int channel) // Calculate how many of each colour index is on the canvas { int i, j = mem_width * mem_height; unsigned char *img = mem_img[channel]; memset(mem_histogram, 0, sizeof(mem_histogram)); for (i = 0; i < j; i++) mem_histogram[*img++]++; } typedef struct { int last_gamma, last_br, last_co, last_ps; unsigned char gamma_table[256], bc_table[256], ps_table[256]; } transform_cache; void do_transform(int start, int step, int cnt, unsigned char *mask, unsigned char *imgr, unsigned char *img0, int m0) { static const int ixx[7] = {0, 1, 2, 0, 1, 2, 0}; static unsigned char fmask = 255; static transform_cache tc[2]; int do_gamma, do_bc, /*do_sa,*/ do_ps; unsigned char rgb[3]; int br, co, sa; int dH, sH, tH, ix0, ix1, ix2, c0, c1, c2, dc = 0, ops = 0; int j, mstep, r, g, b; transform_cache *tp = tc; transform_state *mp = mem_bcsp; if (m0 > 255) tp++ , mp++; // Brush mode if (!mp->allow[0]) ops |= 0xFF; if (!mp->allow[1]) ops |= 0xFF00; if (!mp->allow[2]) ops |= 0xFF0000; br = mp->bcsp[0] * 256; co = mp->bcsp[1]; if (co > 0) co *= 3; co += 100; co = (256 * co) / 100; sa = (256 * mp->bcsp[2]) / 100; dH = sH = mp->bcsp[5]; // Map bitwise to truncated do_ps = mp->pmode ? mp->bcsp[3] : 1 << mp->bcsp[3]; // Disable if 1:1, else separate truncated from rounded if (do_ps &= 255) do_ps += (mp->pmode > 1) << 8; do_gamma = mp->bcsp[4] - 100; do_bc = br | (co - 256); // do_sa = sa - 255; /* Prepare posterize table */ if (do_ps && (do_ps != tp->last_ps)) { int mul = do_ps & 255, div = 256, add = 0, div2 = mul - 1; int i, j; tp->last_ps = do_ps; if (do_ps > 255) // Rounded { mul += mul - 2; div = 255 * 2; add = 255; } for (i = 0; i < 256; i++) { j = (i * mul + add) / div; tp->ps_table[i] = (j * 255 * 2 + div2) / (div2 + div2); } } /* Prepare gamma table */ if (do_gamma && (do_gamma != tp->last_gamma)) { double w; int i; tp->last_gamma = do_gamma; w = 100.0 / (double)(do_gamma + 100); for (i = 0; i < 256; i++) { tp->gamma_table[i] = rint(255.0 * pow((double)i / 255.0, w)); } } /* Prepare brightness-contrast table */ if (do_bc && ((br ^ tp->last_br) | (co ^ tp->last_co))) { int i, j; tp->last_br = br; tp->last_co = co; for (i = 0; i < 256; i++) { j = ((i + i - 255) * co + (255 * 256)) / 2 + br; tp->bc_table[i] = j < 0 ? 0 : j > (255 * 256) ? 255 : j >> 8; } } if (dH) { if (dH < 0) dH += 1530; dc = (dH / 510) * 2; dH -= dc * 255; if ((sH = dH > 255)) { dH = 510 - dH; dc = dc < 4 ? dc + 2 : 0; } } ix0 = ixx[dc]; ix1 = ixx[dc + 1]; ix2 = ixx[dc + 2]; /* Use fake mask if no real one provided */ if (!mask) mask = &fmask , mstep = 0; else mask += start - step , mstep = step; start *= 3; step *= 3; // Step by triples img0 += start - step; imgr += start - step; while (cnt-- > 0) { img0 += step; imgr += step; mask += mstep; if (*mask == (unsigned char)m0) continue; rgb[0] = img0[0]; rgb[1] = img0[1]; rgb[2] = img0[2]; /* If we do gamma transform */ if (do_gamma) { rgb[0] = tp->gamma_table[rgb[0]]; rgb[1] = tp->gamma_table[rgb[1]]; rgb[2] = tp->gamma_table[rgb[2]]; } /* If we do hue transform & colour has a hue */ if (dH && ((rgb[0] ^ rgb[1]) | (rgb[0] ^ rgb[2]))) { /* Min. component */ c2 = dc; if (rgb[ix2] < rgb[ix0]) c2++; if (rgb[ixx[c2]] >= rgb[ixx[c2 + 1]]) c2++; /* Actual indices */ c2 = ixx[c2]; c0 = ixx[c2 + 1]; c1 = ixx[c2 + 2]; /* Max. component & edge dir */ if ((tH = rgb[c0] <= rgb[c1])) { c0 = ixx[c2 + 2]; c1 = ixx[c2 + 1]; } /* Do adjustment */ j = dH * (rgb[c0] - rgb[c2]) + 127; /* Round up (?) */ j = (j + (j >> 8) + 1) >> 8; r = rgb[c0]; g = rgb[c1]; b = rgb[c2]; if (tH ^ sH) /* Falling edge */ { rgb[c1] = r = g > j + b ? g - j : b; rgb[c2] += j + r - g; } else /* Rising edge */ { rgb[c1] = b = g < r - j ? g + j : r; rgb[c0] -= j + g - b; } } r = rgb[ix0]; g = rgb[ix1]; b = rgb[ix2]; /* If we do brightness/contrast transform */ if (do_bc) { r = tp->bc_table[r]; g = tp->bc_table[g]; b = tp->bc_table[b]; } /* If we do saturation transform */ if (sa) { j = (299 * r + 587 * g + 114 * b) / 1000; r = r * 256 + (r - j) * sa; r = r < 0 ? 0 : r > (255 * 256) ? 255 : r >> 8; g = g * 256 + (g - j) * sa; g = g < 0 ? 0 : g > (255 * 256) ? 255 : g >> 8; b = b * 256 + (b - j) * sa; b = b < 0 ? 0 : b > (255 * 256) ? 255 : b >> 8; } /* If we do posterize transform */ if (do_ps) { r = tp->ps_table[r]; g = tp->ps_table[g]; b = tp->ps_table[b]; } /* If we do channel masking */ if (ops) { r ^= (r ^ img0[0]) & ops; g ^= (g ^ img0[1]) & (ops >> 8); b ^= (b ^ img0[2]) & (ops >> 16); } imgr[0] = r; imgr[1] = g; imgr[2] = b; } } static unsigned char pal_dupes[256]; int scan_duplicates() // Find duplicate palette colours, return number found { int i, j, c, found, pmap[256]; for (i = 0; i < mem_cols; i++) pmap[i] = PNG_2_INT(mem_pal[i]); /* Transparent color is different from any normal one */ if (mem_xpm_trans >= 0) pmap[mem_xpm_trans] = -1; for (found = 0 , i = mem_cols - 1; i >= 0; i--) { c = pmap[i]; for (j = 0; pmap[j] != c; j++); pal_dupes[i] = j; found += i != j; } return (found); } void remove_duplicates() // Remove duplicate palette colours - call AFTER scan_duplicates { do_xlate(pal_dupes, mem_img[CHN_IMAGE], mem_width * mem_height); } int mem_remove_unused_check() { int i, found = 0; mem_get_histogram(CHN_IMAGE); for (i = 0; i < mem_cols; i++) if (!mem_histogram[i]) found++; if (!found) return 0; // All palette colours are used on the canvas // Leave at least one colour even if canvas is 0x0 return (mem_cols > found ? found : mem_cols - 1); } int mem_remove_unused() { unsigned char conv[256]; int i, j, found = mem_remove_unused_check(); if (found <= 0) return (0); conv[0] = 0; // Ensure this works even with empty histogram for (i = j = 0; i < 256; i++) // Create conversion table { if (mem_histogram[i]) { mem_pal[j] = mem_pal[i]; conv[i] = j++; } } // Re-adjust transparent colour index if it exists mem_xpm_trans = (mem_xpm_trans < 0) || !mem_histogram[mem_xpm_trans] ? -1 : conv[mem_xpm_trans]; do_xlate(conv, mem_img[CHN_IMAGE], mem_width * mem_height); mem_cols -= found; return found; } // Generate black-to-white palette void mem_bw_pal(png_color *pal, int i1, int i2) { int i, j, step = i2 > i1 ? 1 : -1, d = abs(i2 - i1); if (!d) return; for (i = i1 , j = d , d += d; i != i2 + step; i += step , j += 255 * 2) { pal[i].red = pal[i].green = pal[i].blue = j / d; } } void transform_pal(png_color *pal1, png_color *pal2, int p1, int p2) { int l = p2 - p1 + 1; unsigned char tmp[256 * 3]; pal2rgb(tmp, pal2 + p1, l, 0); do_transform(0, 1, l, NULL, tmp, tmp, 0); rgb2pal(pal1 + p1, tmp, l); } void set_zoom_centre( int x, int y ) { IF_IN_RANGE( x, y ) { mem_icx = ((float) x ) / mem_width; mem_icy = ((float) y ) / mem_height; mem_ics = 1; } } // Convert image to RGB void do_convert_rgb(int start, int step, int cnt, unsigned char *dest, unsigned char *src, png_color *pal) { dest += start * 3; src += start; while (cnt-- > 0) { png_color *col = pal + *src; dest[0] = col->red; dest[1] = col->green; dest[2] = col->blue; dest += step * 3; src += step; } } /* With 16-bit rg[], would be a little bit more compact (24K vs 26K) */ typedef struct { uint32_t rg[0x10000 / 32], b[256 * (0x100 / 32)]; unsigned char rgx[0x10000 / 32], vx[256 * 32]; int nv, nb; } rgb_256_map; // Convert RGB image to Indexed Palette int mem_convert_indexed(unsigned char *dest, unsigned char *src, int cnt, int cols, png_color *pal) { rgb_256_map m; unsigned char bx[256 * (0x100 / 32)], idx[256]; int i, j, k, l, n, v, vn, pix; /* Put palette into bitmap */ memset(&m, 0, sizeof(m)); for (i = 0; i < cols; i++) { pix = PNG_2_INT(pal[i]); k = pix & 0xFF; n = (pix >> 8) & 0x1F; v = pix >> (8 + 5); /* Insert into tiers */ if (!m.rg[v]) m.rgx[v] = m.nv++; vn = m.rgx[v] * 32 + n; if (!((m.rg[v] >> n) & 1)) m.vx[vn] = m.nb++ , m.rg[v] |= 1U << n; m.b[m.vx[vn] * 8 + (k >> 5)] |= 1U << (k & 0x1F); } /* Calculate bitcounts */ for (i = j = 0; i < sizeof(bx); i++) { bx[i] = j; j += bitcount(m.b[i]); } /* Prepare mapping */ for (i = 0; i < cols; i++) { pix = PNG_2_INT(pal[i]); k = pix & 0xFF; n = (pix >> 8) & 0x1F; v = pix >> (8 + 5); /* Locate in bitmap */ vn = m.rgx[v] * 32 + n; j = m.vx[vn] * 8 + (k >> 5); j = bx[j] + bitcount(m.b[j] & ((1U << (k & 0x1F)) - 1)); /* Remember the palette slot for the location */ idx[j] = i; } for (i = 0; i < cnt; i++) { pix = MEM_2_INT(src, 0); k = pix & 0xFF; n = (pix >> 8) & 0x1F; v = pix >> (8 + 5); /* Test presence on both tiers at once: if the 1st is unset, * the 2nd simply defaults to block #0 */ vn = m.rgx[v] * 32 + n; l = m.vx[vn] * 8 + (k >> 5); if (!((m.rg[v] >> n) & 1 & (m.b[l] >> (k & 0x1F)))) return (1); // No index found - BAD ERROR!! /* Get index */ l = bx[l] + bitcount(m.b[l] & ((1U << (k & 0x1F)) - 1)); /* Map to palette */ *dest++ = idx[l]; src += 3; } return (0); } /* Max-Min quantization algorithm - good for preserving saturated colors, * and because of that, bad when used without dithering - WJ */ #define HISTSIZE (64 * 64 * 64) int maxminquan(unsigned char *inbuf, int width, int height, int quant_to, png_color *userpal) { int i, j, k, ii, r, g, b, dr, dg, db, l = width * height, *hist; /* Allocate histogram */ hist = calloc(1, HISTSIZE * sizeof(int)); if (!hist) return (-1); /* Fill histogram */ for (i = 0; i < l; i++) { ++hist[((inbuf[0] & 0xFC) << 10) + ((inbuf[1] & 0xFC) << 4) + (inbuf[2] >> 2)]; inbuf += 3; } /* Find the most frequent color */ j = k = -1; for (i = 0; i < HISTSIZE; i++) { if (hist[i] <= k) continue; j = i; k = hist[i]; } /* Make it first */ userpal[0].red = r = j >> 12; userpal[0].green = g = (j >> 6) & 0x3F; userpal[0].blue = b = j & 0x3F; /* Find distances from all others to it */ if (quant_to > 1) { for (i = 0; i < HISTSIZE; i++) { if (!hist[i]) continue; dr = (i >> 12) - r; dg = ((i >> 6) & 0x3F) - g; db = (i & 0x3F) - b; hist[i] = dr * dr + dg * dg + db * db; } } /* Add more colors */ for (ii = 1; ii < quant_to; ii++) { /* Find farthest color */ j = -1; for (i = k = 0; i < HISTSIZE; i++) { if (hist[i] <= k) continue; j = i; k = hist[i]; } /* No more colors? */ if (j < 0) break; /* Store into palette */ userpal[ii].red = r = j >> 12; userpal[ii].green = g = (j >> 6) & 0x3F; userpal[ii].blue = b = j & 0x3F; /* Update distances */ for (i = 0; i < HISTSIZE; i++) { if (!hist[i]) continue; dr = (i >> 12) - r; dg = ((i >> 6) & 0x3F) - g; db = (i & 0x3F) - b; k = dr * dr + dg * dg + db * db; if (k < hist[i]) hist[i] = k; } } /* Upconvert colors */ for (i = 0; i < ii; i++) { userpal[i].red = (userpal[i].red << 2) + (userpal[i].red >> 4); userpal[i].green = (userpal[i].green << 2) + (userpal[i].green >> 4); userpal[i].blue = (userpal[i].blue << 2) + (userpal[i].blue >> 4); } /* Clear empty slots */ for (i = ii; i < quant_to; i++) userpal[i].red = userpal[i].green = userpal[i].blue = 0; free(hist); return (0); } /* Pairwise Nearest Neighbor quantization algorithm - minimizes mean square * error measure; time used is proportional to number of bins squared - WJ */ typedef struct { double rc, gc, bc, err; int cnt; unsigned short nn, fw, bk, tm, mtm; } pnnbin; static void find_nn(pnnbin *bins, int idx) { pnnbin *bin1, *bin2; int i, nn = 0; double n1, wr, wg, wb, err = 1e100; bin1 = bins + idx; n1 = bin1->cnt; wr = bin1->rc; wg = bin1->gc; wb = bin1->bc; for (i = bin1->fw; i; i = bin2->fw) { double nerr, n2; bin2 = bins + i; nerr = (bin2->rc - wr) * (bin2->rc - wr) + (bin2->gc - wg) * (bin2->gc - wg) + (bin2->bc - wb) * (bin2->bc - wb); n2 = bin2->cnt; nerr *= (n1 * n2) / (n1 + n2); if (nerr >= err) continue; err = nerr; nn = i; } bin1->err = err; bin1->nn = nn; } int pnnquan(unsigned char *inbuf, int width, int height, int quant_to, png_color *userpal) { unsigned short heap[32769]; pnnbin *bins, *tb, *nb; double d, err, n1, n2; int i, j, k, l, l2, h, b1, maxbins, extbins, res = 1; heap[0] = 0; // Empty bins = calloc(32768, sizeof(pnnbin)); if (!bins) return (-1); progress_init(_("Quantize Pass 1"), 1); /* Build histogram */ k = width * height; for (i = 0; i < k; i++ , inbuf += 3) { // !!! Can throw gamma correction in here, but what to do about perceptual // !!! nonuniformity then? j = ((inbuf[0] & 0xF8) << 7) + ((inbuf[1] & 0xF8) << 2) + (inbuf[2] >> 3); tb = bins + j; tb->rc += inbuf[0]; tb->gc += inbuf[1]; tb->bc += inbuf[2]; tb->cnt++; } /* Cluster nonempty bins at one end of array */ tb = bins; for (i = 0; i < 32768; i++) { if (!bins[i].cnt) continue; *tb = bins[i]; d = 1.0 / (double)tb->cnt; tb->rc *= d; tb->gc *= d; tb->bc *= d; if (quan_sqrt) tb->cnt = sqrt(tb->cnt); tb++; } maxbins = tb - bins; for (i = 0; i < maxbins - 1; i++) { bins[i].fw = i + 1; bins[i + 1].bk = i; } // !!! Already zeroed out by calloc() // bins[0].bk = bins[i].fw = 0; /* Initialize nearest neighbors and build heap of them */ for (i = 0; i < maxbins; i++) { if (((i * 50) % maxbins >= maxbins - 50)) if (progress_update((float)i / maxbins)) goto quit; find_nn(bins, i); /* Push slot on heap */ err = bins[i].err; for (l = ++heap[0]; l > 1; l = l2) { l2 = l >> 1; if (bins[h = heap[l2]].err <= err) break; heap[l] = h; } heap[l] = i; } progress_end(); progress_init(_("Quantize Pass 2"), 1); /* Merge bins which increase error the least */ extbins = maxbins - quant_to; for (i = 0; i < extbins; ) { if (((i * 50) % extbins >= extbins - 50)) if (progress_update((float)i / extbins)) goto quit; /* Use heap to find which bins to merge */ while (TRUE) { tb = bins + (b1 = heap[1]); /* One with least error */ /* Is stored error up to date? */ if ((tb->tm >= tb->mtm) && (bins[tb->nn].mtm <= tb->tm)) break; if (tb->mtm == 0xFFFF) /* Deleted node */ b1 = heap[1] = heap[heap[0]--]; else /* Too old error value */ { find_nn(bins, b1); tb->tm = i; } /* Push slot down */ err = bins[b1].err; for (l = 1; (l2 = l + l) <= heap[0]; l = l2) { if ((l2 < heap[0]) && (bins[heap[l2]].err > bins[heap[l2 + 1]].err)) l2++; if (err <= bins[h = heap[l2]].err) break; heap[l] = h; } heap[l] = b1; } /* Do a merge */ nb = bins + tb->nn; n1 = tb->cnt; n2 = nb->cnt; d = 1.0 / (n1 + n2); tb->rc = d * rint(n1 * tb->rc + n2 * nb->rc); tb->gc = d * rint(n1 * tb->gc + n2 * nb->gc); tb->bc = d * rint(n1 * tb->bc + n2 * nb->bc); tb->cnt += nb->cnt; tb->mtm = ++i; /* Unchain deleted bin */ bins[nb->bk].fw = nb->fw; bins[nb->fw].bk = nb->bk; nb->mtm = 0xFFFF; } /* Fill palette */ i = j = 0; while (TRUE) { userpal[j].red = rint(bins[i].rc); userpal[j].green = rint(bins[i].gc); userpal[j++].blue = rint(bins[i].bc); if (!(i = bins[i].fw)) break; } /* Clear empty slots */ for (; j < quant_to; j++) userpal[j].red = userpal[j].green = userpal[j].blue = 0; res = 0; quit: progress_end(); free(bins); return (res); } /* Distance functions for 3 distance measures */ #if defined(__GNUC__) && defined(__i386__) #define REGPARM2 __attribute__ ((regparm (2))) #else #define REGPARM2 #endif typedef double REGPARM2 (*distance_func)(const double *v0, const double *v1); static double REGPARM2 distance_linf(const double *v0, const double *v1) { double td, td2; td = fabs(v0[0] - v1[0]); td2 = fabs(v0[1] - v1[1]); if (td < td2) td = td2; td2 = fabs(v0[2] - v1[2]); if (td < td2) td = td2; return (td); } static double REGPARM2 distance_l1(const double *v0, const double *v1) { return (fabs(v0[0] - v1[0]) + fabs(v0[1] - v1[1]) + fabs(v0[2] - v1[2])); } static double REGPARM2 distance_l2(const double *v0, const double *v1) { return (sqrt((v0[0] - v1[0]) * (v0[0] - v1[0]) + (v0[1] - v1[1]) * (v0[1] - v1[1]) + (v0[2] - v1[2]) * (v0[2] - v1[2]))); } static const distance_func distance_3d[NUM_DISTANCES] = { distance_linf, distance_l1, distance_l2 }; /* Dithering works with 6-bit colours, because hardware VGA palette is 6-bit, * and any kind of dithering is imprecise by definition anyway - WJ */ typedef struct { double xyz256[768], gamma[256 * 2], lin[256 * 2]; int cspace, cdist, ncols; guint32 xcmap[64 * 64 * 2 + 128 * 2]; /* Cache bitmap */ guint32 lcmap[64 * 64 * 2]; /* Extension bitmap */ unsigned char cmap[64 * 64 * 64 + 128 * 64]; /* Index cache */ } ctable; static ctable *ctp; /* !!! Beware of GCC misoptimizing this! The two functions below is the result * of much trial and error, and hopefully not VERY brittle; but still, after any * modification to them, compare the performance to what it was before - WJ */ static int find_nearest(int col[3], int n) { /* !!! Stack misalignment is a very real issue here */ unsigned char tmp_[4 * sizeof(double)]; double *tmp = ALIGNED(tmp_, sizeof(double)); /* Prepare colour coords */ switch (ctp->cspace) { default: case CSPACE_RGB: tmp[0] = ctp->lin[n + col[0]]; tmp[1] = ctp->lin[n + col[1]]; tmp[2] = ctp->lin[n + col[2]]; break; case CSPACE_SRGB: tmp[0] = ctp->gamma[n + col[0]]; tmp[1] = ctp->gamma[n + col[1]]; tmp[2] = ctp->gamma[n + col[2]]; break; case CSPACE_LXN: rgb2LXN(tmp, ctp->gamma[n + col[0]], ctp->gamma[n + col[1]], ctp->gamma[n + col[2]]); break; } /* Find nearest colour */ { const distance_func dist = distance_3d[ctp->cdist]; double d = 1000000000.0, td, *xyz = ctp->xyz256; int i, j, l = ctp->ncols; for (i = j = 0; i < l; i++) { td = dist(tmp, xyz + i * 3); if (td < d) j = i , d = td; } return (j); } } static int lookup_srgb(double *srgb) { int k, n = 0, col[3]; /* Convert to 8-bit RGB coords */ col[0] = UNGAMMA256(srgb[0]); col[1] = UNGAMMA256(srgb[1]); col[2] = UNGAMMA256(srgb[2]); /* Check if there is extended precision */ k = ((col[0] & 0xFC) << 10) + ((col[1] & 0xFC) << 4) + (col[2] >> 2); if (ctp->lcmap[k >> 5] & (1U << (k & 31))) k = 64 * 64 * 64 + ctp->cmap[k] * 64 + ((col[0] & 3) << 4) + ((col[1] & 3) << 2) + (col[2] & 3); else n = 256; /* Use posterized values for 6-bit part */ /* Use colour cache if possible */ if (!(ctp->xcmap[k >> 5] & (1U << (k & 31)))) { ctp->xcmap[k >> 5] |= 1U << (k & 31); ctp->cmap[k] = find_nearest(col, n); } return (ctp->cmap[k]); } // !!! No support for transparency yet !!! /* Damping functions roughly resemble old GIMP's behaviour, but may need some * tuning because linear sRGB is just too different from normal RGB */ int mem_dither(unsigned char *old, int ncols, short *dither, int cspace, int dist, int limit, int selc, int serpent, int rgb8b, double emult) { int i, j, k, l, kk, j0, j1, dj, rlen, col0, col1, progress; unsigned char *ddata, *src, *dest; double *row0, *row1, *row2, *tmp; double err, intd, extd, *gamma6, *lin6; double tc0[3], tc1[3], color0[3], color1[3]; double fdiv = 0, gamut[6] = {1, 1, 1, 0, 0, 0}; /* Allocate working space */ rlen = (mem_width + 4) * 3 * sizeof(double); ddata = multialloc(MA_ALIGN_DOUBLE, &row0, rlen, &row1, rlen, &row2, rlen, &ctp, sizeof(ctable), NULL); if (!ddata) return (1); if ((progress = mem_width * mem_height > 1000000)) progress_init(_("Converting to Indexed Palette"), 0); /* Preprocess palette to find whether to extend precision and where */ for (i = 0; i < ncols; i++) { j = ((mem_pal[i].red & 0xFC) << 10) + ((mem_pal[i].green & 0xFC) << 4) + (mem_pal[i].blue >> 2); if (!(l = ctp->cmap[j])) { ctp->cmap[j] = l = i + 1; ctp->xcmap[l * 4 + 2] = j; } k = ((mem_pal[i].red & 3) << 4) + ((mem_pal[i].green & 3) << 2) + (mem_pal[i].blue & 3); ctp->xcmap[l * 4 + (k & 1)] |= 1U << (k >> 1); } memset(ctp->cmap, 0, 64 * 64 * 64); for (k = 0 , i = 4; i < 256 * 4; i += 4) { guint32 v = ctp->xcmap[i] | ctp->xcmap[i + 1]; /* Are 2+ colors there somewhere? */ if (!((v & (v - 1)) | (ctp->xcmap[i] & ctp->xcmap[i + 1]))) continue; rgb8b = TRUE; /* Force 8-bit precision */ j = ctp->xcmap[i + 2]; ctp->lcmap[j >> 5] |= 1U << (j & 31); ctp->cmap[j] = k++; } memset(ctp->xcmap, 0, 257 * 4 * sizeof(guint32)); /* Prepare tables */ for (i = 0; i < 256; i++) { j = (i & 0xFC) + (i >> 6); ctp->gamma[i] = gamma256[i]; ctp->gamma[i + 256] = gamma256[j]; ctp->lin[i] = i * (1.0 / 255.0); ctp->lin[i + 256] = j * (1.0 / 255.0); } /* Keep all 8 bits of input or posterize to 6 bits? */ i = rgb8b ? 0 : 256; gamma6 = ctp->gamma + i; lin6 = ctp->lin + i; tmp = ctp->xyz256; for (i = 0; i < ncols; i++ , tmp += 3) { /* Update gamut limits */ tmp[0] = gamma6[mem_pal[i].red]; tmp[1] = gamma6[mem_pal[i].green]; tmp[2] = gamma6[mem_pal[i].blue]; for (j = 0; j < 3; j++) { if (tmp[j] < gamut[j]) gamut[j] = tmp[j]; if (tmp[j] > gamut[j + 3]) gamut[j + 3] = tmp[j]; } /* Store colour coords */ switch (cspace) { default: case CSPACE_RGB: tmp[0] = lin6[mem_pal[i].red]; tmp[1] = lin6[mem_pal[i].green]; tmp[2] = lin6[mem_pal[i].blue]; break; case CSPACE_SRGB: break; /* Done already */ case CSPACE_LXN: rgb2LXN(tmp, tmp[0], tmp[1], tmp[2]); break; } } ctp->cspace = cspace; ctp->cdist = dist; ctp->ncols = ncols; serpent = serpent ? 0 : 2; if (dither) fdiv = 1.0 / *dither++; /* Process image */ for (i = 0; i < mem_height; i++) { src = old + i * mem_width * 3; dest = mem_img[CHN_IMAGE] + i * mem_width; memset(row2, 0, rlen); if (serpent ^= 1) { j0 = 0; j1 = mem_width * 3; dj = 1; } else { j0 = (mem_width - 1) * 3; j1 = -3; dj = -1; dest += mem_width - 1; } for (j = j0; j != j1; j += dj * 3) { for (k = 0; k < 3; k++) { /* Posterize to 6 bits as natural for palette */ color0[k] = gamma6[src[j + k]]; /* Add in error, maybe limiting it */ err = row0[j + k + 6]; if (limit == 1) /* To half of SRGB range */ { err = err < -0.5 ? -0.5 : err > 0.5 ? 0.5 : err; } else if (limit == 2) /* To 1/4, with damping */ { err = err < -0.1 ? (err < -0.4 ? -0.25 : 0.5 * err - 0.05) : err > 0.1 ? (err > 0.4 ? 0.25 : 0.5 * err + 0.05) : err; } color1[k] = color0[k] + err; /* Limit result to palette gamut */ if (color1[k] < gamut[k]) color1[k] = gamut[k]; if (color1[k] > gamut[k + 3]) color1[k] = gamut[k + 3]; } /* Output best colour */ col1 = lookup_srgb(color1); *dest = col1; dest += dj; if (!dither) continue; /* Evaluate new error */ tc1[0] = gamma6[mem_pal[col1].red]; tc1[1] = gamma6[mem_pal[col1].green]; tc1[2] = gamma6[mem_pal[col1].blue]; if (selc) /* Selective error damping */ { col0 = lookup_srgb(color0); tc0[0] = gamma6[mem_pal[col0].red]; tc0[1] = gamma6[mem_pal[col0].green]; tc0[2] = gamma6[mem_pal[col0].blue]; /* Split error the obvious way */ if (!(selc & 1) && (col0 == col1)) { color1[0] = (color1[0] - color0[0]) * emult + color0[0] - tc0[0]; color1[1] = (color1[1] - color0[1]) * emult + color0[1] - tc0[1]; color1[2] = (color1[2] - color0[2]) * emult + color0[2] - tc0[2]; } /* Weigh component errors separately */ else if (selc < 3) { for (k = 0; k < 3; k++) { intd = fabs(color0[k] - tc0[k]); extd = fabs(color0[k] - color1[k]); if (intd + extd == 0.0) err = 1.0; else err = (intd + emult * extd) / (intd + extd); color1[k] = err * (color1[k] - tc1[k]); } } /* Weigh errors by vector length */ else { intd = sqrt((color0[0] - tc0[0]) * (color0[0] - tc0[0]) + (color0[1] - tc0[1]) * (color0[1] - tc0[1]) + (color0[2] - tc0[2]) * (color0[2] - tc0[2])); extd = sqrt((color0[0] - color1[0]) * (color0[0] - color1[0]) + (color0[1] - color1[1]) * (color0[1] - color1[1]) + (color0[2] - color1[2]) * (color0[2] - color1[2])); if (intd + extd == 0.0) err = 1.0; else err = (intd + emult * extd) / (intd + extd); color1[0] = err * (color1[0] - tc1[0]); color1[1] = err * (color1[1] - tc1[1]); color1[2] = err * (color1[2] - tc1[2]); } } else /* Indiscriminate error damping */ { color1[0] = (color1[0] - tc1[0]) * emult; color1[1] = (color1[1] - tc1[1]) * emult; color1[2] = (color1[2] - tc1[2]) * emult; } /* Distribute the error */ color1[0] *= fdiv; color1[1] *= fdiv; color1[2] *= fdiv; for (k = 0; k < 5; k++) { kk = j + (k - 2) * dj * 3 + 6; for (l = 0; l < 3; l++ , kk++) { row0[kk] += color1[l] * dither[k]; row1[kk] += color1[l] * dither[k + 5]; row2[kk] += color1[l] * dither[k + 10]; } } } tmp = row0; row0 = row1; row1 = row2; row2 = tmp; if (progress && (i * 10) % mem_height >= mem_height - 10) progress_update((float)(i + 1) / mem_height); } if (progress) progress_end(); free(ddata); return (0); } /* Dumb (but fast) Floyd-Steinberg dithering in RGB space, loosely based on * Dennis Lee's dithering implementation from dl3quant.c, in turn based on * dithering code from the IJG's jpeg library - WJ */ int mem_dumb_dither(unsigned char *old, unsigned char *new, png_color *pal, int width, int height, int ncols, int dither) { unsigned short cols[32768], sqrtb[512], *sqr; short limtb[512], *lim, fr[3] = {0, 0, 0}; short *rows = NULL, *row0 = fr, *row1 = fr; unsigned char clamp[768], *src, *dest; int i, j, k, j0, dj, dj3, r, g, b, rlen, serpent = 2; /* Allocate working space */ rlen = (width + 2) * 3; if (dither) { rows = calloc(rlen * 2, sizeof(short)); if (!rows) return (1); serpent = 0; } /* Color cache, squares table, clamp table */ memset(cols, 0, sizeof(cols)); sqr = sqrtb + 256; for (i = -255; i < 256; i++) sqr[i] = i * i; memset(clamp, 0, 256); memset(clamp + 512, 255, 256); for (i = 0; i < 256; i++) clamp[i + 256] = i; /* Error limiter table, Dennis Lee's way */ #define ERR_LIM 20 lim = limtb + 256; for (i = 0; i < ERR_LIM; i++) lim[i] = i , lim[-i] = -i; for (; i < 256; i++) lim[i] = ERR_LIM , lim[-i] = -ERR_LIM; #undef ERR_LIM /* Process image */ for (i = 0; i < height; i++) { src = old + i * width * 3; dest = new + i * width; if (serpent ^= 1) { j0 = 0; dj = 1; } else { j0 = (width - 1) * 3; dj = -1; dest += width - 1; } if (dither) { row0 = row1 = rows + 3; *(serpent ? &row1 : &row0) += rlen; memset(row1 - 3, 0, rlen * sizeof(short)); src += j0; row0 += j0; row1 += j0; } dj3 = dj * 3; for (j = 0; j < width; j++ , src += dj3 , dest += dj) { r = clamp[src[0] + ((row0[0] + 0x1008) >> 4)]; g = clamp[src[1] + ((row0[1] + 0x1008) >> 4)]; b = clamp[src[2] + ((row0[2] + 0x1008) >> 4)]; k = ((r & 0xF8) << 7) + ((g & 0xF8) << 2) + (b >> 3); if (!cols[k]) /* Find nearest color in RGB */ { int i, j, n = 0, l = 1000000; /* Searching for color nearest to first color in cell, instead of to cell * itself, looks like a bug, but works like a feature - makes FS dither less * prone to patterning. This trick I learned from Dennis Lee's code - WJ */ for (i = 0; i < ncols; i++) { j = sqr[r - pal[i].red] + sqr[g - pal[i].green] + sqr[b - pal[i].blue]; if (j >= l) continue; l = j; n = i; } cols[k] = n + 1; } *dest = k = cols[k] - 1; if (!dither) continue; r = lim[r - pal[k].red]; g = lim[g - pal[k].green]; b = lim[b - pal[k].blue]; k = r + r; row1[0 + dj3] += r; row1[0 - dj3] += (r += k); row1[0 + 0 ] += (r += k); row0[0 + dj3] += r + k; k = g + g; row1[1 + dj3] += g; row1[1 - dj3] += (g += k); row1[1 + 0 ] += (g += k); row0[1 + dj3] += g + k; k = b + b; row1[2 + dj3] += b; row1[2 - dj3] += (b += k); row1[2 + 0 ] += (b += k); row0[2 + dj3] += b + k; row0 += dj3; row1 += dj3; } } free(rows); return (0); } void mem_find_dither(int red, int green, int blue) { int pat = 4, dp = 3; int i, ix1, ix2, pn, tpn, pp2 = pat * pat * 2; double r, g, b, r1, g1, b1, dr0, dg0, db0, dr, dg, db; double l, l2, tl, t; r = gamma256[red]; g = gamma256[green]; b = gamma256[blue]; l = 16.0; ix1 = 0; for (i = 0; i < mem_cols; i++) { dr = r - gamma256[mem_pal[i].red]; dg = g - gamma256[mem_pal[i].green]; db = b - gamma256[mem_pal[i].blue]; tl = dr * dr + dg * dg + db * db; if (tl >= l) continue; l = tl; ix1 = i; } r1 = gamma256[mem_pal[ix1].red]; g1 = gamma256[mem_pal[ix1].green]; b1 = gamma256[mem_pal[ix1].blue]; dr0 = r - r1; dg0 = g - g1; db0 = b - b1; l2 = l; ix2 = ix1; pn = 0; for (i = 0; i < mem_cols; i++) { if (i == ix1) continue; dr = gamma256[mem_pal[i].red] - r1; dg = gamma256[mem_pal[i].green] - g1; db = gamma256[mem_pal[i].blue] - b1; t = pp2 * (dr0 * dr + dg0 * dg + db0 * db) / (dr * dr + dg * dg + db * db); if ((t <= dp) || (t >= pp2 - dp)) continue; t = (tpn = rint(0.5 * t)) / (double)(pp2 >> 1); dr = dr * t - dr0; dg = dg * t - dg0; db = db * t - db0; tl = dr * dr + dg * dg + db * db; if (tl >= l2) continue; l2 = tl; ix2 = i; pn = tpn; } mem_col_A = ix1; mem_col_B = ix2; /* !!! A mix with less than half of nearest color cannot be better than it, so * !!! patterns less dense than 50:50 won't be needed */ mem_tool_pat = -pn; /* pn*4 for 8x8 */ if (pattern_B) mem_tool_pat_B = pn - 16; /* pat**2 */ mem_col_A24 = mem_pal[mem_col_A]; mem_col_B24 = mem_pal[mem_col_B]; } int mem_quantize( unsigned char *old_mem_image, int target_cols, int type ) // type = 1:flat, 2:dither, 3:scatter { unsigned char *new_img = mem_img[CHN_IMAGE]; int i, j, k;//, res=0; int closest[3][2]; png_color pcol; j = mem_width * mem_height; progress_init(_("Converting to Indexed Palette"),1); for ( j=0; j= closest[1][0] ) if ( closest[1][1]*.67 < (closest[1][1] - closest[1][0]) ) k = closest[0][0]; else { if ( closest[0][0] > closest[0][1] ) k = closest[0][ (i+j) % 2 ]; else k = closest[0][ (i+j+1) % 2 ]; } } if ( type == 3 ) // Scattered { if ( (rand() % (closest[1][1] + closest[1][0])) <= closest[1][1] ) k = closest[0][0]; else k = closest[0][1]; } } } *new_img++ = k; } } progress_end(); return 0; } /* Linear brightness for palette color */ double pal2B(png_color *c) { return (rgb2B(gamma256[c->red], gamma256[c->green], gamma256[c->blue])); } /* Convert image to greyscale */ void mem_greyscale(int gcor) { unsigned char *mask, *img = mem_img[CHN_IMAGE]; int i, j, k, v, ch; mask = malloc(mem_width); if (!mask) { memory_errors(1); return; } if (mem_img_bpp == 1) { for (i = 0; i < 256; i++) { if (gcor) /* Gamma correction + Helmholtz-Kohlrausch effect */ { v = UNGAMMA256(pal2B(mem_pal + i)); } else /* Usual braindead formula */ { v = (299 * mem_pal[i].red + 587 * mem_pal[i].green + 114 * mem_pal[i].blue + 500) / 1000; } mem_pal[i].red = v; mem_pal[i].green = v; mem_pal[i].blue = v; } } else { ch = mem_channel; mem_channel = CHN_IMAGE; for (i = 0; i < mem_height; i++) { row_protected(0, i, mem_width, mask); for (j = 0; j < mem_width; j++) if (paint_gamma && mask[j] && (mask[j] != 255)) { double d, d0, d1, d2, m; m = 1.0 - mask[j] / 255.0; d0 = gamma256[img[0]]; d1 = gamma256[img[1]]; d2 = gamma256[img[2]]; /* Gamma + H-K effect / Usual */ d = gcor ? rgb2B(d0, d1, d2) : gamma256[(299 * img[0] + 587 * img[1] + 114 * img[2] + 500) / 1000]; d0 += (d - d0) * m; d1 += (d - d1) * m; d2 += (d - d2) * m; *img++ = UNGAMMA256(d0); *img++ = UNGAMMA256(d1); *img++ = UNGAMMA256(d2); } else { /* Gamma + H-K effect / Usual */ v = gcor ? UNGAMMA256(rgb2B(gamma256[img[0]], gamma256[img[1]], gamma256[img[2]])) : (299 * img[0] + 587 * img[1] + 114 * img[2] + 500) / 1000; v *= 255 - mask[j]; k = *img * mask[j] + v; *img++ = (k + (k >> 8) + 1) >> 8; k = *img * mask[j] + v; *img++ = (k + (k >> 8) + 1) >> 8; k = *img * mask[j] + v; *img++ = (k + (k >> 8) + 1) >> 8; } } mem_channel = ch; } free(mask); } /* Valid for x=0..5, which is enough here */ #define MOD3(x) ((((x) * 5 + 1) >> 2) & 3) /* Nonclassical HSV: H is 0..6, S is 0..1, V is 0..255 */ void rgb2hsv(unsigned char *rgb, double *hsv) { int c0, c1, c2; if (!((rgb[0] ^ rgb[1]) | (rgb[0] ^ rgb[2]))) { hsv[0] = hsv[1] = 0.0; hsv[2] = rgb[0]; return; } c2 = rgb[2] < rgb[0] ? 1 : 0; if (rgb[c2] >= rgb[c2 + 1]) c2++; c0 = MOD3(c2 + 1); c1 = (c2 + c0) ^ 3; hsv[2] = rgb[c0] > rgb[c1] ? rgb[c0] : rgb[c1]; hsv[1] = hsv[2] - rgb[c2]; hsv[0] = c0 * 2 + 1 + (rgb[c1] - rgb[c0]) / hsv[1]; hsv[1] /= hsv[2]; } void hsv2rgb(unsigned char *rgb, double *hsv) { double h0, h1, h2; int i; h2 = hsv[2] * 2; h1 = h2 * (1.0 - hsv[1]); i = hsv[0]; h0 = (hsv[0] - i) * (h2 - h1); if (i & 1) h2 -= h0 , h0 += h2; else h0 += h1; i >>= 1; rgb[i] = ((int)h2 + 1) >> 1; rgb[MOD3(i + 1)] = ((int)h0 + 1) >> 1; rgb[MOD3(i + 2)] = ((int)h1 + 1) >> 1; } static double rgb_hsl(int t, png_color col) { double hsv[3]; unsigned char rgb[3] = {col.red, col.green, col.blue}; if (t == 2) return (0.299 * rgb[0] + 0.587 * rgb[1] + 0.114 * rgb[2]); rgb2hsv(rgb, hsv); return (hsv[t]); } void mem_pal_index_move( int c1, int c2 ) // Move index c1 to c2 and shuffle in between up/down { png_color temp; int i, j; if (c1 == c2) return; j = c1 < c2 ? 1 : -1; temp = mem_pal[c1]; for (i = c1; i != c2; i += j) mem_pal[i] = mem_pal[i + j]; mem_pal[c2] = temp; } void mem_canvas_index_move( int c1, int c2 ) // Similar to palette item move but reworks canvas pixels { unsigned char table[256]; int i; if (c1 == c2) return; for (i = 0; i < 256; i++) { table[i] = i + (i > c2) - (i > c1); } table[c1] = c2; table[c2] += (c1 > c2); // Remap transparent color if (mem_xpm_trans >= 0) mem_xpm_trans = table[mem_xpm_trans]; // Change pixel index to new palette if (mem_img_bpp == 1) do_xlate(table, mem_img[CHN_IMAGE], mem_width * mem_height); } void mem_pal_sort( int a, int i1, int i2, int rev ) // Sort colours in palette { int tab0[256], tab1[256], tmp, i, j; png_color old_pal[256]; unsigned char map[256]; double lxnA[3], lxn[3]; if ( i2 == i1 || i1>mem_cols || i2>mem_cols ) return; if ( i2 < i1 ) { i = i1; i1 = i2; i2 = i; } if (a == 4) get_lxn(lxnA, PNG_2_INT(mem_col_A24)); if (a == 9) mem_get_histogram(CHN_IMAGE); for (i = 0; i < 256; i++) tab0[i] = i; for (i = i1; i <= i2; i++) { switch (a) { /* Hue */ case 0: tab1[i] = rint(1024 * rgb_hsl(0, mem_pal[i])); break; /* Saturation */ case 1: tab1[i] = rint(1024 * rgb_hsl(1, mem_pal[i])); break; /* Luminance */ case 2: tab1[i] = rint(1024 * rgb_hsl(2, mem_pal[i])); break; /* Brightness */ case 3: tab1[i] = rint(1024 * pal2B(mem_pal + i)); break; /* Distance to A */ case 4: get_lxn(lxn, PNG_2_INT(mem_pal[i])); tab1[i] = rint(1024 * ((lxn[0] - lxnA[0]) * (lxn[0] - lxnA[0]) + (lxn[1] - lxnA[1]) * (lxn[1] - lxnA[1]) + (lxn[2] - lxnA[2]) * (lxn[2] - lxnA[2]))); break; /* Red */ case 5: tab1[i] = mem_pal[i].red; break; /* Green */ case 6: tab1[i] = mem_pal[i].green; break; /* Blue */ case 7: tab1[i] = mem_pal[i].blue; break; /* Projection on A->B */ case 8: tab1[i] = mem_pal[i].red * (mem_col_B24.red - mem_col_A24.red) + mem_pal[i].green * (mem_col_B24.green - mem_col_A24.green) + mem_pal[i].blue * (mem_col_B24.blue - mem_col_A24.blue); break; /* Frequency */ case 9: tab1[i] = mem_histogram[i]; break; } } rev = rev ? 1 : 0; for ( j=i2; j>i1; j-- ) // The venerable bubble sort for ( i=i1; i= 0) mem_xpm_trans = map[mem_xpm_trans]; if (mem_img_bpp != 1) return; // Adjust canvas pixels if in indexed palette mode do_xlate(map, mem_img[CHN_IMAGE], mem_width * mem_height); /* Modify A & B */ mem_col_A = map[mem_col_A]; mem_col_B = map[mem_col_B]; } void mem_invert() // Invert the palette { int i, j; png_color *col = mem_pal; unsigned char *img; if ((mem_channel == CHN_IMAGE) && (mem_img_bpp == 1)) { for ( i=0; i<256; i++ ) { col->red = 255 - col->red; col->green = 255 - col->green; col->blue = 255 - col->blue; col++; } } else { unsigned char *mask = calloc(1, mem_width); j = mem_width * mem_height; if (mem_channel == CHN_IMAGE) j *= 3; img = mem_img[mem_channel]; for (i = 0; i < j; i++) { *img++ ^= 255; } if (mask) { mask_merge(mem_undo_previous(mem_channel), mem_channel, mask); free(mask); } } } void mem_normalize() // Normalize contrast in image or palette { unsigned char map[256], *img = NULL; png_color *col; int i, uninit_(j), k, k0, k1; memset(map, 0, 256); if ((mem_channel == CHN_IMAGE) && (mem_img_bpp == 1)) { for (i = 0 , col = mem_pal; i < mem_cols; i++ , col++) { map[col->red] = 1; map[col->green] = 1; map[col->blue] = 1; } } else { j = mem_width * mem_height; if (mem_channel == CHN_IMAGE) j *= 3; img = mem_img[mem_channel]; for (i = 0; i < j; i++) map[img[i]] = 1; } /* Range */ for (i = 0; (i < 255) && !map[i]; i++); k0 = k1 = i; for (; i < 256; i++) if (map[i]) k1 = i; /* Table */ map[k0] = k0; // Default k = k1 - k0; if (k) for (i = k0; i <= k1; i++) map[i] = 255 * (i - k0) / k; if (img) { unsigned char *mask = calloc(1, mem_width); do_xlate(map, img, j); if (mask) { mask_merge(mem_undo_previous(mem_channel), mem_channel, mask); free(mask); } } else { for (i = 0 , col = mem_pal; i < mem_cols; i++ , col++) { col->red = map[col->red]; col->green = map[col->green]; col->blue = map[col->blue]; } } } void mem_prepare_map(unsigned char *map, int how) { int i, n, wrk[3]; memset(map, 0, 768); // Init /* Greyscale */ if (how == MAP_GREY) for (i = 0; i < 256; i++ , map += 3) map[0] = map[1] = map[2] = i; /* Gradient */ else if (how == MAP_GRAD) for (i = 0; i < 256; i++ , map += 3) { if (!grad_value(wrk, CHN_IMAGE, i / 255.0)) continue; map[0] = wrk[0] >> 8; map[1] = wrk[1] >> 8; map[2] = wrk[2] >> 8; } /* Palette */ else if (how == MAP_PAL) pal2rgb(map, mem_pal, mem_cols, 0); /* Clipboard */ else if (how == MAP_CLIP) { n = mem_clip_w * mem_clip_h; if (n > 256) n = 256; if (mem_clip_bpp == 3) memcpy(map, mem_clipboard, n * 3); else do_convert_rgb(0, 1, n, map, mem_clipboard, mem_pal); } } void mem_remap_rgb(unsigned char *map, int what) // Remap V/R/G/B to color { unsigned char *w, *img = mem_img[CHN_IMAGE]; int cnt = mem_width * mem_height; /* Value */ if (!what) while (cnt-- > 0) { int n = img[0] > img[1] ? img[0] : img[1]; n = n > img[2] ? n : img[2]; w = map + n * 3; *img++ = w[0]; *img++ = w[1]; *img++ = w[2]; } /* R/G/B */ else while (cnt-- > 0) { w = map + img[what - 1] * 3; *img++ = w[0]; *img++ = w[1]; *img++ = w[2]; } w = calloc(1, mem_width); if (w) { mask_merge(mem_undo_previous(CHN_IMAGE), CHN_IMAGE, w); free(w); } } /* Expand palette to RGB triples, pad with 0 if needed */ void pal2rgb(unsigned char *rgb, png_color *pal, int cnt, int len) { len -= cnt; while (cnt-- > 0) { rgb[0] = pal->red; rgb[1] = pal->green; rgb[2] = pal->blue; rgb += 3; pal++; } if (len > 0) memset(rgb, 0, len * 3); } /* Pack RGB triples into palette */ void rgb2pal(png_color *pal, unsigned char *rgb, int cnt) { while (cnt-- > 0) { pal->red = rgb[0]; pal->green = rgb[1]; pal->blue = rgb[2]; pal++; rgb += 3; } } /* !!! The rectangles here exclude bottom & right border */ int clip(int *rxy, int x0, int y0, int x1, int y1, const int *vxy) { rxy[0] = x0 < vxy[0] ? vxy[0] : x0; rxy[1] = y0 < vxy[1] ? vxy[1] : y0; rxy[2] = x1 > vxy[2] ? vxy[2] : x1; rxy[3] = y1 > vxy[3] ? vxy[3] : y1; return ((rxy[2] > rxy[0]) && (rxy[3] > rxy[1])); } /* Intersect outer & inner rectangle, write out 1 to 5 rectangles the outer one * separates into, return number of outer rectangles */ int clip4(int *rect04, int xo, int yo, int wo, int ho, int xi, int yi, int wi, int hi) { int *p = rect04 + 4; int xo1 = xo + wo, yo1 = yo + ho, xi1 = xi + wi, yi1 = yi + hi; // Whole outer rectangle p[0] = xo; p[1] = yo; p[2] = wo; p[3] = ho; // No intersection if ((xi >= xo1) || (yi >= yo1) || (xo >= xi1) || (yo >= yi1)) { rect04[0] = xi; rect04[1] = yi; rect04[2] = rect04[3] = 0; return (1); } if (yi > yo) // Top rectangle p[3] = yi - yo , p += 4; else yi = yo; if (yi1 < yo1) // Bottom rectangle *p++ = xo , *p++ = yi1 , *p++ = wo , *p++ = yo1 - yi1; else yi1 = yo1; hi = yi1 - yi; if (xi > xo) // Left rectangle *p++ = xo , *p++ = yi , *p++ = xi - xo , *p++ = hi; else xi = xo; if (xi1 < xo1) // Right rectangle *p++ = xi1 , *p++ = yi , *p++ = xo1 - xi1 , *p++ = hi; else xi1 = xo1; wi = xi1 - xi; // Clipped inner rectangle rect04[0] = xi; rect04[1] = yi; rect04[2] = wi; rect04[3] = hi; // Number of outer rectangles return ((p - rect04 - 4) >> 2); } int xy_span(int *rxy, int scale, int yf) { return (floor_div(rxy[2 + yf] - 1, scale) - floor_div(rxy[yf], scale) + 1); } void xy_origin(int *rxy, int *vxy, int x, int y) { rxy[0] = vxy[0] - x; rxy[1] = vxy[1] - y; rxy[2] = vxy[2] - x; rxy[3] = vxy[3] - y; } void line_init(linedata line, int x0, int y0, int x1, int y1) { int i; line[0] = x0; line[1] = y0; line[4] = (x1 - x0) * (line[6] = line[8] = x1 - x0 < 0 ? -1 : 1); line[5] = (y1 - y0) * (line[7] = line[9] = y1 - y0 < 0 ? -1 : 1); i = line[4] >= line[5]; /* More horizontal? */ line[2] = line[3] = line[5 - i]; line[4] = 2 * line[4 + i]; line[5] = 2 * line[2]; line[6 + i] = 0; } int line_step(linedata line) { line[3] -= line[4]; if (line[3] <= 0) { line[3] += line[5]; line[0] += line[8]; line[1] += line[9]; } else { line[0] += line[6]; line[1] += line[7]; } return (--line[2]); } void line_nudge(linedata line, int x, int y) { while ((line[0] != x) && (line[1] != y) && (line[2] >= 0)) line_step(line); } /* !!! The clipping rectangle here includes both borders */ int line_clip(linedata line, const int *vxy, int *step) { int vh = !line[6], hv = vh ^ 1, hs = line[8 + vh], vs = line[8 + hv]; int dh = hs < 0, dv = vs < 0, l4 = line[4], steps[2]; int i, j, dx, dy; for (i = 1; 1;) { dx = (vxy[(dh ^ i) * 2 + vh] - line[vh]) * hs + i; if (dx < 0) dx = 0; if (l4) { dy = (vxy[(dv ^ i) * 2 + hv] - line[hv]) * vs + i; if (dy < 0) dy = 0; dy = (line[5] * (dy - 1) + line[3] + l4 - 1) / l4; if ((dy > dx) ^ i) dx = dy; } steps[i] = dx; if (!i--) break; } if (line[5]) // Makes no sense for a single point { /* Too short? */ if ((line[2] -= dx) < 0) return (line[2]); dy = (j = l4 * dx + line[5] - line[3]) / line[5]; line[vh] += hs * dx; line[hv] += vs * dy; line[3] = line[5] * (dy + 1) - j; } /* Misses the rectangle? */ if ((line[0] < vxy[0]) || (line[0] > vxy[2]) || (line[1] < vxy[1]) || (line[1] > vxy[3])) return (line[2] = -1); *step = dx; j = steps[1] - dx - 1; if (j < line[2]) line[2] = j; return (line[2]); } void line_flip(linedata line) { int l, d2; if (!line[2]) return; // Single point l = line[4] * line[2] + line[5] - line[3]; d2 = l / line[5]; line[3] = l - d2 * line[5] + 1; line[0] += line[2] * line[6] + d2 * (line[8] - line[6]); line[1] += line[2] * line[7] + d2 * (line[9] - line[7]); line[6] *= -1; line[7] *= -1; line[8] *= -1; line[9] *= -1; } /* Produce a horizontal segment from two connected lines */ static void twoline_segment(int *xx, linedata line1, linedata line2) { xx[0] = xx[1] = line1[0]; while (TRUE) { if (!line1[7]) /* Segments longer than 1 pixel */ { while ((line1[2] > 0) && (line1[3] > line1[4])) line_step(line1); } if (xx[0] > line1[0]) xx[0] = line1[0]; if (xx[1] < line1[0]) xx[1] = line1[0]; if ((line1[2] > 0) || (line2[2] < 0)) break; memcpy(line1, line2, sizeof(linedata)); line2[2] = -1; if (xx[0] > line1[0]) xx[0] = line1[0]; if (xx[1] < line1[0]) xx[1] = line1[0]; } } void sline( int x1, int y1, int x2, int y2 ) // Draw single thickness straight line { linedata line; line_init(line, x1, y1, x2, y2); for (; line[2] >= 0; line_step(line)) { IF_IN_RANGE(line[0], line[1]) put_pixel(line[0], line[1]); } } void circle_line(int x0, int y0, int dx, int dy, int thick); void tline( int x1, int y1, int x2, int y2, int size ) // Draw size thickness straight line { linedata line; int xdo, ydo, todo; xdo = abs(x2 - x1); ydo = abs(y2 - y1); todo = xdo > ydo ? xdo : ydo; if (todo < 2) return; // The 1st and last points are done by calling procedure if (size < 2) /* One pixel wide */ { sline(x1, y1, x2, y2); return; } /* Draw middle segment */ circle_line(x1, y1, x2 - x1, y2 - y1, size); /* Add four more circles to cover all odd points */ if (!xdo || !ydo || (xdo == ydo)) return; /* Not needed */ line_init(line, x1, y1, x2, y2); line_nudge(line, x1 + line[8] - 2 * line[6], y1 + line[9] - 2 * line[7]); /* Jump to first diagonal step */ f_circle(line[0], line[1], size); f_circle(line[0] - line[8], line[1] - line[9], size); line_nudge(line, x2, y2); /* Jump to last diagonal step */ f_circle(line[0], line[1], size); f_circle(line[0] - line[8], line[1] - line[9], size); } /* Draw whatever is bounded by two pairs of lines */ void draw_quad(linedata line1, linedata line2, linedata line3, linedata line4) { int x1, x2, y1, xx[4]; for (; line1[2] >= 0; line_step(line1) , line_step(line3)) { y1 = line1[1]; twoline_segment(xx + 0, line1, line2); twoline_segment(xx + 2, line3, line4); if ((y1 < 0) || (y1 >= mem_height)) continue; if (xx[0] > xx[2]) xx[0] = xx[2]; if (xx[1] < xx[3]) xx[1] = xx[3]; x1 = xx[0] < 0 ? 0 : xx[0]; x2 = xx[1] >= mem_width ? mem_width - 1 : xx[1]; put_pixel_row(x1, y1, x2 - x1 + 1, NULL); } } /* Draw general parallelogram */ void g_para( int x1, int y1, int x2, int y2, int xv, int yv ) { linedata line1, line2, line3, line4; int i, j, x[2] = {x1, x2}, y[2] = {y1, y2}; j = (y1 < y2) ^ (yv < 0); i = j ^ 1; line_init(line1, x[i], y[i], x[i] + xv, y[i] + yv); line_init(line2, x[i] + xv, y[i] + yv, x[j] + xv, y[j] + yv); line_init(line3, x[i], y[i], x[j], y[j]); line_init(line4, x[j], y[j], x[j] + xv, y[j] + yv); draw_quad(line1, line2, line3, line4); } /* Shapeburst engine */ int sb_dist = DIST_L1; int sb_rect[4]; static void *sb_mem; static unsigned short *sb_buf; static uint32_t *sb_buf2; static void put_pixel_sb(int x, int y) { int j, x1, y1; x1 = x - sb_rect[0]; y1 = y - sb_rect[1]; if ((x1 < 0) || (x1 >= sb_rect[2]) || (y1 < 0) || (y1 >= sb_rect[3])) return; j = pixel_protected(x, y); if (IS_INDEXED ? j : j == 255) return; if (!sb_buf2) sb_buf[y1 * sb_rect[2] + x1] = 0xFFFF; else sb_buf2[y1 * sb_rect[2] + x1] = 0xFFFF; } static void mask_select(unsigned char *mask, unsigned char *xsel, int l); static void put_pixel_row_sb(int x, int y, int len, unsigned char *xsel) { unsigned char mask[ROW_BUFLEN]; int x1, y1, sb_ofs, offset, use_mask, masked; if ((len <= 0) || (x + len <= sb_rect[0])) return; x1 = x - sb_rect[0]; y1 = y - sb_rect[1]; if ((x1 >= sb_rect[2]) || (y1 < 0) || (y1 >= sb_rect[3])) return; if (x1 + len > sb_rect[2]) len = sb_rect[2] - x1; // Clip right side if (x1 < 0) x -= x1 , len += x1 , xsel -= x1 , x1 = 0; // Clip left side sb_ofs = y1 * sb_rect[2] + x1; offset = x + mem_width * y; masked = IS_INDEXED ? 1 : 255; use_mask = (mem_channel <= CHN_ALPHA) && mem_img[CHN_MASK] && !channel_dis[CHN_MASK]; while (TRUE) { int i, l = len <= ROW_BUFLEN ? len : ROW_BUFLEN; prep_mask(0, 1, l, mask, use_mask ? mem_img[CHN_MASK] + offset : NULL, mem_img[CHN_IMAGE] + offset * mem_img_bpp); if (xsel) { mask_select(mask, xsel, l); xsel += l; } for (i = 0; i < l; i++) { if (mask[i] >= masked) continue; if (!sb_buf2) sb_buf[sb_ofs + i] = 0xFFFF; else sb_buf2[sb_ofs + i] = 0xFFFF; } if (!(len -= l)) return; sb_ofs += l; offset += l; } } /* Distance transform of binary image map, using L1 or Linf distance metric */ static int shapeburst() { unsigned short *r0, *dmap = sb_buf; int i, j, k, l, dx, dy, maxd = 0, w = sb_rect[2], h = sb_rect[3]; /* Calculate distance */ r0 = dmap; dx = 1; dy = w; /* Forward pass */ while (TRUE) { /* First row */ for (i = 0; i < w; i++ , r0 += dx) if (*r0) *r0 = 1; /* Other rows */ for (j = 1; j < h; j++) { /* 1st pixel */ if (*r0) *r0 = 1; r0 += dx; /* Other pixels */ for (i = w - 1; i > 0; i-- , r0 += dx) { /* L1 */ k = *(r0 - dx); l = *(r0 - dy); if (k > l) k = l; if (*r0 > k) *r0 = k + 1; if (sb_dist != DIST_LINF) continue; /* Linf */ k = *(r0 - dy - dx); l = *(r0 - dy + dx); if (k > l) k = l; if (*r0 > k) *r0 = k + 1; } } if (dx < 0) break; /* Both passes done */ r0 = dmap + w * h - 1; dx = -1; dy = -w; /* Backward pass */ } /* Find largest */ r0 = dmap; for (k = w * h; k; k-- , r0++) if (maxd < *r0) maxd = *r0; return (maxd); } /* Meijster algorithm for squared Euclidean distance transform */ typedef struct { int x, e, v, w; } par_data; static void dist_pass1(int w, int h, uint32_t *dmap) { uint32_t m, *r0; int i, j, dy; /* Calculate distance by column */ r0 = dmap; dy = w; /* Forward pass */ while (TRUE) { /* First row */ for (i = 0; i < w; i++) if (r0[i]) r0[i] = 1; /* Other rows */ for (j = 1; j < h; j++) { r0 += dy; for (i = 0; i < w; i++) { m = r0[i - dy]; if (r0[i] > m) r0[i] = m + 1; } } if (dy < 0) return; /* Both passes done */ dy = -dy; /* Backward pass */ } } static int dist_pass2_e2(int w, int h, uint32_t *dmap, par_data *pb) { par_data *pn; int x, y, mx = 0; for (y = 0; y < h; y++ , dmap += w) { /* Left border */ pn = pb; pn->x = -1; pn->e = pn->v = 0; pn->w = 1; /* v + x^2 */ /* Find envelope */ for (x = 0; ; x++) { int k = 0, v2 = 0; if (x < w) v2 = dmap[x] * dmap[x]; else if (x > w) break; while (((x - pn->e) * (x - pn->e) + v2) < pn->w) if (--pn - pb < 0) break; if (pn - pb >= 0) /* Find intersection */ { /* 1 + Sep(s[q], u) */ k = (x * x + v2 - pn->x * pn->x - pn->v) / ((x - pn->x) * 2) + 1; if (k >= w) continue; // Not inside } /* Add a segment */ pn++; pn->x = x; pn->v = v2; pn->e = k; pn->w = (x - k) * (x - k) + v2; } /* Fill up squared distances */ // !!! Also possible to run left to right, by using _next_ slot's "e" // (only then need one extra slot allocated, and set pn[1].e=w every time) // (but then, may loop to e, and only then check if this e >= w) for (x = w - 1; x >= 0; x--) { int l = pn->v + (x - pn->x) * (x - pn->x); if (mx < l) mx = l; // Finding the max dmap[x] = l; if (x == pn->e) pn--; } } return (mx); } /* Euclidean (L2 metric) distance transform of binary image map */ static int shapeburst_m() { int maxd, w = sb_rect[2], h = sb_rect[3]; dist_pass1(w, h, sb_buf2); maxd = dist_pass2_e2(w, h, sb_buf2, sb_mem); return (ceil(sqrt(maxd))); } int init_sb() { int l = sb_rect[2] + 3, wh = sb_rect[2] * sb_rect[3]; if (sb_dist != DIST_L2) /* Use simple distance algorithm */ sb_mem = sb_buf = calloc(wh, sizeof(unsigned short)); /* Use squared Euclidean distance */ else if ((sb_mem = calloc(1, l * sizeof(par_data) + wh * sizeof(uint32_t)))) { /* Pointer to uint32 array */ sb_buf2 = (void *)((par_data *)sb_mem + l); } if (!sb_mem) { memory_errors(1); return (FALSE); } put_pixel = put_pixel_sb; put_pixel_row = put_pixel_row_sb; return (TRUE); } /* Mask, if present, must be sb_rect[] sized */ void render_sb(unsigned char *mask) { grad_info svgrad, *grad = gradient + mem_channel; int i, maxd; if (!sb_mem) return; /* Uninitialized */ put_pixel = put_pixel_def; put_pixel_row = put_pixel_row_def; maxd = sb_dist != DIST_L2 ? shapeburst() : shapeburst_m(); if (maxd) /* Have something to draw */ { svgrad = *grad; grad->gmode = GRAD_MODE_BURST; if (!grad->len) grad->len = maxd - (maxd > 1); grad_update(grad); for (i = 0; i < sb_rect[3]; i++) put_pixel_row(sb_rect[0], sb_rect[1] + i, sb_rect[2], mask ? mask + sb_rect[2] * i : NULL); *grad = svgrad; } free(sb_mem); sb_buf2 = sb_mem = sb_buf = NULL; } /* * This flood fill algorithm processes image in quadtree order, and thus has * guaranteed upper bound on memory consumption, of order O(width + height). * This implementation takes O(max(width, height)) for simplicity - X and Y * bitmaps are interleaved. * (C) Dmitry Groshev */ #define QLEVELS 11 #define QMINSIZE 32 #define QMINLEVEL 5 /* * Level bitmaps are ordered from nearest to farthest, with cells interleaved * in the following order: Left-Y Right-Y Top-X Bottom-X. * Pixel bitmap is packed by Y, not by X: byte[x, y / 8] |= 1 << (y % 8) */ static int wjfloodfill(int x, int y, int col, unsigned char *bmap) { short nearq[QMINSIZE * QMINSIZE * 2]; /* QMINSIZE bits per cell */ guint32 tmap, lmap[(MAX_DIM >> QMINLEVEL) * 12 + QLEVELS * 4], maps[4]; int borders[4] = {0, mem_width, 0, mem_height}; int corners[4], coords[4], slots[4]; int i, j, k, tx, ty, fmode = 0, imgc = 0, lastr[3], thisr[3]; int lmax, ntail, bidx = 0, bbit = 0; double lastc[3], thisc[3], dist2, mdist2 = flood_step * flood_step; csel_info *flood_data = NULL; char *tmp = NULL; /* Init */ if ((x < 0) || (x >= mem_width) || (y < 0) || (y >= mem_height) || (get_pixel(x, y) != col) || (pixel_protected(x, y) == 255)) return (FALSE); /* Exact limits are less, but it's too complicated */ lmax = mem_width > mem_height ? mem_width : mem_height; lmax = (lmax >> QMINLEVEL) * 12 + QLEVELS * 4; memset(lmap, 0, lmax * sizeof(*lmap)); /* Start drawing */ if (bmap) bmap[(y >> 3) * mem_width + x] |= 1 << (y & 7); else { put_pixel(x, y); if (get_pixel(x, y) == col) return (FALSE); /* Can't draw */ } /* Configure fuzzy flood fill */ if (flood_step && ((mem_channel == CHN_IMAGE) || flood_img)) { if (flood_slide) fmode = flood_cube ? 2 : 3; else flood_data = ALIGN(tmp = calloc(1, sizeof(csel_info) + sizeof(double))); if (flood_data) { flood_data->center = get_pixel_RGB(x, y); flood_data->range = flood_step; flood_data->mode = flood_cube ? 2 : 0; /* !!! Alpha isn't tested yet !!! */ csel_reset(flood_data); fmode = 1; } } /* Configure by-image flood fill */ else if (!flood_step && flood_img && (mem_channel != CHN_IMAGE)) { imgc = get_pixel_img(x, y); fmode = -1; } /* Set up initial area */ corners[0] = x & ~(QMINSIZE - 1); corners[2] = y & ~(QMINSIZE - 1); nearq[0] = x; nearq[1] = y; ntail = 2; while (1) { corners[1] = corners[0] + QMINSIZE; corners[3] = corners[2] + QMINSIZE; for (i = 0; i < 4; i++) { int j, k, i2 = (i >> 1) ^ 1; int wx = corners[i2 + i2], wy = corners[i]; /* Locate map slots */ j = ((unsigned)(wy & ~(wy - 1)) - 1) >> QMINLEVEL; // Level mask j += j; k = (wx >> QMINLEVEL) & (j + 1); slots[i] = k = (j + k) * 4 + i; /* Prefill near queue */ if (k >= lmax) continue; // Outside image k ^= 1; tmap = lmap[k]; lmap[k] = 0; for (wy -= i & 1; tmap; wx++ , tmap >>= 1) { if (!(tmap & 1)) continue; nearq[ntail++ + i2] = wx; nearq[ntail++ - i2] = wy; } } /* Clear the side bitmaps */ maps[0] = maps[1] = maps[2] = maps[3] = 0; // memset(maps, 0, sizeof(maps)); /* Process near points */ while (ntail) { /* Unqueue last x & y */ coords[2] = y = nearq[--ntail]; coords[0] = x = nearq[--ntail]; if (fmode > 1) { k = get_pixel_RGB(x, y); if (fmode == 3) get_lxn(lastc, k); else { lastr[0] = INT_2_R(k); lastr[1] = INT_2_G(k); lastr[2] = INT_2_B(k); } } for (i = 0; i < 4; i++) { coords[1] = x; coords[3] = y; coords[(i & 2) + 1] += ((i + i) & 2) - 1; /* Is pixel valid? */ if (coords[i] == borders[i]) continue; tx = coords[1]; ty = coords[3]; if (bmap) { bidx = (ty >> 3) * mem_width + tx; bbit = 1 << (ty & 7); if (bmap[bidx] & bbit) continue; } /* Sliding mode */ switch (fmode) { case 3: /* Sliding L*X*N* */ get_lxn(thisc, get_pixel_RGB(tx, ty)); dist2 = (thisc[0] - lastc[0]) * (thisc[0] - lastc[0]) + (thisc[1] - lastc[1]) * (thisc[1] - lastc[1]) + (thisc[2] - lastc[2]) * (thisc[2] - lastc[2]); if (dist2 > mdist2) continue; break; case 2: /* Sliding RGB */ k = get_pixel_RGB(tx, ty); thisr[0] = INT_2_R(k); thisr[1] = INT_2_G(k); thisr[2] = INT_2_B(k); if ((abs(thisr[0] - lastr[0]) > flood_step) || (abs(thisr[1] - lastr[1]) > flood_step) || (abs(thisr[2] - lastr[2]) > flood_step)) continue; break; case 1: /* Centered mode */ if (!csel_scan(ty * mem_width + tx, 1, 1, NULL, mem_img[CHN_IMAGE], flood_data)) continue; break; case 0: /* Normal mode */ if (get_pixel(tx, ty) != col) continue; break; default: /* (-1) - By-image mode */ if (get_pixel_img(tx, ty) != imgc) continue; break; } /* Is pixel writable? */ if (bmap) { if (pixel_protected(tx, ty) == 255) continue; bmap[bidx] |= bbit; } else { put_pixel(tx, ty); if (get_pixel(tx, ty) == col) continue; } /* Near queue */ // if (coords[i] != corners[i]) if (coords[i] & (QMINSIZE - 1)) { nearq[ntail++] = tx; nearq[ntail++] = ty; continue; } /* Far map */ j = coords[(i & 2) ^ 3] & (QMINSIZE - 1); maps[i] |= 1U << j; } } /* Store maps */ for (i = 0; i < 4; i++) { /* !!! Condition prevents out-of-bounds access */ if (maps[i]) lmap[slots[i]] |= maps[i]; } /* Find what else remains */ for (i = 0; (i < lmax) && !lmap[i]; i++); if (i >= lmax) break; // All done /* Determine where that happens to be */ j = ((i >> 2) + 2) << QMINLEVEL; k = nextpow2(j) >> 1; // MSB x = (k >> 1) + ((i & 1) << QMINLEVEL) - QMINSIZE; y = j - k; i &= 2; corners[i] = (corners[i] & ~(k - 1)) + x; i ^= 2; corners[i] = (corners[i] & ~(k - 1)) + y; } free(tmp); return (TRUE); } /* Determine Y-packed bitmap boundaries */ static int bitmap_bounds(int *rect, unsigned char *pat) { unsigned char u, c, buf[MAX_WIDTH]; int n, x, y, y0, y1, w = rect[2], h = (rect[3] + 7) >> 3; /* Scan */ memset(buf, 0, w); for (y0 = y1 = y = 0; y < h; y++) { for (u = x = 0; x < w; x++) u |= c = *pat++ , buf[x] |= c; if (!u) continue; y1 = (y << 8) + u; if (!y0) y0 = y1; } if (!y0) return (0); // Empty /* Analyze */ for (y = (y0 >> 8) * 8; !(y0 & 1); y++ , y0 >>= 1); rect[1] += n = y; for (y = (y1 >> 8) * 8 + 7; !(y1 & 0x80); y-- , y1 <<= 1); rect[3] = y -= n - 1; // h for (x = 0; !buf[x]; x++); rect[0] += n = x; for (x = w - 1; !buf[x]; x--); rect[2] = x -= n - 1; // w return (x * y); } /* Try drawing on a pixel */ int try_pixel(int x, int y) { unsigned char uninit_(ab), ib[3], *img, *uninit_(alpha); int res, bpp = MEM_BPP, ofs = x + mem_width * y, op = mem_undo_opacity; img = mem_img[mem_channel] + ofs * bpp; memcpy(ib, img, bpp); if (mem_img[CHN_ALPHA]) ab = *(alpha = mem_img[CHN_ALPHA] + ofs); mem_undo_opacity = FALSE; // No prepared undo frame put_pixel_def(x, y); mem_undo_opacity = op; res = memcmp(ib, img, bpp); memcpy(img, ib, bpp); if (mem_img[CHN_ALPHA]) { res |= *alpha ^ ab; *alpha = ab; } return (res); } /* Flood fill - may use temporary area (1 bit per pixel) */ int flood_fill(int x, int y, unsigned int target) { unsigned char *pat, *buf, *temp; int i, j, l, sb, res = FALSE; /* Regular fill? */ if (!mem_gradient && !(mem_blend && blend_src) && !mem_tool_pat && !flood_step && (!flood_img || (mem_channel == CHN_IMAGE))) { /* Try modifying the first pixel */ if (!try_pixel(x, y)) return (FALSE); spot_undo(UNDO_TOOL); return (wjfloodfill(x, y, target, NULL)); } /* Patterned or fuzzy fill - use bitmap */ buf = calloc((mem_height + 7 + 8) >> 3, mem_width); if (!buf) { memory_errors(1); return (FALSE); } pat = buf + mem_width; while (wjfloodfill(x, y, target, pat)) { /* Shapeburst - setup rendering backbuffer */ sb = STROKE_GRADIENT; if (sb) { sb_rect[0] = sb_rect[1] = 0; sb_rect[2] = mem_width; sb_rect[3] = mem_height; l = bitmap_bounds(sb_rect, pat); if (!l) break; /* Nothing to draw */ if (!init_sb()) break; /* Not enough memory */ } res = TRUE; spot_undo(UNDO_TOOL); for (i = 0; i < mem_height; i++) { unsigned u, f = 1 << (i & 7); temp = pat + (i >> 3) * mem_width; for (u = j = 0; j < mem_width; j++) u |= buf[j] = (0x10000 - (temp[j] & f)) >> 8; if (!u) continue; // Avoid wasting time on empty rows put_pixel_row(0, i, mem_width, buf); } if (sb) render_sb(NULL); /* Finalize */ break; } free(buf); return (res); } void f_rectangle(int x, int y, int w, int h) // Draw a filled rectangle { w += x; h += y; if (x < 0) x = 0; if (y < 0) y = 0; if (w > mem_width) w = mem_width; if (h > mem_height) h = mem_height; w -= x; /* !!! Test is oversimplified and is overkill, see rec_continuous() */ if ((tool_type == TOOL_CLONE) && (clone_dy < 0)) { while (--h >= y) put_pixel_row(x, h, w, NULL); return; } for (; y < h; y++) put_pixel_row(x, y, w, NULL); } /* * This code uses midpoint ellipse algorithm modified for uncentered ellipses, * with floating-point arithmetics to prevent overflows. (C) Dmitry Groshev */ static void trace_ellipse(int w, int h, int *left, int *right) { int dx, dy; double err, stx, sty, w2, h2; if (left[0] > w) left[0] = w; if (right[0] < w) right[0] = w; if (h <= 1) return; /* Too small */ h2 = h * h; w2 = w * w; dx = w & 1; dy = h; stx = h2 * dx; sty = w2 * dy; err = h2 * (dx * 5 + 4) + w2 * (1 - h - h); while (1) /* Have to force first step */ { if (left[dy >> 1] > dx) left[dy >> 1] = dx; if (right[dy >> 1] < dx) right[dy >> 1] = dx; if (err >= 0.0) { dy -= 2; sty -= w2 + w2; err -= 4.0 * sty; } dx += 2; stx += h2 + h2; err += 4.0 * (h2 + stx); if ((dy < 2) || (stx >= sty)) break; } err += 3.0 * (w2 - h2) - 2.0 * (stx + sty); while (dy > 1) { if (left[dy >> 1] > dx) left[dy >> 1] = dx; if (right[dy >> 1] < dx) right[dy >> 1] = dx; if (err < 0.0) { dx += 2; stx += h2 + h2; err += 4.0 * stx; } dy -= 2; sty -= w2 + w2; err += 4.0 * (w2 - sty); } /* For too-flat ellipses */ if (left[1] > dx) left[1] = dx; if (right[1] < w - 2) right[1] = w - 2; } static void wjellipse(int xs, int ys, int w, int h, int type, int thick) { int i, j, k, dx0, dx1, dy, *left, *right; /* Prepare */ ys += ys + --h; xs += xs + --w; k = type ? w + 1 : w & 1; j = h / 2 + 1; left = malloc(2 * j * sizeof(int)); if (!left) return; right = left + j; for (i = 0; i < j; i++) { left[i] = k; right[i] = 0; } /* Plot outer */ trace_ellipse(w, h, left, right); /* Plot inner */ if (type && (thick > 1)) { int i, j, k; /* Determine possible height */ thick += thick - 2; for (i = h; i >= 0; i -= 2) { if (left[i >> 1] > thick + 1) break; } i = i >= h - thick ? h - thick : i + 2; /* Determine possible width */ j = left[thick >> 1]; if (j > w - thick) j = w - thick; if (j < 2) i = h & 1; /* Do the plotting */ for (k = i >> 1; k <= h >> 1; k++) left[k] = w & 1; if (i > 1) trace_ellipse(j, i, left, right); } /* Draw result */ for (dy = h & 1; dy <= h; dy += 2) { int y0 = ys - dy, y1 = ys + dy; if (y1 < 0) continue; if (y0 < 0) y0 = y1; y0 >>= 1; y1 >>= 1; if (y0 >= mem_height) continue; dx0 = right[dy >> 1]; dx1 = left[dy >> 1]; if (dx1 <= 1) dx1 = -dx0; // Merge two spans while (TRUE) { int x0 = xs - dx0, x1 = xs - dx1; if ((x1 >= 0) && (x0 < mem_width * 2)) { x0 >>= 1; x1 >>= 1; if (x0 < 0) x0 = 0; if (++x1 > mem_width) x1 = mem_width; x1 -= x0; put_pixel_row(x0, y0, x1, NULL); if (y1 != y0) put_pixel_row(x0, y1, x1, NULL); } if (dx1 <= 0) break; x1 = -dx0; dx0 = -dx1; dx1 = x1; } } free(left); } /* Thickness 0 means filled */ void mem_ellipse(int x1, int y1, int x2, int y2, int thick) { int xs, ys, xl, yl, sb = FALSE; xs = x1 < x2 ? x1 : x2; ys = y1 < y2 ? y1 : y2; xl = abs(x2 - x1) + 1; yl = abs(y2 - y1) + 1; /* Shapeburst mode */ if (STROKE_GRADIENT) { sb_rect[0] = xs; sb_rect[1] = ys; sb_rect[2] = xl; sb_rect[3] = yl; sb = init_sb(); } /* Draw rectangle instead if too small */ if ((xl <= 2) || (yl <= 2)) f_rectangle(xs, ys, xl, yl); else wjellipse(xs, ys, xl, yl, thick && (thick * 2 < xl) && (thick * 2 < yl), thick); if (sb) render_sb(NULL); } static int circ_r, circ_trace[128]; static void retrace_circle(int r) { int sz, left[128]; circ_r = r--; sz = ((r >> 1) + 1) * sizeof(int); memset(left, 0, sz); memset(circ_trace, 0, sz); trace_ellipse(r, r, left, circ_trace); } void f_circle( int x, int y, int r ) // Draw a filled circle { int i, x0, x1, y0, y1, r1 = r - 1, half = r1 & 1; /* Prepare & cache circle contour */ if (circ_r != r) retrace_circle(r); /* Draw result */ for (i = half; i <= r1; i += 2) { y0 = y - ((i + half) >> 1); y1 = y + ((i - half) >> 1); if ((y0 >= mem_height) || (y1 < 0)) continue; x0 = x - ((circ_trace[i >> 1] + half) >> 1); x1 = x + ((circ_trace[i >> 1] - half) >> 1) + 1; if (x0 < 0) x0 = 0; if (x1 > mem_width) x1 = mem_width; x1 -= x0; if (y0 >= 0) put_pixel_row(x0, y0, x1, NULL); if ((y1 != y0) && (y1 < mem_height)) put_pixel_row(x0, y1, x1, NULL); } } static int find_tangent(int dx, int dy) { int i, j = 0, yy = (circ_r + 1) & 1, d, dist = 0; dx = abs(dx); dy = abs(dy); for (i = 0; i < (circ_r + 1) >> 1; i++) { d = (i + i + yy) * dy + circ_trace[i] * dx; if (d < dist) continue; dist = d; j = i; } return (j); } /* Draw line as if traced by circle brush */ void circle_line(int x0, int y0, int dx, int dy, int thick) { int n, ix, iy, xx[2], yy[2], dt = (thick + 1) & 1; if (circ_r != thick) retrace_circle(thick); n = find_tangent(dx, dy); ix = dx >= 0 ? 0 : 1; iy = dy >= 0 ? 0 : 1; xx[ix] = x0 - n - dt; xx[ix ^ 1] = x0 + n; yy[iy] = y0 + ((circ_trace[n] - dt) >> 1); yy[iy ^ 1] = y0 - ((circ_trace[n] + dt) >> 1); g_para(xx[0], yy[0], xx[1], yy[1], dx, dy); } void mem_flip_v(char *mem, char *tmp, int w, int h, int bpp) { unsigned char *src, *dest; int i, k; k = w * bpp; src = mem; dest = mem + (h - 1) * k; h /= 2; for (i = 0; i < h; i++) { memcpy(tmp, src, k); memcpy(src, dest, k); memcpy(dest, tmp, k); src += k; dest -= k; } } void mem_flip_h( char *mem, int w, int h, int bpp ) { unsigned char tmp, *src, *dest; int i, j, k; k = w * bpp; w /= 2; for (i = 0; i < h; i++) { src = mem + i * k; dest = src + k - bpp; if (bpp == 1) { for (j = 0; j < w; j++) { tmp = *src; *src++ = *dest; *dest-- = tmp; } } else { for (j = 0; j < w; j++) { tmp = src[0]; src[0] = dest[0]; dest[0] = tmp; tmp = src[1]; src[1] = dest[1]; dest[1] = tmp; tmp = src[2]; src[2] = dest[2]; dest[2] = tmp; src += 3; dest -= 3; } } } } void mem_bacteria( int val ) // Apply bacteria effect val times the canvas area { // Ode to 1994 and my Acorn A3000 int i, j, x, y, w = mem_width-2, h = mem_height-2, tot = w*h, np, cancel; unsigned int pixy; unsigned char *img; while ( tot > PROGRESS_LIM ) // Ensure the user gets a regular opportunity to cancel { tot /= 2; val *= 2; } cancel = (w * h * val > PROGRESS_LIM); if (cancel) progress_init(_("Bacteria Effect"), 1); for ( i=0; i= val - 20)) if (progress_update((float)i / val)) break; for ( j=0; j PROGRESS_LIM * 4); j = old_w * bpp; l = dir ? -bpp : bpp; k = -old_w * l; old += dir ? j - bpp: (old_h - 1) * j; if (flag) progress_init(_("Rotating"), 1); for (i = 0; i < old_w; i++) { if (flag && ((i * 5) % old_w >= old_w - 5)) progress_update((float)i / old_w); src = old; if (bpp == 1) { for (j = 0; j < old_h; j++) { *new++ = *src; src += k; } } else { for (j = 0; j < old_h; j++) { *new++ = src[0]; *new++ = src[1]; *new++ = src[2]; src += k; } } old += l; } if (flag) progress_end(); } int mem_sel_rot( int dir ) // Rotate clipboard 90 degrees { unsigned char *buf = NULL; int i, j = mem_clip_w * mem_clip_h, bpp = mem_clip_bpp; for (i = 0; i < NUM_CHANNELS; i++ , bpp = 1) { if (!mem_clip.img[i]) continue; buf = malloc(j * bpp); if (!buf) break; // Not enough memory mem_rotate(buf, mem_clip.img[i], mem_clip_w, mem_clip_h, dir, bpp); free(mem_clip.img[i]); mem_clip.img[i] = buf; } /* Don't leave a mix of rotated and unrotated channels */ if (!buf && i) mem_free_image(&mem_clip, FREE_ALL); if (!buf) return (1); i = mem_clip_w; mem_clip_w = mem_clip_h; // Flip geometry mem_clip_h = i; return (0); } /* Clear the channels */ static void mem_clear_img(chanlist img, int w, int h, int bpp) { int i, j, k, l = w * h; if (!img[CHN_IMAGE]); // !!! Here, image channel CAN be absent else if (bpp == 3) { unsigned char *tmp = img[CHN_IMAGE]; tmp[0] = mem_col_A24.red; tmp[1] = mem_col_A24.green; tmp[2] = mem_col_A24.blue; j = l * 3; for (i = 3; i < j; i++) tmp[i] = tmp[i - 3]; } else memset(img[CHN_IMAGE], mem_col_A, l); for (k = CHN_IMAGE + 1; k < NUM_CHANNELS; k++) if (img[k]) memset(img[k], 0, l); } void mem_rotate_free_real(chanlist old_img, chanlist new_img, int ow, int oh, int nw, int nh, int bpp, double angle, int mode, int gcor, int dis_a, int silent) { unsigned char *src, *dest, *alpha, A_rgb[3]; unsigned char *pix1, *pix2, *pix3, *pix4; int nx, ny, ox, oy, cc; double rangle = (M_PI / 180.0) * angle; // Radians double s1, s2, c1, c2; // Trig values double cx0, cy0, cx1, cy1; double x00, y00, x0y, y0y; // Quick look up values double fox, foy, k1, k2, k3, k4; // Pixel weights double aa1, aa2, aa3, aa4, aa; double rr, gg, bb; double tw, th, ta, ca, sa, sca, csa, Y00, Y0h, Yw0, Ywh, X00, Xwh; c2 = cos(rangle); s2 = sin(rangle); c1 = -s2; s1 = c2; /* Centerpoints, including half-pixel offsets */ cx0 = (ow - 1) / 2.0; cy0 = (oh - 1) / 2.0; cx1 = (nw - 1) / 2.0; cy1 = (nh - 1) / 2.0; x00 = cx0 - cx1 * s1 - cy1 * s2; y00 = cy0 - cx1 * c1 - cy1 * c2; A_rgb[0] = mem_col_A24.red; A_rgb[1] = mem_col_A24.green; A_rgb[2] = mem_col_A24.blue; /* Prepare clipping rectangle */ tw = 0.5 * (ow + (mode ? 1 : 0)); th = 0.5 * (oh + (mode ? 1 : 0)); ta = M_PI * (angle / 180.0 - floor(angle / 180.0)); ca = cos(ta); sa = sin(ta); sca = ca ? sa / ca : 0.0; csa = sa ? ca / sa : 0.0; Y00 = cy1 - th * ca - tw * sa; Y0h = cy1 + th * ca - tw * sa; Yw0 = cy1 - th * ca + tw * sa; Ywh = cy1 + th * ca + tw * sa; X00 = cx1 - tw * ca + th * sa; Xwh = cx1 + tw * ca - th * sa; mem_clear_img(new_img, nw, nh, bpp); /* Clear the channels */ for (ny = 0; ny < nh; ny++) { int xl, xm; if (!silent && ((ny * 10) % nh >= nh - 10)) progress_update((float)ny / nh); /* Clip this row */ if (ny < Y0h) xl = ceil(X00 + (Y00 - ny) * sca); else if (ny < Ywh) xl = ceil(Xwh + (ny - Ywh) * csa); else /* if (ny < Yw0) */ xl = ceil(Xwh + (Ywh - ny) * sca); if (ny < Y00) xm = ceil(X00 + (Y00 - ny) * sca); else if (ny < Yw0) xm = ceil(X00 + (ny - Y00) * csa); else /* if (ny < Ywh) */ xm = ceil(Xwh + (Ywh - ny) * sca); if (xl < 0) xl = 0; if (--xm >= nw) xm = nw - 1; x0y = ny * s2 + x00; y0y = ny * c2 + y00; for (cc = 0; cc < NUM_CHANNELS; cc++) { if (!new_img[cc]) continue; /* RGB nearest neighbour */ if (!mode && (cc == CHN_IMAGE) && (bpp == 3)) { dest = new_img[CHN_IMAGE] + (ny * nw + xl) * 3; for (nx = xl; nx <= xm; nx++ , dest += 3) { WJ_ROUND(ox, nx * s1 + x0y); WJ_ROUND(oy, nx * c1 + y0y); src = old_img[CHN_IMAGE] + (oy * ow + ox) * 3; dest[0] = src[0]; dest[1] = src[1]; dest[2] = src[2]; } continue; } /* One-bpp nearest neighbour */ if (!mode) { dest = new_img[cc] + ny * nw + xl; for (nx = xl; nx <= xm; nx++) { WJ_ROUND(ox, nx * s1 + x0y); WJ_ROUND(oy, nx * c1 + y0y); *dest++ = old_img[cc][oy * ow + ox]; } continue; } /* RGB/RGBA bilinear */ if (cc == CHN_IMAGE) { alpha = NULL; if (new_img[CHN_ALPHA] && !dis_a) alpha = new_img[CHN_ALPHA] + ny * nw + xl; dest = new_img[CHN_IMAGE] + (ny * nw + xl) * 3; for (nx = xl; nx <= xm; nx++ , dest += 3) { fox = nx * s1 + x0y; foy = nx * c1 + y0y; /* floor() is *SLOW* on Win32 - avoiding... */ ox = (int)(fox + 2.0) - 2; oy = (int)(foy + 2.0) - 2; fox -= ox; foy -= oy; k4 = fox * foy; k3 = foy - k4; k2 = fox - k4; k1 = 1.0 - fox - foy + k4; pix1 = old_img[CHN_IMAGE] + (oy * ow + ox) * 3; pix2 = pix1 + 3; pix3 = pix1 + ow * 3; pix4 = pix3 + 3; if (ox > ow - 2) pix2 = pix4 = A_rgb; else if (ox < 0) pix1 = pix3 = A_rgb; if (oy > oh - 2) pix3 = pix4 = A_rgb; else if (oy < 0) pix1 = pix2 = A_rgb; if (alpha) { aa1 = aa2 = aa3 = aa4 = 0.0; src = old_img[CHN_ALPHA] + oy * ow + ox; if (pix1 != A_rgb) aa1 = src[0] * k1; if (pix2 != A_rgb) aa2 = src[1] * k2; if (pix3 != A_rgb) aa3 = src[ow] * k3; if (pix4 != A_rgb) aa4 = src[ow + 1] * k4; aa = aa1 + aa2 + aa3 + aa4; if ((*alpha++ = rint(aa))) { aa = 1.0 / aa; k1 = aa1 * aa; k2 = aa2 * aa; k3 = aa3 * aa; k4 = aa4 * aa; } } if (gcor) /* Gamma-correct */ { rr = gamma256[pix1[0]] * k1 + gamma256[pix2[0]] * k2 + gamma256[pix3[0]] * k3 + gamma256[pix4[0]] * k4; gg = gamma256[pix1[1]] * k1 + gamma256[pix2[1]] * k2 + gamma256[pix3[1]] * k3 + gamma256[pix4[1]] * k4; bb = gamma256[pix1[2]] * k1 + gamma256[pix2[2]] * k2 + gamma256[pix3[2]] * k3 + gamma256[pix4[2]] * k4; dest[0] = UNGAMMA256(rr); dest[1] = UNGAMMA256(gg); dest[2] = UNGAMMA256(bb); } else /* Leave as is */ { rr = pix1[0] * k1 + pix2[0] * k2 + pix3[0] * k3 + pix4[0] * k4; gg = pix1[1] * k1 + pix2[1] * k2 + pix3[1] * k3 + pix4[1] * k4; bb = pix1[2] * k1 + pix2[2] * k2 + pix3[2] * k3 + pix4[2] * k4; dest[0] = rint(rr); dest[1] = rint(gg); dest[2] = rint(bb); } } continue; } /* Alpha channel already done... maybe */ if ((cc == CHN_ALPHA) && !dis_a) continue; /* Utility channel bilinear */ dest = new_img[cc] + ny * nw + xl; for (nx = xl; nx <= xm; nx++) { fox = nx * s1 + x0y; foy = nx * c1 + y0y; /* floor() is *SLOW* on Win32 - avoiding... */ ox = (int)(fox + 2.0) - 2; oy = (int)(foy + 2.0) - 2; fox -= ox; foy -= oy; k4 = fox * foy; k3 = foy - k4; k2 = fox - k4; k1 = 1.0 - fox - foy + k4; src = old_img[cc] + oy * ow + ox; aa1 = aa2 = aa3 = aa4 = 0.0; if (ox < ow - 1) { if (oy < oh - 1) aa4 = src[ow + 1] * k4; if (oy >= 0) aa2 = src[1] * k2; } if (ox >= 0) { if (oy < oh - 1) aa3 = src[ow] * k3; if (oy >= 0) aa1 = src[0] * k1; } *dest++ = rint(aa1 + aa2 + aa3 + aa4); } } } } #define PIX_ADD (127.0 / 128.0) /* Include all _visibly_ altered pixels */ void mem_rotate_geometry(int ow, int oh, double angle, int *nw, int *nh) // Get new image geometry of rotation. angle = degrees { int dx, dy; double rangle = (M_PI / 180.0) * angle, // Radians s2, c2; // Trig values c2 = fabs(cos(rangle)); s2 = fabs(sin(rangle)); /* Preserve original centering */ dx = ow & 1; dy = oh & 1; /* Exchange Y with X when rotated Y is nearer to old X */ if ((dx ^ dy) && (c2 < s2)) dx ^= 1 , dy ^= 1; *nw = 2 * (int)(0.5 * (ow * c2 + oh * s2 - dx) + PIX_ADD) + dx; *nh = 2 * (int)(0.5 * (oh * c2 + ow * s2 - dy) + PIX_ADD) + dy; } // Rotate canvas or clipboard by any angle (degrees) int mem_rotate_free(double angle, int type, int gcor, int clipboard) { chanlist old_img, new_img; int ow, oh, nw, nh, res, rot_bpp; if (clipboard) { if (!mem_clipboard) return (-1); // Nothing to rotate ow = mem_clip_w; oh = mem_clip_h; rot_bpp = mem_clip_bpp; } else { ow = mem_width; oh = mem_height; rot_bpp = mem_img_bpp; } mem_rotate_geometry(ow, oh, angle, &nw, &nh); if ( nw>MAX_WIDTH || nh>MAX_HEIGHT ) return -5; // If new image is too big return -5 if (!clipboard) { memcpy(old_img, mem_img, sizeof(chanlist)); res = undo_next_core(UC_NOCOPY, nw, nh, mem_img_bpp, CMASK_ALL); if (res) return (res); // No undo space memcpy(new_img, mem_img, sizeof(chanlist)); progress_init(_("Free Rotation"), 0); } else { /* Note: even if the original clipboard doesn't have a mask, * the rotation will need one to chop off the corners of * a rotated rectangle. */ if (!mem_clip_mask && mem_clip_mask_init(255)) return (1); // Not enough memory res = mem_clip_new(nw, nh, mem_clip_bpp, cmask_from(mem_clip.img), old_img); if (res) return (1); // Not enough memory memcpy(new_img, mem_clip.img, sizeof(chanlist)); } if ( rot_bpp == 1 ) type = FALSE; mem_rotate_free_real(old_img, new_img, ow, oh, nw, nh, rot_bpp, angle, type, gcor, channel_dis[CHN_ALPHA] && !clipboard, clipboard); if (!clipboard) progress_end(); /* Lose old unwanted clipboard */ if (clipboard) mem_free_chanlist(old_img); return 0; } int mem_image_rot( int dir ) // Rotate image 90 degrees { chanlist old_img; int i, ow = mem_width, oh = mem_height; memcpy(old_img, mem_img, sizeof(chanlist)); i = undo_next_core(UC_NOCOPY, oh, ow, mem_img_bpp, CMASK_ALL); if (i) return (i); // Not enough memory for (i = 0; i < NUM_CHANNELS; i++) { if (!mem_img[i]) continue; mem_rotate(mem_img[i], old_img[i], ow, oh, dir, BPP(i)); } mem_undo_prepare(); return 0; } /// Code for scaling contributed by Dmitry Groshev, January 2006 /// Multicore support added by Dmitry Groshev, November 2010 typedef struct { float *k; int idx; } fstep; static double Cubic(double x, double A) { if (x < -1.5) return (0.0); else if (x < -0.5) return (A * (-1.0 / 8.0) * (((x * 8.0 + 28.0) * x + 30.0) * x + 9.0)); else if (x < 0.5) return (0.5 * (((-4.0 * A - 4.0) * x * x + A + 3.0) * x + 1.0)); else if (x < 1.5) return (A * (-1.0 / 8.0) * (((x * 8.0 - 28.0) * x + 30.0) * x - 9.0) + 1.0); else return (1.0); } static double BH1(double x) { if (x < 1e-7) return (1.0); return ((sin(M_PI * x) / (M_PI * x)) * (0.42323 + 0.49755 * cos(x * (M_PI * 2.0 / 6.0)) + 0.07922 * cos(x * (M_PI * 4.0 / 6.0)))); } static double BH(double x) { double y = 0.0, xx = fabs(x); if (xx < 2.5) { y = BH1(xx + 0.5); if (xx < 1.5) y += BH1(xx + 1.5); if (xx < 0.5) y += BH1(xx + 2.5); } return (x > 0.0 ? 1.0 - y : y); } static const double Aarray[4] = {-0.5, -2.0 / 3.0, -0.75, -1.0}; /* !!! Filter as a whole must be perfectly symmetric, and "idx" of step 0 * must be <= 0; these natural properties are relied on when allocating and * extending horizontal temp arrays for BOUND_TILE mode. * 2 extra steps at end hold end pointer & index, and terminating NULL. */ static fstep *make_filter(int l0, int l1, int type, int sharp, int bound) { fstep *res, *buf; __typeof__(*res->k) *kp; double x, y, basept, scale; double A = 0.0, kk = 1.0, sum; int i, j, k, ix, j0, fwidth, delta, k0 = 0; /* Untransformed bilinear is useless for reduction */ if (type == 1) sharp = TRUE; /* 1:1 transform is special */ if (l1 == l0) type = 0; switch (type) { case 1: fwidth = 2; /* Bilinear / Area-mapping */ break; case 2: case 3: case 4: case 5: /* Bicubic, all flavors */ fwidth = 4; A = Aarray[type - 2]; break; case 6: fwidth = 6; /* Blackman-Harris windowed sinc */ break; default: /* 1:1 */ fwidth = 0; break; } type *= 2; scale = (double)l1 / (double)l0; /* !!! fwidth is rational (l1 denominator) to prevent rounding errors */ if (l1 < l0) { kk = scale; fwidth *= l0; if (sharp) fwidth += l1 - l0 , type++; } else fwidth *= l1; buf = multialloc(MA_ALIGN_DOUBLE, &res, (l1 + 2) * sizeof(*res), &kp, (fwidth + l1) * sizeof(*res->k), NULL); if (!buf) return (NULL); res = buf; /* No need to double-align the index array */ /* To correct scale-shift */ delta = l0 - l1; // 2*l1 denominator for (i = l1 , l1 *= 2; i > 0; i-- , buf++ , delta += l0 * 2) { basept = delta / (double)l1; j = j0 = ceil_div(delta - fwidth, l1); k = k0 = (delta + fwidth) / l1 + 1; if (j0 < 0) j0 = 0; if (k0 > l0) k0 = l0; /* If filter doesn't cover source from end to end, tiling will * require physical copying */ if ((bound == BOUND_TILE) && (k0 - j0 < l0)) k0 = k , j0 = j; buf->idx = j0; buf->k = kp; kp += k0 - j0; sum = 0.0; for (; j < k; j++) { ix = j; if ((j < j0) || (j >= k0)) { if (bound == BOUND_VOID) continue; if (bound == BOUND_TILE) { if (ix < 0) ix = k0 - (-ix % k0); ix %= k0; } else if (k0 == 1) ix = 0; else { ix = abs(ix) % (k0 + k0 - 2); if (ix >= k0) ix = k0 + k0 - 2 - ix; } } ix -= j0; x = fabs(((double)j - basept) * kk); switch (type) { case 0: /* 1:1 */ case 2: /* Bilinear */ y = 1.0 - x; break; case 3: /* Area mapping */ if (x <= 0.5 - scale / 2.0) y = 1.0; else y = 0.5 - (x - 0.5) / scale; break; case 4: case 6: case 8: case 10: /* Bicubic */ if (x < 1.0) y = ((A + 2.0) * x - (A + 3)) * x * x + 1.0; else y = A * (((x - 5.0) * x + 8.0) * x - 4.0); break; case 5: case 7: case 9: case 11: /* Sharpened bicubic */ y = Cubic(x + scale * 0.5, A) - Cubic(x - scale * 0.5, A); break; case 12: /* Blackman-Harris */ y = BH1(x); break; case 13: /* Sharpened Blackman-Harris */ y = BH(x + scale * 0.5) - BH(x - scale * 0.5); break; default: /* Bug */ y = 0; break; } buf->k[ix] += y; sum += y; } /* Normalize */ if ((sum != 0.0) && (sum != 1.0)) { __typeof__(*kp) *tp = buf->k; sum = 1.0 / sum; while (tp != kp) *tp++ *= sum; } } /* Finalize */ buf->idx = k0; // The rightmost extent buf->k = kp; return (res); } typedef struct { int tmask, gcor, progress; int ow, oh, nw, nh, bpp; unsigned char **src, **dest; double *rgb; fstep *hfilter, *vfilter; threaddata *tdata; // For simplicity } scale_context; static void clear_scale(scale_context *ctx) { free(ctx->hfilter); free(ctx->vfilter); free(ctx->tdata); } static int prepare_scale(scale_context *ctx, int type, int sharp, int bound) { ctx->hfilter = ctx->vfilter = NULL; ctx->tdata = NULL; /* We don't use threading for NN */ if (!type || (ctx->bpp == 1)) return (TRUE); if ((ctx->hfilter = make_filter(ctx->ow, ctx->nw, type, sharp, bound)) && (ctx->vfilter = make_filter(ctx->oh, ctx->nh, type, sharp, bound))) { int l = (ctx->ow - ctx->hfilter[0].idx * 2) * sizeof(double); if ((ctx->tdata = talloc(MA_ALIGN_DOUBLE, image_threads(ctx->nw, ctx->nh), ctx, sizeof(*ctx), NULL, // !!! No space for RGBAS for now &ctx->rgb, l * (ctx->tmask ? 7 : 3), NULL))) return (TRUE); } clear_scale(ctx); return (FALSE); } static void tile_extend(double *temp, int w, int l) { memcpy(temp - l, temp + w - l, l * sizeof(*temp)); memcpy(temp + w, temp, l * sizeof(*temp)); } typedef void REGPARM2 (*istore_func)(unsigned char *img, const double *sum); static void REGPARM2 istore_gc(unsigned char *img, const double *sum) { /* Reverse gamma correction */ img[0] = UNGAMMA256X(sum[0]); img[1] = UNGAMMA256X(sum[1]); img[2] = UNGAMMA256X(sum[2]); } static void REGPARM2 istore_3(unsigned char *img, const double *sum) { int j = (int)rint(sum[0]); img[0] = j < 0 ? 0 : j > 0xFF ? 0xFF : j; j = (int)rint(sum[1]); img[1] = j < 0 ? 0 : j > 0xFF ? 0xFF : j; j = (int)rint(sum[2]); img[2] = j < 0 ? 0 : j > 0xFF ? 0xFF : j; } static void REGPARM2 istore_1(unsigned char *img, const double *sum) { int j = (int)rint(sum[0]); img[0] = j < 0 ? 0 : j > 0xFF ? 0xFF : j; } /* !!! Once again, beware of GCC misoptimization! The two functions below * should not be both inlineable at once, otherwise poor code wasting both * time and space will be produced - WJ */ static void scale_row(fstep *tmpy, fstep *hfilter, double *work_area, int bpp, int gc, int ow, int oh, int nw, int i, unsigned char *src, unsigned char *dest) { /* !!! Protect from possible stack misalignment */ unsigned char sum_[4 * sizeof(double)]; double *sum = ALIGNED(sum_, sizeof(double)); istore_func istore; unsigned char *img; fstep *tmpx; __typeof__(*tmpy->k) *kp = tmpy->k - tmpy->idx; int j, y, h = tmpy[1].k - kp, ll = hfilter[0].idx; work_area -= ll * bpp; ow *= bpp; memset(work_area, 0, ow * sizeof(double)); /* Build one vertically-scaled row */ for (y = tmpy->idx; y < h; y++) { const double tk = kp[y]; double *wrk = work_area; /* Only simple tiling isn't built into filter */ img = src + ((y + oh) % oh) * ow; if (gc) /* Gamma-correct */ { for (j = 0; j < ow; j++) *wrk++ += gamma256[*img++] * tk; } else /* Leave as is */ { for (j = 0; j < ow; j++) *wrk++ += *img++ * tk; } } tile_extend(work_area, ow, -ll * bpp); /* Scale it horizontally */ istore = gc ? istore_gc : bpp == 1 ? istore_1 : istore_3; img = dest + i * nw * bpp; for (tmpx = hfilter; tmpx[1].k; tmpx++ , img += bpp) { __typeof__(*tmpx->k) *tp, *kp = tmpx[1].k; double *wrk = work_area + tmpx->idx * bpp; double sum0, sum1, sum2; sum0 = sum1 = sum2 = 0.0; tp = tmpx->k; while (tp != kp) { const double kk = *tp++; sum0 += *wrk++ * kk; if (bpp == 1) continue; sum1 += *wrk++ * kk; sum2 += *wrk++ * kk; } sum[0] = sum0; sum[1] = sum1; sum[2] = sum2; istore(img, sum); } } static void scale_rgba(fstep *tmpy, fstep *hfilter, double *work_area, int bpp, int gc, int ow, int oh, int nw, int i, unsigned char *src, unsigned char *dest, unsigned char *srca, unsigned char *dsta) { /* !!! Protect from possible stack misalignment */ unsigned char sum_[4 * sizeof(double)]; double *sum = ALIGNED(sum_, sizeof(double)); istore_func istore; unsigned char *img, *imga; fstep *tmpx; __typeof__(*tmpy->k) *kp = tmpy->k - tmpy->idx; int j, y, h = tmpy[1].k - kp, ll = hfilter[0].idx; double *wrka = work_area + ow * 6 - ll * 13; work_area -= ll * 6; memset(work_area, 0, (ow - ll) * 7 * sizeof(double)); for (y = tmpy->idx; y < h; y++) { double *wrk = work_area; unsigned char *img, *imga; int ix = (y + oh) % oh; img = src + ix * ow * 3; imga = srca + ix * ow; if (gc) /* Gamma-correct */ { const double tk = kp[y]; for (j = 0; j < ow; j++) { const double kk = imga[j] * tk; double tv; wrka[j] += kk; wrk[0] += (tv = gamma256[img[0]]) * tk; wrk[3] += tv * kk; wrk[1] += (tv = gamma256[img[1]]) * tk; wrk[4] += tv * kk; wrk[2] += (tv = gamma256[img[2]]) * tk; wrk[5] += tv * kk; wrk += 6; img += 3; } } else /* Leave as is */ { const double tk = kp[y]; for (j = 0; j < ow; j++) { const double kk = imga[j] * tk; double tv; wrka[j] += kk; wrk[0] += (tv = img[0]) * tk; wrk[3] += tv * kk; wrk[1] += (tv = img[1]) * tk; wrk[4] += tv * kk; wrk[2] += (tv = img[2]) * tk; wrk[5] += tv * kk; wrk += 6; img += 3; } } } tile_extend(work_area, ow * 6, -ll * 6); tile_extend(wrka, ow, -ll); /* Scale it horizontally */ istore = gc ? istore_gc : bpp == 1 ? istore_1 : istore_3; img = dest + i * nw * 3; imga = dsta + i * nw; for (tmpx = hfilter; tmpx[1].k; tmpx++) { __typeof__(*tmpx->k) *tp, *kp = tmpx[1].k; double *wrk; double sum0, sum1, sum2, mult; sum0 = 0.0; wrk = wrka + tmpx->idx; tp = tmpx->k; while (tp != kp) sum0 += *wrk++ * *tp++; j = (int)rint(sum0); *imga = j < 0 ? 0 : j > 0xFF ? 0xFF : j; wrk = work_area + tmpx->idx * 6; mult = 1.0; if (*imga++) { wrk += 3; mult /= sum0; } sum0 = sum1 = sum2 = 0.0; tp = tmpx->k; while (tp != kp) { const double kk = *tp++; sum0 += wrk[0] * kk; sum1 += wrk[1] * kk; sum2 += wrk[2] * kk; wrk += 6; } sum[0] = sum0 * mult; sum[1] = sum1 * mult; sum[2] = sum2 * mult; istore(img, sum); img += 3; } } static void do_scale(tcb *thread) { scale_context ctx = *(scale_context *)thread->data; fstep *tmpy; int i, ii, cc, cnt = thread->nsteps; /* For each destination line */ for (i = thread->step0 , ii = 0; ii < cnt; i++ , ii++) { tmpy = ctx.vfilter + i; if (ctx.dest[CHN_IMAGE]) // Chanlist may contain, e.g., only mask { (ctx.tmask == CMASK_NONE ? (__typeof__(&scale_rgba))scale_row : scale_rgba)(tmpy, ctx.hfilter, ctx.rgb, 3, ctx.gcor, ctx.ow, ctx.oh, ctx.nw, i, ctx.src[CHN_IMAGE], ctx.dest[CHN_IMAGE], ctx.src[CHN_ALPHA], ctx.dest[CHN_ALPHA]); } for (cc = CHN_IMAGE + 1; cc < NUM_CHANNELS; cc++) { if (ctx.dest[cc] && !(ctx.tmask & CMASK_FOR(cc))) scale_row(tmpy, ctx.hfilter, ctx.rgb, 1, FALSE, ctx.ow, ctx.oh, ctx.nw, i, ctx.src[cc], ctx.dest[cc]); } if (ctx.progress && thread_step(thread, ii + 1, cnt, 10)) break; } thread_done(thread); } static void do_scale_nn(chanlist old_img, chanlist neo_img, int img_bpp, int type, int ow, int oh, int nw, int nh, int gcor, int progress) { char *src, *dest; int i, j, oi, oj, cc, bpp; double scalex, scaley, deltax, deltay; scalex = (double)ow / (double)nw; scaley = (double)oh / (double)nh; deltax = 0.5 * scalex - 0.5; deltay = 0.5 * scaley - 0.5; for (j = 0; j < nh; j++) { for (cc = 0 , bpp = img_bpp; cc < NUM_CHANNELS; cc++ , bpp = 1) { if (!neo_img[cc]) continue; dest = neo_img[cc] + nw * j * bpp; WJ_ROUND(oj, scaley * j + deltay); src = old_img[cc] + ow * oj * bpp; for (i = 0; i < nw; i++) { WJ_ROUND(oi, scalex * i + deltax); oi *= bpp; *dest++ = src[oi]; if (bpp == 1) continue; *dest++ = src[oi + 1]; *dest++ = src[oi + 2]; } } if (progress && ((j * 10) % nh >= nh - 10)) progress_update((float)(j + 1) / nh); } } int mem_image_scale_real(chanlist old_img, int ow, int oh, int bpp, chanlist new_img, int nw, int nh, int type, int gcor, int sharp) { scale_context ctx; ctx.tmask = CMASK_NONE; ctx.gcor = gcor; ctx.progress = FALSE; ctx.ow = ow; ctx.oh = oh; ctx.nw = nw; ctx.nh = nh; ctx.bpp = bpp; ctx.src = old_img; ctx.dest = new_img; if (!prepare_scale(&ctx, type, sharp, BOUND_MIRROR)) return (1); // Not enough memory if (type && (bpp == 3)) launch_threads(do_scale, ctx.tdata, NULL, nh); else do_scale_nn(old_img, new_img, bpp, type, ow, oh, nw, nh, gcor, FALSE); return (0); } int mem_image_scale(int nw, int nh, int type, int gcor, int sharp, int bound) // Scale image { scale_context ctx; chanlist old_img; int res; memcpy(old_img, mem_img, sizeof(chanlist)); nw = nw < 1 ? 1 : nw > MAX_WIDTH ? MAX_WIDTH : nw; nh = nh < 1 ? 1 : nh > MAX_HEIGHT ? MAX_HEIGHT : nh; ctx.tmask = mem_img[CHN_ALPHA] && !channel_dis[CHN_ALPHA] ? CMASK_RGBA : CMASK_NONE; ctx.gcor = gcor; ctx.progress = TRUE; ctx.ow = mem_width; ctx.oh = mem_height; ctx.nw = nw; ctx.nh = nh; ctx.bpp = mem_img_bpp; ctx.src = old_img; ctx.dest = mem_img; if (!prepare_scale(&ctx, type, sharp, bound)) return (1); // Not enough memory if (!(res = undo_next_core(UC_NOCOPY, nw, nh, mem_img_bpp, CMASK_ALL))) { progress_init(_("Scaling Image"), 0); if (type && (mem_img_bpp == 3)) launch_threads(do_scale, ctx.tdata, NULL, mem_height); else do_scale_nn(old_img, mem_img, mem_img_bpp, type, ctx.ow, ctx.oh, nw, nh, gcor, TRUE); progress_end(); } clear_scale(&ctx); return (res); } int mem_isometrics(int type) { unsigned char *wrk, *src, *dest, *fill; int i, j, k, l, cc, step, bpp, ow = mem_width, oh = mem_height; if ( type<2 ) { if ( (oh + (ow-1)/2) > MAX_HEIGHT ) return -5; i = mem_image_resize(ow, oh + (ow-1)/2, 0, 0, 0); } if ( type>1 ) { if ( (ow+oh-1) > MAX_WIDTH ) return -5; i = mem_image_resize(ow + oh - 1, oh, 0, 0, 0); } if (i) return (i); for (cc = 0; cc < NUM_CHANNELS; cc++) { if (!mem_img[cc]) continue; bpp = BPP(cc); if ( type < 2 ) // Left/Right side down { fill = mem_img[cc] + (mem_height - 1) * ow * bpp; step = ow * bpp; if (type) step = -step; else fill += (2 - (ow & 1)) * bpp; for (i = mem_height - 1; i >= 0; i--) { k = i + i + 2; if (k > ow) k = ow; l = k; j = 0; dest = mem_img[cc] + i * ow * bpp; src = dest - step; if (!type) { j = ow - k; dest += j * bpp; src += (j - ow * ((ow - j - 1) >> 1)) * bpp; j = j ? 0 : ow & 1; k += j; if (j) src += step; } for (; j < k; j++) { if (!(j & 1)) src += step; *dest++ = *src++; if (bpp == 1) continue; *dest++ = *src++; *dest++ = *src++; } if (l < ow) { if (!type) dest = mem_img[cc] + i * ow * bpp; memcpy(dest, fill, (ow - l) * bpp); } } } else // Top/Bottom side right { step = mem_width * bpp; fill = mem_img[cc] + ow * bpp; k = (oh - 1) * mem_width * bpp; if (type == 2) { fill += k; step = -step; } wrk = fill + step - 1; k = ow * bpp; for (i = 1; i < oh; i++) { src = wrk; dest = wrk + i * bpp; for (j = 0; j < k; j++) *dest-- = *src--; memcpy(src + 1, fill, i * bpp); wrk += step; } } } return 0; } /* Modes: 0 - clear, 1 - tile, 2 - mirror tile */ int mem_image_resize(int nw, int nh, int ox, int oy, int mode) { chanlist old_img; char *src, *dest; int i, h, ow = mem_width, oh = mem_height, hmode = mode; int res, hstep, vstep, vstep2 = 0, oxo = 0, oyo = 0, nxo = 0, nyo = 0; int rspan1 = 0, span1 = 0, rspan2 = 0, span2 = 0, rep = 0, tail = 0; nw = nw < 1 ? 1 : nw > MAX_WIDTH ? MAX_WIDTH : nw; nh = nh < 1 ? 1 : nh > MAX_HEIGHT ? MAX_HEIGHT : nh; memcpy(old_img, mem_img, sizeof(chanlist)); res = undo_next_core(UC_NOCOPY, nw, nh, mem_img_bpp, CMASK_ALL); if (res) return (res); // Not enough memory /* Special mode for simplest, one-piece-covering case */ if ((ox <= 0) && (nw - ox <= ow)) hmode = -1; if ((oy <= 0) && (nh - oy <= oh)) mode = -1; /* Clear */ if (!mode || !hmode) { int i, l, cc; l = nw * nh; for (cc = 0; cc < NUM_CHANNELS; cc++) { if (!mem_img[cc]) continue; dest = mem_img[cc]; if ((cc != CHN_IMAGE) || (mem_img_bpp == 1)) { memset(dest, cc == CHN_IMAGE ? mem_col_A : 0, l); continue; } for (i = 0; i < l; i++) // Background is current colour A { *dest++ = mem_col_A24.red; *dest++ = mem_col_A24.green; *dest++ = mem_col_A24.blue; } } /* All done if source out of bounds */ if ((ox >= nw) || (ox + ow <= 0) || (oy >= nh) || (oy + oh <= 0)) return (0); } /* Tiled vertically */ if (mode > 0) { /* No mirror when height < 3 */ if (oh < 3) mode = 1; /* Period length */ if (mode == 2) vstep = 2 * (vstep2 = oh - 1); else vstep = oh; /* Normalize offset */ oyo = oy <= 0 ? -oy % vstep : vstep - 1 - (oy - 1) % vstep; h = nh; } /* Single vertical span */ else { /* No periodicity */ vstep = nh + oh; /* Normalize offset */ if (oy < 0) oyo = -oy; else nyo = oy; h = oh + oy; if (h > nh) h = nh; } /* Tiled horizontally */ if (hmode > 0) { /* No mirror when width < 3 */ if (ow < 3) hmode = 1; /* Period length */ if (hmode == 2) hstep = ow + ow - 2; else hstep = ow; /* Normalize offset */ oxo = ox <= 0 ? -ox % hstep : hstep - 1 - (ox - 1) % hstep; /* Single direct span? */ if ((oxo <= 0) && (oxo + ow >= nw)) hmode = -1; if (hmode == 2) /* Mirror tiling */ { if (oxo < ow - 1) span1 = ow - 1 - oxo; res = nw - span1; rspan1 = hstep - oxo - span1; if (rspan1 > res) rspan1 = res; span2 = (res = res - rspan1); if (span2 > ow - 1 - span1) span2 = ow - 1 - span1; rspan2 = res - span2; if (rspan2 > ow - 1 - rspan1) rspan2 = ow - 1 - rspan1; } else /* Normal tiling */ { span1 = ow - oxo; span2 = nw - span1; if (span2 > oxo) span2 = oxo; } rep = nw / hstep; if (rep) tail = nw % hstep; } /* Single horizontal span */ else { /* No periodicity */ hstep = nw; /* Normalize offset */ if (ox < 0) oxo = -ox; else nxo = ox; /* First direct span */ span1 = nw - nxo; if (span1 > ow - oxo) span1 = ow - oxo; } /* Row loop */ for (i = nyo; i < h; i++) { int j, k, l, bpp, cc; /* Main period */ k = i - vstep; /* Mirror period */ if ((k < 0) && (vstep2 > 1)) k = i - ((i + oyo) % vstep2) * 2; /* The row is there - copy it */ if ((k >= 0) && (k < i)) { for (cc = 0; cc < NUM_CHANNELS; cc++) { if (!mem_img[cc]) continue; l = nw * BPP(cc); src = mem_img[cc] + k * l; dest = mem_img[cc] + i * l; memcpy(dest, src, l); } continue; } /* First encounter - have to build the row anew */ k = (i - nyo + oyo) % vstep; if (k >= oh) k = vstep - k; for (cc = 0; cc < NUM_CHANNELS; cc++) { if (!mem_img[cc]) continue; bpp = BPP(cc); dest = mem_img[cc] + (i * nw + nxo) * bpp; /* First direct span */ if (span1) { src = old_img[cc] + (k * ow + oxo) * bpp; memcpy(dest, src, span1 * bpp); if (hmode < 1) continue; /* Single-span mode */ dest += span1 * bpp; } /* First reverse span */ if (rspan1) { src = old_img[cc] + (k * ow + hstep - oxo - span1) * bpp; for (j = 0; j < rspan1; j++ , src -= bpp) { *dest++ = src[0]; if (bpp == 1) continue; *dest++ = src[1]; *dest++ = src[2]; } } /* Second direct span */ if (span2) { src = old_img[cc] + k * ow * bpp; memcpy(dest, src, span2 * bpp); dest += span2 * bpp; } /* Second reverse span */ if (rspan2) { src = old_img[cc] + (k * ow + ow - 1) * bpp; for (j = 0; j < rspan2; j++ , src -= bpp) { *dest++ = src[0]; if (bpp == 1) continue; *dest++ = src[1]; *dest++ = src[2]; } } /* Repeats */ if (rep) { src = mem_img[cc] + i * nw * bpp; l = hstep * bpp; for (j = 1; j < rep; j++) { memcpy(dest, src, l); dest += l; } memcpy(dest, src, tail * bpp); } } } mem_undo_prepare(); return (0); } /* Threshold channel values */ void mem_threshold(unsigned char *img, int len, int level) { if (!img) return; /* Paranoia */ level += 0xFFFF; for (; len; len-- , img++) *img = (level - *img) >> 8; } /* Industrial-grade thresholding */ void do_xhold(int start, int step, int cnt, unsigned char *mask, unsigned char *imgr, unsigned char *img0) { unsigned char lo = mem_ts.lo, hi = mem_ts.hi; int n, mstep = step, bpp = MEM_BPP; mask += start - step; start *= bpp; step *= bpp; img0 += start - step; imgr += start - step; if ((bpp > 1) && (mem_ts.mode <= XHOLD_MIN)) /* By max or min */ { int m = mem_ts.mode; // 0 for max, 1 for min while (cnt-- > 0) { img0 += step; imgr += step; mask += mstep; if (*mask == 255) continue; n = (img0[0] > img0[1]) ^ m ? img0[0] : img0[1]; n = (n > img0[2]) ^ m ? n : img0[2]; imgr[0] = imgr[1] = imgr[2] = ((0xFFFF + lo - n) & (0xFFFF - hi + n)) >> 8; } } else /* By R/G/B/value */ { unsigned char mx = 255; if (bpp > 1) img0 += mem_ts.mode - XHOLD_RED; else if (mem_channel == CHN_IMAGE) mx = mem_cols - 1; while (cnt-- > 0) { img0 += step; imgr += step; mask += mstep; if (*mask == 255) continue; n = *img0; imgr[0] = n = mx & (((0xFFFF + lo - n) & (0xFFFF - hi + n)) >> 8); if (bpp == 1) continue; imgr[1] = imgr[2] = n; } } } /* Only supports BPP = 1 and 3 */ void mem_demultiply(unsigned char *img, unsigned char *alpha, int len, int bpp) { int i, k; double d; for (i = 0; i < len; i++ , img += bpp) { if (!alpha[i]) continue; d = 255.0 / (double)alpha[i]; k = rint(d * img[0]); img[0] = k > 255 ? 255 : k; if (bpp == 1) continue; k = rint(d * img[1]); img[1] = k > 255 ? 255 : k; k = rint(d * img[2]); img[2] = k > 255 ? 255 : k; } } /* Build value rescaling table */ void set_xlate_n(unsigned char *xlat, int n) { int i, j, m; for (i = 0 , j = n , m = n + n; i <= n; i++ , j += 255 * 2) xlat[i] = j / m; } /* Check if byte array is all one value */ int is_filled(unsigned char *data, unsigned char val, int len) { len++; while (--len && (*data++ == val)); return (!len); } int get_pixel( int x, int y ) /* Mixed */ { x = mem_width * y + x; if ((mem_channel != CHN_IMAGE) || (mem_img_bpp == 1)) return (mem_img[mem_channel][x]); x *= 3; return (MEM_2_INT(mem_img[CHN_IMAGE], x)); } int get_pixel_RGB( int x, int y ) /* RGB */ { x = mem_width * y + x; if (mem_img_bpp == 1) return (PNG_2_INT(mem_pal[mem_img[CHN_IMAGE][x]])); x *= 3; return (MEM_2_INT(mem_img[CHN_IMAGE], x)); } int get_pixel_img( int x, int y ) /* RGB or indexed */ { x = mem_width * y + x; if (mem_img_bpp == 1) return (mem_img[CHN_IMAGE][x]); x *= 3; return (MEM_2_INT(mem_img[CHN_IMAGE], x)); } int mem_protected_RGB(int intcol) // Is this intcol in bitmap? { return (mem_mask_test(intcol) * 255); } int pixel_protected(int x, int y) { int offset = y * mem_width + x; if (mem_unmask) return (0); /* Colour protection */ if (mem_img_bpp == 1) { if (mem_prot_mask[mem_img[CHN_IMAGE][offset]]) return (255); } else { if (mem_prot && mem_protected_RGB(MEM_2_INT(mem_img[CHN_IMAGE], offset * 3))) return (255); } /* Colour selectivity */ if (mem_cselect && csel_scan(offset, 1, 1, NULL, mem_img[CHN_IMAGE], csel_data)) return (255); /* Mask channel */ if ((mem_channel <= CHN_ALPHA) && mem_img[CHN_MASK] && !channel_dis[CHN_MASK]) return (mem_img[CHN_MASK][offset]); return (0); } void prep_mask(int start, int step, int cnt, unsigned char *mask, unsigned char *mask0, unsigned char *img0) { int i, j; j = start + step * (cnt - 1) + 1; if (mem_unmask) { memset(mask, 0, j); return; } /* Clear mask or copy mask channel into it */ if (mask0) memcpy(mask, mask0, j); else memset(mask, 0, j); /* Add colour protection to it */ if (mem_img_bpp == 1) { for (i = start; i < j; i += step) { mask[i] |= mem_prot_mask[img0[i]]; } } else if (mem_prot) { for (i = start; i < j; i += step) { mask[i] |= mem_protected_RGB(MEM_2_INT(img0, i * 3)); } } /* Add colour selectivity to it */ if (mem_cselect) csel_scan(start, step, cnt, mask, img0, csel_data); } /* Prepare mask array - for each pixel >0 if masked, 0 if not */ void row_protected(int x, int y, int len, unsigned char *mask) { unsigned char *mask0 = NULL; int ofs = y * mem_width + x; /* Clear mask or copy mask channel into it */ if ((mem_channel <= CHN_ALPHA) && mem_img[CHN_MASK] && !channel_dis[CHN_MASK]) mask0 = mem_img[CHN_MASK] + ofs; prep_mask(0, 1, len, mask, mask0, mem_img[CHN_IMAGE] + ofs * mem_img_bpp); } /* Make code not compile if it cannot work */ typedef char Too_Many_Blend_Modes[2 * (BLEND_NMODES <= BLEND_MMASK + 1) - 1]; static void blend_pixels(int start, int step, int cnt, const unsigned char *mask, unsigned char *imgr, unsigned char *img0, unsigned char *img, int bpp, int mode) { static const unsigned char hhsv[8] = { 0x24, /* 0, 1, 2 = #0: B..M */ 0x06, /* 2, 1, 0 = #1: M+..R- */ 0x24, /* 0, 1, 2 = #2: B..M alt */ 0x21, /* 1, 0, 2 = #3: C+..B- */ 0x12, /* 2, 0, 1 = #4: G..C */ 0x18, /* 0, 2, 1 = #5: Y+..G- */ 0x09, /* 1, 2, 0 = #6: R..Y */ 0x49 /* 1, 2, 0, 1 = #7: W */ }; #define HHSV(X,N) (((X) >> ((N) * 2)) & 3) const unsigned char *new, *old; int j, step3, mx, uninit_(nhex), uninit_(ohex); /* Backward transfer? */ if (mode & BLEND_REVERSE) new = img0 , old = img; else new = img , old = img0; mx = mode & BLENDF_IDX ? mem_cols - 1 : 255; mode &= BLEND_MMASK; if (bpp == 1) mode += BLEND_NMODES; j = start - step; mask += j; j *= bpp; step3 = step * bpp; new += j; old += j; while (cnt-- > 0) { unsigned char *dest; int j0, j1, j2; old += step3; new += step3; mask += step; j += step3; if (!*mask) continue; dest = imgr + j; if (mode < BLEND_1BPP) { nhex = hhsv[(((0x200 + new[0]) - new[1]) ^ ((0x400 + new[1]) - new[2]) ^ ((0x100 + new[2]) - new[0])) >> 8]; ohex = hhsv[(((0x200 + old[0]) - old[1]) ^ ((0x400 + old[1]) - old[2]) ^ ((0x100 + old[2]) - old[0])) >> 8]; } switch (mode) { case BLEND_HUE: /* HS* Hue */ { int i; unsigned char os, ov, ns; ov = old[HHSV(ohex, 2)]; if (nhex & 0x40) /* New is white */ { dest[0] = dest[1] = dest[2] = ov; break; } os = old[HHSV(ohex, 1)]; ns = new[HHSV(nhex, 1)]; i = new[HHSV(nhex, 2)] - ns; dest[HHSV(nhex, 0)] = (i + (ov - os) * 2 * (new[HHSV(nhex, 0)] - ns)) / (i + i) + os; dest[HHSV(nhex, 1)] = os; dest[HHSV(nhex, 2)] = ov; break; } case BLEND_SAT: /* HSV Saturation */ { int i; unsigned char ov, os, ns, nv; if (ohex & 0x40) /* Old is white - leave it so */ { dest[0] = old[0]; dest[1] = old[1]; dest[2] = old[2]; break; } ov = old[HHSV(ohex, 2)]; if (nhex & 0x40) /* New is white */ { dest[0] = dest[1] = dest[2] = ov; break; } os = old[HHSV(ohex, 1)]; nv = new[HHSV(nhex, 2)]; ns = (new[HHSV(nhex, 1)] * ov * 2 + nv) / (nv + nv); i = ov - os; dest[HHSV(ohex, 0)] = (i + (ov - ns) * 2 * (old[HHSV(ohex, 0)] - os)) / (i + i) + ns; dest[HHSV(ohex, 1)] = ns; dest[HHSV(ohex, 2)] = ov; break; } case BLEND_VALUE: /* HSV Value */ { unsigned char ov, nv; nv = new[HHSV(nhex, 2)]; if (ohex & 0x40) /* Old is white */ { dest[0] = dest[1] = dest[2] = nv; break; } ov = old[HHSV(ohex, 2)]; dest[HHSV(ohex, 0)] = (old[HHSV(ohex, 0)] * nv * 2 + ov) / (ov + ov); dest[HHSV(ohex, 1)] = (old[HHSV(ohex, 1)] * nv * 2 + ov) / (ov + ov); dest[HHSV(ohex, 2)] = nv; break; } case BLEND_COLOR: /* HSL Hue + Saturation */ { int x0, x1, y0, y1, vsy1, vs1y; unsigned char os, ov; os = old[HHSV(ohex, 1)]; ov = old[HHSV(ohex, 2)]; x0 = os + ov; /* New is white */ if (nhex & 0x40) { dest[0] = dest[1] = dest[2] = (x0 + 1) >> 1; break; } x1 = new[HHSV(nhex, 2)] + new[HHSV(nhex, 1)]; y1 = x1 > 255 ? 510 - x1 : x1; vs1y = (x0 + 1) * y1; y0 = x0 > 255 ? 510 - x0 : x0; vsy1 = (new[HHSV(nhex, 2)] - new[HHSV(nhex, 1)]) * y0; y1 += y1; dest[HHSV(nhex, 0)] = (vs1y + (new[HHSV(nhex, 0)] * 2 - x1) * y0) / y1; dest[HHSV(nhex, 1)] = (vs1y - vsy1) / y1; dest[HHSV(nhex, 2)] = (vs1y + vsy1) / y1; break; } case BLEND_SATPP: /* Perceived saturation */ { int i, xyz = (new[0] + new[1] + new[2]) / 3; i = old[0] + new[0] - xyz; dest[0] = i < 0 ? 0 : i > 255 ? 255 : i; i = old[1] + new[1] - xyz; dest[1] = i < 0 ? 0 : i > 255 ? 255 : i; i = old[2] + new[2] - xyz; dest[2] = i < 0 ? 0 : i > 255 ? 255 : i; break; } case BLEND_SCREEN: // ~mult(~old, ~new) j1 = (old[1] + new[1]) * 255 - old[1] * new[1]; dest[1] = (j1 + (j1 >> 8) + 1) >> 8; j2 = (old[2] + new[2]) * 255 - old[2] * new[2]; dest[2] = (j2 + (j2 >> 8) + 1) >> 8; case BLEND_SCREEN + BLEND_NMODES: j0 = (old[0] + new[0]) * 255 - old[0] * new[0]; dest[0] = (j0 + (j0 >> 8) + 1) >> 8; break; case BLEND_MULT: j1 = old[1] * new[1]; dest[1] = (j1 + (j1 >> 8) + 1) >> 8; j2 = old[2] * new[2]; dest[2] = (j2 + (j2 >> 8) + 1) >> 8; case BLEND_MULT + BLEND_NMODES: j0 = old[0] * new[0]; dest[0] = (j0 + (j0 >> 8) + 1) >> 8; break; case BLEND_BURN: // ~div(~old, new) j1 = ((unsigned char)~old[1] << 8) / (new[1] + 1); dest[1] = 255 - j1 >= 0 ? 255 - j1 : 0; j2 = ((unsigned char)~old[2] << 8) / (new[2] + 1); dest[2] = 255 - j2 >= 0 ? 255 - j2 : 0; case BLEND_BURN + BLEND_NMODES: j0 = ((unsigned char)~old[0] << 8) / (new[0] + 1); dest[0] = 255 - j0 >= 0 ? 255 - j0 : 0; break; case BLEND_DODGE: // div(old, ~new) j1 = (old[1] << 8) / ((unsigned char)~new[1] + 1); dest[1] = j1 < 255 ? j1 : 255; j2 = (old[2] << 8) / ((unsigned char)~new[2] + 1); dest[2] = j2 < 255 ? j2 : 255; case BLEND_DODGE + BLEND_NMODES: j0 = (old[0] << 8) / ((unsigned char)~new[0] + 1); dest[0] = j0 < 255 ? j0 : 255; break; case BLEND_DIV: j1 = (old[1] << 8) / (new[1] + 1); dest[1] = j1 < 255 ? j1 : 255; j2 = (old[2] << 8) / (new[2] + 1); dest[2] = j2 < 255 ? j2 : 255; case BLEND_DIV + BLEND_NMODES: j0 = (old[0] << 8) / (new[0] + 1); dest[0] = j0 < 255 ? j0 : 255; break; case BLEND_HLIGHT: j1 = old[1] * new[1] * 2; if (new[1] >= 128) j1 = (old[1] + new[1]) * (255 * 2) - (255 * 255) - j1; dest[1] = (j1 + (j1 >> 8) + 1) >> 8; j2 = old[2] * new[2] * 2; if (new[2] >= 128) j2 = (old[2] + new[2]) * (255 * 2) - (255 * 255) - j2; dest[2] = (j2 + (j2 >> 8) + 1) >> 8; case BLEND_HLIGHT + BLEND_NMODES: j0 = old[0] * new[0] * 2; if (new[0] >= 128) j0 = (old[0] + new[0]) * (255 * 2) - (255 * 255) - j0; dest[0] = (j0 + (j0 >> 8) + 1) >> 8; break; case BLEND_SLIGHT: // !!! This formula is equivalent to one used in Pegtop XFader and GIMP, // !!! and differs from one used by Photoshop and PhotoPaint j1 = old[1] * ((255 * 255) - (unsigned char)~old[1] * (255 - (new[1] << 1))); // Precise division by 255^2 j1 += j1 >> 7; dest[1] = (j1 + ((j1 * 3 + 0x480) >> 16)) >> 16; j2 = old[2] * ((255 * 255) - (unsigned char)~old[2] * (255 - (new[2] << 1))); j2 += j2 >> 7; dest[2] = (j2 + ((j2 * 3 + 0x480) >> 16)) >> 16; case BLEND_SLIGHT + BLEND_NMODES: j0 = old[0] * ((255 * 255) - (unsigned char)~old[0] * (255 - (new[0] << 1))); j0 += j0 >> 7; dest[0] = (j0 + ((j0 * 3 + 0x480) >> 16)) >> 16; break; // "Negation" : ~BLEND_DIFF(~old, new) case BLEND_DIFF: dest[1] = abs(old[1] - new[1]); dest[2] = abs(old[2] - new[2]); case BLEND_DIFF + BLEND_NMODES: dest[0] = abs(old[0] - new[0]); break; case BLEND_DARK: dest[1] = old[1] < new[1] ? old[1] : new[1]; dest[2] = old[2] < new[2] ? old[2] : new[2]; case BLEND_DARK + BLEND_NMODES: dest[0] = old[0] < new[0] ? old[0] : new[0]; break; case BLEND_LIGHT: dest[1] = old[1] > new[1] ? old[1] : new[1]; dest[2] = old[2] > new[2] ? old[2] : new[2]; case BLEND_LIGHT + BLEND_NMODES: dest[0] = old[0] > new[0] ? old[0] : new[0]; break; case BLEND_GRAINX: j1 = old[1] - new[1] + 128; dest[1] = j1 < 0 ? 0 : j1 > 255 ? 255 : j1; j2 = old[2] - new[2] + 128; dest[2] = j2 < 0 ? 0 : j2 > 255 ? 255 : j2; case BLEND_GRAINX + BLEND_NMODES: j0 = old[0] - new[0] + 128; dest[0] = j0 < 0 ? 0 : j0 > 255 ? 255 : j0; break; case BLEND_GRAINM: j1 = old[1] + new[1] - 128; dest[1] = j1 < 0 ? 0 : j1 > 255 ? 255 : j1; j2 = old[2] + new[2] - 128; dest[2] = j2 < 0 ? 0 : j2 > 255 ? 255 : j2; case BLEND_GRAINM + BLEND_NMODES: j0 = old[0] + new[0] - 128; dest[0] = j0 < 0 ? 0 : j0 > 255 ? 255 : j0; break; case BLEND_XHOLD: dest[1] = (0xFFFF + new[1] - old[1]) >> 8; dest[2] = (0xFFFF + new[2] - old[2]) >> 8; case BLEND_XHOLD + BLEND_NMODES: /* For indexed, upper limit is last palette index */ dest[0] = mx & ((0xFFFF + new[0] - old[0]) >> 8); break; // Photoshop's "Linear light" is equivalent to XFader's "Stamp" with swapped A&B default: /* RGB mode applied to 1bpp */ dest[0] = img0[j]; break; } } #undef HHSV } void put_pixel_def(int x, int y) /* Combined */ { unsigned char *src, *ti, *old_image, *old_alpha = NULL; unsigned char fmask, opacity = 255, cset[NUM_CHANNELS + 3]; int i, j, offset, idx, bpp, op = tool_opacity; idx = IS_INDEXED; j = pixel_protected(x, y); if (idx ? j : j == 255) return; bpp = MEM_BPP; ti = cset + (bpp == 3 ? 0 : mem_channel + 3); old_image = mem_undo_opacity ? mem_undo_previous(mem_channel) : mem_img[mem_channel]; if ((mem_channel == CHN_IMAGE) && RGBA_mode) old_alpha = mem_undo_opacity ? mem_undo_previous(CHN_ALPHA) : mem_img[CHN_ALPHA]; offset = x + mem_width * y; if (mem_gradient) /* Gradient mode - ask for one pixel */ { fmask = 0; // Fake mask on input grad_pixels(0, 1, 1, x, y, &fmask, &fmask, ti, cset + CHN_ALPHA + 3); if (!(op = fmask)) return; } else if (mem_blend && blend_src) /* Source mode - copy from layer */ { cset[CHN_ALPHA + 3] = channel_col_A[CHN_ALPHA]; // Fake alpha if ((blend_src == SRC_IMAGE) || // Same layer (blend_src == SRC_LAYER + layer_selected)) { if (bpp == 3) goto set3; cset[mem_channel + 3] = old_image[offset]; goto seta; } else // Other layer { layer_node *t = layer_table + blend_src - SRC_LAYER; image_info *img = &t->image->image_; int u, w; src = img->img[mem_channel]; if (!src) return; // Nothing here w = img->width; u = floor_mod(y - t->y, img->height) * w + floor_mod(x - t->x, w); if (mem_channel == CHN_IMAGE) { if (img->bpp > bpp) return; // Incompatible if (img->bpp < bpp) { png_color *p = img->pal + src[u]; cset[0] = p->red; cset[1] = p->green; cset[2] = p->blue; } else if (bpp == 3) { src += u * 3; cset[0] = src[0]; cset[1] = src[1]; cset[2] = src[2]; } else cset[CHN_IMAGE + 3] = src[u]; } else cset[mem_channel + 3] = src[u]; if ((src = img->img[CHN_ALPHA])) cset[CHN_ALPHA + 3] = src[u]; } } /* Transform mode - copy from dest */ else if (mem_blend && (blend_mode & BLEND_XFORM) && (bpp == 3)) { set3: src = old_image + offset * 3; cset[0] = src[0]; cset[1] = src[1]; cset[2] = src[2]; seta: if (old_alpha) cset[CHN_ALPHA + 3] = old_alpha[offset]; } else /* Default mode - init from pattern */ { i = ((x & 7) + 8 * (y & 7)); cset[mem_channel + 3] = channel_col_[mem_pattern[i]][mem_channel]; cset[CHN_ALPHA + 3] = channel_col_[mem_pattern[i]][CHN_ALPHA]; cset[CHN_IMAGE + 3] = mem_col_pat[i]; /* !!! This must be last! */ i *= 3; cset[0] = mem_col_pat24[i + 0]; cset[1] = mem_col_pat24[i + 1]; cset[2] = mem_col_pat24[i + 2]; } if (!idx) // No use for opacity with indexed images { j = (255 - j) * op; opacity = (j + (j >> 8) + 1) >> 8; } /* Coupled alpha channel */ if (old_alpha && mem_img[CHN_ALPHA]) { unsigned char newc = cset[CHN_ALPHA + 3]; if (opacity < 255) { unsigned char oldc = old_alpha[offset]; int j = oldc * 255 + (newc - oldc) * opacity; if (j && !channel_dis[CHN_ALPHA]) opacity = (255 * opacity * newc) / j; newc = (j + (j >> 8) + 1) >> 8; } mem_img[CHN_ALPHA][offset] = newc; } offset *= bpp; process_img(0, 1, 1, &opacity, mem_img[mem_channel] + offset, old_image + offset, ti, ti, bpp, 0); } /* Repeat pattern in buffer */ static void pattern_rep(unsigned char *dest, unsigned char *src, int ofs, int rep, int len, int bpp) { int l1; ofs *= bpp; rep *= bpp; len *= bpp; l1 = rep - ofs; if (l1 > len) l1 = len; memcpy(dest, src + ofs, l1); if (!(len -= l1)) return; dest += l1; if ((len -= rep) > 0) { memcpy(dest, src, rep); src = dest; dest += rep; while ((len -= rep) > 0) { memcpy(dest, src, rep); dest += rep; rep += rep; } } memcpy(dest, src, len + rep); } /* Merge mask with selection */ static void mask_select(unsigned char *mask, unsigned char *xsel, int l) { int i, j, k; for (i = 0; i < l; i++) { k = mask[i] * (j = xsel[i]); mask[i] = ((k + (k >> 8) + 1) >> 8) + 255 - j; } } enum { PP_DEF = 0, // Default (pattern) PP_OFS, // Offset PP_BUF, // Buffer PP_GRAD, // Gradient PP_LR, // Layer PP_L2R, // Indexed layer to RGB PP_LBUF // Buffered layer }; /* Faster function for large brushes and fills */ void put_pixel_row_def(int x, int y, int len, unsigned char *xsel) { unsigned char tmp_image[ROW_BUFLEN * 3], mask[ROW_BUFLEN], tmp_alpha[ROW_BUFLEN], tmp_opacity[ROW_BUFLEN], *source_image = tmp_image, *source_alpha = NULL, *source_opacity = NULL; unsigned char *old_image, *old_alpha, *srcp, src1[8]; image_info *img = NULL; int offset, use_mask, bpp, idx, uninit_(cx), cy, d = 0, s = ROW_BUFLEN; int mode = PP_DEF; if (len <= 0) return; old_image = mem_undo_opacity ? mem_undo_previous(mem_channel) : mem_img[mem_channel]; old_alpha = mem_undo_opacity ? mem_undo_previous(CHN_ALPHA) : mem_img[CHN_ALPHA]; bpp = MEM_BPP; idx = IS_INDEXED; use_mask = (mem_channel <= CHN_ALPHA) && mem_img[CHN_MASK] && !channel_dis[CHN_MASK]; if ((mem_channel == CHN_IMAGE) && RGBA_mode && mem_img[CHN_ALPHA]) source_alpha = tmp_alpha; if (tool_type == TOOL_CLONE) /* Clone mode */ { cy = y + clone_dy; if ((cy < 0) || (cy >= mem_height)) return; cx = x + clone_dx; if (cx + len > mem_width) len = mem_width - cx; if (cx < 0) len += cx , x -= cx; if (len <= 0) return; d = clone_dx + clone_dy * mem_width; mode = PP_OFS; // Use offset if (!clone_dy && (old_image == mem_img[mem_channel])) { mode = PP_BUF; // Use buffering // Backward step in the rare case of unbufferable overlap if ((clone_dx < 0) && (clone_dx > -len) && (len > ROW_BUFLEN)) x += len - ROW_BUFLEN , s = -ROW_BUFLEN; } } else if (mem_gradient) mode = PP_GRAD; /* Gradient mode */ else if (mem_blend && blend_src) /* Source mode */ { if ((blend_src == SRC_IMAGE) || // Same layer - use offset (blend_src == SRC_LAYER + layer_selected)) mode = PP_OFS; else // From other layer { layer_node *t = layer_table + blend_src - SRC_LAYER; int u, w; img = &t->image->image_; if (!img->img[mem_channel]) return; // Nothing here mode = PP_LR; if (mem_channel == CHN_IMAGE) { if (img->bpp > bpp) return; // Incompatible if (img->bpp < bpp) mode = PP_L2R; // Idx to RGB } w = img->width; cx = floor_mod(x - t->x, w); d = floor_mod(y - t->y, img->height) * w; u = len; if ((len > w) && (w <= ROW_BUFLEN / 2)) // Buffered repeat { u += cx; if (u > ROW_BUFLEN) u = ROW_BUFLEN; if (mode == PP_LR) memcpy(tmp_image, img->img[mem_channel] + d * bpp, w * bpp); else do_convert_rgb(0, 1, w, tmp_image, img->img[CHN_IMAGE] + d, img->pal); pattern_rep(tmp_image + w * bpp, tmp_image, 0, w, u - w, bpp); if (source_alpha && img->img[CHN_ALPHA]) pattern_rep(tmp_alpha, img->img[CHN_ALPHA] + d, 0, w, u, 1); mode = PP_LBUF; } /* Fake alpha */ if (source_alpha && !img->img[CHN_ALPHA]) memset(tmp_alpha, channel_col_A[CHN_ALPHA], u > ROW_BUFLEN ? ROW_BUFLEN : u); } } /* Transform mode - use offset */ else if (mem_blend && (blend_mode & BLEND_XFORM) && (bpp == 3)) mode = PP_OFS; // !!! This depends on buffer length being a multiple of pattern length else /* Default mode - init buffer(s) from pattern */ { int i, dy = 8 * (y & 7), l = len <= ROW_BUFLEN ? len : ROW_BUFLEN; srcp = mem_pattern + dy; if (source_alpha) { for (i = 0; i < 8; i++) src1[i] = channel_col_[srcp[i]][CHN_ALPHA]; pattern_rep(tmp_alpha, src1, x & 7, 8, l, 1); } if (mem_channel != CHN_IMAGE) { for (i = 0; i < 8; i++) src1[i] = channel_col_[srcp[i]][mem_channel]; srcp = src1; } else srcp = idx ? mem_col_pat + dy : mem_col_pat24 + dy * 3; pattern_rep(tmp_image, srcp, x & 7, 8, l, bpp); } offset = x + mem_width * y; idx ^= 1; // 0 if indexed, now while (TRUE) { int l = len <= ROW_BUFLEN ? len : ROW_BUFLEN; /* Offset mode */ if (mode == PP_OFS) { source_image = old_image + (offset + d) * bpp; if (source_alpha) source_alpha = old_alpha + offset + d; } /* Buffered mode */ if (mode == PP_BUF) { memcpy(tmp_image, old_image + (offset + d) * bpp, l * bpp); if (source_alpha) memcpy(tmp_alpha, old_alpha + offset + d, l); } /* Layer mode, direct */ if ((mode == PP_LR) || (mode == PP_L2R)) { int w = img->width; if (l + cx > w) l = w - cx; if (mode == PP_L2R) do_convert_rgb(0, 1, l, tmp_image, img->img[CHN_IMAGE] + d + cx, img->pal); else source_image = img->img[mem_channel] + (d + cx) * bpp; if (source_alpha && img->img[CHN_ALPHA]) source_alpha = img->img[CHN_ALPHA] + d + cx; cx = (cx + l) % w; s = l; } /* Layer mode, buffered */ if (mode == PP_LBUF) { if (l + cx > ROW_BUFLEN) l = ROW_BUFLEN - cx; source_image = tmp_image + cx * bpp; if (source_alpha) source_alpha = tmp_alpha + cx; cx = (cx + l) % img->width; s = l; } /* Buffers stay unchanged for default mode */ /* Mask */ prep_mask(0, 1, l, mask, use_mask ? mem_img[CHN_MASK] + offset : NULL, mem_img[CHN_IMAGE] + offset * mem_img_bpp); if (xsel) { mask_select(mask, xsel, l); xsel += l; } /* Gradient mode */ if (mode == PP_GRAD) grad_pixels(0, 1, l, x, y, mask, source_opacity = tmp_opacity, tmp_image, source_alpha); process_mask(0, 1, l, mask, mem_img[CHN_ALPHA] + offset, old_alpha + offset, source_alpha, source_opacity, idx * tool_opacity, channel_dis[CHN_ALPHA]); process_img(0, 1, l, mask, mem_img[mem_channel] + offset * bpp, old_image + offset * bpp, source_image, tmp_image, bpp, 0); if ((len -= l) <= 0) return; x += s; offset += s; } } void process_mask(int start, int step, int cnt, unsigned char *mask, unsigned char *alphar, unsigned char *alpha0, unsigned char *alpha, unsigned char *trans, int opacity, int noalpha) { unsigned char *xalpha = NULL; int i, j, k; /* Use alpha as selection when pasting RGBA to RGB */ if (alpha && !alphar) { *(trans ? &xalpha : &trans) = alpha; alpha = NULL; } i = start - step; /* Opacity mode */ if (opacity) { while (cnt-- > 0) { unsigned char newc, oldc; i += step; k = (255 - mask[i]) * opacity; if (!k) { mask[i] = 0; continue; } k = (k + (k >> 8) + 1) >> 8; if (trans) /* Have transparency mask */ { if (xalpha) /* Have two :-) */ { k *= xalpha[i]; k = (k + (k >> 8) + 1) >> 8; } k *= trans[i]; k = (k + (k >> 8) + 1) >> 8; } mask[i] = k; if (!alpha || !k) continue; /* Have coupled alpha channel - process it */ newc = alpha[i]; oldc = alpha0[i]; j = oldc * 255 + (newc - oldc) * k; alphar[i] = (j + (j >> 8) + 1) >> 8; if (noalpha) continue; if (j) mask[i] = (255 * k * newc) / j; } } /* Indexed mode - set mask to on-off */ else { while (cnt-- > 0) { i += step; k = mask[i]; if (trans) { unsigned char oldc = trans[i]; if (xalpha) oldc &= xalpha[i]; k |= oldc ^ 255; } mask[i] = k = k ? 0 : 255; if (!alpha || !k) continue; /* Have coupled alpha channel - process it */ alphar[i] = alpha[i]; } } } void process_img(int start, int step, int cnt, unsigned char *mask, unsigned char *imgr, unsigned char *img0, unsigned char *img, unsigned char *xbuf, int bpp, int blend) { int opm = 0; /* Calculate drawing mode */ if (!(blend & BLENDF_SET)) { blend = mem_blend ? blend_mode : 0; if (tint_mode[0]) blend |= tint_mode[1] ^ (tint_mode[2] < 2) ? BLENDF_TINTM : BLENDF_TINT; if (IS_INDEXED) blend |= BLENDF_IDX; } if (blend & BLENDF_INVM) opm = 255; /* Apply blend mode's transform parts */ // !!! Both calls ignore BLENDF_INVM, as are never combined with it if ((blend & BLEND_XFORM) && (bpp == 3)) { do_transform(start, step, cnt, mask, xbuf, img, 256); img = xbuf; } if (blend & BLEND_MMASK) { blend_pixels(start, step, cnt, mask, xbuf, img0, img, bpp, blend); img = xbuf; } /* Indexed image or utility channel */ if (bpp < 3) { unsigned char newc, oldc; int i, j, mx = blend & BLENDF_IDX ? mem_cols - 1 : 255; for (i = start; cnt-- > 0; i += step) { j = mask[i] ^ opm; if (!j) continue; newc = img[i]; oldc = img0[i]; if (!(blend & (BLENDF_TINTM | BLENDF_TINT))); // Do nothing else if (blend & BLENDF_TINTM) newc = oldc + newc < mx ? oldc + newc : mx; else newc = oldc > newc ? oldc - newc : 0; if (j < 255) { j = oldc * 255 + (newc - oldc) * j; newc = (j + (j >> 8) + 1) >> 8; } imgr[i] = newc; } } /* RGB image */ else { int ops = (blend >> BLEND_RGBSHIFT) & 7; unsigned char r, g, b, nrgb[3]; int j, opacity; /* Make mask */ ops = (ops + (ops >> 1) * 0xFE + (ops >> 2) * 0xFE00) * 0xFF; img0 += (start - step) * 3; img += (start - step) * 3; imgr += (start - step) * 3; mask += start - step; while (cnt-- > 0) { img0 += step * 3; img += step * 3; imgr += step * 3; mask += step; opacity = *mask ^ opm; if (!opacity) continue; nrgb[0] = img[0]; nrgb[1] = img[1]; nrgb[2] = img[2]; /* !!! On x86, register pressure here is too large already, so rereading img0 * is preferable to lengthening r/g/b's living ranges - WJ */ if (blend & (BLENDF_TINTM | BLENDF_TINT)) { r = img0[0]; g = img0[1]; b = img0[2]; if (blend & BLENDF_TINTM) { nrgb[0] = r > 255 - nrgb[0] ? 255 : r + nrgb[0]; nrgb[1] = g > 255 - nrgb[1] ? 255 : g + nrgb[1]; nrgb[2] = b > 255 - nrgb[2] ? 255 : b + nrgb[2]; } else { nrgb[0] = r > nrgb[0] ? r - nrgb[0] : 0; nrgb[1] = g > nrgb[1] ? g - nrgb[1] : 0; nrgb[2] = b > nrgb[2] ? b - nrgb[2] : 0; } } if (opacity == 255); else if (paint_gamma) { double r, g, b, o = opacity / 255.0; r = gamma256[img0[0]]; r += (gamma256[nrgb[0]] - r) * o; g = gamma256[img0[1]]; g += (gamma256[nrgb[1]] - g) * o; b = gamma256[img0[2]]; b += (gamma256[nrgb[2]] - b) * o; nrgb[0] = UNGAMMA256(r); nrgb[1] = UNGAMMA256(g); nrgb[2] = UNGAMMA256(b); } else { r = img0[0]; g = img0[1]; b = img0[2]; j = r * 255 + (nrgb[0] - r) * opacity; nrgb[0] = (j + (j >> 8) + 1) >> 8; j = g * 255 + (nrgb[1] - g) * opacity; nrgb[1] = (j + (j >> 8) + 1) >> 8; j = b * 255 + (nrgb[2] - b) * opacity; nrgb[2] = (j + (j >> 8) + 1) >> 8; } if (ops) { nrgb[0] ^= (nrgb[0] ^ img0[0]) & ops; nrgb[1] ^= (nrgb[1] ^ img0[1]) & (ops >> 8); nrgb[2] ^= (nrgb[2] ^ img0[2]) & (ops >> 16); } imgr[0] = nrgb[0]; imgr[1] = nrgb[1]; imgr[2] = nrgb[2]; } } } /* !!! This assumes dest area lies entirely within src, its bpp matches src's * current channel bpp, and it has alpha channel only if src has it too */ void copy_area(image_info *dest, image_info *src, int x, int y) { int w = dest->width, h = dest->height, bpp = dest->bpp, ww = src->width; int i, ofs, delta, len; /* Current channel */ ofs = (y * ww + x) * bpp; delta = 0; len = w * bpp; for (i = 0; i < h; i++) { memcpy(dest->img[CHN_IMAGE] + delta, src->img[mem_channel] + ofs, len); ofs += ww * bpp; delta += len; } /* Alpha channel */ if (!dest->img[CHN_ALPHA]) return; ofs = y * ww + x; delta = 0; for (i = 0; i < h; i++) { memcpy(dest->img[CHN_ALPHA] + delta, src->img[CHN_ALPHA] + ofs, w); ofs += ww; delta += w; } } int mem_count_all_cols() // Count all colours - Using main image { return mem_count_all_cols_real(mem_img[CHN_IMAGE], mem_width, mem_height); } int mem_count_all_cols_real(unsigned char *im, int w, int h) // Count all colours - very memory greedy { guint32 *tab; int i, j, k, ix; j = 0x80000; tab = calloc(j, sizeof(guint32)); // HUGE colour cube if (!tab) return -1; // Not enough memory Mr Greedy ;-) k = w * h; for (i = 0; i < k; i++) // Scan each pixel { ix = (im[0] >> 5) + (im[1] << 3) + (im[2] << 11); tab[ix] |= 1U << (im[0] & 31); im += 3; } // Count each colour for (i = k = 0; i < j; i++) k += bitcount(tab[i]); free(tab); return k; } int mem_cols_used(png_color *pal) // Count and collect colours used in main RGB image { if ( mem_img_bpp == 1 ) return -1; // RGB only return (mem_cols_used_real(mem_img[CHN_IMAGE], mem_width, mem_height, pal)); } int mem_cols_used_real(unsigned char *im, int w, int h, png_color *pal) // Count and collect up to 256 colours used in RGB chunk { rgb_256_map m; int i, j = w * h, k, l, n, v, vn, res, pix; memset(&m, 0, sizeof(m)); for (i = res = 0; i < j; i++ , im += 3) // Skim all pixels { pix = MEM_2_INT(im, 0); k = pix & 0xFF; n = (pix >> 8) & 0x1F; v = pix >> (8 + 5); /* Test presence on both tiers at once: if the 1st is unset, * the 2nd simply defaults to block #0 */ vn = m.rgx[v] * 32 + n; l = m.vx[vn] * 8 + (k >> 5); if ((m.rg[v] >> n) & 1 & (m.b[l] >> (k & 0x1F))) continue; /* New color - stop if too many */ if (++res > 256) break; /* Insert into tiers */ if (!m.rg[v]) m.rgx[v] = m.nv++; vn = m.rgx[v] * 32 + n; if (!((m.rg[v] >> n) & 1)) m.vx[vn] = m.nb++ , m.rg[v] |= 1U << n; l = m.vx[vn] * 8 + (k >> 5); m.b[l] |= 1U << (k & 0x1F); /* Add to palette */ if (!pal) continue; pal->red = im[0]; pal->green = im[1]; pal->blue = im[2]; pal++; } return (res); } //// EFFECTS static inline double dist(int n1, int n2) { return (sqrt(n1 * n1 + n2 * n2)); } void do_effect(int type, int param) { unsigned char *src, *dest, *tmp, *mask, *buf; int i, j, uninit_(k), k1, k2, bpp, ll, dxp1, dxm1, dyp1, dym1; int op, md, ms; double blur = (double)param / 200.0; bpp = MEM_BPP; ll = mem_width * bpp; ms = bpp == 3 ? 1 : 4; src = mem_undo_previous(mem_channel); mask = malloc(mem_width * (bpp + 1)); if (!mask) { memory_errors(1); return; } buf = mask + mem_width; progress_init(_("Applying Effect"), 1); for (i = 0; i < mem_height; i++) { row_protected(0, i, mem_width, tmp = mask); dyp1 = i < mem_height - 1 ? ll : -ll; dym1 = i ? -ll : ll; dest = buf; for (md = j = 0; j < ll; j++ , src++ , dest++) { op = *tmp; /* One step for 1 or 3 bytes */ md += ms + (md >> 1); tmp += md >> 2; md &= 3; if (op == 255) continue; dxp1 = j < ll - bpp ? bpp : -bpp; dxm1 = j >= bpp ? -bpp : bpp; switch (type) { case FX_EDGE: /* Edge detect */ k = *src; k = abs(k - src[dym1]) + abs(k - src[dyp1]) + abs(k - src[dxm1]) + abs(k - src[dxp1]); k += k >> 1; break; case FX_EMBOSS: /* Emboss */ k = src[dym1] + src[dxm1] + src[dxm1 + dym1] + src[dxp1 + dym1]; k = k / 4 - *src + 127; break; case FX_SHARPEN: /* Edge sharpen */ k = src[dym1] + src[dyp1] + src[dxm1] + src[dxp1] - 4 * src[0]; k = *src - blur * k; break; case FX_SOFTEN: /* Edge soften */ k = src[dym1] + src[dyp1] + src[dxm1] + src[dxp1] - 4 * src[0]; k = *src + (5 * k) / (125 - param); break; case FX_SOBEL: /* Another edge detector */ k = dist((src[dxp1] - src[dxm1]) * 2 + src[dym1 + dxp1] - src[dym1 + dxm1] + src[dyp1 + dxp1] - src[dyp1 + dxm1], (src[dyp1] - src[dym1]) * 2 + src[dyp1 + dxm1] + src[dyp1 + dxp1] - src[dym1 + dxm1] - src[dym1 + dxp1]); break; case FX_PREWITT: /* Yet another edge detector */ /* Actually, the filter kernel used is "Robinson"; what is attributable to * Prewitt is "compass filtering", which can be done with other filter * kernels too - WJ */ case FX_KIRSCH: /* Compass detector with another kernel */ /* Optimized compass detection algorithm: I calculate three values (compass, * plus and minus) and then mix them according to filter type - WJ */ k = 0; k1 = src[dyp1 + dxm1] - src[dxp1]; if (k < k1) k = k1; k1 += src[dyp1] - src[dym1 + dxp1]; if (k < k1) k = k1; k1 += src[dyp1 + dxp1] - src[dym1]; if (k < k1) k = k1; k1 += src[dxp1] - src[dym1 + dxm1]; if (k < k1) k = k1; k1 += src[dym1 + dxp1] - src[dxm1]; if (k < k1) k = k1; k1 += src[dym1] - src[dyp1 + dxm1]; if (k < k1) k = k1; k1 += src[dym1 + dxm1] - src[dyp1]; if (k < k1) k = k1; k1 = src[dym1 + dxm1] + src[dym1] + src[dym1 + dxp1] + src[dxm1] + src[dxp1]; k2 = src[dyp1 + dxm1] + src[dyp1] + src[dyp1 + dxp1]; if (type == FX_PREWITT) k = k * 2 + k1 - k2 - src[0] * 2; else /* if (type == FX_KIRSCH) */ k = (k * 8 + k1 * 3 - k2 * 5) / 4; // Division is for equalizing weight of edge break; case FX_GRADIENT: /* Still another edge detector */ k = 4.0 * dist(src[dxp1] - src[0], src[dyp1] - src[0]); break; case FX_ROBERTS: /* One more edge detector */ k = 4.0 * dist(src[dyp1 + dxp1] - src[0], src[dxp1] - src[dyp1]); break; case FX_LAPLACE: /* The last edge detector... I hope */ k = src[dym1 + dxm1] + src[dym1] + src[dym1 + dxp1] + src[dxm1] - 8 * src[0] + src[dxp1] + src[dyp1 + dxm1] + src[dyp1] + src[dyp1 + dxp1]; break; case FX_MORPHEDGE: /* Morphological edge detection */ case FX_ERODE: /* Greyscale erosion */ k = src[0]; if (k > src[dym1 + dxm1]) k = src[dym1 + dxm1]; if (k > src[dym1]) k = src[dym1]; if (k > src[dym1 + dxp1]) k = src[dym1 + dxp1]; if (k > src[dxm1]) k = src[dxm1]; if (k > src[dxp1]) k = src[dxp1]; if (k > src[dyp1 + dxm1]) k = src[dyp1 + dxm1]; if (k > src[dyp1]) k = src[dyp1]; if (k > src[dyp1 + dxp1]) k = src[dyp1 + dxp1]; if (type == FX_MORPHEDGE) k = (src[0] - k) * 2; break; case FX_DILATE: /* Greyscale dilation */ k = src[0]; if (k < src[dym1 + dxm1]) k = src[dym1 + dxm1]; if (k < src[dym1]) k = src[dym1]; if (k < src[dym1 + dxp1]) k = src[dym1 + dxp1]; if (k < src[dxm1]) k = src[dxm1]; if (k < src[dxp1]) k = src[dxp1]; if (k < src[dyp1 + dxm1]) k = src[dyp1 + dxm1]; if (k < src[dyp1]) k = src[dyp1]; if (k < src[dyp1 + dxp1]) k = src[dyp1 + dxp1]; break; } *dest = k < 0 ? 0 : k > 0xFF ? 0xFF : k; } dest = mem_img[mem_channel] + i * ll; process_img(0, 1, mem_width, mask, dest, dest, buf, NULL, bpp, BLENDF_SET | BLENDF_INVM); if ((i * 10) % mem_height >= mem_height - 10) if (progress_update((float)(i + 1) / mem_height)) break; } free(mask); progress_end(); } /* Apply vertical filter */ static void vert_gauss(unsigned char *chan, int w, int h, int y, double *temp, double *gaussY, int lenY, int gcor) { unsigned char *src0, *src1; double gv = gaussY[0]; int j, k, mh2 = h > 1 ? h + h - 2 : 1; src0 = chan + y * w; if (gcor) /* Gamma-correct RGB values */ { for (j = 0; j < w; j++) temp[j] = gamma256[src0[j]] * gv; } else /* Leave RGB values as they were */ { for (j = 0; j < w; j++) temp[j] = src0[j] * gv; } for (j = 1; j < lenY; j++) { double gv = gaussY[j]; k = (y + j) % mh2; if (k >= h) k = mh2 - k; src0 = chan + k * w; k = abs(y - j) % mh2; if (k >= h) k = mh2 - k; src1 = chan + k * w; if (gcor) /* Gamma-correct */ { for (k = 0; k < w; k++) { temp[k] += (gamma256[src0[k]] + gamma256[src1[k]]) * gv; } } else /* Leave alone */ { for (k = 0; k < w; k++) { temp[k] += (src0[k] + src1[k]) * gv; } } } } typedef struct { double *gaussX, *gaussY, *temp; unsigned char *mask; int *idx; int lenX, lenY; int channel, gcor; // For unsharp mask int threshold; double amount; } gaussd; /* Extend horizontal array, using precomputed indices */ static void gauss_extend(gaussd *gd, double *temp, int w, int bpp) { double *dest, *src; int i, l = gd->lenX - 1, *tp = gd->idx; dest = temp - l * bpp; while (TRUE) { for (i = 0; i < l; i++ , dest += bpp) { src = temp + *tp++ * bpp; dest[0] = src[0]; if (bpp == 1) continue; dest[1] = src[1]; dest[2] = src[2]; } if (dest != temp) break; // "w * bpp" is definitely nonzero dest += w * bpp; } } /* Apply RGB horizontal filter */ static void hor_gauss3(double *temp, int w, double *gaussX, int lenX, unsigned char *mask) { int j, jj, k, x1, x2; double sum0, sum1, sum2; for (j = jj = 0; jj < w; jj++ , j += 3) { if (mask[jj] == 255) continue; sum0 = temp[j] * gaussX[0]; sum1 = temp[j + 1] * gaussX[0]; sum2 = temp[j + 2] * gaussX[0]; x1 = x2 = j; for (k = 1; k < lenX; k++) { double gv = gaussX[k]; x1 -= 3; x2 += 3; sum0 += (temp[x1] + temp[x2]) * gv; sum1 += (temp[x1 + 1] + temp[x2 + 1]) * gv; sum2 += (temp[x1 + 2] + temp[x2 + 2]) * gv; } temp[x1] = sum0; temp[x1 + 1] = sum1; temp[x1 + 2] = sum2; } } // !!! Will need extra checks if used for out-of-range values static void pack_row3(unsigned char *dest, const double *src, int w, int gcor, unsigned char *mask) { int j, jj, uninit_(k0), uninit_(k1), uninit_(k2), m; double sum0, sum1, sum2, mm; for (j = jj = 0; jj < w; jj++ , j += 3) { if (mask[jj] == 255) continue; sum0 = src[j]; sum1 = src[j + 1]; sum2 = src[j + 2]; if (!gcor) /* Simply round to nearest */ { k0 = rint(sum0); k1 = rint(sum1); k2 = rint(sum2); } m = mask[jj]; if (paint_gamma && m) /* Gamma corrected mask blend */ { if (!gcor) // RGB to linear { sum0 = gamma256[k0]; sum1 = gamma256[k1]; sum2 = gamma256[k2]; } mm = m / 255.0; sum0 += (gamma256[dest[j + 0]] - sum0) * mm; sum1 += (gamma256[dest[j + 1]] - sum1) * mm; sum2 += (gamma256[dest[j + 2]] - sum2) * mm; m = 0; goto ungamma; } if (gcor) /* Reverse gamma correction */ { ungamma: k0 = UNGAMMA256(sum0); k1 = UNGAMMA256(sum1); k2 = UNGAMMA256(sum2); } k0 = k0 * 255 + (dest[j] - k0) * m; dest[j] = (k0 + (k0 >> 8) + 1) >> 8; k1 = k1 * 255 + (dest[j + 1] - k1) * m; dest[j + 1] = (k1 + (k1 >> 8) + 1) >> 8; k2 = k2 * 255 + (dest[j + 2] - k2) * m; dest[j + 2] = (k2 + (k2 >> 8) + 1) >> 8; } } /* Most-used variables are local to inner blocks to shorten their live ranges - * otherwise stupid compilers might allocate them to memory */ static void gauss_filter(tcb *thread) { gaussd *gd = thread->data; int lenX = gd->lenX, gcor = gd->gcor, channel = gd->channel; int i, ii, cnt, wid, bpp; double sum, *temp, *gaussX = gd->gaussX; unsigned char *chan, *dest, *mask = gd->mask; cnt = thread->nsteps; bpp = BPP(channel); wid = mem_width * bpp; chan = mem_undo_previous(channel); temp = gd->temp + (lenX - 1) * bpp; for (i = thread->step0 , ii = 0; ii < cnt; i++ , ii++) { vert_gauss(chan, wid, mem_height, i, temp, gd->gaussY, gd->lenY, gcor); gauss_extend(gd, temp, mem_width, bpp); row_protected(0, i, mem_width, mask); dest = mem_img[channel] + i * wid; if (bpp == 3) /* Run 3-bpp horizontal filter */ { hor_gauss3(temp, mem_width, gaussX, lenX, mask); pack_row3(dest, gd->temp, mem_width, gcor, mask); } else /* Run 1-bpp horizontal filter - no gamma here */ { int j, k, k0; for (j = 0; j < mem_width; j++) { if (mask[j] == 255) continue; sum = temp[j] * gaussX[0]; for (k = 1; k < lenX; k++) { sum += (temp[j - k] + temp[j + k]) * gaussX[k]; } k0 = rint(sum); k0 = k0 * 255 + (dest[j] - k0) * mask[j]; dest[j] = (k0 + (k0 >> 8) + 1) >> 8; } } if (thread_step(thread, ii + 1, cnt, 10)) break; } thread_done(thread); } /* The inner loops are coded the way they are because one must spell everything * out for dumb compiler to get acceptable code out of it */ static void gauss_filter_rgba(tcb *thread) { gaussd *gd = thread->data; int i, ii, cnt, mh2, lenX = gd->lenX, lenY = gd->lenY, gcor = gd->gcor; double sum, sum1, sum2, mult, *temp, *tmpa, *atmp, *src, *gaussX, *gaussY; unsigned char *chan, *dest, *alpha, *dsta, *mask = gd->mask; cnt = thread->nsteps; chan = mem_undo_previous(CHN_IMAGE); alpha = mem_undo_previous(CHN_ALPHA); gaussX = gd->gaussX; gaussY = gd->gaussY; temp = gd->temp + (lenX - 1) * 3; mh2 = mem_height > 1 ? 2 * mem_height - 2 : 1; /* Set up the main row buffer and process the image */ tmpa = temp + mem_width * 3 + (lenX - 1) * (3 + 3); atmp = tmpa + mem_width * 3 + (lenX - 1) * (3 + 1); for (i = thread->step0 , ii = 0; ii < cnt; i++ , ii++) { /* Apply vertical filter */ { unsigned char *srcc, *src0, *src1; unsigned char *alff, *alf0, *alf1; int j, k; alff = alpha + i * mem_width; srcc = chan + i * mem_width * 3; if (gcor) /* Gamma correct */ { double gk = gaussY[0]; int j, jj; for (j = jj = 0; j < mem_width; j++) { double ak, tv; atmp[j] = ak = alff[j] * gk; temp[jj] = (tv = gamma256[srcc[jj]]) * gk; tmpa[jj++] = tv * ak; temp[jj] = (tv = gamma256[srcc[jj]]) * gk; tmpa[jj++] = tv * ak; temp[jj] = (tv = gamma256[srcc[jj]]) * gk; tmpa[jj++] = tv * ak; } } else /* Use as is */ { double gk = gaussY[0]; int j, jj; for (j = jj = 0; j < mem_width; j++) { double ak, tv; atmp[j] = ak = alff[j] * gk; temp[jj] = (tv = srcc[jj]) * gk; tmpa[jj++] = tv * ak; temp[jj] = (tv = srcc[jj]) * gk; tmpa[jj++] = tv * ak; temp[jj] = (tv = srcc[jj]) * gk; tmpa[jj++] = tv * ak; } } for (j = 1; j < lenY; j++) { double gk = gaussY[j]; k = (i + j) % mh2; if (k >= mem_height) k = mh2 - k; alf0 = alpha + k * mem_width; src0 = chan + k * mem_width * 3; k = abs(i - j) % mh2; if (k >= mem_height) k = mh2 - k; alf1 = alpha + k * mem_width; src1 = chan + k * mem_width * 3; if (gcor) /* Gamma correct */ { int k, kk; for (k = kk = 0; k < mem_width; k++) { double ak0, ak1, tv0, tv1; ak0 = alf0[k] * gk; ak1 = alf1[k] * gk; atmp[k] += ak0 + ak1; tv0 = gamma256[src0[kk]]; tv1 = gamma256[src1[kk]]; temp[kk] += (tv0 + tv1) * gk; tmpa[kk++] += tv0 * ak0 + tv1 * ak1; tv0 = gamma256[src0[kk]]; tv1 = gamma256[src1[kk]]; temp[kk] += (tv0 + tv1) * gk; tmpa[kk++] += tv0 * ak0 + tv1 * ak1; tv0 = gamma256[src0[kk]]; tv1 = gamma256[src1[kk]]; temp[kk] += (tv0 + tv1) * gk; tmpa[kk++] += tv0 * ak0 + tv1 * ak1; } } else /* Use as is */ { int k, kk; for (k = kk = 0; k < mem_width; k++) { double ak0, ak1, tv0, tv1; ak0 = alf0[k] * gk; ak1 = alf1[k] * gk; atmp[k] += ak0 + ak1; tv0 = src0[kk]; tv1 = src1[kk]; temp[kk] += (tv0 + tv1) * gk; tmpa[kk++] += tv0 * ak0 + tv1 * ak1; tv0 = src0[kk]; tv1 = src1[kk]; temp[kk] += (tv0 + tv1) * gk; tmpa[kk++] += tv0 * ak0 + tv1 * ak1; tv0 = src0[kk]; tv1 = src1[kk]; temp[kk] += (tv0 + tv1) * gk; tmpa[kk++] += tv0 * ak0 + tv1 * ak1; } } } } gauss_extend(gd, temp, mem_width, 3); gauss_extend(gd, tmpa, mem_width, 3); gauss_extend(gd, atmp, mem_width, 1); row_protected(0, i, mem_width, mask); dest = mem_img[CHN_IMAGE] + i * mem_width * 3; dsta = mem_img[CHN_ALPHA] + i * mem_width; /* Horizontal RGBA filter */ { int j, jj, k, kk, x1, x2; for (j = jj = 0; j < mem_width; j++ , jj += 3) { if (mask[j] == 255) continue; sum = atmp[j] * gaussX[0]; for (k = 1; k < lenX; k++) { sum += (atmp[j - k] + atmp[j + k]) * gaussX[k]; } k = rint(sum); src = temp; mult = 1.0; if (k) { src = tmpa; mult /= sum; } kk = mask[j]; k = k * 255 + (dsta[j] - k) * kk; if (k) mask[j] = (255 * kk * dsta[j]) / k; dsta[j] = (k + (k >> 8) + 1) >> 8; sum = src[jj] * gaussX[0]; sum1 = src[jj + 1] * gaussX[0]; sum2 = src[jj + 2] * gaussX[0]; x1 = x2 = jj; for (k = 1; k < lenX; k++) { double gv = gaussX[k]; x1 -= 3; x2 += 3; sum += (src[x1] + src[x2]) * gv; sum1 += (src[x1 + 1] + src[x2 + 1]) * gv; sum2 += (src[x1 + 2] + src[x2 + 2]) * gv; } temp[x1] = sum * mult; temp[x1 + 1] = sum1 * mult; temp[x1 + 2] = sum2 * mult; } pack_row3(dest, gd->temp, mem_width, gcor, mask); } if (thread_step(thread, ii + 1, cnt, 10)) break; } thread_done(thread); } /* Modes: 0 - normal, 1 - RGBA, 2 - DoG */ static threaddata *init_gauss(gaussd *gd, double radiusX, double radiusY, int mode) { threaddata *tdata; int i, j, k, l, lenX, lenY, w, bpp = MEM_BPP; double sum, exkX, exkY, *gauss; /* Cutoff point is where gaussian becomes < 1/255 */ gd->lenX = lenX = ceil(radiusX) + 2; gd->lenY = lenY = ceil(radiusY) + 2; exkX = -log(255.0) / ((radiusX + 1.0) * (radiusX + 1.0)); exkY = -log(255.0) / ((radiusY + 1.0) * (radiusY + 1.0)); /* Allocate memory */ if (mode == 1) i = 7; /* Extra linebuffer for RGBA */ else if (mode == 2) i = bpp + bpp; /* Extra buffer in DoG mode */ else i = bpp; l = 2 * (lenX - 1); w = mem_width + l; tdata = talloc(MA_ALIGN_DOUBLE, image_threads(mem_width, mem_height), gd, sizeof(gaussd), &gd->gaussX, lenX * sizeof(double), &gd->gaussY, lenY * sizeof(double), &gd->idx, l * sizeof(int), NULL, &gd->temp, i * w * sizeof(double), &gd->mask, mem_width, NULL); if (!tdata) return (NULL); /* Prepare filters */ j = lenX; gauss = gd->gaussX; while (1) { sum = gauss[0] = 1.0; for (i = 1; i < j; i++) { sum += 2.0 * (gauss[i] = exp((double)(i * i) * exkX)); } sum = 1.0 / sum; for (i = 0; i < j; i++) { gauss[i] *= sum; } if (gauss != gd->gaussX) break; exkX = exkY; j = lenY; gauss = gd->gaussY; } /* Prepare horizontal indices, assuming mirror boundary */ if (mem_width > 1) // Else, good already (zeroed out) { int *idx = gd->idx + lenX - 1; // To simplify indexing k = 2 * mem_width - 2; for (i = 1; i < lenX; i++) { j = i % k; idx[-i] = j < mem_width ? j : k - j; j = (mem_width + i - 1) % k; idx[i - 1] = j < mem_width ? j : k - j; } } return (tdata); } /* Gaussian blur */ void mem_gauss(double radiusX, double radiusY, int gcor) { gaussd gd; threaddata *tdata; int rgba, rgbb; /* RGBA or not? */ rgba = (mem_channel == CHN_IMAGE) && mem_img[CHN_ALPHA] && RGBA_mode; rgbb = rgba && !channel_dis[CHN_ALPHA]; /* Create arrays */ if (mem_channel != CHN_IMAGE) gcor = FALSE; gd.gcor = gcor; gd.channel = mem_channel; tdata = init_gauss(&gd, radiusX, radiusY, rgbb); if (!tdata) { memory_errors(1); return; } progress_init(_("Gaussian Blur"), 1); if (rgbb) /* Coupled RGBA */ launch_threads(gauss_filter_rgba, tdata, NULL, mem_height); else /* One channel, or maybe two */ { launch_threads(gauss_filter, tdata, NULL, mem_height); if (rgba) /* Need to process alpha too */ { #ifdef U_THREADS int i, j = tdata->count; for (i = 0; i < j; i++) { gaussd *gp = tdata->threads[i]->data; gp->channel = CHN_ALPHA; gp->gcor = FALSE; } #else gaussd *gp = tdata->threads[0]->data; gp->channel = CHN_ALPHA; gp->gcor = FALSE; #endif launch_threads(gauss_filter, tdata, NULL, mem_height); } } progress_end(); free(tdata); } static void unsharp_filter(tcb *thread) { gaussd *gd = thread->data; int lenX = gd->lenX, threshold = gd->threshold, channel = gd->channel; int i, ii, cnt, wid, bpp, gcor = gd->gcor; double *temp, *gaussX = gd->gaussX, *gt = gd->temp; double sum, amount = gd->amount, u = gcor ? 1.0 : 255.0; unsigned char *chan, *dest, *mask = gd->mask; cnt = thread->nsteps; bpp = BPP(channel); wid = mem_width * bpp; chan = mem_undo_previous(channel); temp = gd->temp + (lenX - 1) * bpp; for (i = thread->step0 , ii = 0; ii < cnt; i++ , ii++) { vert_gauss(chan, wid, mem_height, i, temp, gd->gaussY, gd->lenY, gcor); gauss_extend(gd, temp, mem_width, bpp); row_protected(0, i, mem_width, mask); dest = mem_img[channel] + i * wid; if (bpp == 3) /* Run 3-bpp horizontal filter */ { int j, jj, k, k1, k2; hor_gauss3(temp, mem_width, gaussX, lenX, mask); /* Threshold to mask */ if (threshold) for (j = jj = 0; jj < mem_width; jj++ , j += 3) { if (mask[jj] == 255) continue; if (gcor) /* Reverse gamma correction */ { k = UNGAMMA256(gt[j]); k1 = UNGAMMA256(gt[j + 1]); k2 = UNGAMMA256(gt[j + 2]); } else /* Simply round to nearest */ { k = rint(gt[j]); k1 = rint(gt[j + 1]); k2 = rint(gt[j + 2]); } /* !!! GIMP has an apparent bug which I won't reproduce - so mtPaint's * threshold value means _actual_ difference, not half of it - WJ */ if ((abs(k - dest[j]) < threshold) && (abs(k1 - dest[j + 1]) < threshold) && (abs(k2 - dest[j + 2]) < threshold)) mask[jj] = 255; } /* !!! Mask is ignored here - but this pass takes about * 25% time at worst, and masking adds 5% time at best; * so the common case of no mask is optimized for - WJ */ k = mem_width * 3; for (j = 0; j < k; j++) { sum = gcor ? gamma256[dest[j]] : dest[j]; sum += amount * (sum - gt[j]); /* Limit values, for pack_row3() cannot */ gt[j] = sum < 0.0 ? 0.0 : sum > u ? u : sum; } pack_row3(dest, gt, mem_width, gcor, mask); } else /* Run 1-bpp horizontal filter - no gamma here */ { int j, k; for (j = 0; j < mem_width; j++) { if (mask[j] == 255) continue; sum = temp[j] * gaussX[0]; for (k = 1; k < lenX; k++) { sum += (temp[j - k] + temp[j + k]) * gaussX[k]; } k = rint(sum); /* Threshold */ /* !!! Same non-bug as above */ if (abs(k - dest[j]) < threshold) continue; /* Combine values */ k = rint(dest[j] + amount * (dest[j] - sum)); k = k < 0 ? 0 : k > 255 ? 255 : k; /* Store the result */ k = k * 255 + (dest[j] - k) * mask[j]; dest[j] = (k + (k >> 8) + 1) >> 8; } } if (thread_step(thread, ii + 1, cnt, 10)) break; } thread_done(thread); } /* Unsharp mask */ void mem_unsharp(double radius, double amount, int threshold, int gcor) { gaussd gd; threaddata *tdata; /* Create arrays */ if (mem_channel != CHN_IMAGE) gcor = 0; gd.gcor = gcor; gd.channel = mem_channel; gd.amount = amount; gd.threshold = threshold; // !!! No RGBA mode for now tdata = init_gauss(&gd, radius, radius, 0); if (!tdata) { memory_errors(1); return; } /* Run filter */ launch_threads(unsharp_filter, tdata, _("Unsharp Mask"), mem_height); free(tdata); } /* Retroactive masking - by blending with undo frame */ void mask_merge(unsigned char *old, int channel, unsigned char *mask) { chanlist tlist; unsigned char *dest, *mask0 = NULL; int i, ofs, bpp = BPP(channel); memcpy(tlist, mem_img, sizeof(chanlist)); tlist[channel] = old; /* Clear mask or copy mask channel into it */ if ((channel <= CHN_ALPHA) && mem_img[CHN_MASK] && !channel_dis[CHN_MASK]) mask0 = tlist[CHN_MASK]; for (i = 0; i < mem_height; i++) { ofs = i * mem_width; prep_mask(0, 1, mem_width, mask, mask0 ? mask0 + ofs : NULL, tlist[CHN_IMAGE] + ofs * mem_img_bpp); dest = mem_img[channel] + ofs * bpp; process_img(0, 1, mem_width, mask, dest, dest, old + ofs * bpp, NULL, bpp, BLENDF_SET); } } static void dog_filter(tcb *thread) { gaussd *gd = thread->data; int channel = gd->channel, bpp = BPP(channel), wid = mem_width * bpp; int i, ii, cnt, gcor = gd->gcor; int lenW = gd->lenX, lenN = gd->lenY; double sum, sum1, sum2, *tmp1, *tmp2; double *gaussW = gd->gaussX, *gaussN = gd->gaussY; unsigned char *chan, *dest; cnt = thread->nsteps; chan = mem_undo_previous(channel); tmp1 = gd->temp + (lenW - 1) * bpp; tmp2 = tmp1 + wid + (lenW - 1) * bpp * 2; for (i = thread->step0 , ii = 0; ii < cnt; i++ , ii++) { vert_gauss(chan, wid, mem_height, i, tmp1, gaussW, lenW, gcor); vert_gauss(chan, wid, mem_height, i, tmp2, gaussN, lenN, gcor); gauss_extend(gd, tmp1, mem_width, bpp); gauss_extend(gd, tmp2, mem_width, bpp); dest = mem_img[channel] + i * wid; if (bpp == 3) /* Run 3-bpp horizontal filter */ { int j, jj, k, k1, k2; for (j = jj = 0; jj < mem_width; jj++ , j += 3) { int x1, x2, x3, x4; sum = tmp1[j] * gaussW[0] - tmp2[j] * gaussN[0]; sum1 = tmp1[j + 1] * gaussW[0] - tmp2[j + 1] * gaussN[0]; sum2 = tmp1[j + 2] * gaussW[0] - tmp2[j + 2] * gaussN[0]; x1 = x2 = j; for (k = 1; k < lenW; k++) { double gv = gaussW[k]; x1 -= 3; x2 += 3; sum += (tmp1[x1] + tmp1[x2]) * gv; sum1 += (tmp1[x1 + 1] + tmp1[x2 + 1]) * gv; sum2 += (tmp1[x1 + 2] + tmp1[x2 + 2]) * gv; } x3 = x4 = j; for (k = 1; k < lenN; k++) { double gv = gaussN[k]; x3 -= 3; x4 += 3; sum -= (tmp2[x3] + tmp2[x4]) * gv; sum1 -= (tmp2[x3 + 1] + tmp2[x4 + 1]) * gv; sum2 -= (tmp2[x3 + 2] + tmp2[x4 + 2]) * gv; } if (gcor) { #if 1 /* Reverse gamma - but does it make sense? */ k = UNGAMMA256X(sum); k1 = UNGAMMA256X(sum1); k2 = UNGAMMA256X(sum2); #else /* Let values remain linear */ k = rint(sum * 255.0); k = k < 0 ? 0 : k; k1 = rint(sum1 * 255.0); k1 = k1 < 0 ? 0 : k1; k2 = rint(sum2 * 255.0); k2 = k2 < 0 ? 0 : k2; #endif } else { k = rint(sum); k = k < 0 ? 0 : k; k1 = rint(sum1); k1 = k1 < 0 ? 0 : k1; k2 = rint(sum2); k2 = k2 < 0 ? 0 : k2; } /* Store the result */ dest[j] = k; dest[j + 1] = k1; dest[j + 2] = k2; } } else /* Run 1-bpp horizontal filter - no gamma here */ { int j, k; for (j = 0; j < mem_width; j++) { sum = tmp1[j] * gaussW[0] - tmp2[j] * gaussN[0]; for (k = 1; k < lenW; k++) { sum += (tmp1[j - k] + tmp1[j + k]) * gaussW[k]; } for (k = 1; k < lenN; k++) { sum -= (tmp2[j - k] + tmp2[j + k]) * gaussN[k]; } k = rint(sum); dest[j] = k < 0 ? 0 : k; } } if (thread_step(thread, ii + 1, cnt, 10)) break; } thread_done(thread); } /* Difference of Gaussians */ void mem_dog(double radiusW, double radiusN, int norm, int gcor) { gaussd gd; threaddata *tdata; /* Create arrays */ if (mem_channel != CHN_IMAGE) gcor = 0; gd.gcor = gcor; gd.channel = mem_channel; // !!! No RGBA mode for ever - DoG mode instead tdata = init_gauss(&gd, radiusW, radiusN, 2); if (!tdata) { memory_errors(1); return; } /* Run filter */ progress_init(_("Difference of Gaussians"), 1); launch_threads(dog_filter, tdata, NULL, mem_height); /* Normalize values (expand to full 0..255) */ while (norm) { unsigned char *tmp, xtb[256]; double d; int i, l, mx = 0; l = mem_height * mem_width * BPP(mem_channel); tmp = mem_img[mem_channel]; for (i = l; i; i-- , tmp++) if (*tmp > mx) mx = *tmp; if (!mx) break; d = 255.0 / (double)mx; for (i = 0; i <= mx; i++) xtb[i] = rint(i * d); tmp = mem_img[mem_channel]; for (i = l; i; i-- , tmp++) *tmp = xtb[*tmp]; break; } /* Mask-merge with prior picture */ mask_merge(mem_undo_previous(mem_channel), mem_channel, gd.mask); progress_end(); free(tdata); } /* !!! Kuwahara-Nagao filter's radius is limited to 255, to use byte offsets */ typedef struct { int *idx; // Index array double *rs; // Sum of gamma-corrected RGB if using gamma int *avg; // Sum of pixel values (for average) int *dis; // Sum of pixel values squared (for variance) unsigned char *min; // Offset to minimum-variance square double r2i; // 1/r^2 to multiply things with int w, r; // Row width & filter radius int gcor; // Gamma correction toggle int l, rl; // Row array lengths } kuwahara_info; /* This function uses running sums, which gives x87 FPU's "precision jitter" * a chance to accumulate; to avoid, reduced-precision gamma is used - WJ */ static void kuwahara_row(unsigned char *src, int base, int add, kuwahara_info *info) { double rs0 = 0.0, rs1 = 0.0, rs2 = 0.0; int avg[3] = { 0, 0, 0 }, dis[3] = { 0, 0, 0 }; int i, w, r = info->r, gc = info->gcor, *idx = info->idx; w = info->w + r++; for (i = -r; i < w; i++) { unsigned char *tvv; int tv, i3, *iavg, *idis; tvv = src + idx[i]; avg[0] += (tv = tvv[0]); dis[0] += tv * tv; avg[1] += (tv = tvv[1]); dis[1] += tv * tv; avg[2] += (tv = tvv[2]); dis[2] += tv * tv; if (gc) { rs0 += Fgamma256[tvv[0]]; rs1 += Fgamma256[tvv[1]]; rs2 += Fgamma256[tvv[2]]; } if (i < 0) continue; tvv = src + idx[i - r]; avg[0] -= (tv = tvv[0]); dis[0] -= tv * tv; avg[1] -= (tv = tvv[1]); dis[1] -= tv * tv; avg[2] -= (tv = tvv[2]); dis[2] -= tv * tv; i3 = (base + i) * 3; iavg = info->avg + i3; idis = info->dis + i3; if (add) { iavg[0] += avg[0]; iavg[1] += avg[1]; iavg[2] += avg[2]; idis[0] += dis[0]; idis[1] += dis[1]; idis[2] += dis[2]; } else { iavg[0] -= avg[0]; iavg[1] -= avg[1]; iavg[2] -= avg[2]; idis[0] -= dis[0]; idis[1] -= dis[1]; idis[2] -= dis[2]; } if (gc) { double *irs = info->rs + i3; rs0 -= Fgamma256[tvv[0]]; rs1 -= Fgamma256[tvv[1]]; rs2 -= Fgamma256[tvv[2]]; if (add) { irs[0] += rs0; irs[1] += rs1; irs[2] += rs2; } else { irs[0] -= rs0; irs[1] -= rs1; irs[2] -= rs2; } } } } static void kuwahara_copy(int dest, int src, kuwahara_info *info) { src *= 3; dest *= 3; memcpy(info->rs + dest, info->rs + src, info->rl * 3 * sizeof(double)); memcpy(info->avg + dest, info->avg + src, info->l * 3 * sizeof(int)); memcpy(info->dis + dest, info->dis + src, info->l * 3 * sizeof(int)); } static double kuwahara_square(int idx, kuwahara_info *info) { double r2i = info->r2i; int *dp = info->dis + idx * 3, *ap = info->avg + idx * 3; // !!! Multiplication is done this way to avoid integer overflow return (dp[0] + dp[1] + dp[2] - ((r2i * ap[0]) * ap[0] + (r2i * ap[1]) * ap[1] + (r2i * ap[2]) * ap[2])); } /* For each X, locate the square with minimum variance & store its offset */ static void kuwahara_min(int base, kuwahara_info *info) { double da[256]; int i, j, j1, w = info->w, r = info->r, min = -1; for (i = 0; i < r; i++) da[i] = kuwahara_square(base + i, info); for (i = 0; i < w; i++) { j1 = (i + r) & 255; da[j1] = kuwahara_square(base + (i + r), info); if (min > i) // Old minimum still valid { if (da[j1] <= da[min & 255]) min = i + r; } else // Forced to find a new one { min = i; for (j = 1; j <= r; j++) if (da[(i + j) & 255] <= da[min & 255]) min = i + j; } info->min[base + i] = min - i; } } /* Replace each pixel in image row by nearest color in 3x3 Kuwahara'ed region */ static void kuwahara_detailed(unsigned char *buf, unsigned char *mask, unsigned char *dest, int y, int gcor) { unsigned char *tmp; int l, w = mem_width * 3; #define REGION_SIZE 9 int steps[REGION_SIZE] = { 3, 3, w, 3, 3, w, 3, 3, w }; #if 0 /* Make scanning order the same as with flat image */ l = (y + 2) % 3; buf += (w + 6) * l; steps [8 - 3 * l] -= (w + 6) * 3; #endif row_protected(0, y, mem_width, mask); tmp = mem_img[CHN_IMAGE] + y * w; for (l = 0; l < mem_width; l++ , tmp += 3 , dest += 3) { unsigned char *tb, *found; int rr, gg, bb, op = *mask++; if (op == 255) continue; /* Find the nearest color pixel */ rr = tmp[0]; gg = tmp[1]; bb = tmp[2]; found = tb = buf + l * 3; if (gcor) // Gamma corrected { double d, r2, g2, b2; int i; d = 100.0; // More than 3*1.0^2 r2 = gamma256[rr]; g2 = gamma256[gg]; b2 = gamma256[bb]; for (i = 0; i < REGION_SIZE; tb += steps[i++]) { double d2, dr, dg, db; dr = gamma256[tb[0]] - r2; dg = gamma256[tb[1]] - g2; db = gamma256[tb[2]] - b2; d2 = dr * dr + dg * dg + db * db; if (d2 >= d) continue; found = tb; d = d2; } } else // Raw RGB { int i, d, d2; d = 1000000; // More than 3*255^2 for (i = 0; i < REGION_SIZE; tb += steps[i++]) { d2 = (rr - tb[0]) * (rr - tb[0]) + (gg - tb[1]) * (gg - tb[1]) + (bb - tb[2]) * (bb - tb[2]); if (d2 >= d) continue; found = tb; d = d2; } } dest[0] = found[0]; dest[1] = found[1]; dest[2] = found[2]; } #undef REGION_SIZE } /* Convert virtual row to row index (mirror boundary) */ static int idx2row(int idx) { int j, k; if (mem_height == 1) return (0); k = mem_height + mem_height - 2; j = abs(idx) % k; if (j >= mem_height) j = k - j; return (j); } /* RGB only - cannot be generalized without speed loss */ void mem_kuwahara(int r, int gcor, int detail) { kuwahara_info info; unsigned char *mem, *src, *buf, *mask, *tmp, *timg, *tx; int i, j, k, l, ir, len, rl, r1 = r + 1; int w = mem_width * 3, wbuf = w + 3 * 2, ch = mem_channel; double r2i = 1.0 / (double)(r1 * r1); if (mem_img_bpp != 3) return; // Sanity check len = mem_width + r + r + 1; info.l = l = mem_width + r; info.rl = rl = gcor ? l : 0; mem = multialloc(MA_ALIGN_DOUBLE, &info.rs, rl * r1 * 3 * sizeof(double), &info.avg, l * r1 * 3 * sizeof(int), &info.dis, l * r1 * 3 * sizeof(int), &info.idx, len * sizeof(int), &info.min, l * r1, &mask, mem_width, &timg, wbuf * 3, NULL); if (!mem) { memory_errors(1); return; } info.r2i = r2i; info.w = mem_width; info.r = r; info.gcor = gcor; progress_init(_("Kuwahara-Nagao Filter"), 1); info.idx += r1; if (mem_width > 1) // All indices remain zero otherwise { k = mem_width + mem_width - 2; for (i = -(r + 1); i < mem_width + r; i++) { j = abs(i) % k; if (j >= mem_width) j = k - j; info.idx[i] = j * 3; } } mem_channel = CHN_IMAGE; // For row_protected() src = mem_undo_previous(CHN_IMAGE); /* Initialize the bottom sum */ for (i = -r; i <= 0; i++) kuwahara_row(src + idx2row(i) * w, 0, TRUE, &info); kuwahara_min(0, &info); /* Initialize the rest of sums */ for (i = 1; i <= r; i++) { int j = l * i; kuwahara_copy(j, j - l, &info); kuwahara_row(src + idx2row(i - r1) * w, j, FALSE, &info); kuwahara_row(src + idx2row(i) * w, j, TRUE, &info); kuwahara_min(j, &info); } /* Actually process image */ ir = i = 0; while (TRUE) { int j, k, jp; if ((i * 10) % mem_height >= mem_height - 10) if (progress_update((float)(i + 1) / mem_height)) break; /* Process a pixel row */ if (!detail) row_protected(0, i, mem_width, mask); tmp = buf = timg + wbuf * (i % 3); for (j = 0; j < mem_width; j++) { double dis; int jj, jk; tmp += 3; if (!detail && (mask[j] == 255)) continue; /* Select minimum variance square from covered rows */ jj = j + l; jk = j + info.min[j]; dis = kuwahara_square(jk, &info); // !!! Only the all-or-nothing mode for now - weighted mode not implemented yet for (k = 1; k < r1; k++ , jj += l) { int jv = jj + info.min[jj]; double dv = kuwahara_square(jv, &info); if (dv < dis) jk = jv , dis = dv; } /* Calculate & store new RGB */ jk *= 3; if (gcor) { double *wr = info.rs + jk; tmp[0] = UNGAMMA256(wr[0] * r2i); tmp[1] = UNGAMMA256(wr[1] * r2i); tmp[2] = UNGAMMA256(wr[2] * r2i); } else { int *ar = info.avg + jk; tmp[0] = rint(*ar++ * r2i); tmp[1] = rint(*ar++ * r2i); tmp[2] = rint(*ar * r2i); } } if (detail) { /* Copy-extend the row on both ends */ memcpy(buf, buf + 3, 3); memcpy(tmp + 3, tmp, 3); /* Copy-extend the top row */ if (!i) memcpy(timg + wbuf * 2, buf, wbuf); else /* Build and mask-merge the previous row */ { // Overwrite outgoing pixels of outgoing row tx = timg + wbuf * ((i + 1) % 3); kuwahara_detailed(timg, mask, tx, i - 1, gcor); tmp = mem_img[CHN_IMAGE] + (i - 1) * w; process_img(0, 1, mem_width, mask, tmp, tmp, tx, NULL, 3, BLENDF_SET | BLENDF_INVM); } } else { /* Mask-merge current row */ tmp = mem_img[CHN_IMAGE] + i * w; process_img(0, 1, mem_width, mask, tmp, tmp, buf + 3, NULL, 3, BLENDF_SET | BLENDF_INVM); } if (++i < mem_height) { /* Update sums for a new row */ jp = ir * l; kuwahara_copy(jp, ((ir + r) % r1) * l, &info); kuwahara_row(src + idx2row(i - 1) * w, jp, FALSE, &info); kuwahara_row(src + idx2row(i + r) * w, jp, TRUE, &info); kuwahara_min(jp, &info); ir = (ir + 1) % r1; continue; } if (detail) { /* Copy-extend the bottom row */ memcpy(timg + wbuf * (i % 3), buf, wbuf); /* Build and mask-merge it */ kuwahara_detailed(timg, mask, timg, i - 1, gcor); tmp = mem_img[CHN_IMAGE] + (i - 1) * w; process_img(0, 1, mem_width, mask, tmp, tmp, timg, NULL, 3, BLENDF_SET | BLENDF_INVM); } break; } mem_channel = ch; progress_end(); free(mem); } /// CLIPBOARD MASK int mem_clip_mask_init(unsigned char val) // Initialise the clipboard mask { int j = mem_clip_w*mem_clip_h; if (mem_clipboard) mem_clip_mask_clear(); // Remove old mask mem_clip_mask = malloc(j); if (!mem_clip_mask) return 1; // Not able to allocate memory memset(mem_clip_mask, val, j); // Start with fully opaque/clear mask return 0; } void mem_mask_colors(unsigned char *mask, unsigned char *img, unsigned char v, int width, int height, int bpp, int col0, int col1) { int i, j = width * height, k; if (bpp == 1) { for (i = 0; i < j; i++) { if ((img[i] == col0) || (img[i] == col1)) mask[i] = v; } } else { for (i = 0; i < j; i++ , img += 3) { k = MEM_2_INT(img, 0); if ((k == col0) || (k == col1)) mask[i] = v; } } } void mem_clip_mask_set(unsigned char val) // (un)Mask colours A and B on the clipboard { int aa, bb; if (mem_clip_bpp == 1) /* Indexed/utility */ { if (mem_channel == CHN_IMAGE) { aa = mem_col_A; bb = mem_col_B; } else { aa = channel_col_A[mem_channel]; bb = channel_col_B[mem_channel]; } } else /* RGB */ { aa = PNG_2_INT(mem_col_A24); bb = PNG_2_INT(mem_col_B24); } mem_mask_colors(mem_clip_mask, mem_clipboard, val, mem_clip_w, mem_clip_h, mem_clip_bpp, aa, bb); } void mem_clip_mask_clear() // Clear/remove the clipboard mask { free(mem_clip_mask); mem_clip_mask = NULL; } /* * Extract alpha information from RGB image - alpha if pixel is in colour * scale of A->B. Return 0 if OK, 1 otherwise */ int mem_scale_alpha(unsigned char *img, unsigned char *alpha, int width, int height, int mode) { int i, j = width * height, AA[3], BB[3], DD[6], chan, c1, c2, dc1, dc2; double p0, p1, p2, dchan, KK[6]; if (!img || !alpha) return (1); AA[0] = mem_col_A24.red; AA[1] = mem_col_A24.green; AA[2] = mem_col_A24.blue; BB[0] = mem_col_B24.red; BB[1] = mem_col_B24.green; BB[2] = mem_col_B24.blue; for (i = 0; i < 3; i++) { if (AA[i] < BB[i]) { DD[i] = AA[i]; DD[i + 3] = BB[i]; } else { DD[i] = BB[i]; DD[i + 3] = AA[i]; } } chan = 0; // Find the channel with the widest range - gives most accurate result later if (DD[4] - DD[1] > DD[3] - DD[0]) chan = 1; if (DD[5] - DD[2] > DD[chan + 3] - DD[chan]) chan = 2; if (AA[chan] == BB[chan]) /* if A == B then work GIMP-like way */ { for (i = 0; i < 3; i++) { KK[i] = AA[i] ? 255.0 / AA[i] : 1.0; KK[i + 3] = AA[i] < 255 ? -255.0 / (255 - AA[i]) : 0.0; } for (i = 0; i < j; i++ , alpha++ , img += 3) { /* Already semi-opaque so don't touch */ if (*alpha != 255) continue; /* Evaluate the three possible alphas */ p0 = (AA[0] - img[0]) * (img[0] <= AA[0] ? KK[0] : KK[3]); p1 = (AA[1] - img[1]) * (img[1] <= AA[1] ? KK[1] : KK[4]); p2 = (AA[2] - img[2]) * (img[2] <= AA[2] ? KK[2] : KK[5]); if (p0 < p1) p0 = p1; if (p0 < p2) p0 = p2; /* Set alpha */ *alpha = rint(p0); /* Demultiply image if this is alpha and nonzero */ if (!mode) continue; dchan = p0 ? 255.0 / p0 : 0.0; img[0] = rint((img[0] - AA[0]) * dchan) + AA[0]; img[1] = rint((img[1] - AA[1]) * dchan) + AA[1]; img[2] = rint((img[2] - AA[2]) * dchan) + AA[2]; } } else /* Limit processing to A->B scale */ { dchan = 1.0 / (BB[chan] - AA[chan]); c1 = 1 ^ (chan & 1); c2 = 2 ^ (chan & 2); dc1 = BB[c1] - AA[c1]; dc2 = BB[c2] - AA[c2]; for (i = 0; i < j; i++ , alpha++ , img += 3) { /* Already semi-opaque so don't touch */ if (*alpha != 255) continue; /* Ensure pixel lies between A and B for each channel */ if ((img[0] < DD[0]) || (img[0] > DD[3])) continue; if ((img[1] < DD[1]) || (img[1] > DD[4])) continue; if ((img[2] < DD[2]) || (img[2] > DD[5])) continue; p0 = (img[chan] - AA[chan]) * dchan; /* Check delta for all channels is roughly the same ... * ... if it isn't, ignore this pixel as its not in A->B scale */ if (abs(AA[c1] + (int)rint(p0 * dc1) - img[c1]) > 2) continue; if (abs(AA[c2] + (int)rint(p0 * dc2) - img[c2]) > 2) continue; /* Pixel is a shade of A/B so set alpha */ *alpha = (int)rint(p0 * 255) ^ 255; /* Demultiply image if this is alpha */ if (!mode) continue; img[0] = AA[0]; img[1] = AA[1]; img[2] = AA[2]; } } return 0; } void mem_smudge(int ox, int oy, int nx, int ny) { unsigned char mask[256], img[256 * 2 * 3], alf[256 * 2]; unsigned char *src, *dest, *srca = NULL, *dsta = NULL; int ax, ay, bx, by, w, h; int xv = nx - ox, yv = ny - oy; // Vector int i, j, delta, delta1, bpp; int y0, y1, dy, opw, op2, cpf, mode; if (tool_opacity < 2) return; /* Clip source and dest areas to image bounds */ ax = ox - tool_size / 2; bx = ax + tool_size; if (ax < 0) ax = 0; if (ax + xv < 0) ax = -xv; if (bx > mem_width) bx = mem_width; if (bx + xv > mem_width) bx = mem_width - xv; w = bx - ax; ay = oy - tool_size / 2; by = ay + tool_size; if (ay < 0) ay = 0; if (ay + yv < 0) ay = -yv; if (by > mem_height) by = mem_height; if (by + yv > mem_height) by = mem_height - yv; h = by - ay; if ((w < 1) || (h < 1)) return; /* !!! I modified this tool action somewhat - White Jaguar */ mode = smudge_mode && mem_undo_opacity; if (mode) src = mem_undo_previous(mem_channel); else src = mem_img[mem_channel]; dest = mem_img[mem_channel]; if ((mem_channel == CHN_IMAGE) && RGBA_mode && mem_img[CHN_ALPHA]) { if (mode) srca = mem_undo_previous(CHN_ALPHA); else srca = mem_img[CHN_ALPHA]; dsta = mem_img[CHN_ALPHA]; } bpp = MEM_BPP; delta1 = yv * mem_width + xv; delta = delta1 * bpp; /* Copy source if destination overwrites it */ cpf = (src == dest) && !yv && (xv > 0) && (w > xv); /* Set up Y pass to prevent overwriting source */ if ((src == dest) && (yv > 0) && (h > yv)) y0 = ay + h - 1 , y1 = ay - 1 , dy = -1; // Bottom to top else y0 = ay , y1 = ay + h , dy = 1; // Top to bottom for (j = y0; j != y1; j += dy) // Blend old area with new area { unsigned char *ts, *td, *tsa = NULL, *tda = NULL; int offs = j * mem_width + ax; row_protected(ax + xv, j + yv, w, mask); ts = src + offs * bpp; td = dest + offs * bpp + delta; if (cpf) { memcpy(img, ts, w * bpp + delta); ts = img; } if (dsta) { tsa = srca + offs; tda = dsta + offs + delta1; if (cpf) { memcpy(alf, tsa, w + delta1); tsa = alf; } } for (i = 0; i < w; i++ , ts += bpp , td += bpp) { int k = mask[i], k0, k1, k2; opw = (255 - k) * (tool_opacity >> 1); opw = (opw + (opw >> 8) + 1) >> 8; if (!opw) continue; if (tda) { int k = tsa[i + delta1]; k = k * 255 + (tsa[i] - k) * opw + 127; tda[i] = (k + (k >> 8) + 1) >> 8; if (k && !channel_dis[CHN_ALPHA]) opw = (255 * opw * tsa[i]) / k; } op2 = 255 - opw; k0 = ts[0] * opw + ts[delta] * op2 + 127; td[0] = (k0 + (k0 >> 8) + 1) >> 8; if (bpp == 1) continue; k1 = ts[1] * opw + ts[delta + 1] * op2 + 127; td[1] = (k1 + (k1 >> 8) + 1) >> 8; k2 = ts[2] * opw + ts[delta + 2] * op2 + 127; td[2] = (k2 + (k2 >> 8) + 1) >> 8; } } } /// GRADIENTS /* Evaluate channel gradient at coordinate, return opacity * Coordinate 0 is center of 1st pixel, 1 center of last * Scale of return values is 0x0000..0xFF00 (NOT 0xFFFF) */ int grad_value(int *dest, int slot, double x) { int i, k, len, op; unsigned char *gdata, *gmap; grad_map *gradmap; double xx, hsv[6]; /* Gradient slot (first RGB, then 1-bpp channels) */ gradmap = graddata + slot; /* Get opacity */ gdata = gradmap->op; gmap = gradmap->opmap; len = gradmap->oplen; xx = (gradmap->orev ? 1.0 - x : x) * (len - 1); i = xx; if (i > len - 2) i = len - 2; k = gmap[i] == GRAD_TYPE_CONST ? 0 : (int)((xx - i) * 0x10000 + 0.5); op = (gdata[i] << 8) + ((k * (gdata[i + 1] - gdata[i]) + 127) >> 8); if (!op) return (0); /* Stop if zero opacity */ /* Get channel value */ gdata = gradmap->vs; gmap = gradmap->vsmap; len = gradmap->vslen; xx = (gradmap->grev ? 1.0 - x : x) * (len - 1); i = xx; if (i > len - 2) i = len - 2; k = gmap[i] == GRAD_TYPE_CONST ? 0 : (int)((xx - i) * 0x10000 + 0.5); if (!slot) /* RGB */ { unsigned char *gslot = gdata + i * 3; int j3 = 0; switch (gmap[i]) { case GRAD_TYPE_BK_HSV: /* Backward HSV interpolation */ j3 = 3; case GRAD_TYPE_HSV: /* HSV interpolation */ /* Convert */ rgb2hsv(gslot + 0, hsv + 0); rgb2hsv(gslot + 3, hsv + 3); /* Grey has no hue */ if (hsv[1] == 0.0) hsv[0] = hsv[3]; if (hsv[4] == 0.0) hsv[3] = hsv[0]; /* Prevent wraparound */ if (hsv[j3] > hsv[j3 ^ 3]) hsv[j3] -= 6.0; /* Interpolate */ hsv[0] += (xx - i) * (hsv[3] - hsv[0]); hsv[1] += (xx - i) * (hsv[4] - hsv[1]); hsv[2] += (xx - i) * (hsv[5] - hsv[2]); /* Convert back */ hsv[2] *= 512; hsv[1] = hsv[2] * (1.0 - hsv[1]); if (hsv[0] < 0.0) hsv[0] += 6.0; j3 = hsv[0]; hsv[0] = (hsv[0] - j3) * (hsv[2] - hsv[1]); if (j3 & 1) { hsv[2] -= hsv[0]; hsv[0] += hsv[2]; } else hsv[0] += hsv[1]; j3 >>= 1; dest[j3] = ((int)hsv[2] + 1) >> 1; dest[MOD3(j3 + 1)] = ((int)hsv[0] + 1) >> 1; dest[MOD3(j3 + 2)] = ((int)hsv[1] + 1) >> 1; break; case GRAD_TYPE_SRGB: /* sRGB interpolation */ dest[0] = ungamma65281(gamma256[gslot[0]] + (xx - i) * (gamma256[gslot[3]] - gamma256[gslot[0]])); dest[1] = ungamma65281(gamma256[gslot[1]] + (xx - i) * (gamma256[gslot[4]] - gamma256[gslot[1]])); dest[2] = ungamma65281(gamma256[gslot[2]] + (xx - i) * (gamma256[gslot[5]] - gamma256[gslot[2]])); break; default: /* RGB interpolation */ dest[0] = (gslot[0] << 8) + ((k * (gslot[3] - gslot[0]) + 127) >> 8); dest[1] = (gslot[1] << 8) + ((k * (gslot[4] - gslot[1]) + 127) >> 8); dest[2] = (gslot[2] << 8) + ((k * (gslot[5] - gslot[2]) + 127) >> 8); break; } } else if (slot == CHN_IMAGE + 1) /* Indexed */ { dest[0] = gdata[i]; dest[1] = gdata[i + ((k + 0xFFFF) >> 16)]; dest[CHN_IMAGE + 3] = (k + 127) >> 8; } else /* Utility */ { dest[slot + 2] = (gdata[i] << 8) + ((k * (gdata[i + 1] - gdata[i]) + 127) >> 8); } return (op); } /* Evaluate (coupled) alpha gradient at coordinate */ static void grad_alpha(int *dest, double x) { int i, k, len; unsigned char *gdata, *gmap; grad_map *gradmap; double xx; /* Get coupled alpha */ gradmap = graddata + CHN_ALPHA + 1; gdata = gradmap->vs; gmap = gradmap->vsmap; len = gradmap->vslen; xx = (gradmap->grev ? 1.0 - x : x) * (len - 1); i = xx; if (i > len - 2) i = len - 2; k = gmap[i] == GRAD_TYPE_CONST ? 0 : (int)((xx - i) * 0x10000 + 0.5); dest[CHN_ALPHA + 3] = (gdata[i] << 8) + ((k * (gdata[i + 1] - gdata[i]) + 127) >> 8); } /* Evaluate gradient at a sequence of points */ /* !!! For now, works only in (slower) exact mode */ void grad_pixels(int start, int step, int cnt, int x, int y, unsigned char *mask, unsigned char *op0, unsigned char *img0, unsigned char *alpha0) { grad_info *grad = gradient + mem_channel; unsigned char *dest; int i, mmask, dither, op, slot, wrk[NUM_CHANNELS + 3]; double dist, len1, l2; if (!RGBA_mode) alpha0 = NULL; mmask = IS_INDEXED ? 1 : 255; /* On/off opacity */ slot = mem_channel + ((0x81 + mem_channel + mem_channel - mem_img_bpp) >> 7); cnt = start + step * cnt; x += start; for (i = start; i < cnt; op0[i] = op , x += step , i += step) { op = 0; if (mask[i] >= mmask) continue; /* Disabled because of unusable settings? */ if (grad->wmode == GRAD_MODE_NONE) continue; /* Distance for gradient mode */ if (grad->status == GRAD_NONE) { /* Stroke gradient */ if (grad->wmode != GRAD_MODE_BURST) dist = grad_path + (x - grad_x0) * grad->xv + (y - grad_y0) * grad->yv; /* Shapeburst gradient */ else if (!sb_buf2) { int n = sb_buf[(y - sb_rect[1]) * sb_rect[2] + (x - sb_rect[0])] - 1; if (n < 0) continue; dist = n; } else { int n = sb_buf2[(y - sb_rect[1]) * sb_rect[2] + (x - sb_rect[0])]; if (!n) continue; dist = sqrt(n) - 1.0; } } else { int dx = x - grad->xy[0], dy = y - grad->xy[1]; switch (grad->wmode) { default: case GRAD_MODE_LINEAR: /* Linear/bilinear gradient */ case GRAD_MODE_BILINEAR: dist = dx * grad->xv + dy * grad->yv; if (grad->wmode == GRAD_MODE_LINEAR) break; dist = fabs(dist); /* Bilinear */ break; case GRAD_MODE_RADIAL: /* Radial gradient */ dist = sqrt(dx * dx + dy * dy); break; case GRAD_MODE_SQUARE: /* Square gradient */ /* !!! Here is code duplication with linear/ * bilinear path - but merged paths actually * LOSE in both time and space, at least * with GCC - WJ */ dist = fabs(dx * grad->xv + dy * grad->yv) + fabs(dx * grad->yv - dy * grad->xv); break; case GRAD_MODE_ANGULAR: /* Angular/conical gradient */ case GRAD_MODE_CONICAL: dist = atan360(dx, dy) - grad->wa; if (dist < 0.0) dist += 360.0; if (grad->wmode == GRAD_MODE_ANGULAR) break; if (dist >= 180.0) dist = 360.0 - dist; break; } } dist -= grad->ofs; /* Apply repeat mode */ len1 = grad->wrep; switch (grad->wrmode) { case GRAD_BOUND_MIRROR: /* Mirror repeat */ l2 = len1 + len1; dist -= l2 * (int)(dist * grad->wil2); if (dist < 0.0) dist += l2; if (dist > len1) dist = l2 - dist; break; case GRAD_BOUND_REPEAT: /* Repeat */ l2 = len1 + 1.0; /* Repeat period is 1 pixel longer */ dist -= l2 * (int)((dist + 0.5) * grad->wil2); if (dist < -0.5) dist += l2; break; case GRAD_BOUND_REP_A: /* Angular repeat */ dist -= len1 * (int)(dist * grad->wil2); if (dist < 0.0) dist += len1; break; case GRAD_BOUND_STOP: /* Nothing is outside bounds */ if ((dist < -0.5) || (dist >= len1 + 0.5)) continue; break; case GRAD_BOUND_STOP_A: /* Nothing is outside angle */ if ((dist < 0.0) || (dist > len1)) continue; break; case GRAD_BOUND_LEVEL: /* Constant extension */ default: break; } /* Rescale to 0..1, enforce boundaries */ dist = dist <= 0.0 ? 0.0 : dist >= len1 ? 1.0 : dist * grad->wil1; /* Value from Bayer dither matrix */ dither = BAYER(x, y); /* Get gradient */ wrk[CHN_IMAGE + 3] = 0; op = (grad_value(wrk, slot, dist) + dither) >> 8; if (!op) continue; if (mem_channel == CHN_IMAGE) { if (alpha0) { grad_alpha(wrk, dist); alpha0[i] = (wrk[CHN_ALPHA + 3] + dither) >> 8; } if (mem_img_bpp == 3) { dest = img0 + i * 3; dest[0] = (wrk[0] + dither) >> 8; dest[1] = (wrk[1] + dither) >> 8; dest[2] = (wrk[2] + dither) >> 8; } else { img0[i] = (unsigned char)wrk[(wrk[CHN_IMAGE + 3] + dither) >> 8]; op = 255; } } else img0[i] = (wrk[mem_channel + 3] + dither) >> 8; } } /* Reevaluate gradient placement functions */ void grad_update(grad_info *grad) { double len, len1, l2; int dx = grad->xy[2] - grad->xy[0], dy = grad->xy[3] - grad->xy[1]; /* Distance for gradient mode */ grad->wmode = grad->gmode; len = grad->len; while (1) { /* Stroke gradient */ if (grad->status == GRAD_NONE) { if (!len) len = grad->rep + grad->ofs; if (len <= 0.0) grad->wmode = GRAD_MODE_NONE; break; } /* Placement length */ l2 = sqrt(dx * dx + dy * dy); if (l2 == 0.0) { grad->wmode = GRAD_MODE_RADIAL; break; } grad->xv = dx / l2; grad->yv = dy / l2; grad->wa = atan360(dx, dy); if (!len) len = grad->wmode == GRAD_MODE_ANGULAR ? 360.0 : grad->wmode == GRAD_MODE_CONICAL ? 180.0 : l2; break; } /* Base length (one repeat) */ len1 = grad->rep > 0 ? grad->rep : len - grad->ofs; if (len1 < 1.0) len1 = 1.0; grad->wrep = len1; grad->wil1 = 1.0 / len1; /* Inverse period */ l2 = 1.0; grad->wrmode = grad->rmode; if (grad->rmode == GRAD_BOUND_MIRROR) /* Mirror repeat */ l2 = len1 + len1; else if (grad->rmode == GRAD_BOUND_REPEAT) /* Repeat */ l2 = len1 + 1.0; /* Angular distance is in degrees, not pixels */ if ((grad->wmode == GRAD_MODE_ANGULAR) || (grad->wmode == GRAD_MODE_CONICAL)) { if (grad->rmode == GRAD_BOUND_REPEAT) grad->wrmode = GRAD_BOUND_REP_A , l2 = len1; else if (grad->rmode == GRAD_BOUND_STOP) grad->wrmode = GRAD_BOUND_STOP_A; } grad->wil2 = 1.0 / l2; } static unsigned char grad_def[4 + 8 + NUM_CHANNELS * 4]; /* Setup gradient mapping */ void gmap_setup(grad_map *gmap, grad_store gstore, int slot) { unsigned char *data, *map; data = grad_def + (slot ? 8 + slot * 4 : 4); map = grad_def + 10 + slot * 4; gmap->vslen = 2; if (gmap->gtype == GRAD_TYPE_CUSTOM) { gmap->vs = gstore + GRAD_CUSTOM_DATA(slot); gmap->vsmap = gstore + GRAD_CUSTOM_DMAP(slot); if (gmap->cvslen > 1) gmap->vslen = gmap->cvslen; else { memcpy(gmap->vs, data, slot ? 2 : 6); gmap->vsmap[0] = map[0]; } } else { gmap->vs = data; gmap->vsmap = map; grad_def[10 + slot * 4] = (unsigned char)gmap->gtype; } gmap->oplen = 2; if (gmap->otype == GRAD_TYPE_CUSTOM) { gmap->op = gstore + GRAD_CUSTOM_OPAC(slot); gmap->opmap = gstore + GRAD_CUSTOM_OMAP(slot); if (gmap->coplen > 1) gmap->oplen = gmap->coplen; else { gmap->op[0] = grad_def[0]; gmap->op[1] = grad_def[1]; gmap->opmap[0] = grad_def[2]; } } else { gmap->op = grad_def; gmap->opmap = grad_def + 2; grad_def[2] = gmap->otype; } } /* Store default gradient */ void grad_def_update(int slot) { grad_map *gradmap; /* Gradient slot (first RGB, then 1-bpp channels) */ if (slot < 0) slot = mem_channel + ((0x81 + mem_channel + mem_channel - mem_img_bpp) >> 7); gradmap = graddata + slot; grad_def[0] = tool_opacity; /* !!! As there's only 1 tool_opacity, use 0 for 2nd point */ grad_def[1] = 0; grad_def[2] = gradmap->otype; grad_def[10 + slot * 4] = gradmap->gtype; if (slot) { grad_def[8 + slot * 4] = channel_col_A[slot - 1]; grad_def[9 + slot * 4] = channel_col_B[slot - 1]; grad_def[12] = mem_col_A; grad_def[13] = mem_col_B; } else { grad_def[4] = mem_col_A24.red; grad_def[5] = mem_col_A24.green; grad_def[6] = mem_col_A24.blue; grad_def[7] = mem_col_B24.red; grad_def[8] = mem_col_B24.green; grad_def[9] = mem_col_B24.blue; } gradmap = graddata + CHN_ALPHA + 1; grad_def[12 + CHN_ALPHA * 4] = channel_col_A[CHN_ALPHA]; grad_def[13 + CHN_ALPHA * 4] = channel_col_B[CHN_ALPHA]; grad_def[14 + CHN_ALPHA * 4] = gradmap->gtype; } /* Convert to RGB & blend indexed/indexed+alpha for preview */ void blend_indexed(int start, int step, int cnt, unsigned char *rgb, unsigned char *img0, unsigned char *img, unsigned char *alpha0, unsigned char *alpha, int opacity) { png_color *col, *col0; int i, j, k, i3; for (i = start; cnt-- > 0; i += step) { j = opacity; if (alpha) { if (alpha[i]) { if (alpha0[i]) /* Opaque both */ alpha[i] = 255; else /* Opaque new */ { alpha[i] = opacity; j = 255; } } else if (alpha0[i]) /* Opaque old */ { alpha[i] = opacity ^ 255; j = 0; } else /* Transparent both */ { alpha[i] = 0; continue; } } col = mem_pal + img[i]; col0 = mem_pal + img0[i]; i3 = i * 3; k = col0->red * 255 + j * (col->red - col0->red); rgb[i3 + 0] = (k + (k >> 8) + 1) >> 8; k = col0->green * 255 + j * (col->green - col0->green); rgb[i3 + 1] = (k + (k >> 8) + 1) >> 8; k = col0->blue * 255 + j * (col->blue - col0->blue); rgb[i3 + 2] = (k + (k >> 8) + 1) >> 8; } } static void grad_point(double *xyz, int cspace, int idx) { int wrk[NUM_CHANNELS + 3]; grad_value(wrk, 0, idx * (1.0 / 4096.0)); switch (cspace) { default: case CSPACE_RGB: xyz[0] = wrk[0] * (1.0 / 256.0); xyz[1] = wrk[1] * (1.0 / 256.0); xyz[2] = wrk[2] * (1.0 / 256.0); break; case CSPACE_LXN: case CSPACE_SRGB: xyz[0] = gamma65281(wrk[0]); xyz[1] = gamma65281(wrk[1]); xyz[2] = gamma65281(wrk[2]); if (cspace == CSPACE_LXN) rgb2LXN(xyz, xyz[0], xyz[1], xyz[2]); break; } } int mem_pick_gradient(unsigned char *buf, int cspace, int mode) { grad_map oldgr; double pal[256 * 3], near[256 * 3], dist[256], len[256], lastc[3]; unsigned char *tb = buf; int i, j, k, l; /* Set up new RGB gradient */ oldgr = graddata[0]; memset(graddata, 0, sizeof(grad_map)); graddata[0].gtype = mode; graddata[0].otype = GRAD_TYPE_CONST; graddata[0].grev = graddata[0].orev = FALSE; grad_def_update(0); gmap_setup(graddata, gradbytes, 0); /* Map palette to colorspace, and init point/distance/position */ grad_point(lastc, cspace, 0); for (i = 0; i < mem_cols; i++) { double *tmp = pal + i * 3; switch (cspace) { default: case CSPACE_RGB: tmp[0] = mem_pal[i].red; tmp[1] = mem_pal[i].green; tmp[2] = mem_pal[i].blue; break; case CSPACE_SRGB: tmp[0] = gamma256[mem_pal[i].red]; tmp[1] = gamma256[mem_pal[i].green]; tmp[2] = gamma256[mem_pal[i].blue]; break; case CSPACE_LXN: get_lxn(tmp, PNG_2_INT(mem_pal[i])); break; } dist[i] = (tmp[0] - lastc[0]) * (tmp[0] - lastc[0]) + (tmp[1] - lastc[1]) * (tmp[1] - lastc[1]) + (tmp[2] - lastc[2]) * (tmp[2] - lastc[2]); memcpy(near + i * 3, lastc, sizeof(lastc)); } memset(len, 0, sizeof(len)); /* Find nearest point on gradient curve for each palette color */ for (i = 1; i < 4096; i++) { double thisc[3], dx, dy, dz, l2; grad_point(thisc, cspace, i); dx = thisc[0] - lastc[0]; dy = thisc[1] - lastc[1]; dz = thisc[2] - lastc[2]; l2 = dx * dx + dy * dy + dz * dz; if (l2 == 0.0) continue; for (j = 0; j < mem_cols; j++) { double a, d, newc[3], *tmp = pal + j * 3; a = ((tmp[0] - lastc[0]) * dx + (tmp[1] - lastc[1]) * dy + (tmp[2] - lastc[2]) * dz) / l2; a = a < 0.0 ? 0.0 : a > 1.0 ? 1.0 : a; newc[0] = lastc[0] + a * dx; newc[1] = lastc[1] + a * dy; newc[2] = lastc[2] + a * dz; d = (tmp[0] - newc[0]) * (tmp[0] - newc[0]) + (tmp[1] - newc[1]) * (tmp[1] - newc[1]) + (tmp[2] - newc[2]) * (tmp[2] - newc[2]); if (d >= dist[j]) continue; dist[j] = d; // Distance from the curve len[j] = a + i; // Position along the curve memcpy(near + j * 3, newc, sizeof(newc)); // Point } memcpy(lastc, thisc, sizeof(thisc)); } /* Include gradient's second end */ grad_point(lastc, cspace, 4096); for (i = 0; i < mem_cols; i++) { double d, *tmp = pal + i * 3; d = (tmp[0] - lastc[0]) * (tmp[0] - lastc[0]) + (tmp[1] - lastc[1]) * (tmp[1] - lastc[1]) + (tmp[2] - lastc[2]) * (tmp[2] - lastc[2]); if (d >= dist[i]) continue; dist[i] = d; len[i] = 4096.0; memcpy(near + i * 3, lastc, sizeof(lastc)); } /* Restore old RGB gradient */ graddata[0] = oldgr; grad_def_update(-1); gmap_setup(graddata, gradbytes, 0); /* Pick colors with *uncontested* nearest points */ scan_duplicates(); // Need to avoid duplicated colors for (i = 0; i < mem_cols; i++) { double d, d0, *tmp, *xyz; if (pal_dupes[i] != i) continue; *tb++ = i; // Add to result set by default d0 = dist[i]; xyz = near + i * 3; for (j = 0 , tmp = pal; j < mem_cols; j++ , tmp += 3) { if (pal_dupes[j] == i) continue; tmp = pal + j * 3; d = (tmp[0] - xyz[0]) * (tmp[0] - xyz[0]) + (tmp[1] - xyz[1]) * (tmp[1] - xyz[1]) + (tmp[2] - xyz[2]) * (tmp[2] - xyz[2]); if (d <= d0) { tb--; // Fail - remove this color break; } } } /* Bubble-sort the result set by position */ l = tb - buf; for (i = l - 1; i > 0; i--) for (j = 0; j < i; j++) { k = buf[j + 1]; if (len[buf[j]] > len[k]) { buf[j + 1] = buf[j]; buf[j] = k; } } /* Return number of colors in result set */ return (l); } /// SKEW ENGINE #define FILT_MAX 6 /* Must be no less than largest filter width */ static void *make_skew_filter(double **filt, int **dcc, int *fw, int len, double shift, double skew, int type) { void *tmp; double x, y, x0, dy, fw2, sum, A = 0.0, *fdata; int i, j, k, y0, fwidth = 0, *ofdata; // Use NN "filter" for integer shifts if ((fabs(skew - rint(skew)) < 1e-10) && (fabs(shift - rint(shift)) < 1e-10)) type = 0; switch (type) { case 0: fwidth = 1; /* Nearest neighbor */ break; case 1: fwidth = 2; /* Bilinear */ break; case 2: case 3: case 4: case 5: /* Bicubic, all flavors */ fwidth = 4; A = Aarray[type - 2]; break; case 6: fwidth = 6; /* Blackman-Harris windowed sinc */ break; } *filt = NULL; *dcc = NULL; *fw = fwidth; tmp = multialloc(MA_ALIGN_DOUBLE, filt, len * fwidth * sizeof(double), dcc, len * sizeof(int), NULL); if (!tmp) return (NULL); fdata = *filt; ofdata = *dcc; /* Generate filter */ fw2 = fwidth >> 1; x0 = 0.5 * (len - 1); for (i = 0; i < len; i++) { /* As mapping is dest-to-src, shifts are negative */ dy = (x0 - i) * skew - shift; /* Specialcase NN filter, for simplicity */ if (!type) { WJ_FLOOR(*ofdata++, dy + 0.5); *fdata++ = 1.0; continue; } /* Build regular filters*/ dy -= (*ofdata++ = y0 = ceil(dy - fw2)); // Mirrored offset sum = 0.0; for (j = 0; j < fwidth; j++ , dy -= 1.0) { x = fabs(dy); y = 0; switch (type) { case 1: /* Bilinear */ y = 1.0 - x; break; case 2: case 3: case 4: case 5: /* Bicubic */ if (x < 1.0) y = ((A + 2.0) * x - (A + 3)) * x * x + 1.0; else y = A * (((x - 5.0) * x + 8.0) * x - 4.0); break; case 6: /* Blackman-Harris */ y = BH1(x); break; } sum += (fdata[j] = y); } /* Normalization pass */ sum = 1.0 / sum; for (k = 0; k < fwidth; k++) *fdata++ *= sum; } return (tmp); } static void skew_fill_rgba(double *buf, double *filler, unsigned char *src, unsigned char *srca, int y0, int ow, int xl, int xr, int x0l, int x0r, int xfsz, double *xfilt, int *dxx, int *dyy, int gcor) { double *dest, *tmp; int j, k, l; /* Initialize dest buffer */ k = x0l < xl ? x0l : xl; l = (x0r > xr ? x0r : xr) - k - 1; if (l < 0) return; // Nothing to do tmp = buf + k * 7; memcpy(tmp, filler, sizeof(double) * 7); for (tmp += 7 , l *= 7; l > 0; tmp++ , l--) *tmp = *(tmp - 7); /* Collect pixels */ dest = buf + xl * 7; for (j = xl; j < xr; j++ , dest += 7) { unsigned char *img, *alpha; double *filt, acc = 0.0; int x, y, x1, ofs; /* Get location */ y = y0 + dyy[j]; x = j + dxx[y]; x1 = x + xfsz; filt = xfilt - x + y * xfsz; /* Accumulate empty space */ while (x1 > ow) acc += filt[--x1]; while (x < 0) acc += filt[x++]; /* Setup source & dest */ ofs = y * ow + x; img = src + ofs * 3; alpha = srca + ofs; // !!! Maybe use temp vars for accumulators - but will it make a difference? dest[0] *= acc; dest[1] *= acc; dest[2] *= acc; /* Accumulate image data */ filt += x; for (; x < x1; x++ , img += 3) { double rr, gg, bb, aa, fv; fv = *filt++; if (gcor) { rr = gamma256[img[0]] * fv; gg = gamma256[img[1]] * fv; bb = gamma256[img[2]] * fv; } else { rr = img[0] * fv; gg = img[1] * fv; bb = img[2] * fv; } dest[6] += (aa = *alpha++) * fv; dest[0] += rr; dest[1] += gg; dest[2] += bb; dest[3] += rr * aa; dest[4] += gg * aa; dest[5] += bb * aa; } } } static void skew_fill_rgb(double *buf, double *filler, unsigned char *src, unsigned char *srca, int y0, int ow, int xl, int xr, int x0l, int x0r, int xfsz, double *xfilt, int *dxx, int *dyy, int gcor) { double *dest, *tmp; int j, k, l; /* Initialize dest buffer */ k = x0l < xl ? x0l : xl; l = (x0r > xr ? x0r : xr) - k - 1; if (l < 0) return; // Nothing to do tmp = buf + k * 3; memcpy(tmp, filler, sizeof(double) * 3); for (tmp += 3 , l *= 3; l > 0; tmp++ , l--) *tmp = *(tmp - 3); /* Collect pixels */ dest = buf + xl * 3; for (j = xl; j < xr; j++ , dest += 3) { unsigned char *img; double *filt, acc = 0.0; double rv, gv, bv; int x, y, x1; /* Get location */ y = y0 + dyy[j]; x = j + dxx[y]; x1 = x + xfsz; filt = xfilt - x + y * xfsz; /* Accumulate empty space */ while (x1 > ow) acc += filt[--x1]; while (x < 0) acc += filt[x++]; /* Setup source & dest */ img = src + (y * ow + x) * 3; rv = dest[0] * acc; gv = dest[1] * acc; bv = dest[2] * acc; /* Accumulate image data */ filt += x; for (; x < x1; x++ , img += 3) { double fv = *filt++; if (gcor) { rv += gamma256[img[0]] * fv; gv += gamma256[img[1]] * fv; bv += gamma256[img[2]] * fv; } else { rv += img[0] * fv; gv += img[1] * fv; bv += img[2] * fv; } } dest[0] = rv; dest[1] = gv; dest[2] = bv; } } static void skew_fill_util(double *buf, double *filler, unsigned char *src, unsigned char *srca, int y0, int ow, int xl, int xr, int x0l, int x0r, int xfsz, double *xfilt, int *dxx, int *dyy, int gcor) { double *dest; int j, k, l; /* Initialize dest buffer */ k = x0l < xl ? x0l : xl; l = (x0r > xr ? x0r : xr) - k; if (l <= 0) return; // Nothing to do memset(buf + k, 0, l * sizeof(double)); /* Collect pixels */ dest = buf + xl * 3; for (j = xl; j < xr; j++) { unsigned char *img; double *filt, sum; int x, y, x1; /* Get location */ y = y0 + dyy[j]; x = j + dxx[y]; x1 = x + xfsz; filt = xfilt - x + y * xfsz; /* Skip empty space */ while (x1 > ow) x1--; while (x < 0) x++; /* Setup source */ img = src + y * ow + x; /* Accumulate image data */ filt += x; sum = 0.0; for (; x < x1; x++) sum += *img++ * *filt++; *dest++ = sum; } } /* !!! This works, after a fashion - but remains 2.5 times slower than a smooth * free-rotate if using 6-tap filter, or 1.5 times if using 2-tap one. Which, * while still being several times faster than anything else, is rather bad * for a high-quality tool like mtPaint. Needs improvement. - WJ */ static void mem_skew_filt(chanlist old_img, chanlist new_img, int ow, int oh, int nw, int nh, double xskew, double yskew, int mode, int gcor, int dis_a, int silent) { void *xmem, *ymem, *tmem; double *xfilt, *yfilt, *wbuf, *rbuf; int *dxx, *dyy; double x0, y0, d, Kh, Kv, XX[4], YY[4], filler[7]; int i, cc, /*fw2, fh2,*/ xfsz, yfsz, wbsz, rgba, step, ny, nr; /* Create temp data */ step = (rgba = new_img[CHN_ALPHA] && !dis_a) ? 7 : 3; xmem = make_skew_filter(&xfilt, &dxx, &xfsz, oh, (nw - ow) * 0.5, xskew, mode); ymem = make_skew_filter(&yfilt, &dyy, &yfsz, nw, (nh - oh) * 0.5, yskew, mode); // fw2 = xfsz >> 1; fh2 = yfsz >> 1; wbsz = nw * step; tmem = multialloc(MA_ALIGN_DOUBLE, &wbuf, wbsz * yfsz * sizeof(double), &rbuf, wbsz * sizeof(double), NULL); if (!xmem || !ymem || !tmem) goto fail; x0 = 0.5 * (nw - 1); y0 = 0.5 * (nh - 1); /* Calculate clipping parallelogram's corners */ // To avoid corner cases, we add an extra pixel to original dimensions XX[1] = XX[3] = (XX[0] = XX[2] = 0.5 * (nw - ow) - 1) + ow + 1; YY[2] = YY[3] = (YY[0] = YY[1] = 0.5 * (nh - oh) - 1) + oh + 1; for (i = 0; i < 4; i++) { XX[i] += (YY[i] - y0) * xskew; YY[i] += (XX[i] - x0) * yskew; } d = 1.0 + xskew * yskew; Kv = d ? xskew / d : 0.0; // for left & right Kh = yskew ? 1.0 / yskew : 0.0; // for top & bottom /* Init filler */ memset(filler, 0, sizeof(filler)); if (gcor) { filler[0] = gamma256[mem_col_A24.red]; filler[1] = gamma256[mem_col_A24.green]; filler[2] = gamma256[mem_col_A24.blue]; } else { filler[0] = mem_col_A24.red; filler[1] = mem_col_A24.green; filler[2] = mem_col_A24.blue; } /* Process image channels */ for (nr = cc = 0; cc < NUM_CHANNELS; cc++) nr += !!new_img[cc]; nr = (nr - rgba) * (nh + yfsz - 1); for (ny = cc = 0; cc < NUM_CHANNELS; cc++) { int ring_l[FILT_MAX], ring_r[FILT_MAX]; int i, idx, bpp = cc == CHN_IMAGE ? step : 1; if (!new_img[cc]) continue; /* Alpha already processed for RGBA */ if ((cc == CHN_ALPHA) && rgba) continue; /* Init border rings to all-filled */ for (i = 0; i < yfsz; i++) ring_l[i] = 0 , ring_r[i] = nw; /* Row loop */ for (i = 1 - yfsz , idx = 0; i < nh; i++ , ++idx >= yfsz ? idx = 0 : 0) { double *filt0, *thatbuf, *thisbuf = wbuf + idx * wbsz; int j, k, y0, xl, xr, len, ofs, lfx = -xfsz; if (!silent && ((++ny * 10) % nr >= nr - 10)) progress_update((float)ny / nr); /* Locate source row */ y0 = i + yfsz - 1; // Effective Y offset /* !!! A reliable equation for pixel-precise clipping * of source rows stubbornly refuses to be found, so * a brute-force approach is used instead - WJ */ xl = 0; xr = nw; for (; xl < xr; xl++) // Skip empty pixels on the left { int j = y0 + dyy[xl]; if ((j < 0) || (j >= oh)) continue; j = xl + dxx[j]; if ((j <= lfx) || (j >= ow)) continue; break; } for (; xl < xr; xr--) // Same on the right { int j = y0 + dyy[xr - 1]; if ((j < 0) || (j >= oh)) continue; j = xr - 1 + dxx[j]; if ((j <= lfx) || (j >= ow)) continue; break; } if (xl >= xr) xl = xr = ring_r[idx]; /* Read in a new row */ (cc != CHN_IMAGE ? skew_fill_util : rgba ? skew_fill_rgba : skew_fill_rgb)(thisbuf, filler, old_img[cc], old_img[CHN_ALPHA], y0, ow, xl, xr, ring_l[idx], ring_r[idx], xfsz, xfilt, dxx, dyy, gcor); if (xl >= xr) xl = nw , xr = 0; ring_l[idx] = xl; ring_r[idx] = xr; if (i < 0) continue; // Initialization phase /* Clip target row */ if (i <= YY[0]) xl = ceil(XX[0] + (i - YY[0]) * Kh); else if (i <= YY[2]) xl = ceil(XX[2] + (i - YY[2]) * Kv); else /* if (i <= YY[3]) */ xl = ceil(XX[2] + (i - YY[2]) * Kh); if (i <= YY[1]) xr = ceil(XX[1] + (i - YY[1]) * Kh); else if (i <= YY[3]) xr = ceil(XX[3] + (i - YY[3]) * Kv); else /* if (i <= YY[2]) */ xr = ceil(XX[3] + (i - YY[3]) * Kh); if (xl < 0) xl = 0; if (xr > nw) xr = nw; // Right boundary is exclusive /* Run vertical filter over the row buffers */ thisbuf = rbuf + xl * bpp; thatbuf = wbuf + xl * bpp; len = xr - xl; if (len <= 0); // Do nothing else if (yfsz == 1) // Just copy memcpy(thisbuf, thatbuf, len * bpp * sizeof(double)); else // Apply filter { memset(thisbuf, 0, len * bpp * sizeof(double)); filt0 = yfilt + xl * yfsz; for (j = 0 , k = idx; j < yfsz; j++) { double *dsrc, *ddest = thisbuf, *filt = filt0++; int l = len; if (++k >= yfsz) k = 0; dsrc = thatbuf + k * wbsz; while (l-- > 0) { double kk = *filt; filt += yfsz; *ddest++ += *dsrc++ * kk; if (bpp < 3) continue; *ddest++ += *dsrc++ * kk; *ddest++ += *dsrc++ * kk; if (bpp == 3) continue; *ddest++ += *dsrc++ * kk; *ddest++ += *dsrc++ * kk; *ddest++ += *dsrc++ * kk; *ddest++ += *dsrc++ * kk; } } } /* Write out results */ ofs = i * nw + xl; if (cc == CHN_IMAGE) // RGB and RGBA { double *dsrc = thisbuf; unsigned char *dest, *dsta; int l = len, n = step; dest = new_img[CHN_IMAGE] + ofs * 3; dsta = rgba ? new_img[CHN_ALPHA] + ofs : NULL; while (l-- > 0) { double rr, gg, bb, aa; int a; if (dsta && (a = rint(aa = dsrc[6]) , *dsta++ = a < 0 ? 0 : a > 0xFF ? 0xFF : a)) { aa = 1.0 / aa; rr = dsrc[3] * aa; gg = dsrc[4] * aa; bb = dsrc[5] * aa; } else { rr = dsrc[0]; gg = dsrc[1]; bb = dsrc[2]; } if (gcor) { dest[0] = UNGAMMA256X(rr); dest[1] = UNGAMMA256X(gg); dest[2] = UNGAMMA256X(bb); } else { int r, g, b; r = rint(rr); dest[0] = r < 0 ? 0 : r > 0xFF ? 0xFF : r; g = rint(gg); dest[1] = g < 0 ? 0 : g > 0xFF ? 0xFF : g; b = rint(bb); dest[2] = b < 0 ? 0 : b > 0xFF ? 0xFF : b; } dsrc += n; dest += 3; } } else // Utility channel { double *dsrc = thisbuf; unsigned char *dest = new_img[cc] + ofs; int l = len, n; while (l-- > 0) { n = rint(*dsrc++); *dest++ = n < 0 ? 0 : n > 0xFF ? 0xFF : n; } } } } fail: free(xmem); free(ymem); free(tmem); } static void mem_skew_nn(chanlist old_img, chanlist new_img, int ow, int oh, int nw, int nh, int bpp, double xskew, double yskew, int silent) { double x0, y0, d, Kh, Kv, XX[4], YY[4]; int i, ny; /* Calculate clipping parallelogram's corners */ x0 = 0.5 * (nw - 1); y0 = 0.5 * (nh - 1); XX[1] = XX[3] = (XX[0] = XX[2] = 0.5 * (nw - ow - 1)) + ow; YY[2] = YY[3] = (YY[0] = YY[1] = 0.5 * (nh - oh - 1)) + oh; for (i = 0; i < 4; i++) { XX[i] += (YY[i] - y0) * xskew; YY[i] += (XX[i] - x0) * yskew; } d = 1.0 + xskew * yskew; Kv = d ? xskew / d : 0.0; // for left & right Kh = yskew ? 1.0 / yskew : 0.0; // for top & bottom /* Process image row by row */ for (ny = 0; ny < nh; ny++) { int cc, xl, xr; if (!silent && ((ny * 10) % nh >= nh - 10)) progress_update((float)ny / nh); /* Clip row */ if (ny <= YY[0]) xl = ceil(XX[0] + (ny - YY[0]) * Kh); else if (ny <= YY[2]) xl = ceil(XX[2] + (ny - YY[2]) * Kv); else /* if (ny <= YY[3]) */ xl = ceil(XX[2] + (ny - YY[2]) * Kh); if (ny <= YY[1]) xr = ceil(XX[1] + (ny - YY[1]) * Kh); else if (ny <= YY[3]) xr = ceil(XX[3] + (ny - YY[3]) * Kv); else /* if (ny <= YY[2]) */ xr = ceil(XX[3] + (ny - YY[3]) * Kh); if (xl < 0) xl = 0; if (xr > nw) xr = nw; // Right boundary is exclusive for (cc = 0; cc < NUM_CHANNELS; cc++) { unsigned char *src, *dest; double x0y, y0y; int nx, ox, oy; if (!new_img[cc]) continue; x0y = 0.5 * (ow - 1) - x0 * d + (y0 - ny) * xskew; y0y = x0 * yskew - 0.5 * (nh - oh) + ny; /* RGB nearest neighbour */ if ((cc == CHN_IMAGE) && (bpp == 3)) { dest = new_img[CHN_IMAGE] + (ny * nw + xl) * 3; for (nx = xl; nx < xr; nx++ , dest += 3) { // !!! Later, try reimplementing these calculations in row-then-column way - // !!! while less theoretically precise, it might cause less jitter, and better // !!! match what other skew-transform code does - WJ WJ_ROUND(ox, x0y + nx * d); WJ_ROUND(oy, y0y - nx * yskew); src = old_img[CHN_IMAGE] + (oy * ow + ox) * 3; dest[0] = src[0]; dest[1] = src[1]; dest[2] = src[2]; } } /* One-bpp nearest neighbour */ else { dest = new_img[cc] + ny * nw + xl; for (nx = xl; nx < xr; nx++) { WJ_ROUND(ox, x0y + nx * d); WJ_ROUND(oy, y0y - nx * yskew); *dest++ = old_img[cc][oy * ow + ox]; } } } } } /* Skew geometry calculation is far nastier than same for rotation, and worse, * the approaches don't quite match in case of 3-skew rotation - WJ */ static void mem_skew_geometry(int ow, int oh, double xskew, double yskew, int rotation, int *nw, int *nh) { double nww, nhh, ax, ay; int dx, dy, dx0, dy0; /* Select new centering */ dx0 = ow & 1; dy0 = oh & 1; /* Pure skew */ if (!rotation) { /* For certain skew factors, when the other dimension is even, * rows/columns nearest to axis fit the pixel grid better if * skew dimension is realigned to offset them half a pixel */ dx = dy0 ? dx0 : dx0 ^ ((int)(fabs(xskew) + 0.5) & 1); dy = dx ? dy0 : dy0 ^ ((int)(fabs(yskew) + 0.5) & 1); } /* Rotation for 45 degrees or less */ else if (fabs(yskew) <= M_SQRT1_2) dx = dx0 , dy = dy0; /* Rotation for more than 45 degrees */ else { // Height gets to be odd - do width realign now if (dx0) dx = dy0; // Leave width realign till 3rd pass else if (dy0) dx = 0; // Let double realign happen when possible & useful else dx = (int)(fabs(xskew) + 0.5) & 1; dy = dx0; } /* Calculate theoretical dimensions */ ax = fabs(xskew); ay = fabs(yskew); nww = ow + oh * ax; if (xskew * yskew >= 0) nhh = nww * ay + oh; else if (ax * ay > 1) nhh = nww * ay - oh; else nhh = (ow - oh * ax) * ay + oh; /* Convert to actual pixel dimensions */ *nw = 2 * (int)(0.5 * (nww - dx) + PIX_ADD) + dx; *nh = 2 * (int)(0.5 * (nhh - dy) + PIX_ADD) + dy; } // Skew canvas in one or two directions (X then Y) // !!! Later, extend to handle skew+shift in both directions, too int mem_skew(double xskew, double yskew, int type, int gcor) { chanlist old_img, new_img; int ow, oh, nw, nh, res, bpp; ow = mem_width; oh = mem_height; bpp = mem_img_bpp; mem_skew_geometry(ow, oh, xskew, yskew, FALSE, &nw, &nh); if ((nw > MAX_WIDTH) || (nh > MAX_HEIGHT)) return (-5); memcpy(old_img, mem_img, sizeof(chanlist)); res = undo_next_core(UC_NOCOPY, nw, nh, bpp, CMASK_ALL); if (res) return (res); // No undo space memcpy(new_img, mem_img, sizeof(chanlist)); progress_init(_("Skew"), 0); mem_clear_img(new_img, nw, nh, bpp); if (!type || (mem_img_bpp == 1)) mem_skew_nn(old_img, new_img, ow, oh, nw, nh, bpp, xskew, yskew, FALSE); else mem_skew_filt(old_img, new_img, ow, oh, nw, nh, xskew, yskew, type, gcor, channel_dis[CHN_ALPHA], FALSE); progress_end(); return (0); } // Get average of utility channel pixels in an area int average_channel(unsigned char *src, int iw, int *vxy) { unsigned char *tmp; unsigned int nn, wh; int i, j, x, y, w, h; w = vxy[2] - (x = vxy[0]); h = vxy[3] - (y = vxy[1]); src += y * iw + x; /* Average area */ for (nn = i = 0; i < h; i++) { tmp = src + i * iw; for (j = w; j--; nn += *tmp++); } wh = w * h; return ((nn + (wh >> 1)) / wh); } // Get gamma-corrected average of RGB/RGBA pixels in an area int average_pixels(unsigned char *rgb, unsigned char *alpha, int iw, int *vxy) { unsigned char *tmp, *tma; double rr, gg, bb, dd; int i, j, k, x, y, w, h; w = vxy[2] - (x = vxy[0]); h = vxy[3] - (y = vxy[1]); rgb += (y * iw + x) * 3; if (alpha) alpha += y * iw + x; /* Average (gamma corrected) area */ rr = gg = bb = dd = 0.0; for (i = 0; i < h; i++) { tmp = rgb + i * iw * 3; if (alpha) { tma = alpha + i * iw; for (j = 0; j < w; j++ , tmp += 3) { dd += k = *tma++; rr += k * gamma256[tmp[0]]; gg += k * gamma256[tmp[1]]; bb += k * gamma256[tmp[2]]; } } else { dd += w; for (j = 0; j < w; j++ , tmp += 3) { rr += gamma256[tmp[0]]; gg += gamma256[tmp[1]]; bb += gamma256[tmp[2]]; } } } dd = 1.0 / dd; rr *= dd; gg *= dd; bb *= dd; return (RGB_2_INT(UNGAMMA256(rr), UNGAMMA256(gg), UNGAMMA256(bb))); } // Convert a row of pixels to any of 3 colorspaces static void mem_convert_row(double *dest, unsigned char *src, int l, int cspace) { if (cspace == CSPACE_LXN) { while (l-- > 0) { get_lxn(dest, MEM_2_INT(src, 0)); dest += 3; src += 3; } } else if (cspace == CSPACE_SRGB) { l *= 3; while (l-- > 0) *dest++ = gamma256[*src++]; } else /* if (cspace == CSPACE_RGB) */ { l *= 3; while (l-- > 0) *dest++ = *src++; } } /// SEGMENTATION /* * This code implements a 4-way variation of the segmentation algorithm * described in: * Pedro F. Felzenszwalb, "Efficient Graph-Based Image Segmentation" */ static int cmp_edge(const void *v1, const void *v2) { float f1 = ((seg_edge *)v1)->diff, f2 = ((seg_edge *)v2)->diff; return (f1 < f2 ? -1 : f1 != f2 ? f1 > f2 : ((seg_edge *)v1)->which - ((seg_edge *)v2)->which); } static inline int seg_find(seg_pixel *pix, int n) { unsigned int i, j; for (i = n; i != (j = pix[i].group); i = j); return (pix[n].group = i); } static inline int seg_join(seg_pixel *pix, int a, int b) { seg_pixel *ca = pix + a, *cb = pix + b; if (ca->rank > cb->rank) { ca->cnt += cb->cnt; return (cb->group = a); } cb->cnt += ca->cnt; cb->rank += (ca->rank == cb->rank); return (ca->group = b); } seg_state *mem_seg_prepare(seg_state *s, unsigned char *img, int w, int h, int flags, int cspace, int dist) { static const unsigned char dist_scales[NUM_CSPACES] = { 1, 255, 1 }; seg_edge *e; double mult, *row0, *row1, *rows[2]; int i, j, k, l, bsz, sz = w * h; // !!! Will need a longer int type (and twice the memory) otherwise if (sz > (INT_MAX >> 1) + 1) return (NULL); /* 3 buffers will be sharing space */ bsz = w * 3 * 2 * sizeof(double); l = sz * sizeof(seg_pixel); if (l > bsz) bsz = l; if (!s) // Reuse existing allocation if possible { /* Allocation is HUGE, but no way to make do with smaller one - WJ */ void *v[3]; s = multialloc(MA_ALIGN_DOUBLE, v, sizeof(seg_state), // Dummy pointer (header struct) v + 1, bsz, // Row buffers/pixel nodes v + 2, sz * 2 * sizeof(seg_edge), // Pixel connections NULL); if (!s) return (NULL); s->pix = v[1]; s->edges = v[2]; s->w = w; s->h = h; } rows[0] = (void *)s->pix; // 1st row buffer rows[1] = rows[0] + w * 3; // 2nd row buffer s->phase = 0; // Struct is to be refilled if (flags & SEG_PROGRESS) progress_init(_("Segmentation Pass 1"), 1); /* Compute color distances, fill connections buffer */ l = w * 3; mult = dist_scales[cspace]; // Make all colorspaces use similar scale for (i = 0 , e = s->edges; i < h; i++) { k = i * w; mem_convert_row(row1 = rows[i & 1], img + k * 3, w, cspace); /* Right vertices for this row */ for (j = 3 , k *= 2; j < l; j += 3 , k += 2 , e++) { e->which = k; e->diff = mult * distance_3d[dist](row1 + j - 3, row1 + j); } if (!i) continue; /* Bottom vertices for previous row */ k = (i - 1) * w * 2 + 1; row0 = rows[~i & 1]; for (j = 0; j < l; j += 3 , k += 2 , e++) { e->which = k; e->diff = mult * distance_3d[dist](row0 + j, row1 + j); } if ((flags & SEG_PROGRESS) && ((i * 20) % h >= h - 20)) if (progress_update((0.9 * i) / h)) goto quit; } /* Sort connections, smallest distances first */ s->cnt = e - s->edges; qsort(s->edges, s->cnt, sizeof(seg_edge), cmp_edge); s->phase = 1; quit: if (flags & SEG_PROGRESS) progress_end(); return (s); } int mem_seg_process_chunk(int start, int cnt, seg_state *s) { seg_edge *edge; seg_pixel *cp, *pix = s->pix; double threshold = s->threshold; int minrank = s->minrank, minsize = s->minsize; int sz = s->w * s->h, w1[2] = { 1, s->w }; int i, ix, pass; /* Initialize pixel nodes */ if (!start) { for (i = 0 , cp = pix; i < sz; i++ , cp++) { cp->group = i; cp->cnt = 1; cp->rank = 0; cp->threshold = threshold; } } /* Setup loop range */ pass = start / s->cnt; i = start % s->cnt; cnt += i; for (; pass < 3; pass++) { ix = cnt < s->cnt ? cnt : s->cnt; edge = s->edges + i; for (; i < ix; i++ , edge++) { float dist; int j, k, idx; /* Get the original pixel */ dist = edge->diff; idx = edge->which; j = idx >> 1; /* Get the neighboring pixel's index */ k = j + w1[idx & 1]; /* Get segment anchors */ j = seg_find(pix, j); k = seg_find(pix, k); if (j == k) continue; /* Merge segments if difference is small enough in pass 0, * one of segments is too low rank in pass 1, or is too * small in pass 2 */ if (!pass ? ((dist <= pix[j].threshold) && (dist <= pix[k].threshold)) : pass == 1 ? ((pix[j].rank < minrank) || (pix[k].rank < minrank)) : ((pix[j].cnt < minsize) || (pix[k].cnt < minsize))) { seg_pixel *cp = pix + seg_join(pix, j, k); cp->threshold = dist + threshold / cp->cnt; } } /* Pass not yet completed - return progress */ if (cnt < s->cnt) return (pass * s->cnt + cnt); cnt -= s->cnt; i = 0; pass += !pass && !minrank; // Maybe skip pass 1 pass += pass && (minsize <= (1 << minrank)); // Maybe skip pass 2 } /* Normalize groups */ for (i = 0; i < sz; i++) seg_find(pix, i); /* All done */ s->phase |= 2; return (s->cnt * 3); } int mem_seg_process(seg_state *s) { int i, n, cnt = s->cnt * 3; if (s->w * s->h < 1024 * 1024) { /* Run silently */ mem_seg_process_chunk(0, cnt, s); return (TRUE); } /* Show progress */ n = (cnt + 19) / 20; progress_init(_("Segmentation Pass 2"), 1); for (i = 0; s->phase < 2; i = mem_seg_process_chunk(i, n, s)) if (progress_update((float)i / cnt)) break; progress_end(); return (s->phase >= 2); } /* This produces for one row 2 difference bits per pixel: left & up; if called * with segmentation still in progress, will show oversegmentation */ void mem_seg_scan(unsigned char *dest, int y, int x, int w, int zoom, const seg_state *s) { int i, j, k, l, ofs, dy; seg_pixel *pix = s->pix; memset(dest, 0, (w + 3) >> 2); ofs = (y * s->w + x) * zoom; dy = y ? s->w * zoom : 0; // No up neighbors for Y=0 j = pix[ofs + (!x - 1) * zoom].group; // No left neighbor for X=0 for (i = 0; i < w; i++ , j = k , ofs += zoom) { k = pix[ofs].group , l = pix[ofs - dy].group; dest[i >> 2] |= ((j != k) * 2 + (k != l)) << ((i + i) & 6); } } /* Draw segments in unique colors */ void mem_seg_render(unsigned char *img, const seg_state *s) { int i, k, l, sz = s->w * s->h; seg_pixel *pix = s->pix; for (i = l = 0; i < sz; i++) { int j, k, r, g, b; if (pix[i].group != i) continue; // Only new groups k = l++; /* Transform index to most distinct RGB color */ for (j = r = g = b = 0; j < 8; j++) { r += r + (k & 1); k >>= 1; g += g + (k & 1); k >>= 1; b += b + (k & 1); k >>= 1; } pix[i].cnt = RGB_2_INT(r, g, b); } for (i = 0; i < sz; i++ , img += 3) { k = pix[pix[i].group].cnt; img[0] = INT_2_R(k); img[1] = INT_2_G(k); img[2] = INT_2_B(k); } } #define FRACTAL_DIM 1.25 //#define FRACTAL_THR 20 /* dragban2.jpg */ #define FRACTAL_THR 15 /* dragban2.jpg after K-N */ #define THRESHOLD_MULT 20.0 /* Estimate contour length by fractal dimension, use the difference value found * this way as threshold's base value */ double mem_seg_threshold(seg_state *s) { int k = s->cnt - FRACTAL_THR * pow(s->cnt, 0.5 * FRACTAL_DIM); while (!s->edges[k].diff && (k < s->cnt - 1)) k++; return (s->edges[k].diff ? s->edges[k].diff * THRESHOLD_MULT : 1.0); } #undef FRACTAL_DIM #undef FRACTAL_THR #undef THRESHOLD_MULT /// NOISE /* * This code implements classical Perlin noise, with the added tweak that nodes * of every octave are offset against all the others, so that you won't observe * N successively smaller copies of same thing over one another at the upper left */ static uint32_t ran_seed[2]; void ran_init(uint32_t seed) { ran_seed[1] = (ran_seed[0] = seed ^ 0xC0FFEE) * 0x10450405 + 1; } #define ROL(V,N) (((V) << (N)) | (V) >> (32 - (N))) /* xoroshiro64** 1.0 PRNG */ uint32_t ran() { uint32_t r, s0 = ran_seed[0], s1 = ran_seed[1]; r = s0 * 0x9E3779BB; r = ROL(r, 5) * 5; s1 ^= s0; ran_seed[0] = ROL(s0, 26) ^ s1 ^ (s1 << 9); ran_seed[1] = ROL(s1, 13); return (r); } static struct { int xstep, ystep, lvl; float grad[256 * 2]; unsigned char p[256], map[768]; } perlin_info; void init_perlin(int seed, int xstep, int ystep, int lvl, int maptype) { float *fp = perlin_info.grad; int i, j; mem_prepare_map(perlin_info.map, maptype); perlin_info.xstep = xstep; perlin_info.ystep = ystep; /* Limit lvl to max of log2(xstep,ystep) */ i = nlog2(xstep); j = nlog2(ystep); if (i < j) i = j; i += !i; // Allow for useless setup of 1/1 if (lvl > i) lvl = i; perlin_info.lvl = lvl; ran_init(seed); /* Random gradient vectors, equidistributed on unit circle */ for (i = 0; i < 256; i++) { double a = (2 * M_PI / 0x1000000) * (int)(ran() >> 8); // 24 random bits *fp++ = sin(a); *fp++ = cos(a); } /* Permutation table */ for (i = 0; i < 256; i++) perlin_info.p[i] = i; for (i = 0; i < 255; i++) { unsigned char v = perlin_info.p[i]; int n = ran() % (256 - i) + i; perlin_info.p[i] = perlin_info.p[n]; perlin_info.p[n] = v; } } void do_perlin(int start, int step, int cnt, unsigned char *mask, unsigned char *imgr, int x, int y) { double sum, tx, ty, yb, d, dx, dy, sc, wyy[8], ybb[8]; int i, k, lvl, a, b, yp0[8], yp1[8], mstep = step, bpp = MEM_BPP; /* Y-dependent values stay same for whole row */ dy = 0; ty = (double)y / perlin_info.ystep; for (lvl = 0; lvl < perlin_info.lvl; lvl++) { yb = ty + dy; ybb[lvl] = yb -= (b = (int)yb); wyy[lvl] = ((yb * 6.0 - 15.0) * yb + 10.0) * yb * yb * yb; k = perlin_info.p[lvl] * lvl; yp0[lvl] = perlin_info.p[(b + k) & 255]; yp1[lvl] = perlin_info.p[(b + 1 + k) & 255]; ty *= 2; dy = 0.5; // Dealign levels' anchor grid } /* Normalization factor */ i = 1 << perlin_info.lvl; sc = 255 * i / (M_SQRT2 * 2 * (i - 1)); x += start - step; start *= bpp; step *= bpp; imgr += start - step; while (cnt-- > 0) { imgr += step; x += mstep; if (mask[x] == 255) continue; sum = dx = 0; tx = (double)x / perlin_info.xstep; d = 1; for (lvl = 0; lvl < perlin_info.lvl; lvl++) { float *xp0, *xp1, *xp2, *xp3; double xa, yb, wx, wy, dd, dd1; xa = tx + dx; xa -= (a = (int)xa); wx = ((xa * 6.0 - 15.0) * xa + 10.0) * xa * xa * xa; yb = ybb[lvl]; wy = wyy[lvl]; a += perlin_info.p[lvl] * lvl; b = a + yp0[lvl]; xp0 = perlin_info.grad + perlin_info.p[b & 255] * 2; dd = xp0[0] * xa + xp0[1] * yb; xp1 = perlin_info.grad + perlin_info.p[(b + 1) & 255] * 2; dd += wx * (xp1[0] * (xa - 1) + xp1[1] * yb - dd); b = a + yp1[lvl]; xp2 = perlin_info.grad + perlin_info.p[b & 255] * 2; dd1 = xp2[0] * xa + xp2[1] * (yb - 1); xp3 = perlin_info.grad + perlin_info.p[(b + 1) & 255] * 2; dd1 += wx * (xp3[0] * (xa - 1) + xp3[1] * (yb - 1) - dd1); sum += (dd + (dd1 - dd) * wy) * d; tx += tx; d *= 0.5; dx = 0.5; // Dealign levels' anchor grid } k = rint(sum * sc + 0.5 * 255.0); if (bpp == 1) *imgr = k; else { k *= 3; imgr[0] = perlin_info.map[k + 0]; imgr[1] = perlin_info.map[k + 1]; imgr[2] = perlin_info.map[k + 2]; } } } typedef struct { unsigned char *buf, *mask; } noised; static void perlin_noise(tcb *thread) { noised *nd = thread->data; unsigned char *dest, *buf = nd->buf, *mask = nd->mask; int i, ii, cnt = thread->nsteps, bpp = MEM_BPP; for (i = thread->step0 , ii = 0; ii < cnt; i++ , ii++) { row_protected(0, i, mem_width, mask); do_perlin(0, 1, mem_width, mask, buf, 0, i); dest = mem_img[mem_channel] + i * mem_width * bpp; process_img(0, 1, mem_width, mask, dest, dest, buf, NULL, bpp, BLENDF_SET | BLENDF_INVM); if (thread_step(thread, ii + 1, cnt, 10)) break; } thread_done(thread); } void mem_perlin() { noised nd; threaddata *tdata; tdata = talloc(MA_ALIGN_DEFAULT, image_threads(mem_width, mem_height), &nd, sizeof(nd), NULL, &nd.buf, mem_width * MEM_BPP, &nd.mask, mem_width, NULL); if (!tdata) { memory_errors(1); return; } launch_threads(perlin_noise, tdata, _("Solid Noise"), mem_height); free(tdata); } mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/memory.h000066400000000000000000001052661471325446300224350ustar00rootroot00000000000000/* memory.h Copyright (C) 2004-2024 Mark Tyler and Dmitry Groshev This file is part of mtPaint. mtPaint 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. mtPaint 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 mtPaint in the file COPYING. */ #include #include /// Definitions, structures & variables #define MAX_WIDTH 16384 #define MAX_HEIGHT 16384 #define MIN_WIDTH 1 #define MIN_HEIGHT 1 /* !!! If MAX_WIDTH * MAX_HEIGHT * max bpp won't fit into int, lots of code * !!! will have to be modified to use size_t instead */ #define MAX_DIM (MAX_WIDTH > MAX_HEIGHT ? MAX_WIDTH : MAX_HEIGHT) #define DEFAULT_WIDTH 640 #define DEFAULT_HEIGHT 480 /* Palette area layout */ #define PALETTE_SWATCH_X 25 #define PALETTE_SWATCH_Y 1 #define PALETTE_SWATCH_W 26 #define PALETTE_SWATCH_H 16 #define PALETTE_INDEX_X 0 #define PALETTE_INDEX_DY 5 #define PALETTE_DIGIT_W 7 #define PALETTE_DIGIT_H 7 #define PALETTE_CROSS_X 53 #define PALETTE_CROSS_DX 4 #define PALETTE_CROSS_DY 4 #define PALETTE_CROSS_W 8 #define PALETTE_CROSS_H 8 #define PALETTE_WIDTH 70 #define PALETTE_W3 (PALETTE_WIDTH * 3) #define PALETTE_HEIGHT (PALETTE_SWATCH_H * 256 + PALETTE_SWATCH_Y * 2) enum { TOOL_SQUARE = 0, TOOL_CIRCLE, TOOL_HORIZONTAL, TOOL_VERTICAL, TOOL_SLASH, TOOL_BACKSLASH, TOOL_SPRAY, TOOL_SHUFFLE, TOOL_FLOOD, TOOL_SELECT, TOOL_LINE, TOOL_SMUDGE, TOOL_POLYGON, TOOL_CLONE, TOOL_GRADIENT, TOTAL_CURSORS }; #define NO_PERIM(T) (((T) == TOOL_FLOOD) || ((T) == TOOL_SELECT) || \ ((T) == TOOL_POLYGON) || ((T) == TOOL_GRADIENT)) #define PROGRESS_LIM 262144 #define CHN_IMAGE 0 #define CHN_ALPHA 1 #define CHN_SEL 2 #define CHN_MASK 3 #define NUM_CHANNELS 4 #define CMASK_NONE 0 #define CMASK_IMAGE (1 << CHN_IMAGE) #define CMASK_ALPHA (1 << CHN_ALPHA) #define CMASK_SEL (1 << CHN_SEL) #define CMASK_MASK (1 << CHN_MASK) #define CMASK_RGBA ((1 << CHN_IMAGE) | (1 << CHN_ALPHA)) #define CMASK_ALL ((1 << NUM_CHANNELS) - 1) #define CMASK_CURR (1 << mem_channel) #define CMASK_FOR(A) (1 << (A)) #define CMASK_CLIP ((1 << CHN_IMAGE) | (1 << CHN_ALPHA) | (1 << CHN_SEL)) #define SIZEOF_PALETTE (256 * sizeof(png_color)) // Both limits should be powers of two #define FRAMES_MIN 16 #define FRAMES_MAX (1024 * 1024) /* A million frames should be QUITE enough */ /* Frame flags */ #define FM_DISPOSAL 3 /* Disposal mask */ #define FM_DISP_REMOVE 0 /* Remove (make transparent) (default) */ #define FM_DISP_LEAVE 1 /* Leave in place */ #define FM_DISP_RESTORE 2 /* Restore to previous state */ #define FM_NUKE 4 /* Delete this frame at earliest opportunity */ /* Undo data types */ #define UD_FILENAME 0 /* Filename */ #define UD_TEMPFILES 1 /* Temp files list */ #define NUM_UTYPES 2 /* Should be no larger than 32 */ // List in here all types which need freeing #define UD_FREE_MASK (1 << UD_FILENAME) typedef unsigned char *chanlist[NUM_CHANNELS]; typedef struct { chanlist img; png_color *pal; int width, height; int x, y, delay; short cols, bpp, trans; unsigned short flags; } image_frame; typedef struct { image_frame *frames; // Pointer to frames array png_color *pal; // Default palette int cur; // Index of current frame int cnt; // Number of frames in use int max; // Total number of frame slots size_t size; // Total used memory (0 means count it anew) } frameset; typedef struct { void *store[NUM_UTYPES]; unsigned int map; } undo_data; typedef struct { chanlist img; png_color *pal_; unsigned char *tileptr; undo_data *dataptr; size_t size; int width, height, flags; short cols, bpp, trans; } undo_item; typedef struct { undo_item **items; // Array of pointers to undo frames int pointer; // Index of currently used image on canvas/screen int done; // Undo images that we have behind current image (i.e. possible UNDO) int redo; // Undo images that we have ahead of current image (i.e. possible REDO) int max; // Total number of undo slots size_t size; // Total used memory (0 means count it anew) } undo_stack; typedef struct { chanlist img; // Array of pointers to image channels png_color pal[256]; // RGB entries for all 256 palette colours int cols; // Number of colours in the palette: 1..256 or 0 for no image int bpp; // Bytes per pixel = 1 or 3 int trans; // Transparent colour index (-1 if none) int width, height; // Image geometry undo_stack undo_; // Image's undo stack char *filename; // File name of file loaded/saved (must be shorter than PATHBUF) void *tempfiles; // List of up-to-date temp files int changed; // Changed since last load/save flag } image_info; typedef struct { int channel; // Current active channel int ics; // Has the centre been set by the user? float ic[2]; // Current centre x,y int tool_pat, tool_pat_B; // Tool pattern number int xbm_hot_x, xbm_hot_y; // Current XBM hot spot char prot_mask[256]; // 256 bytes used for indexed images int prot; // Number of protected colours int col_[2]; // Index for colour A & B png_color col_24[2]; // RGB for colour A & B int iover, aover; // Image hidden / alpha overlayed } image_state; /// GRADIENTS #define MAX_GRAD 65536 #define GRAD_POINTS 256 typedef struct { /* Base values */ int status, xy[4]; // Gradient placement tool int len, rep, ofs; // Gradient length, repeat, and offset int gmode, rmode; // Gradient mode and repeat mode /* Derived values */ double wrep, wil1, wil2, xv, yv, wa; int wmode, wrmode; } grad_info; typedef struct { char gtype, otype; // Main and opacity gradient types char grev, orev; // Main and opacity reversal flags int vslen, oplen; // Current gradient lengths int cvslen, coplen; // Custom gradient lengths unsigned char *vs, *vsmap; // Current gradient data unsigned char *op, *opmap; // Current gradient opacities } grad_map; typedef unsigned char grad_store[(6 + NUM_CHANNELS * 4) * GRAD_POINTS]; grad_info gradient[NUM_CHANNELS]; // Per-channel gradient placement double grad_path, grad_x0, grad_y0; // Stroke gradient temporaries grad_map graddata[NUM_CHANNELS + 1]; // RGB + per-channel gradient data grad_store gradbytes; // Storage space for custom gradients int grad_opacity; // Preview opacity /* Gradient modes */ #define GRAD_MODE_NONE 0 #define GRAD_MODE_BURST 1 #define GRAD_MODE_LINEAR 2 #define GRAD_MODE_BILINEAR 3 #define GRAD_MODE_RADIAL 4 #define GRAD_MODE_SQUARE 5 #define GRAD_MODE_ANGULAR 6 #define GRAD_MODE_CONICAL 7 /* Boundary conditions */ #define GRAD_BOUND_STOP 0 #define GRAD_BOUND_LEVEL 1 #define GRAD_BOUND_REPEAT 2 #define GRAD_BOUND_MIRROR 3 #define GRAD_BOUND_STOP_A 4 /* Stop mode for angular gradient */ #define GRAD_BOUND_REP_A 5 /* Repeat mode for same */ /* Gradient types */ #define GRAD_TYPE_RGB 0 #define GRAD_TYPE_SRGB 1 #define GRAD_TYPE_HSV 2 #define GRAD_TYPE_BK_HSV 3 #define GRAD_TYPE_CONST 4 #define GRAD_TYPE_CUSTOM 5 #define STROKE_GRADIENT (mem_gradient && (gradient[mem_channel].status == GRAD_NONE)) /// Bayer ordered dithering const unsigned char bayer[16]; #define BAYER_MASK 15 /* Use 16x16 matrix */ #define BAYER(x,y) (bayer[((x) ^ (y)) & BAYER_MASK] * 2 + bayer[(y) & BAYER_MASK]) /// Tint tool - contributed by Dmitry Groshev, January 2006 int tint_mode[3]; // [0] = off/on, [1] = add/subtract, [2] = button (none, left, middle, right : 0-3) int mem_cselect; int mem_blend; int mem_unmask; int mem_gradient; int paint_gamma; /// BLEND MODE int blend_mode; int blend_src; /* Blend modes */ enum { /* RGB-only modes */ BLEND_NORMAL = 0, BLEND_HUE, BLEND_SAT, BLEND_VALUE, BLEND_COLOR, BLEND_SATPP, /* Per-channel modes */ BLEND_1BPP, // First one-byte mode BLEND_MULT = BLEND_1BPP, BLEND_DIV, BLEND_SCREEN, // !!! No "Overlay" - it is a reverse "Hard Light" BLEND_DODGE, BLEND_BURN, BLEND_HLIGHT, BLEND_SLIGHT, BLEND_DIFF, BLEND_DARK, BLEND_LIGHT, BLEND_GRAINX, BLEND_GRAINM, BLEND_XHOLD, BLEND_NMODES }; #define BLEND_MMASK 0x3F #define BLEND_XFORM 0x40 #define BLEND_REVERSE 0x80 #define BLEND_RGBSHIFT 8 /* Flags for internal use */ #define BLENDF_TINT 0x01000000 /* Tint add */ #define BLENDF_TINTM 0x02000000 /* Tint sub */ #define BLENDF_IDX 0x04000000 /* Indexed mode */ #define BLENDF_INVM 0x08000000 /* Invert mask */ #define BLENDF_SET 0x10000000 /* Ignore settings, use parameter */ /* Blend sources */ enum { SRC_NORMAL = 0, SRC_IMAGE, SRC_LAYER }; /// FLOOD FILL SETTINGS double flood_step; int flood_cube, flood_img, flood_slide; int smudge_mode; /// QUANTIZATION SETTINGS int quan_sqrt; // "Diameter based weighting" - use sqrt of pixel count /// IMAGE #define MIN_UNDO 11 // Number of undo levels + 1 #define DEF_UNDO 101 #define MAX_UNDO 1001 int mem_undo_depth; // Current undo depth image_info mem_image; // Current image #define mem_img mem_image.img #define mem_pal mem_image.pal #define mem_cols mem_image.cols #define mem_img_bpp mem_image.bpp #define mem_xpm_trans mem_image.trans #define mem_width mem_image.width #define mem_height mem_image.height #define mem_undo_im_ mem_image.undo_.items #define mem_undo_pointer mem_image.undo_.pointer #define mem_undo_done mem_image.undo_.done #define mem_undo_redo mem_image.undo_.redo #define mem_undo_max mem_image.undo_.max #define mem_filename mem_image.filename #define mem_tempfiles mem_image.tempfiles #define mem_changed mem_image.changed image_info mem_clip; // Current clipboard #define mem_clipboard mem_clip.img[CHN_IMAGE] #define mem_clip_alpha mem_clip.img[CHN_ALPHA] #define mem_clip_mask mem_clip.img[CHN_SEL] #define mem_clip_bpp mem_clip.bpp #define mem_clip_w mem_clip.width #define mem_clip_h mem_clip.height // Repurpose the field #define mem_clip_paletted mem_clip.changed #define mem_clip_pal mem_clip.pal image_state mem_state; // Current edit settings #define mem_channel mem_state.channel #define mem_ic mem_state.ic #define mem_icx mem_state.ic[0] #define mem_icy mem_state.ic[1] #define mem_ics mem_state.ics #define mem_tool_pat mem_state.tool_pat #define mem_tool_pat_B mem_state.tool_pat_B #define mem_xbm_hot_x mem_state.xbm_hot_x #define mem_xbm_hot_y mem_state.xbm_hot_y #define mem_prot_mask mem_state.prot_mask #define mem_prot mem_state.prot #define mem_col_ mem_state.col_ #define mem_col_A mem_state.col_[0] #define mem_col_B mem_state.col_[1] #define mem_col_24 mem_state.col_24 #define mem_col_A24 mem_state.col_24[0] #define mem_col_B24 mem_state.col_24[1] #define hide_image mem_state.iover #define overlay_alpha mem_state.aover int mem_clip_x, mem_clip_y; // Clipboard location on canvas #define BRUSH_CELL 36 #define BRUSH_GRID_W 9 #define BRUSH_GRID_H 9 #define NUM_BRUSHES (BRUSH_GRID_W * BRUSH_GRID_H) #define PATCH_WIDTH (BRUSH_CELL * BRUSH_GRID_W) #define PATCH_HEIGHT (BRUSH_CELL * BRUSH_GRID_H) extern unsigned char mem_brushes[]; // Preset brushes image int mem_brush_list[NUM_BRUSHES][3]; // Preset brushes parameters int mem_nudge; // Nudge pixels per SHIFT+Arrow key during selection/paste int mem_undo_limit; // Max MB memory allocation limit int mem_undo_common; // Percent of undo space in common arena int mem_undo_opacity; // Use previous image for opacity calculations? int mem_undo_fail; // Undo space shortfall /// COLOR TRANSFORM typedef struct { int bcsp[6]; // BR, CO, SA, POSTERIZE, GAMMA, Hue int allow[3]; // R/G/B int pmode; // bitwise/truncated/rounded } transform_state; transform_state mem_bcsp[2]; #define BRCOSA_ITEMS 6 #define BRCOSA_POSTERIZE 3 #define DEF_POSTERIZE(T) ((T) ? 256 : 8) /* truncated/rounded vs bitwise */ /// THRESHOLD enum { XHOLD_MAX = 0, XHOLD_MIN = 1, XHOLD_RED, XHOLD_GREEN, XHOLD_BLUE, XHOLD_NMODES }; typedef struct { int lo, hi, mode; } threshold_state; threshold_state mem_ts; /// PATTERNS int pattern_B; // Let colour B have its own pattern unsigned char *mem_pattern; // Current pattern unsigned char mem_col_pat[8 * 8]; // Indexed 8x8 colourised pattern using colours A & B unsigned char mem_col_pat24[8 * 8 * 3]; // RGB 8x8 colourised pattern using colours A & B /// TOOLS typedef struct { int type, brush; int var[3]; // Size, flow, opacity } tool_info; tool_info tool_state; #define tool_type tool_state.type /* Currently selected tool */ #define brush_type tool_state.brush /* Last brush tool type */ #define tool_size tool_state.var[0] #define tool_flow tool_state.var[1] #define tool_opacity tool_state.var[2] /* Opacity - 255 = solid */ int pen_down; // Are we drawing? - Used to see if we need to do an UNDO int tool_ox, tool_oy; // Previous tool coords - used by continuous mode int mem_continuous; // Area we painting the static shapes continuously? /// PALETTE png_color mem_pal_def[256]; // Default palette entries for new image int mem_pal_def_i; // Items in default palette int mem_pal_id_c, mem_pal_ab_c; // Text & A/B highlight colors extern unsigned char mem_pals[]; // RGB screen memory holding current palette int mem_background; // Non paintable area int mem_histogram[256]; /// Number in bounds static inline int bounded(int n, int n0, int n1) { return (n < n0 ? n0 : n > n1 ? n1 : n); } /// Next power of two static inline unsigned int nextpow2(unsigned int n) { n |= n >> 1; n |= n >> 2; n |= n >> 4; n |= n >> 8; n |= n >> 16; #if UINT_MAX > 0xFFFFFFFFUL n |= n >> 32; #endif return (n + 1); } /// Binary logarithm, rounding up static inline unsigned int nlog2(unsigned int n) { unsigned int m; #if UINT_MAX > 0xFFFFFFFFUL m = (n >= 0x100000000U) << 5; m += (n >> m >= 0x10000) << 4; #else m = (n >= 0x10000) << 4; #endif m += (n >> m >= 0x100) << 3; m += (n >> m >= 0x10) << 2; m += (0xFFFFAA50U >> ((n >> m) << 1)) & 3; return (m + (n > 1U << m)); } /// Number of set bits static inline unsigned int bitcount(unsigned int n) { unsigned int m; #if UINT_MAX > 0xFFFFFFFFUL n -= (n >> 1) & 0x5555555555555555U; m = n & 0xCCCCCCCCCCCCCCCCU; n = (n ^ m) + (m >> 2); n = (n + (n >> 4)) & 0x0F0F0F0F0F0F0F0FU; n = (n * 0x0101010101010101U) >> 56; #else n -= (n >> 1) & 0x55555555; m = n & 0x33333333; n = m + ((n ^ m) >> 2); n = (n + (n >> 4)) & 0x0F0F0F0F; n = (n * 0x01010101) >> 24; #endif return (n); } /// Floored integer division static inline int floor_div(int dd, int dr) { return (dd / dr - (dd % dr < 0)); // optimizes to perfection on x86 } /// Ceiling integer division static inline int ceil_div(int dd, int dr) { return (dd / dr + (dd % dr > 0)); } /// Floored integer modulus static inline int floor_mod(int dd, int dr) { return (dd - dr * floor_div(dd, dr)); } /// Table-based translation static inline void do_xlate(unsigned char *xlat, unsigned char *data, int len) { int i; for (i = 0; i < len; i++) data[i] = xlat[data[i]]; } /// Copying "x0y0x1y1" quad #define copy4(D,S) memcpy(D, S, 4 * sizeof(int)) /// Block allocator typedef struct { char *block; unsigned int here, size; unsigned int minsize, incr; } wjmem; wjmem *wjmemnew(int size, int incr); void wjmemfree(wjmem *mem); void *wjmalloc(wjmem *mem, int size, int align); /// Simple doubling allocator typedef struct { char *buf; // data block int here; // current position int size; // currently allocated } memx2; #define MEMX2_MAX INT_MAX /* How much it can hold */ size_t getmemx2(memx2 *mem, size_t length); void addstr(memx2 *mem, char *s, int bk); void addchars(memx2 *mem, int c, int l); extern char MEM_NONE_[]; #define MEM_NONE (void *)MEM_NONE_ /* Non-NULL pointer which means nothing */ /// Multiblock allocator #define MA_ALIGN_MASK 0x03 /* For alignment constraints */ #define MA_ALIGN_DEFAULT 0x00 #define MA_ALIGN_DOUBLE 0x01 #define MA_SKIP_ZEROSIZE 0x04 /* Leave pointers to zero-size areas unchanged */ #define MA_FLAG_NONE 0x08 /* Return MEM_NONE if total size is zero */ void *multialloc(int flags, void *ptr, int size, ...); /// Vectorized low-level drawing functions void (*put_pixel)(int x, int y); void (*put_pixel_row)(int x, int y, int len, unsigned char *xsel); // Intersect two rectangles int clip(int *rxy, int x0, int y0, int x1, int y1, const int *vxy); // Intersect outer & inner rectangle, write out what it separates into int clip4(int *rect04, int xo, int yo, int wo, int ho, int xi, int yi, int wi, int hi); // Get scaled span of rectangle on X or Y int xy_span(int *rxy, int scale, int yf); // Rebase rectangle to origin X, Y void xy_origin(int *rxy, int *vxy, int x, int y); /// Line iterator /* Indices 0 and 1 are current X and Y, 2 is number of pixels remaining */ typedef int linedata[10]; void line_init(linedata line, int x0, int y0, int x1, int y1); int line_step(linedata line); void line_nudge(linedata line, int x, int y); int line_clip(linedata line, const int *vxy, int *step); void line_flip(linedata line); /// Procedures // Add one more frame to a frameset int mem_add_frame(frameset *fset, int w, int h, int bpp, int cmask, png_color *pal); // Remove specified frame from a frameset void mem_remove_frame(frameset *fset, int frame); // Empty a frameset void mem_free_frames(frameset *fset); void init_istate(image_state *state, image_info *image); // Set initial state of image variables void mem_replace_filename(int layer, char *fname); // Change layer's filename void mem_file_modified(char *fname); // Label file's frames in current layer as changed int init_undo(undo_stack *ustack, int depth); // Create new undo stack of a given depth void update_undo_depth(); // Resize all undo stacks void mem_free_chanlist(chanlist img); int cmask_from(chanlist img); // Chanlist to cmask int mem_count_all_cols(); // Count all colours - Using main image int mem_count_all_cols_real(unsigned char *im, int w, int h); // Count all colours - very memory greedy int mem_cols_used(png_color *pal); // Count and collect colours used in main RGB image int mem_cols_used_real(unsigned char *im, int w, int h, png_color *pal); // Count and collect colours used in RGB chunk #define FREE_IMAGE 1 #define FREE_UNDO 2 #define FREE_ALL 3 // Clear/remove image data void mem_free_image(image_info *image, int mode); #define AI_COPY 1 /* Duplicate source channels, not insert them */ #define AI_NOINIT 2 /* Do not initialize source-less channels */ #define AI_CLEAR 4 /* Initialize image structure first */ // Allocate new image data int mem_alloc_image(int mode, image_info *image, int w, int h, int bpp, int cmask, image_info *src); // Allocate space for new image, removing old if needed int mem_new( int width, int height, int bpp, int cmask ); // Allocate new clipboard, removing or preserving old as needed int mem_clip_new(int width, int height, int bpp, int cmask, chanlist backup); int load_def_palette(char *name); int load_def_patterns(char *name); void mem_init(); // Initialise memory // Return the number of bytes used in image + undo stuff size_t mem_used(); // Return the number of bytes used in image + undo in all layers size_t mem_used_layers(); #define FX_EDGE 0 #define FX_EMBOSS 2 #define FX_SHARPEN 3 #define FX_SOFTEN 4 #define FX_SOBEL 5 #define FX_PREWITT 6 #define FX_GRADIENT 7 #define FX_ROBERTS 8 #define FX_LAPLACE 9 #define FX_KIRSCH 10 #define FX_ERODE 11 #define FX_DILATE 12 #define FX_MORPHEDGE 13 void do_effect( int type, int param ); // 0=edge detect 1=UNUSED 2=emboss void mem_bacteria( int val ); // Apply bacteria effect val times the canvas area void mem_gauss(double radiusX, double radiusY, int gcor); void mem_unsharp(double radius, double amount, int threshold, int gcor); void mem_dog(double radiusW, double radiusN, int norm, int gcor); void mem_kuwahara(int r, int gcor, int detail); /* Colorspaces */ #define CSPACE_RGB 0 #define CSPACE_SRGB 1 #define CSPACE_LXN 2 #define NUM_CSPACES 3 /* Distance measures */ #define DIST_LINF 0 /* Largest absolute difference (Linf measure) */ #define DIST_L1 1 /* Sum of absolute differences (L1 measure) */ #define DIST_L2 2 /* Euclidean distance (L2 measure) */ #define NUM_DISTANCES 3 /// PALETTE PROCS void mem_pal_load_def(); // Load default palette #define mem_pal_copy(A, B) memcpy((A), (B), SIZEOF_PALETTE) void mem_pal_init(); // Initialise whole of palette RGB // Expand palette to RGB triples, pad with 0 if needed void pal2rgb(unsigned char *rgb, png_color *pal, int cnt, int len); // Pack RGB triples into palette void rgb2pal(png_color *pal, unsigned char *rgb, int cnt); double pal2B(png_color *c); // Linear brightness for palette color void mem_greyscale(int gcor); // Convert image to greyscale void do_convert_rgb(int start, int step, int cnt, unsigned char *dest, unsigned char *src, png_color *pal); // Convert image to RGB int mem_convert_indexed(unsigned char *dest, unsigned char *src, int cnt, int cols, png_color *pal); // Convert image to Indexed Palette // Quantize image using Max-Min algorithm int maxminquan(unsigned char *inbuf, int width, int height, int quant_to, png_color *userpal); // Quantize image using PNN algorithm int pnnquan(unsigned char *inbuf, int width, int height, int quant_to, png_color *userpal); // Convert RGB->indexed using error diffusion with variety of options int mem_dither(unsigned char *old, int ncols, short *dither, int cspace, int dist, int limit, int selc, int serpent, int rgb8b, double emult); // Do the same in dumb but fast way int mem_dumb_dither(unsigned char *old, unsigned char *new, png_color *pal, int width, int height, int ncols, int dither); // Set up colors A, B, and pattern for dithering a given RGB color void mem_find_dither(int red, int green, int blue); // Convert image to Indexed Palette using quantize int mem_quantize( unsigned char *old_mem_image, int target_cols, int type ); void mem_invert(); // Invert the palette void mem_normalize(); // Normalize contrast in image or palette // Clear/set protection (what = NULL - color n, n = -1 - all colors) void mem_mask_setv(int *what, int n, int state); void mem_mask_init(); // Initialise RGB protection mask int mem_protected_RGB(int intcol); // Is this intcol in mask? void mem_swap_cols(int redraw); // Swaps colours and update memory void mem_set_trans(int trans); // Set transparent colour and update void mem_get_histogram(int channel); // Calculate how many of each colour index is on the canvas int scan_duplicates(); // Find duplicate palette colours void remove_duplicates(); // Remove duplicate palette colours - call AFTER scan_duplicates int mem_remove_unused_check(); // Check to see if we can remove unused palette colours int mem_remove_unused(); // Remove unused palette colours void mem_bw_pal(png_color *pal, int i1, int i2); // Generate black-to-white palette // Create colour-transformed palette void transform_pal(png_color *pal1, png_color *pal2, int p1, int p2); void mem_pal_sort( int a, int i1, int i2, int rev ); // Sort colours in palette 0=luminance, 1=RGB void mem_pal_index_move( int c1, int c2 ); // Move index c1 to c2 and shuffle in between up/down void mem_canvas_index_move( int c1, int c2 ); // Similar to palette item move but reworks canvas pixels void set_zoom_centre( int x, int y ); // Nonclassical HSV: H is 0..6, S is 0..1, V is 0..255 void rgb2hsv(unsigned char *rgb, double *hsv); void hsv2rgb(unsigned char *rgb, double *hsv); //// UNDO enum { UNDO_PAL = 0, /* Palette changes */ UNDO_XPAL, /* Palette and indexed image changes */ UNDO_COL, /* Palette and/or RGB image changes */ UNDO_DRAW, /* Changes to current channel / RGBA */ UNDO_INV, /* "Invert" operation */ UNDO_XFORM, /* Changes to all channels */ UNDO_FILT, /* Changes to current channel */ UNDO_PASTE, /* Paste operation (current / RGBA) */ UNDO_TOOL, /* Same as UNDO_DRAW but respects pen_down */ UNDO_TRANS /* Transparent colour change (cumulative) */ }; void mem_undo_next(int mode); // Call this after a draw event but before any changes to image // Get address of previous channel data (or current if none) unsigned char *mem_undo_previous(int channel); void mem_undo_prepare(); // Call this after changes to image, to compress last frame void mem_do_undo(int redo); // Undo or redo requested by user #define UC_CREATE 0x01 /* Force create */ #define UC_NOCOPY 0x02 /* Forbid copy */ #define UC_DELETE 0x04 /* Force delete */ #define UC_PENDOWN 0x08 /* Respect pen_down */ #define UC_GETMEM 0x10 /* Get memory and do nothing */ #define UC_ACCUM 0x20 /* Cumulative change */ #define UC_RESET 0x40 /* Delete all, create flagged */ int undo_next_core(int mode, int new_width, int new_height, int new_bpp, int cmask); void update_undo(image_info *image); // Copy image state into current undo frame // Try to allocate a memory block, releasing undo frames if needed void *mem_try_malloc(size_t size); //// Drawing Primitives int sb_dist; // Distance measure int sb_rect[4]; // Backbuffer placement int init_sb(); // Create shapeburst backbuffer void render_sb(unsigned char *mask); // Render from shapeburst backbuffer int mem_clip_mask_init(unsigned char val); // Initialise the clipboard mask // Extract alpha info from RGB clipboard int mem_scale_alpha(unsigned char *img, unsigned char *alpha, int width, int height, int mode); void mem_mask_colors(unsigned char *mask, unsigned char *img, unsigned char v, int width, int height, int bpp, int col0, int col1); void mem_clip_mask_set(unsigned char val); // Mask colours A and B on the clipboard void mem_clip_mask_clear(); // Clear the clipboard mask void mem_smudge(int ox, int oy, int nx, int ny); // Apply colour transform void do_transform(int start, int step, int cnt, unsigned char *mask, unsigned char *imgr, unsigned char *img0, int m0); // Apply thresholding void do_xhold(int start, int step, int cnt, unsigned char *mask, unsigned char *imgr, unsigned char *img0); void mem_flip_v(char *mem, char *tmp, int w, int h, int bpp); // Flip image vertically void mem_flip_h( char *mem, int w, int h, int bpp ); // Flip image horizontally int mem_sel_rot( int dir ); // Rotate clipboard 90 degrees int mem_image_rot( int dir ); // Rotate canvas 90 degrees // Get new image geometry of rotation. angle = degrees void mem_rotate_geometry(int ow, int oh, double angle, int *nw, int *nh); // Rotate canvas or clipboard by any angle (degrees) int mem_rotate_free(double angle, int type, int gcor, int clipboard); void mem_rotate_free_real(chanlist old_img, chanlist new_img, int ow, int oh, int nw, int nh, int bpp, double angle, int mode, int gcor, int dis_a, int silent); #define BOUND_MIRROR 0 /* Mirror image beyond edges */ #define BOUND_TILE 1 /* Tiled image beyond edges */ #define BOUND_VOID 2 /* Transparency beyond edges */ // Scale image int mem_image_scale(int nw, int nh, int type, int gcor, int sharp, int bound); int mem_image_scale_real(chanlist old_img, int ow, int oh, int bpp, chanlist new_img, int nw, int nh, int type, int gcor, int sharp); int mem_image_resize(int nw, int nh, int ox, int oy, int mode); // Resize image int mem_isometrics(int type); void mem_threshold(unsigned char *img, int len, int level); // Threshold channel values void mem_demultiply(unsigned char *img, unsigned char *alpha, int len, int bpp); void set_xlate_n(unsigned char *xlat, int n); // Build value rescaling table #define set_xlate(A,B) set_xlate_n((A), (1 << (B)) - 1) /* Bitdepth translation table */ int is_filled(unsigned char *data, unsigned char val, int len); // Check if byte array is all one value int flood_fill(int x, int y, unsigned int target); void sline( int x1, int y1, int x2, int y2 ); // Draw single thickness straight line void tline( int x1, int y1, int x2, int y2, int size ); // Draw size thickness straight line void g_para( int x1, int y1, int x2, int y2, int xv, int yv ); // Draw general parallelogram void f_rectangle( int x, int y, int w, int h ); // Draw a filled rectangle void f_circle( int x, int y, int r ); // Draw a filled circle void mem_ellipse( int x1, int y1, int x2, int y2, int thick ); // Thickness 0 means filled // Draw whatever is bounded by two pairs of lines void draw_quad(linedata line1, linedata line2, linedata line3, linedata line4); // A couple of shorthands to get an int representation of an RGB colour #define PNG_2_INT(P) (((P).red << 16) + ((P).green << 8) + ((P).blue)) #define MEM_2_INT(M,I) (((M)[(I)] << 16) + ((M)[(I) + 1] << 8) + (M)[(I) + 2]) #define INT_2_R(A) ((A) >> 16) #define INT_2_G(A) (((A) >> 8) & 0xFF) #define INT_2_B(A) ((A) & 0xFF) #define RGB_2_INT(R,G,B) (((R) << 16) + ((G) << 8) + (B)) #define MEM_BPP (mem_channel == CHN_IMAGE ? mem_img_bpp : 1) #define BPP(x) ((x) == CHN_IMAGE ? mem_img_bpp : 1) #define IS_INDEXED ((mem_channel == CHN_IMAGE) && (mem_img_bpp == 1)) /* Whether process_img() needs extra buffer passed in */ #define NEED_XBUF_DRAW (mem_blend && (blend_mode & (BLEND_MMASK | BLEND_XFORM))) #define NEED_XBUF_PASTE (NEED_XBUF_DRAW || \ ((mem_channel == CHN_IMAGE) && (mem_clip_bpp < mem_img_bpp))) void prep_mask(int start, int step, int cnt, unsigned char *mask, unsigned char *mask0, unsigned char *img0); void process_mask(int start, int step, int cnt, unsigned char *mask, unsigned char *alphar, unsigned char *alpha0, unsigned char *alpha, unsigned char *trans, int opacity, int noalpha); void process_img(int start, int step, int cnt, unsigned char *mask, unsigned char *imgr, unsigned char *img0, unsigned char *img, unsigned char *xbuf, int bpp, int blend); void copy_area(image_info *dest, image_info *src, int x, int y); // Retroactive masking - by blending with undo frame void mask_merge(unsigned char *old, int channel, unsigned char *mask); int pixel_protected(int x, int y); // generic void row_protected(int x, int y, int len, unsigned char *mask); void put_pixel_def( int x, int y ); // generic void put_pixel_row_def(int x, int y, int len, unsigned char *xsel); // generic int get_pixel( int x, int y ); // generic int get_pixel_RGB( int x, int y ); // converter int get_pixel_img( int x, int y ); // from image int grad_value(int *dest, int slot, double x); void grad_pixels(int start, int step, int cnt, int x, int y, unsigned char *mask, unsigned char *op0, unsigned char *img0, unsigned char *alpha0); void grad_update(grad_info *grad); void gmap_setup(grad_map *gmap, grad_store gstore, int slot); void grad_def_update(int slot); #define GRAD_CUSTOM_DATA(X) ((X) ? GRAD_POINTS * ((X) * 4 + 2) : 0) #define GRAD_CUSTOM_DMAP(X) (GRAD_POINTS * ((X) * 4 + 3)) #define GRAD_CUSTOM_OPAC(X) (GRAD_POINTS * ((X) * 4 + 4)) #define GRAD_CUSTOM_OMAP(X) (GRAD_POINTS * ((X) * 4 + 5)) void blend_indexed(int start, int step, int cnt, unsigned char *rgb, unsigned char *img0, unsigned char *img, unsigned char *alpha0, unsigned char *alpha, int opacity); // Select colors nearest to A->B gradient int mem_pick_gradient(unsigned char *buf, int cspace, int mode); int mem_skew(double xskew, double yskew, int type, int gcor); int average_channel(unsigned char *src, int iw, int *vxy); int average_pixels(unsigned char *rgb, unsigned char *alpha, int iw, int *vxy); //// SEGMENTATION #define SEG_PROGRESS 1 typedef struct { int which; // Pixel index * 2 + (0 if right / 1 if down) float diff; } seg_edge; typedef struct { unsigned int group, cnt; unsigned char rank; // Value is logarithmic, so this is more than enough // unsigned char reserved[3]; float threshold; } seg_pixel; typedef struct { /* Working set */ seg_edge *edges; seg_pixel *pix; int w, h, cnt; int phase; // Which phase is currently valid /* Parameters */ int minrank; int minsize; double threshold; } seg_state; seg_state *mem_seg_prepare(seg_state *s, unsigned char *img, int w, int h, int flags, int cspace, int dist); int mem_seg_process_chunk(int start, int cnt, seg_state *s); int mem_seg_process(seg_state *s); double mem_seg_threshold(seg_state *s); void mem_seg_scan(unsigned char *dest, int y, int x, int w, int zoom, const seg_state *s); void mem_seg_render(unsigned char *img, const seg_state *s); /// REMAPPING COLORS enum { MAP_GREY = 0, MAP_GRAD, MAP_PAL, MAP_CLIP }; void mem_prepare_map(unsigned char *map, int how); // Set up colors for mapping void mem_remap_rgb(unsigned char *map, int what); // Remap V/R/G/B to color /// NOISE void init_perlin(int seed, int xstep, int ystep, int lvl, int maptype); void do_perlin(int start, int step, int cnt, unsigned char *mask, unsigned char *imgr, int x, int y); void mem_perlin(); #define IF_IN_RANGE( x, y ) if ( x>=0 && y>=0 && x #include #include #include "mtlib.h" MT_Coor MT_coze() // Return zero coordinates { MT_Coor ret; ret.x = 0; ret.y = 0; ret.z = 0; return ret; } MT_Coor MT_co_div_k(MT_Coor AA, double BB) // Divide coords/vector by constant { MT_Coor ret; ret.x = AA.x / BB; ret.y = AA.y / BB; ret.z = AA.z / BB; return ret; } MT_Coor MT_co_mul_k(MT_Coor AA, double BB) // Multiply coords/vector by constant { MT_Coor ret; ret.x = AA.x * BB; ret.y = AA.y * BB; ret.z = AA.z * BB; return ret; } MT_Coor MT_addco(MT_Coor AA, MT_Coor BB) // Add two coords together (AA+BB) { MT_Coor ret; ret.x = AA.x + BB.x; ret.y = AA.y + BB.y; ret.z = AA.z + BB.z; return ret; } MT_Coor MT_subco(MT_Coor AA, MT_Coor BB) // Add two coords together (AA-BB) { MT_Coor ret; ret.x = AA.x - BB.x; ret.y = AA.y - BB.y; ret.z = AA.z - BB.z; return ret; } double MT_lin_len(MT_Coor AA, MT_Coor BB) // Return length of line between two coordinates { return sqrt( (BB.x-AA.x)*(BB.x-AA.x) + (BB.y-AA.y)*(BB.y-AA.y) + (BB.z-AA.z)*(BB.z-AA.z) ); } double MT_lin_len2(MT_Coor AA) // Return length of vector { return sqrt( AA.x*AA.x + AA.y*AA.y + AA.z*AA.z ); } MT_Coor MT_uni_vec(MT_Coor AA, MT_Coor BB) // Return unit vector between two coords (A to B) { MT_Coor ret; double lenny = MT_lin_len(AA, BB); if (lenny != 0) { ret.x = (BB.x - AA.x) / lenny; ret.y = (BB.y - AA.y) / lenny; ret.z = (BB.z - AA.z) / lenny; } else { ret.x = 0; ret.y = 0; ret.z = 0; } return ret; } MT_Coor MT_uni_vec2(MT_Coor AA) // Return unit vector { MT_Coor ret; double lenny = MT_lin_len2(AA); ret = MT_co_div_k(AA, lenny); return ret; } MT_Coor MT_palin(double position, double ratio, MT_Coor p1, MT_Coor p2, MT_Coor p3, MT_Coor p4, MT_Coor lenz) { // Parabolic Linear Interpolation from point 2 to point 3 at position (0-1) and ratio (0=flat, 0.25=curvy, 1=very bendy). lenz contains 3 valuess for the number of frames in each of the 3 lines : p1->p2, p2->p3, p3->p4 MT_Coor res, mmm, mmm2, d[4], dd[4]; double lenny, lenny1, lenny2, qa, qb, fac, fbc; lenny = ratio * MT_lin_len(p2, p3); // Distance of mid line lenny1 = ratio * MT_lin_len(p1, p2); // Distance of 1st line lenny2 = ratio * MT_lin_len(p3, p4); // Distance of 3rd line if (lenny == 0) { mmm = MT_coze(); mmm2 = MT_coze(); } else { qa = lenny1 / lenny; // Adjust acceleration for line length qb = lenny2 / lenny; if (qa > 1) qa = 0; else qa = (qa-1.0) / 3.0; if (qb > 1) qb = 0; else qb = -(qb-1.0) / 3.0; fac = 1.0/3.0 + qa; fbc = 2.0/3.0 + qb; position = 3*position*(1-position)*(1-position)*fac + 3*position*position*(1-position)*fbc + position*position*position; qa = lenz.y / lenz.x; // Adjust acceleration for points in between qb = lenz.y / lenz.z; if (qa >= 1) qa = 0; else qa = (qa-1.0) / 3.0; if (qb >= 1) qb = 0; else qb = -(qb-1.0) / 3.0; fac = 1.0/3.0 + qa; fbc = 2.0/3.0 + qb; position = 3*position*(1-position)*(1-position)*fac + 3*position*position*(1-position)*fbc + position*position*position; d[0] = MT_uni_vec(p1, p2); // Get unit vectors for 1st 2 lines d[1] = MT_uni_vec(p2, p3); // Get unit vectors for 1st 2 lines mmm = MT_addco(d[0], d[1]); mmm = MT_uni_vec2(mmm); mmm = MT_co_mul_k(mmm, lenny); // mult by lenny d[2] = MT_uni_vec(p4, p3); // Get unit vectors for 2nd 2 lines d[3] = MT_uni_vec(p3, p2); mmm2 = MT_addco(d[2], d[3]); mmm2 = MT_uni_vec2(mmm2); mmm2 = MT_co_mul_k(mmm2, lenny); // mult by lenny } dd[1] = MT_addco(p2, mmm); // Control point 1 dd[2] = MT_addco(p3, mmm2); // Control point 2 res.x = (1-position)*(1-position)*(1-position)*p2.x + 3*position*(1-position)*(1-position)*dd[1].x + 3*(1-position)*position*position*dd[2].x + position*position*position*p3.x; res.y = (1-position)*(1-position)*(1-position)*p2.y + 3*position*(1-position)*(1-position)*dd[1].y + 3*(1-position)*position*position*dd[2].y + position*position*position*p3.y; res.z = (1-position)*(1-position)*(1-position)*p2.z + 3*position*(1-position)*(1-position)*dd[1].z + 3*(1-position)*position*position*dd[2].z + position*position*position*p3.z; return res; } mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/mtlib.h000066400000000000000000000031211471325446300222170ustar00rootroot00000000000000/* mtlib.h Copyright (C) 2005-2006 Mark Tyler This file is part of mtPaint. mtPaint 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. mtPaint 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 mtPaint in the file COPYING. */ typedef struct { double x,y,z; } MT_Coor; MT_Coor MT_coze(); // Return zero coordinates MT_Coor MT_co_div_k(MT_Coor AA, double BB); // Divide coords/vector by constant MT_Coor MT_co_mul_k(MT_Coor AA, double BB); // Multiply coords/vector by constant MT_Coor MT_addco(MT_Coor AA, MT_Coor BB); // Add two coords together (AA+BB) MT_Coor MT_subco(MT_Coor AA, MT_Coor BB); // Add two coords together (AA-BB) double MT_lin_len(MT_Coor AA, MT_Coor BB); // Return length of line between two coordinates double MT_lin_len2(MT_Coor AA); // Return length of vector MT_Coor MT_uni_vec(MT_Coor AA, MT_Coor BB); // Return unit vector between two coords (A to B) MT_Coor MT_uni_vec2(MT_Coor AA); // Return unit vector MT_Coor MT_palin(double position, double ratio, MT_Coor p1, MT_Coor p2, MT_Coor p3, MT_Coor p4, MT_Coor lenz); // Parabolic Linear Interpolation from point 2 to point 3 at position (0-1) and ratio (0=flat, 0.25=curvy, 1=very bendy) mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/mygtk.c000066400000000000000000005237101471325446300222510ustar00rootroot00000000000000/* mygtk.c Copyright (C) 2004-2024 Mark Tyler and Dmitry Groshev This file is part of mtPaint. mtPaint 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. mtPaint 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 mtPaint in the file COPYING. */ #include "global.h" #undef _ #define _(X) X #include "mygtk.h" #include "memory.h" #include "vcode.h" #include "png.h" #include "mainwindow.h" #include "canvas.h" #include "inifile.h" #if GTK_MAJOR_VERSION == 1 #include #endif #if (GTK_MAJOR_VERSION == 1) || defined GDK_WINDOWING_X11 #include #include #include #if GTK_MAJOR_VERSION == 3 #include #endif #elif defined GDK_WINDOWING_WIN32 #define WIN32_LEAN_AND_MEAN #include #include #endif GtkWidget *main_window; /// GENERIC WIDGET PRIMITIVES #if GTK_MAJOR_VERSION == 3 #define GtkAdjustment_t GtkAdjustment /* I'm totally sick and tired of this "deprecation" game. Deprecate them players * and the scooter they rode in on - WJ */ G_GNUC_BEGIN_IGNORE_DEPRECATIONS #else #define GtkAdjustment_t GtkObject #endif static GtkWidget *spin_new_x(GtkAdjustment_t *adj, int fpart); GtkWidget *add_a_window(GtkWindowType type, char *title, GtkWindowPosition pos) { GtkWidget *win = gtk_window_new(type); gtk_window_set_title(GTK_WINDOW(win), title); gtk_window_set_position(GTK_WINDOW(win), pos); return win; } GtkWidget *add_a_spin( int value, int min, int max ) { return (spin_new_x(gtk_adjustment_new(value, min, max, 1, 10, 0), 0)); } // Write UTF-8 text to console static void console_printf(char *format, ...) { #ifdef WIN32 static char codepage[16]; #endif va_list args; char *txt, *tx2; va_start(args, format); txt = g_strdup_vprintf(format, args); va_end(args); #if GTK_MAJOR_VERSION == 1 /* Same encoding as console */ fputs(txt, stdout); #else /* if GTK_MAJOR_VERSION >= 2 */ /* UTF-8 */ #ifdef WIN32 if (!codepage[0]) sprintf(codepage, "cp%d", GetConsoleCP()); /* !!! Iconv on Windows knows "utf-8" but no "utf8" */ tx2 = g_convert_with_fallback(txt, -1, codepage, "utf-8", "?", NULL, NULL, NULL); #else tx2 = g_locale_from_utf8(txt, -1, NULL, NULL, NULL); #endif fputs(tx2, stdout); g_free(tx2); #endif g_free(txt); } int user_break; //// PROGRESS WINDOW static void **progress_window; typedef struct { int stop, can_stop; char *what; void **pbar; } progress_dd; static void do_cancel_progress(progress_dd *dt) { dt->stop = 1; user_break = TRUE; } static void delete_progress() { // This stops the user closing the window via the window manager } #define WBbase progress_dd static void *progress_code[] = { WIDTH(400), WINDOWm(_("Please Wait ...")), EVENT(CANCEL, delete_progress), BORDER(FRAME, 0), EFVBOX, // originally was box in viewport REF(pbar), PROGRESSp(what), IFx(can_stop, 1), HSEP, BUTTON(_("STOP"), do_cancel_progress), ENDIF(1), WSHOW }; #undef WBbase /* Print stars for a progress indicator */ #define STARS_IN_ROW 20 static void add_stars(double val) { int i, l, n = rint(val * STARS_IN_ROW) + 1; for (i = l = (int)progress_window; i < n; i++) putc('*', stdout); if (l < n) fflush(stdout); progress_window = (void *)n; } void progress_init(char *text, int canc) // Initialise progress window { progress_dd tdata = { 0, canc, text }; if (cmd_mode) // Console { console_printf("%s - %s\n", __(text), __("Please Wait ...")); progress_window = (void *)(1 + 0); return; } // GUI /* Break pointer grabs, to avoid originating widget misbehaving later on */ release_grab(); update_stuff(CF_NOW); progress_window = run_create(progress_code, &tdata, sizeof(tdata)); progress_update(0.0); } int progress_update(float val) // Update progress window { if (!progress_window); else if (cmd_mode) add_stars(val); // Console else // GUI { progress_dd *dt = GET_DDATA(progress_window); cmd_setv(dt->pbar, (void *)(int)(val * 100), PROGRESS_PERCENT); handle_events(); // !!! Depends on window not being closeable by user return (dt->stop); } return (FALSE); } void progress_end() // Close progress window { if (!progress_window); else if (cmd_mode) // Console { add_stars(1.0); putc('\n', stdout); } // GUI else run_destroy(progress_window); progress_window = NULL; } //// ALERT BOX /* !!! Only up to 2 choices for now */ typedef struct { char *title, *what; char *cancel, *ok; int have2; void **cb, **res; } alert_dd; #define WBbase alert_dd static void *alert_code[] = { DIALOGpm(title), BORDER(LABEL, 8), WLABELp(what), WDONE, // vbox BORDER(BUTTON, 2), REF(cb), CANCELBTNp(cancel, dialog_event), IF(have2), BUTTONp(ok, dialog_event), RAISED, WDIALOG(res) }; #undef WBbase int alert_box(char *title, char *message, char *text1, ...) { alert_dd *dt, tdata = { title, message, _("OK"), NULL, 0 }; va_list args; char *txt; void **dd; int res, aok = FALSE; // Empty string here means, "OK" is ok: no choice but no error if (text1 && !(aok = !text1[0])) { tdata.cancel = text1; va_start(args, text1); if ((txt = va_arg(args, char *))) { tdata.ok = txt; tdata.have2 = TRUE; } va_end(args); } if (cmd_mode) // Console { console_printf("%s\n[ %s ]\n", __(message), __(tdata.ok ? tdata.ok : tdata.cancel)); res = tdata.ok ? 2 : 1; /* Assume "yes" in commandline mode */ } else // GUI { update_stuff(CF_NOW); dd = run_create(alert_code, &tdata, sizeof(tdata)); // run dialog dt = GET_DDATA(dd); res = origin_slot(dt->res) == dt->cb ? 1 : 2; run_destroy(dd); } if (aok) res = 2; if (res == 1) user_break = TRUE; return (res); } // Tablet handling #if GTK_MAJOR_VERSION == 1 GdkDeviceInfo *tablet_device; #else /* #if GTK_MAJOR_VERSION >= 2 */ GdkDevice *tablet_device; #endif void init_tablet() { GList *devs; char *name, buf[64]; int i, n, mode; /* Do nothing if tablet wasn't working the last time */ if (!inifile_get_gboolean("tablet_USE", FALSE)) return; name = inifile_get("tablet_name", "?"); mode = inifile_get_gint32("tablet_mode", 0); #if GTK_MAJOR_VERSION == 1 for (devs = gdk_input_list_devices(); devs; devs = devs->next) { GdkDeviceInfo *device = devs->data; GdkAxisUse *u; if (strcmp(device->name, name)) continue; /* Found the one that was working the last time */ tablet_device = device; gdk_input_set_mode(device->deviceid, mode); n = device->num_axes; u = calloc(n, sizeof(*u)); for (i = 0; i < n; i++) { sprintf(buf, "tablet_axes_v%d", i); u[i] = inifile_get_gint32(buf, GDK_AXIS_IGNORE); } gdk_input_set_axes(device->deviceid, u); free(u); break; } #else /* #if GTK_MAJOR_VERSION >= 2 */ #if GTK_MAJOR_VERSION == 3 devs = gdk_device_manager_list_devices(gdk_display_get_device_manager( gdk_display_get_default()), GDK_DEVICE_TYPE_SLAVE); #else devs = gdk_devices_list(); #endif for (; devs; devs = devs->next) { GdkDevice *device = devs->data; if (strcmp(gdk_device_get_name(device), name)) continue; /* Found the one that was working the last time */ tablet_device = device; gdk_device_set_mode(device, mode); n = gdk_device_get_n_axes(device); for (i = 0; i < n; i++) { sprintf(buf, "tablet_axes_v%d", i); gdk_device_set_axis_use(device, i, inifile_get_gint32(buf, GDK_AXIS_IGNORE)); } break; } #endif inifile_set_gboolean("tablet_USE", !!tablet_device); } // TABLETBTN widget static void **tablet_slot; static void *tablet_dlg; #if GTK_MAJOR_VERSION == 3 #define MAX_AXES 128 /* Unlikely to exist, & too long a list to show this many */ typedef struct { int dev; int mode; // GDK_MODE_DISABLED / GDK_MODE_SCREEN / GDK_MODE_WINDOW int ax[7], ax0[7]; // GDK_AXIS_IGNORE .. GDK_AXIS_WHEEL int lock; char **devnames, **axes; GdkDevice **devices; char *xtra; void **group, **use[7]; } tablet_dd; #endif #if GTK_MAJOR_VERSION == 1 static GdkDeviceInfo *tablet_find(gint deviceid) { GList *devs; for (devs = gdk_input_list_devices(); devs; devs = devs->next) { GdkDeviceInfo *device = devs->data; if (device->deviceid == deviceid) return (device); } return (NULL); } #endif void conf_done(void *cause) { char buf[64]; int i, n; if (!tablet_slot) return; /* Use last selected device if it's active */ { #if GTK_MAJOR_VERSION == 1 GdkDeviceInfo *dev = tablet_find(GTK_INPUT_DIALOG(tablet_dlg)->current_device); #elif GTK_MAJOR_VERSION == 2 GdkDevice *dev = GTK_INPUT_DIALOG(tablet_dlg)->current_device; #else /* #if GTK_MAJOR_VERSION == 3 */ tablet_dd *dt = GET_DDATA((void **)tablet_dlg); GdkDevice *dev = dt->devices[dt->dev]; #endif if (dev && (gdk_device_get_mode(dev) != GDK_MODE_DISABLED)) { tablet_device = dev; // Skip event if within do_destroy() if (cause) cmd_event(tablet_slot, op_EVT_CHANGE); } } if (tablet_device) { inifile_set("tablet_name", (char *)gdk_device_get_name(tablet_device)); inifile_set_gint32("tablet_mode", gdk_device_get_mode(tablet_device)); n = gdk_device_get_n_axes(tablet_device); for (i = 0; i < n; i++) { sprintf(buf, "tablet_axes_v%d", i); inifile_set_gint32(buf, #if GTK_MAJOR_VERSION == 1 tablet_device->axes[i]); #elif GTK_MAJOR_VERSION == 2 tablet_device->axes[i].use); #else /* #if GTK_MAJOR_VERSION == 3 */ gdk_device_get_axis_use(tablet_device, i)); #endif } } inifile_set_gboolean("tablet_USE", !!tablet_device); #if GTK_MAJOR_VERSION == 3 run_destroy(tablet_dlg); #else gtk_widget_destroy(tablet_dlg); #endif tablet_slot = NULL; } #if GTK_MAJOR_VERSION == 3 static void tablet_changed(tablet_dd *dt, void **wdata, int what, void **where) { int i, n, u, u0, axis, *cause = cmd_read(where, dt); GdkDevice *dev = dt->devices[dt->dev]; GList *ids, *id; if (dt->lock) return; dt->lock++; /* Select device */ if (cause == &dt->dev) { dt->mode = gdk_device_get_mode(dev); memset(dt->ax, 0, sizeof(dt->ax)); // Clear axis use n = gdk_device_get_n_axes(dev); ids = id = gdk_device_list_axes(dev); if (n > MAX_AXES) n = MAX_AXES; // Paranoia for (i = 0; i < n; i++ , id = id->next) { /* Put axis name into list */ dt->axes[i + 1] = gdk_atom_name(GDK_POINTER_TO_ATOM(id->data)); /* Attach to use or not-use */ u = gdk_device_get_axis_use(dev, i); dt->ax[u] = i + 1; } dt->axes[n + 1] = NULL; g_list_free(ids); /* Display all that */ cmd_reset(dt->group, dt); } /* Change mode */ else if (cause == &dt->mode) { if (!gdk_device_set_mode(dev, dt->mode)) /* Display actual mode if failed to set */ cmd_set(origin_slot(where), gdk_device_get_mode(dev)); else /* Report the change */ { tablet_device = dt->mode == GDK_MODE_DISABLED ? NULL : dev; cmd_event(tablet_slot, op_EVT_CHANGE); } } /* Change axis use */ else { u = cause - dt->ax; // Use axis = dt->ax[u]; u0 = axis ? gdk_device_get_axis_use(dev, axis - 1) : 0; if (u0) cmd_set(dt->use[u0], 0); // Steal from other use /* Previous axis, if there was one, becomes unused */ if (dt->ax0[u]) gdk_device_set_axis_use(dev, dt->ax0[u] - 1, 0); /* The new one gets new use */ gdk_device_set_axis_use(dev, axis - 1, u); } memcpy(dt->ax0, dt->ax, sizeof(dt->ax)); // Save current state dt->lock--; } #undef _ #define _(X) X static char *input_modes[3] = { _("Disabled"), _("Screen"), _("Window") }; #define WBbase tablet_dd static void *tablet_code[] = { WINDOW(_("Input")), // nonmodal EVENT(DESTROY, conf_done), MKSHRINK, // shrinkable HBOX, MLABEL(_("Device:")), XOPTDe(devnames, dev, tablet_changed), TRIGGER, REF(group), GROUPR, MLABEL(_("Mode:")), OPTe(input_modes, 3, mode, tablet_changed), WDONE, BORDER(NBOOK, 0), NBOOK, BORDER(TABLE, 10), PAGE(_("Axes")), BORDER(SCROLL, 0), WANTMAX, // max size XSCROLL(1, 1), // auto/auto TABLE2(6), REF(use[1]), TOPTDe(_("X:"), axes, ax[1], tablet_changed), REF(use[2]), TOPTDe(_("Y:"), axes, ax[2], tablet_changed), REF(use[3]), TOPTDe(_("Pressure:"), axes, ax[3], tablet_changed), REF(use[4]), TOPTDe(_("X tilt:"), axes, ax[4], tablet_changed), REF(use[5]), TOPTDe(_("Y tilt:"), axes, ax[5], tablet_changed), REF(use[6]), TOPTDe(_("Wheel:"), axes, ax[6], tablet_changed), WDONE, // table WDONE, // page WDONE, // nbook HBOX, DEFBORDER(BUTTON), OKBTN(_("OK"), conf_done), CLEANUP(xtra), WSHOW }; #undef WBbase #undef _ #define _(X) __(X) void conf_tablet(void **slot) { tablet_dd tdata; GList *devs, *d; int n, i; if (tablet_slot) return; // There can be only one tablet_slot = slot; memset(&tdata, 0, sizeof(tdata)); devs = gdk_device_manager_list_devices(gdk_display_get_device_manager( gdk_display_get_default()), GDK_DEVICE_TYPE_SLAVE); n = g_list_length(devs); tdata.xtra = multialloc(MA_ALIGN_DEFAULT, &tdata.devices, sizeof(GdkDevice *) * n, &tdata.devnames, sizeof(char *) * (n + 1), &tdata.axes, sizeof(char *) * (MAX_AXES + 1), NULL); /* Store devices as array */ devs = g_list_reverse(devs); // To get GTK+2-like ordering for (i = 0 , d = devs; d; d = d->next) { /* Skip keyboards */ if (gdk_device_get_source(d->data) == GDK_SOURCE_KEYBOARD) continue; tdata.devices[i] = d->data; tdata.devnames[i] = (char *)gdk_device_get_name(d->data); i++; } tdata.devnames[i] = NULL; g_list_free(devs); tdata.axes[0] = _("none"); tablet_dlg = run_create(tablet_code, &tdata, sizeof(tdata)); } #else /* Use GtkInputDialog on GTK+1&2 */ #if GTK_MAJOR_VERSION == 1 static void tablet_toggle(GtkInputDialog *inputdialog, gint deviceid, gpointer user_data) { GdkDeviceInfo *dev = tablet_find(deviceid); tablet_device = !dev || (dev->mode == GDK_MODE_DISABLED) ? NULL : dev; cmd_event(user_data, op_EVT_CHANGE); } #else /* #if GTK_MAJOR_VERSION == 2 */ static void tablet_toggle(GtkInputDialog *inputdialog, GdkDevice *deviceid, gpointer user_data) { tablet_device = gdk_device_get_mode(deviceid) == GDK_MODE_DISABLED ? NULL : deviceid; cmd_event(user_data, op_EVT_CHANGE); } #endif static gboolean conf_del(GtkWidget *widget) { conf_done(widget); return (TRUE); } void conf_tablet(void **slot) { GtkWidget *inputd; GtkInputDialog *inp; GtkAccelGroup *ag; if (tablet_slot) return; // There can be only one tablet_slot = slot; tablet_dlg = inputd = gtk_input_dialog_new(); gtk_window_set_position(GTK_WINDOW(inputd), GTK_WIN_POS_CENTER); inp = GTK_INPUT_DIALOG(inputd); ag = gtk_accel_group_new(); gtk_signal_connect(GTK_OBJECT(inp->close_button), "clicked", GTK_SIGNAL_FUNC(conf_done), NULL); gtk_widget_add_accelerator(inp->close_button, "clicked", ag, GDK_Escape, 0, (GtkAccelFlags)0); gtk_signal_connect(GTK_OBJECT(inputd), "delete_event", GTK_SIGNAL_FUNC(conf_del), NULL); gtk_signal_connect(GTK_OBJECT(inputd), "enable-device", GTK_SIGNAL_FUNC(tablet_toggle), slot); gtk_signal_connect(GTK_OBJECT(inputd), "disable-device", GTK_SIGNAL_FUNC(tablet_toggle), slot); if (inp->keys_list) gtk_widget_hide(inp->keys_list); if (inp->keys_listbox) gtk_widget_hide(inp->keys_listbox); gtk_widget_hide(inp->save_button); gtk_window_add_accel_group(GTK_WINDOW(inputd), ag); gtk_widget_show(inputd); } #endif /* GTK+1&2 */ // Slider-spin combo (a decorated spinbutton) GtkWidget *mt_spinslide_new(int swidth, int sheight) { GtkWidget *box, *slider, *spin; GtkAdjustment_t *adj = gtk_adjustment_new(0, 0, 1, 1, 10, 0); #if GTK_MAJOR_VERSION == 3 box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); slider = gtk_scale_new(GTK_ORIENTATION_HORIZONTAL, GTK_ADJUSTMENT(adj)); gtk_widget_set_size_request(slider, swidth, sheight); #else box = gtk_hbox_new(FALSE, 0); slider = gtk_hscale_new(GTK_ADJUSTMENT(adj)); gtk_widget_set_usize(slider, swidth, sheight); #endif gtk_box_pack_start(GTK_BOX(box), slider, swidth < 0, TRUE, 0); gtk_scale_set_draw_value(GTK_SCALE(slider), FALSE); gtk_scale_set_digits(GTK_SCALE(slider), 0); spin = spin_new_x(adj, 0); gtk_box_pack_start(GTK_BOX(box), spin, swidth >= 0, TRUE, 2); gtk_widget_show_all(box); return (spin); } // GTK+3 specific support code #if GTK_MAJOR_VERSION == 3 void cairo_surface_fdestroy(cairo_surface_t *s) { cairo_surface_flush(s); // In case it's actually needed cairo_surface_destroy(s); } cairo_surface_t *cairo_upload_rgb(cairo_surface_t *ref, GdkWindow *win, unsigned char *src, int w, int h, int len) { cairo_surface_t *s; unsigned char *dst0; int i, n, st; if (ref) s = cairo_surface_create_similar_image(ref, CAIRO_FORMAT_RGB24, w, h); else s = gdk_window_create_similar_image_surface(win, CAIRO_FORMAT_RGB24, w, h, 1); // !!! See below CAIRO_FORMAT_ARGB32 // !!! But not for exported pixmap cairo_surface_flush(s); dst0 = cairo_image_surface_get_data(s); st = cairo_image_surface_get_stride(s); len -= w * 3; for (i = h; i-- > 0; dst0 += st , src += len) { guint32 *dest = (void *)dst0; for (n = w; n-- > 0; src += 3) *dest++ = MEM_2_INT(src, 0); // !!! Maybe need to upconvert to ARGB (by OR 0xFF000000U), at least for Windows: // see Cairo win32/cairo-win32-display-surface.c // for (n = w; n-- > 0; src += 3) *dest++ = MEM_2_INT(src, 0) | 0xFF000000U; } cairo_surface_mark_dirty(s); return (s); } void cairo_set_rgb(cairo_t *cr, int c) { cairo_set_source_rgb(cr, INT_2_R(c) / 255.0, INT_2_G(c) / 255.0, INT_2_B(c) / 255.0); } /* Prevent color bleed on HiDPI */ void cairo_unfilter(cairo_t *cr) { cairo_pattern_set_filter(cairo_get_source(cr), CAIRO_FILTER_NEAREST); } void css_restyle(GtkWidget *w, char *css, char *class, char *name) { static GData *d; static int dset; GQuark q = g_quark_from_string(css); GtkCssProvider *p; GtkStyleContext *c; if (!dset) g_datalist_init(&d); // First time dset = TRUE; p = g_datalist_id_get_data(&d, q); if (!p) { p = gtk_css_provider_new(); gtk_css_provider_load_from_data(p, css, -1, NULL); g_datalist_id_set_data(&d, q, p); } c = gtk_widget_get_style_context(w); gtk_style_context_add_provider(c, GTK_STYLE_PROVIDER(p), GTK_STYLE_PROVIDER_PRIORITY_USER); if (class) gtk_style_context_add_class(c, class); if (name) g_object_set(w, "name", name, NULL); } void add_css_class(GtkWidget *w, char *class) { gtk_style_context_add_class(gtk_widget_get_style_context(w), class); } /* Add CSS, builtin and user-provided, to default screen */ void init_css(char *cssfile) { GdkScreen *scr = gdk_display_get_default_screen(gdk_display_get_default()); GtkCssProvider *p; GtkIconTheme *theme; char *s, *cp = NULL; /* GTK+ 3.20 switched from classes to "CSS nodes", and added "min-width" & * "min-height" style properties, themed to some crazy values - WJ */ if (gtk3version >= 20) // Make entries same height as buttons { GtkWidget *btn = gtk_button_new(); GtkStyleContext *ctx = gtk_widget_get_style_context(btn); gint n; gtk_style_context_get(ctx, gtk_style_context_get_state(ctx), "min-height", &n, NULL); cp = g_strdup_printf("spinbutton, entry { min-height:%dpx; }", n); g_object_ref_sink(btn); g_object_unref(btn); } s = g_strconcat((gtk3version < 20 ? ".spinbutton *,.grid-child" : "spinbutton button,flowboxchild"), " { padding:0; }" ".image-button { padding:4px; }" ".wjpixmap { padding:4px; outline-offset:-1px; }" ".mtPaint_gradbar_button { padding:4px; }", (gtk3version < 20 ? "" : ".mtPaint_gradbar_button { min-width:0; min-height:0; }"), cp, NULL); p = gtk_css_provider_new(); gtk_css_provider_load_from_data(p, s, -1, NULL); gtk_style_context_add_provider_for_screen(scr, GTK_STYLE_PROVIDER(p), GTK_STYLE_PROVIDER_PRIORITY_USER); g_free(s); g_free(cp); if (!cssfile || !cssfile[0]) return; /* Load user-provided CSS */ p = gtk_css_provider_new(); gtk_css_provider_load_from_path(p, cssfile, NULL); gtk_style_context_add_provider_for_screen(scr, GTK_STYLE_PROVIDER(p), GTK_STYLE_PROVIDER_PRIORITY_USER + 100); /* Make the directory with it the first search dir for icons */ s = resolve_path(NULL, 0, cssfile); cp = strrchr(s, DIR_SEP); theme = gtk_icon_theme_get_for_screen(scr); if (cp && theme) // Paranoia { *cp = '\0'; // Cut off filename gtk_icon_theme_prepend_search_path(theme, s); } free(s); } static void combobox_scan(GtkWidget *widget, gpointer data) { GtkWidget **scan = data; if (GTK_IS_BOX(widget)) scan[1] = widget; else if (GTK_IS_BUTTON(widget)) scan[0] = widget; } /* Find button widget of a GtkComboBox with entry */ GtkWidget *combobox_button(GtkWidget *cbox) { GtkWidget *scan[2] = { NULL, NULL }; gtk_container_forall(GTK_CONTAINER(cbox), combobox_scan, scan); if (!scan[0] && scan[1]) // Structure changed after 3.18 gtk_container_forall(GTK_CONTAINER(scan[1]), combobox_scan, scan); return (scan[0]); } static GQuark radio_key; /* Properties for GtkScrollable */ static char *scroll_pnames[] = { NULL, "hadjustment", "vadjustment", "hscroll-policy", "vscroll-policy" }; enum { P_HADJ = 1, P_VADJ, P_HSCP, P_VSCP }; void get_padding_and_border(GtkStyleContext *ctx, GtkBorder *pad, GtkBorder *bor, GtkBorder *both) { GtkStateFlags state = gtk_style_context_get_state(ctx); GtkBorder tmp; if (both) { if (!pad) pad = &tmp; if (!bor) bor = both; } if (pad) gtk_style_context_get_padding(ctx, state, pad); // ~ xthickness if (bor) gtk_style_context_get_border(ctx, state, bor); if (both) { both->left = pad->left + bor->left; both->right = pad->right + bor->right; both->top = pad->top + bor->top; both->bottom = pad->bottom + bor->bottom; } } #endif // Managing batches of radio buttons with minimum of fuss /* void handler(GtkWidget *btn, gpointer user_data); */ GtkWidget *wj_radio_pack(char **names, int cnt, int vnum, int idx, void **r, GtkSignalFunc handler) { int i, j, x; GtkWidget *table, *button = NULL; #if GTK_MAJOR_VERSION == 3 radio_key = g_quark_from_static_string("mtPaint.radio"); table = gtk_grid_new(); gtk_widget_set_hexpand(table, FALSE); // No "inheriting" it from buttons #else table = gtk_table_new(1, 1, FALSE); #endif for (i = j = x = 0; (i != cnt) && names[i]; i++) { if (!names[i][0]) continue; button = gtk_radio_button_new_with_label_from_widget( GTK_RADIO_BUTTON_0(button), __(names[i])); if (vnum > 0) x = j / vnum; #if GTK_MAJOR_VERSION == 3 g_object_set_qdata(G_OBJECT(button), radio_key, (gpointer)i); /* Adjusted to account for GTK+3 adding more padding */ gtk_container_set_border_width(GTK_CONTAINER(button), 2); gtk_grid_attach(GTK_GRID(table), button, x, j - x * vnum, 1, 1); if (vnum != 1) gtk_widget_set_hexpand(button, TRUE); #else gtk_object_set_user_data(GTK_OBJECT(button), (gpointer)i); gtk_container_set_border_width(GTK_CONTAINER(button), 5); gtk_table_attach(GTK_TABLE(table), button, x, x + 1, j - x * vnum, j - x * vnum + 1, vnum != 1 ? GTK_EXPAND | GTK_FILL : GTK_FILL, 0, 0, 0); #endif if (i == idx) gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(button), TRUE); if (handler) gtk_signal_connect(GTK_OBJECT(button), "toggled", handler, r); j++; } gtk_widget_show_all(table); return (table); } #if GTK_MAJOR_VERSION == 3 int wj_radio_pack_get_active(GtkWidget *widget) { GList *curr, *ch = gtk_container_get_children(GTK_CONTAINER(widget)); int res = 0; for (curr = ch; curr; curr = curr->next) { widget = curr->data; if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) continue; res = (int)g_object_get_qdata(G_OBJECT(widget), radio_key); break; } g_list_free(ch); return (res); } #else int wj_radio_pack_get_active(GtkWidget *widget) { GList *curr; for (curr = GTK_TABLE(widget)->children; curr; curr = curr->next) { widget = ((GtkTableChild *)curr->data)->widget; if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) return ((int)gtk_object_get_user_data(GTK_OBJECT(widget))); } return (0); } #endif // Easier way with spinbuttons int read_spin(GtkWidget *spin) { /* Needed in GTK+2 for late changes */ gtk_spin_button_update(GTK_SPIN_BUTTON(spin)); return (gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(spin))); } double read_float_spin(GtkWidget *spin) { /* Needed in GTK+2 for late changes */ gtk_spin_button_update(GTK_SPIN_BUTTON(spin)); #if GTK_MAJOR_VERSION == 3 return (gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin))); #else return (GTK_SPIN_BUTTON(spin)->adjustment->value); #endif } #if (GTK_MAJOR_VERSION == 1) && !defined(U_MTK) #define MIN_SPIN_BUTTON_WIDTH 30 /* More-or-less correctly evaluate spinbutton size */ static void spin_size_req(GtkWidget *widget, GtkRequisition *requisition, gpointer user_data) { GtkSpinButton *spin = GTK_SPIN_BUTTON(widget); char num[128]; int l1, l2; num[0] = '0'; sprintf(num + 1, "%.*f", spin->digits, spin->adjustment->lower); l1 = gdk_string_width(widget->style->font, num); sprintf(num + 1, "%.*f", spin->digits, spin->adjustment->upper); l2 = gdk_string_width(widget->style->font, num); if (l1 < l2) l1 = l2; if (l1 > MIN_SPIN_BUTTON_WIDTH) requisition->width += l1 - MIN_SPIN_BUTTON_WIDTH; } #endif static GtkWidget *spin_new_x(GtkAdjustment_t *adj, int fpart) { GtkWidget *spin = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 1, fpart); #if (GTK_MAJOR_VERSION == 1) && !defined(U_MTK) gtk_signal_connect(GTK_OBJECT(spin), "size_request", GTK_SIGNAL_FUNC(spin_size_req), NULL); #endif gtk_widget_show(spin); gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(spin), TRUE); return (spin); } GtkWidget *add_float_spin(double value, double min, double max) { return (spin_new_x(gtk_adjustment_new(value, min, max, 1, 10, 0), 2)); } /* void handler(GtkAdjustment *adjustment, gpointer user_data); */ void spin_connect(GtkWidget *spin, GtkSignalFunc handler, gpointer user_data) { GtkAdjustment *adj; adj = gtk_spin_button_get_adjustment(GTK_SPIN_BUTTON(spin)); gtk_signal_connect(GTK_OBJECT(adj), "value_changed", handler, user_data); } #if GTK_MAJOR_VERSION == 1 void spin_set_range(GtkWidget *spin, int min, int max) { GtkAdjustment *adj = GTK_SPIN_BUTTON(spin)->adjustment; adj->lower = min; adj->upper = max; gtk_adjustment_set_value(adj, adj->value); gtk_adjustment_changed(adj); } #endif // Wrapper for utf8->C and C->utf8 translation char *gtkxncpy(char *dest, const char *src, int cnt, int u) { #if GTK_MAJOR_VERSION >= 2 char *c = (u ? g_locale_to_utf8 : g_locale_from_utf8)((gchar *)src, -1, NULL, NULL, NULL); if (c) { if (!dest) return (c); g_strlcpy(dest, c, cnt); g_free(c); } else #endif { if (!dest) return (g_strdup(src)); u = strlen(src); if (u >= cnt) u = cnt - 1; /* Allow for overlapping buffers */ memmove(dest, src, u); dest[u] = 0; } return (dest); } // A more sane replacement for strncat() char *strnncat(char *dest, const char *src, int max) { int l = strlen(dest); if (max > l) strncpy(dest + l, src, max - l - 1); dest[max - 1] = 0; return (dest); } // Add C strings to a string with explicit length char *wjstrcat(char *dest, int max, const char *s0, int l, ...) { va_list args; char *s, *w; int ll; if (!dest) { max = l + 1; va_start(args, l); while ((s = va_arg(args, char *))) max += strlen(s); va_end(args); dest = malloc(max); if (!dest) return (NULL); } va_start(args, l); w = dest; s = (char *)s0; ll = l; while (TRUE) { if (ll >= max) ll = max - 1; memcpy(w, s, ll); w += ll; if ((max -= ll) <= 1) break; s = va_arg(args, char *); if (!s) break; ll = strlen(s); } va_end(args); *w = 0; return (dest); } // Add directory to filename char *file_in_dir(char *dest, const char *dir, const char *file, int cnt) { int dl = strlen(dir); return wjstrcat(dest, cnt, dir, dl - (dir[dl - !!dl] == DIR_SEP), DIR_SEP_STR, file, NULL); } char *file_in_homedir(char *dest, const char *file, int cnt) { return (file_in_dir(dest, get_home_directory(), file, cnt)); } // Add extension to filename, making sure result is not the same file /* !!! tail must be significantly shorter than the buffer */ char *tailed_name(char *dest, const char *file, const char *tail, int max) { int nl = strlen(file), tl = strlen(tail), d = nl + tl + 1 - max; // if (nl <= d) abort(); // Should never happen if (d > 0) /* Pare down the name to make space for tail */ { nl -= d; nl -= file[nl - 1] == '.'; // Drop a trailing dot nl -= !strcmp(file + nl, tail); // Drop another char if old extension was the same } return wjstrcat(dest, max, file, nl, tail, NULL); } #if GTK_MAJOR_VERSION <= 2 // Set minimum size for a widget static void widget_size_req(GtkWidget *widget, GtkRequisition *requisition, gpointer user_data) { int h = (guint32)user_data >> 16, w = (guint32)user_data & 0xFFFF; if (h && (requisition->height < h)) requisition->height = h; if (w && (requisition->width < w)) requisition->width = w; } /* !!! Warning: this function can't extend box containers in their "natural" * direction, because GTK+ takes shortcuts with their allocation, abusing * requisition value. */ void widget_set_minsize(GtkWidget *widget, int width, int height) { guint32 hw; if ((width <= 0) && (height <= 0)) return; hw = (height < 0 ? 0 : height & 0xFFFF) << 16 | (width < 0 ? 0 : width & 0xFFFF); gtk_signal_connect(GTK_OBJECT(widget), "size_request", GTK_SIGNAL_FUNC(widget_size_req), (gpointer)hw); } /* This function is a workaround for boxes and the like, wrapping a widget in a * GtkAlignment and setting size on that - or it can be seen as GtkAlignment * widget with extended functionality - WJ */ GtkWidget *widget_align_minsize(GtkWidget *widget, int width, int height) { GtkWidget *align = gtk_alignment_new(0.5, 0.5, 1.0, 1.0); gtk_widget_show(align); gtk_container_add(GTK_CONTAINER(align), widget); widget_set_minsize(align, width, height); return (align); } #endif // Make widget request no less size than before (in one direction) #if GTK_MAJOR_VERSION == 3 static void widget_size_keep(GtkWidget *widget, GtkAllocation *alloc, gpointer user_data) { gint w, h, w0, h0; gtk_widget_get_size_request(widget, &w0, &h0); if (user_data) // Adjust height if set, width if clear { gtk_widget_get_preferred_height(widget, &h, NULL); h -= gtk_widget_get_margin_top(widget) + gtk_widget_get_margin_bottom(widget); if (h0 >= h) return; h0 = h; } else { gtk_widget_get_preferred_width(widget, &w, NULL); w -= gtk_widget_get_margin_start(widget) + gtk_widget_get_margin_end(widget); if (w0 >= w) return; w0 = w; } gtk_widget_set_size_request(widget, w0, h0); } void widget_set_keepsize(GtkWidget *widget, int keep_height) { g_signal_connect(widget, "size_allocate", G_CALLBACK(widget_size_keep), (gpointer)keep_height); } #else /* #if GTK_MAJOR_VERSION <= 2 */ #define KEEPSIZE_KEY "mtPaint.keepsize" static GQuark keepsize_key; /* And if user manages to change theme on the fly... well, more fool him ;-) */ static void widget_size_keep(GtkWidget *widget, GtkRequisition *requisition, gpointer user_data) { int l, l0; l = (int)gtk_object_get_data_by_id(GTK_OBJECT(widget), keepsize_key); if (user_data) // Adjust height if set, width if clear { if ((l0 = requisition->height) < l) requisition->height = l; } else if ((l0 = requisition->width) < l) requisition->width = l; if (l0 > l) gtk_object_set_data_by_id(GTK_OBJECT(widget), keepsize_key, (gpointer)l0); } /* !!! Warning: this function can't extend box containers in their "natural" * direction, because GTK+ takes shortcuts with their allocation, abusing * requisition value. */ void widget_set_keepsize(GtkWidget *widget, int keep_height) { if (!keepsize_key) keepsize_key = g_quark_from_static_string(KEEPSIZE_KEY); gtk_signal_connect(GTK_OBJECT(widget), "size_request", GTK_SIGNAL_FUNC(widget_size_keep), (gpointer)keep_height); } #endif // Workaround for GtkCList reordering bug /* This bug is the favorite pet of GNOME developer Behdad Esfahbod * See http://bugzilla.gnome.org/show_bug.cgi?id=400249#c2 */ #if GTK_MAJOR_VERSION == 2 static void clist_drag_fix(GtkWidget *widget, GdkDragContext *drag_context, gpointer user_data) { g_dataset_remove_data(drag_context, "gtk-clist-drag-source"); } void clist_enable_drag(GtkWidget *clist) { gtk_signal_connect(GTK_OBJECT(clist), "drag_begin", GTK_SIGNAL_FUNC(clist_drag_fix), NULL); gtk_signal_connect(GTK_OBJECT(clist), "drag_end", GTK_SIGNAL_FUNC(clist_drag_fix), NULL); gtk_clist_set_reorderable(GTK_CLIST(clist), TRUE); } #elif GTK_MAJOR_VERSION == 1 /* GTK1 doesn't have this bug */ void clist_enable_drag(GtkWidget *clist) { gtk_clist_set_reorderable(GTK_CLIST(clist), TRUE); } #endif // Most common use of boxes GtkWidget *pack(GtkWidget *box, GtkWidget *widget) { gtk_box_pack_start(GTK_BOX(box), widget, FALSE, FALSE, 0); return (widget); } GtkWidget *xpack(GtkWidget *box, GtkWidget *widget) { gtk_box_pack_start(GTK_BOX(box), widget, TRUE, TRUE, 0); return (widget); } GtkWidget *pack_end(GtkWidget *box, GtkWidget *widget) { gtk_box_pack_end(GTK_BOX(box), widget, FALSE, FALSE, 0); return (widget); } // Put vbox into container GtkWidget *add_vbox(GtkWidget *cont) { #if GTK_MAJOR_VERSION == 3 GtkWidget *box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); #else GtkWidget *box = gtk_vbox_new(FALSE, 0); #endif gtk_widget_show(box); gtk_container_add(GTK_CONTAINER(cont), box); return (box); } // Fix for paned widgets losing focus in GTK+1 #if GTK_MAJOR_VERSION == 1 static void fix_gdk_events(GdkWindow *window) { XWindowAttributes attrs; GdkWindowPrivate *private = (GdkWindowPrivate *)window; if (!private || private->destroyed) return; XGetWindowAttributes(GDK_WINDOW_XDISPLAY(window), private->xwindow, &attrs); XSelectInput(GDK_WINDOW_XDISPLAY(window), private->xwindow, attrs.your_event_mask & ~OwnerGrabButtonMask); } static void paned_realize(GtkWidget *widget, gpointer user_data) { fix_gdk_events(widget->window); fix_gdk_events(GTK_PANED(widget)->handle); } void paned_mouse_fix(GtkWidget *widget) { gtk_signal_connect(GTK_OBJECT(widget), "realize", GTK_SIGNAL_FUNC(paned_realize), NULL); } #endif // Init-time bugfixes /* Bugs: GtkViewport size request in GTK+1; GtkHScale breakage in Smooth Theme * Engine in GTK+1; GtkListItem and GtkCList stealing Esc key in GTK+1; GtkEntry * and GtkSpinButton stealing Enter key and mishandling keypad Enter key in * GTK+1; mixing up keys in GTK+2/Windows; opaque focus rectangle in Gtk-Qt theme * engine (v0.8) in GTK+2/X */ #if GTK_MAJOR_VERSION == 1 /* This is gtk_viewport_size_request() from GTK+ 1.2.10 with stupid bugs fixed */ static void gtk_viewport_size_request_fixed(GtkWidget *widget, GtkRequisition *requisition) { GtkBin *bin; GtkRequisition child_requisition; g_return_if_fail(widget != NULL); g_return_if_fail(GTK_IS_VIEWPORT(widget)); g_return_if_fail(requisition != NULL); bin = GTK_BIN(widget); requisition->width = requisition->height = GTK_CONTAINER(widget)->border_width * 2; if (GTK_VIEWPORT(widget)->shadow_type != GTK_SHADOW_NONE) { requisition->width += widget->style->klass->xthickness * 2; requisition->height += widget->style->klass->ythickness * 2; } if (bin->child && GTK_WIDGET_VISIBLE(bin->child)) { gtk_widget_size_request(bin->child, &child_requisition); requisition->width += child_requisition.width; requisition->height += child_requisition.height; } } /* This is for preventing Smooth Engine from ruining horizontal sliders */ static void (*hsizereq)(GtkWidget *widget, GtkRequisition *requisition); static void gtk_hscale_size_request_smooth_fixed(GtkWidget *widget, GtkRequisition *requisition) { int realf = GTK_WIDGET_FLAGS(widget) & GTK_REALIZED; GTK_WIDGET_UNSET_FLAGS(widget, GTK_REALIZED); hsizereq(widget, requisition); GTK_WIDGET_SET_FLAGS(widget, realf); } typedef struct { GtkThemeEngine engine; void *library; void *name; void (*init) (GtkThemeEngine *); void (*exit) (void); guint refcount; } GtkThemeEnginePrivate; /* This is for routing Enter keys around GtkEntry's default handler */ static gboolean (*ekeypress)(GtkWidget *widget, GdkEventKey *event); static gboolean gtk_entry_key_press_fixed(GtkWidget *widget, GdkEventKey *event) { if (event && ((event->keyval == GDK_Return) || (event->keyval == GDK_KP_Enter))) return (FALSE); return (ekeypress(widget, event)); } void gtk_init_bugfixes() { GtkWidget *hs; GtkStyle *st; GtkWidgetClass *wc; char *engine = ""; ((GtkWidgetClass*)gtk_type_class(GTK_TYPE_VIEWPORT))->size_request = gtk_viewport_size_request_fixed; /* Detect if Smooth Engine is active, and fix its bugs */ st = gtk_rc_get_style(hs = gtk_hscale_new(NULL)); if (st && st->engine) engine = ((GtkThemeEnginePrivate *)(st->engine))->name; if (!strcmp(engine, "smooth")) { wc = gtk_type_class(GTK_TYPE_HSCALE); hsizereq = wc->size_request; wc->size_request = gtk_hscale_size_request_smooth_fixed; } gtk_object_sink(GTK_OBJECT(hs)); /* Destroy a floating-ref thing */ gtk_binding_entry_remove(gtk_binding_set_by_class(gtk_type_class( GTK_TYPE_CLIST)), GDK_Escape, 0); gtk_binding_entry_remove(gtk_binding_set_by_class(gtk_type_class( GTK_TYPE_LIST_ITEM)), GDK_Escape, 0); wc = gtk_type_class(GTK_TYPE_ENTRY); ekeypress = wc->key_press_event; wc->key_press_event = gtk_entry_key_press_fixed; } #elif GTK_MAJOR_VERSION == 2 #if defined GDK_WINDOWING_WIN32 static int win_last_vk; static guint32 win_last_lp; /* Event filter to look at WM_KEYDOWN and WM_SYSKEYDOWN */ static GdkFilterReturn win_keys_peek(GdkXEvent *xevent, GdkEvent *event, gpointer data) { MSG *msg = xevent; if ((msg->message == WM_KEYDOWN) || (msg->message == WM_SYSKEYDOWN)) { /* No matter that these fields are longer in Win64 */ win_last_vk = msg->wParam; win_last_lp = msg->lParam; } return (GDK_FILTER_CONTINUE); } #elif defined GDK_WINDOWING_X11 /* Gtk-Qt's author was deluded when he decided he knows how to draw focus; * doing nothing is *FAR* preferable to opaque box over a widget - WJ */ static void fake_draw_focus() { return; } #endif static void do_shutup(const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer user_data) { char *s = "Invalid UTF-8"; // The words to never utter if (strncmp(message, s, strlen(s))) g_log_default_handler(log_domain, log_level, message, user_data); } void gtk_init_bugfixes() { #if defined GDK_WINDOWING_WIN32 gdk_window_add_filter(NULL, (GdkFilterFunc)win_keys_peek, NULL); #elif defined GDK_WINDOWING_X11 GtkWidget *bt; GtkStyleClass *sc; GType qtt; /* Detect if Gtk-Qt engine is active, and fix its bugs */ bt = gtk_button_new(); qtt = g_type_from_name("QtEngineStyle"); if (qtt) { sc = g_type_class_ref(qtt); /* Have to ref to get it to init */ sc->draw_focus = fake_draw_focus; } gtk_object_sink(GTK_OBJECT(bt)); /* Destroy a floating-ref thing */ #endif /* X11 */ /* Cut spam from Pango about bad UTF8 */ g_log_set_handler("Pango", G_LOG_LEVEL_WARNING, (GLogFunc)do_shutup, NULL); #ifndef U_LISTS_GTK1 /* Remove crazier keybindings from GtkTreeView */ { GtkBindingSet *bs = gtk_binding_set_by_class(g_type_class_ref( GTK_TYPE_TREE_VIEW)); gtk_binding_entry_remove(bs, GDK_space, 0); // Activate gtk_binding_entry_remove(bs, GDK_KP_Space, 0); gtk_binding_entry_remove(bs, GDK_f, GDK_CONTROL_MASK); // Search gtk_binding_entry_remove(bs, GDK_F, GDK_CONTROL_MASK); gtk_binding_entry_remove(bs, GDK_p, GDK_CONTROL_MASK); // Up gtk_binding_entry_remove(bs, GDK_n, GDK_CONTROL_MASK); // Down } #endif } #else /* if GTK_MAJOR_VERSION == 3 */ #if defined GDK_WINDOWING_WIN32 #error "GTK+3/Win32 not supported yet" #endif /* Drawing in GTK+ is done in an idle handler, so is prone to stalling when the * main thread is busy handling input. Before GTK+3, drawing directly to widgets * worked around the problem where it mattered; with GTK+3, the only solution is * detecting a stall and forcing a drawing cycle soonish - WJ */ #define DOOM_DELAY (1000 / 20) static int doom_tick; static gboolean doom_timer_call(gpointer data) { if (doom_tick > 1) { gdk_window_process_all_updates(); doom_tick = 0; } doom_tick += doom_tick; return (TRUE); } int gtk3version; void gtk_init_bugfixes() { GtkContainerClass *c; GtkBindingSet *bs; gtk3version = gtk_get_minor_version(); if (gtk3version < 20) { /* Fix counting border width twice */ c = g_type_class_ref(GTK_TYPE_RADIO_BUTTON); c->_handle_border_width = 0; c = g_type_class_ref(GTK_TYPE_CHECK_BUTTON); c->_handle_border_width = 0; /* !!! The wrong idea is introduced at GTK_CHECK_BUTTON level; descendants of * GTK_BUTTON should let gtk_container_class_handle_border_width() do its thing, * not add gtk_container_get_border_width() to size by themselves. */ } /* Remove crazier keybindings from GtkTreeView */ bs = gtk_binding_set_by_class(g_type_class_ref(GTK_TYPE_TREE_VIEW)); gtk_binding_entry_remove(bs, KEY(space), 0); // Activate gtk_binding_entry_remove(bs, KEY(KP_Space), 0); gtk_binding_entry_remove(bs, KEY(f), GDK_CONTROL_MASK); // Search gtk_binding_entry_remove(bs, KEY(F), GDK_CONTROL_MASK); gtk_binding_entry_remove(bs, KEY(p), GDK_CONTROL_MASK); // Up gtk_binding_entry_remove(bs, KEY(n), GDK_CONTROL_MASK); // Down threads_timeout_add(DOOM_DELAY, doom_timer_call, NULL); } #endif /* GTK+3 */ // Whatever is needed to move mouse pointer #if GTK_MAJOR_VERSION == 3 int move_mouse_relative(int dx, int dy) { gint x0, y0; GdkScreen *screen; GdkDisplay *dp = gtk_widget_get_display(main_window); GdkDevice *dev; dev = gdk_device_manager_get_client_pointer(gdk_display_get_device_manager(dp)); gdk_device_get_position(dev, &screen, &x0, &y0); gdk_device_warp(dev, screen, x0 + dx, y0 + dy); return (TRUE); } #elif (GTK_MAJOR_VERSION == 1) || defined GDK_WINDOWING_X11 /* Call X */ int move_mouse_relative(int dx, int dy) { XWarpPointer(GDK_WINDOW_XDISPLAY(main_window->window), None, None, 0, 0, 0, 0, dx, dy); return (TRUE); } #elif defined GDK_WINDOWING_WIN32 /* Call GDI */ int move_mouse_relative(int dx, int dy) { POINT point; if (GetCursorPos(&point)) { SetCursorPos(point.x + dx, point.y + dy); return (TRUE); } else return (FALSE); } #elif GTK2VERSION >= 8 /* GTK+ 2.8+ */ int move_mouse_relative(int dx, int dy) { gint x0, y0; GdkScreen *screen; GdkDisplay *display = gtk_widget_get_display(main_window); gdk_display_get_pointer(display, &screen, &x0, &y0, NULL); gdk_display_warp_pointer(display, screen, x0 + dx, y0 + dy); return (TRUE); } #else /* Always fail */ int move_mouse_relative(int dx, int dy) { return (FALSE); } #endif // Whatever is needed to map keyval to key #if GTK_MAJOR_VERSION == 1 /* Call X */ guint real_key(GdkEventKey *event) { return (XKeysymToKeycode(GDK_WINDOW_XDISPLAY(main_window->window), event->keyval)); } guint low_key(GdkEventKey *event) { return (gdk_keyval_to_lower(event->keyval)); } guint keyval_key(guint keyval) { return (XKeysymToKeycode(GDK_WINDOW_XDISPLAY(main_window->window), keyval)); } #else /* Use GDK */ guint real_key(GdkEventKey *event) { return (event->hardware_keycode); } #ifdef GDK_WINDOWING_WIN32 /* Keypad translation helpers */ static unsigned char keypad_vk[] = { VK_CLEAR, VK_PRIOR, VK_NEXT, VK_END, VK_HOME, VK_LEFT, VK_UP, VK_RIGHT, VK_DOWN, VK_INSERT, VK_DELETE, VK_NUMPAD0, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3, VK_NUMPAD4, VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7, VK_NUMPAD8, VK_NUMPAD9, VK_DECIMAL, 0 }; static unsigned short keypad_wgtk[] = { GDK_Clear, GDK_Page_Up, GDK_Page_Down, GDK_End, GDK_Home, GDK_Left, GDK_Up, GDK_Right, GDK_Down, GDK_Insert, GDK_Delete, GDK_0, GDK_1, GDK_2, GDK_3, GDK_4, GDK_5, GDK_6, GDK_7, GDK_8, GDK_9, GDK_period, 0 }; static unsigned short keypad_xgtk[] = { GDK_KP_Begin, GDK_KP_Page_Up, GDK_KP_Page_Down, GDK_KP_End, GDK_KP_Home, GDK_KP_Left, GDK_KP_Up, GDK_KP_Right, GDK_KP_Down, GDK_KP_Insert, GDK_KP_Delete, GDK_KP_0, GDK_KP_1, GDK_KP_2, GDK_KP_3, GDK_KP_4, GDK_KP_5, GDK_KP_6, GDK_KP_7, GDK_KP_8, GDK_KP_9, GDK_KP_Decimal, 0 }; guint low_key(GdkEventKey *event) { /* Augment braindead GDK translation by recognizing keypad keys */ if (win_last_vk == event->hardware_keycode) /* Paranoia */ { if (win_last_lp & 0x01000000) /* Extended key */ { if (event->keyval == GDK_Return) return (GDK_KP_Enter); } else /* Normal key */ { unsigned char *cp = strchr(keypad_vk, event->hardware_keycode); if (cp && (event->keyval == keypad_wgtk[cp - keypad_vk])) return (keypad_xgtk[cp - keypad_vk]); } } return (gdk_keyval_to_lower(event->keyval)); } #else /* X11/Quartz/whatever */ guint low_key(GdkEventKey *event) { return (gdk_keyval_to_lower(event->keyval)); } #endif guint keyval_key(guint keyval) { GdkDisplay *display = gtk_widget_get_display(main_window); GdkKeymap *keymap = gdk_keymap_get_for_display(display); GdkKeymapKey *key; gint nkeys; if (!gdk_keymap_get_entries_for_keyval(keymap, keyval, &key, &nkeys)) { #ifdef GDK_WINDOWING_WIN32 /* Keypad keys need specialcasing on Windows */ for (nkeys = 0; keypad_xgtk[nkeys] && (keyval != keypad_xgtk[nkeys]); nkeys++); return (keypad_vk[nkeys]); #endif return (0); } if (!nkeys) return (0); keyval = key[0].keycode; g_free(key); return (keyval); } #endif // Interpreting arrow keys int arrow_key_(unsigned key, unsigned state, int *dx, int *dy, int mult) { if ((state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK)) != GDK_SHIFT_MASK) mult = 1; *dx = *dy = 0; switch (key) { case KEY(KP_Left): case KEY(Left): *dx = -mult; break; case KEY(KP_Right): case KEY(Right): *dx = mult; break; case KEY(KP_Up): case KEY(Up): *dy = -mult; break; case KEY(KP_Down): case KEY(Down): *dy = mult; break; } return (*dx || *dy); } // Create pixmap cursor #if GTK_MAJOR_VERSION == 3 /* Assemble two XBMs into one BW ARGB32 surface */ static cairo_surface_t *xbms_to_surface(unsigned char *image, unsigned char *mask, int w, int h) { cairo_surface_t *s = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, w, h); unsigned char *dst0 = cairo_image_surface_get_data(s); int st = cairo_image_surface_get_stride(s); unsigned int b = 0; cairo_surface_flush(s); while (h-- > 0) { guint32 *dest = (void *)dst0; int n; for (n = w; n-- > 0; b++) *dest++ = ((image[b >> 3] >> (b & 7)) & 1) * 0x00FFFFFFU + ((mask[b >> 3] >> (b & 7)) & 1) * 0xFF000000U; dst0 += st; b += (~b + 1) & 7; } cairo_surface_mark_dirty(s); return (s); } GdkCursor *make_cursor(char *icon, char *mask, int w, int h, int tip_x, int tip_y) { cairo_surface_t *s = xbms_to_surface(icon, mask, w, h); GdkCursor *cursor = gdk_cursor_new_from_surface( gtk_widget_get_display(main_window), s, tip_x, tip_y); cairo_surface_fdestroy(s); return (cursor); } #else /* GTK_MAJOR_VERSION <= 2 */ GdkCursor *make_cursor(char *icon, char *mask, int w, int h, int tip_x, int tip_y) { static GdkColor cfg = { -1, -1, -1, -1 }, cbg = { 0, 0, 0, 0 }; GdkPixmap *icn, *msk; GdkCursor *cursor; icn = gdk_bitmap_create_from_data(NULL, icon, w, h); msk = gdk_bitmap_create_from_data(NULL, mask, w, h); cursor = gdk_cursor_new_from_pixmap(icn, msk, &cfg, &cbg, tip_x, tip_y); gdk_pixmap_unref(icn); gdk_pixmap_unref(msk); return (cursor); } #endif // Menu-like combo box #if GTK_MAJOR_VERSION == 3 /* Making GtkComboBox behave is quite nontrivial, here */ static gboolean wj_combo_click(GtkWidget *widget, GdkEventButton *event, gpointer user_data) { if (user_data) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(user_data), TRUE); return (TRUE); } /* void handler(GtkWidget *combo, gpointer user_data); */ GtkWidget *wj_combo_box(char **names, int cnt, int u, int idx, void **r, GCallback handler) { GtkWidget *cbox, *entry, *button; int i; if (idx >= cnt) idx = 0; cbox = gtk_combo_box_text_new_with_entry(); /* Find the button */ button = combobox_button(cbox); /* Make the entry a dumb display */ entry = gtk_bin_get_child(GTK_BIN(cbox)); g_object_set(entry, "editable", FALSE, NULL); gtk_widget_set_can_focus(entry, FALSE); /* Make click on entry do popup too */ g_signal_connect(entry, "button_press_event", G_CALLBACK(wj_combo_click), NULL); g_signal_connect(entry, "button_release_event", G_CALLBACK(wj_combo_click), button); for (i = 0; i < cnt; i++) gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(cbox), __(names[i])); gtk_combo_box_set_active(GTK_COMBO_BOX(cbox), idx); if (handler) g_signal_connect(G_OBJECT(cbox), "changed", handler, r); return (cbox); } int wj_combo_box_get_history(GtkWidget *combobox) { return (gtk_combo_box_get_active(GTK_COMBO_BOX(combobox))); } /* Use GtkComboBox when available */ #elif GTK2VERSION >= 4 /* GTK+ 2.4+ */ /* Tweak style settings for combo box */ static void wj_combo_restyle(GtkWidget *cbox) { static int done; if (!done) { gtk_rc_parse_string("style \"mtPaint_cblist\" {\n" "GtkComboBox::appears-as-list = 1\n}\n"); gtk_rc_parse_string("widget \"*.mtPaint_cbox\" " "style \"mtPaint_cblist\"\n"); done = TRUE; } gtk_widget_set_name(cbox, "mtPaint_cbox"); } /* void handler(GtkWidget *combo, gpointer user_data); */ GtkWidget *wj_combo_box(char **names, int cnt, int u, int idx, void **r, GtkSignalFunc handler) { GtkWidget *cbox; GtkComboBox *combo; int i; if (idx >= cnt) idx = 0; combo = GTK_COMBO_BOX(cbox = gtk_combo_box_new_text()); wj_combo_restyle(cbox); for (i = 0; i < cnt; i++) gtk_combo_box_append_text(combo, __(names[i])); gtk_combo_box_set_active(combo, idx); if (handler) gtk_signal_connect(GTK_OBJECT(cbox), "changed", handler, r); return (cbox); } int wj_combo_box_get_history(GtkWidget *combobox) { return (gtk_combo_box_get_active(GTK_COMBO_BOX(combobox))); } #else /* Use GtkCombo before GTK+ 2.4.0 */ /* !!! In GTK+2, this handler is called twice for each change; in GTK+1, * once if using cursor keys, twice if selecting from list */ static void wj_combo(GtkWidget *entry, gpointer handler) { GtkWidget *combo = entry->parent; gpointer user_data; /* GTK+1 updates the entry constantly - wait it out */ #if GTK_MAJOR_VERSION == 1 if (GTK_WIDGET_VISIBLE(GTK_COMBO(combo)->popwin)) return; #endif user_data = gtk_object_get_user_data(GTK_OBJECT(entry)); ((void (*)(GtkWidget *, gpointer))handler)(combo, user_data); } #if GTK_MAJOR_VERSION == 1 /* Notify the main handler that meaningless updates are finished */ static void wj_combo_restart(GtkWidget *widget, GtkCombo *combo) { gtk_signal_emit_by_name(GTK_OBJECT(combo->entry), "changed"); } #endif #if GTK_MAJOR_VERSION == 2 /* Tweak style settings for combo entry */ static void wj_combo_restyle(GtkWidget *entry) { static int done; if (!done) { gtk_rc_parse_string("style \"mtPaint_extfocus\" {\n" "GtkWidget::interior-focus = 0\n}\n"); gtk_rc_parse_string("widget \"*.mtPaint_cbentry\" " "style \"mtPaint_extfocus\"\n"); done = TRUE; } gtk_widget_set_name(entry, "mtPaint_cbentry"); } /* Prevent cursor from appearing */ static gboolean wj_combo_kill_cursor(GtkWidget *widget, GdkEventExpose *event, gpointer user_data) { /* !!! Private field - future binary compatibility isn't guaranteed */ GTK_ENTRY(widget)->cursor_visible = FALSE; return (FALSE); } #endif /* void handler(GtkWidget *combo, gpointer user_data); */ GtkWidget *wj_combo_box(char **names, int cnt, int u, int idx, void **r, GtkSignalFunc handler) { GtkWidget *cbox; GtkCombo *combo; GtkEntry *entry; GList *list = NULL; int i; if (idx >= cnt) idx = 0; combo = GTK_COMBO(cbox = gtk_combo_new()); #if GTK_MAJOR_VERSION == 2 wj_combo_restyle(combo->entry); gtk_signal_connect(GTK_OBJECT(combo->entry), "expose_event", GTK_SIGNAL_FUNC(wj_combo_kill_cursor), NULL); #endif gtk_combo_set_value_in_list(combo, TRUE, FALSE); for (i = 0; i < cnt; i++) list = g_list_append(list, __(names[i])); gtk_combo_set_popdown_strings(combo, list); g_list_free(list); gtk_widget_show_all(cbox); entry = GTK_ENTRY(combo->entry); gtk_entry_set_editable(entry, FALSE); gtk_entry_set_text(entry, names[idx]); if (!handler) return (cbox); /* Install signal handler */ gtk_object_set_user_data(GTK_OBJECT(combo->entry), r); gtk_signal_connect(GTK_OBJECT(combo->entry), "changed", GTK_SIGNAL_FUNC(wj_combo), (gpointer)handler); #if GTK_MAJOR_VERSION == 1 gtk_signal_connect(GTK_OBJECT(combo->popwin), "hide", GTK_SIGNAL_FUNC(wj_combo_restart), combo); #endif return (cbox); } int wj_combo_box_get_history(GtkWidget *combobox) { GtkList *list = GTK_LIST(GTK_COMBO(combobox)->list); if (!list->selection || !list->selection->data) return (-1); return(gtk_list_child_position(list, GTK_WIDGET(list->selection->data))); } #endif #if GTK_MAJOR_VERSION == 3 // Bin widget with customizable size handling /* The only way to intercept size requests in GTK+3 is a wrapper widget. This is * such a widget, with installable handlers */ #define WJSIZEBIN(obj) G_TYPE_CHECK_INSTANCE_CAST(obj, wjsizebin_get_type(), wjsizebin) #define IS_WJSIZEBIN(obj) G_TYPE_CHECK_INSTANCE_TYPE(obj, wjsizebin_get_type()) typedef void (*size_alloc_f)(GtkWidget *widget, GtkAllocation *allocation, gpointer user_data); typedef void (*get_size_f)(GtkWidget *widget, gint vert, gint *min, gint *nat, gint for_width, gpointer user_data); typedef struct { GtkBin bin; // Parent class size_alloc_f size_alloc; // Allocate child get_size_f get_size; // Modify requested size gpointer udata; } wjsizebin; typedef struct { GtkBinClass parent_class; } wjsizebinClass; G_DEFINE_TYPE(wjsizebin, wjsizebin, GTK_TYPE_BIN) static void wjsizebin_size_allocate(GtkWidget *widget, GtkAllocation *allocation) { wjsizebin *sbin = WJSIZEBIN(widget); GtkWidget *child = gtk_bin_get_child(GTK_BIN(widget)); gtk_widget_set_allocation(widget, allocation); if (!child || !gtk_widget_get_visible(child)) return; /* Call handler if installed, do default thing if not */ if (sbin->size_alloc) sbin->size_alloc(child, allocation, sbin->udata); else gtk_widget_size_allocate(child, allocation); } static void wjsizebin_get_size(GtkWidget *widget, gint vert, gint *min, gint *nat, gint for_width) { wjsizebin *sbin = WJSIZEBIN(widget); GtkWidget *child = gtk_bin_get_child(GTK_BIN(widget)); /* Preset the size */ *min = *nat = 0; // Default if (!child || !gtk_widget_get_visible(child)); // Invisible doesn't matter else if (for_width >= 0) gtk_widget_get_preferred_height_for_width(child, for_width, min, nat); else (vert ? gtk_widget_get_preferred_height : gtk_widget_get_preferred_width)(child, min, nat); /* Let handler modify it */ if (sbin->get_size) sbin->get_size(child, vert, min, nat, for_width, sbin->udata); } static void wjsizebin_get_preferred_width(GtkWidget *widget, gint *min, gint *nat) { wjsizebin_get_size(widget, FALSE, min, nat, -1); } static void wjsizebin_get_preferred_height(GtkWidget *widget, gint *min, gint *nat) { wjsizebin_get_size(widget, TRUE, min, nat, -1); } static void wjsizebin_get_preferred_width_for_height(GtkWidget *widget, gint h, gint *min, gint *nat) { wjsizebin_get_size(widget, FALSE, min, nat, -1); } /* Specialcase only height-for-width, same as GtkFrame does */ static void wjsizebin_get_preferred_height_for_width(GtkWidget *widget, gint w, gint *min, gint *nat) { wjsizebin_get_size(widget, TRUE, min, nat, w); } static void wjsizebin_class_init(wjsizebinClass *class) { GtkWidgetClass *wclass = GTK_WIDGET_CLASS(class); wclass->size_allocate = wjsizebin_size_allocate; wclass->get_preferred_width = wjsizebin_get_preferred_width; wclass->get_preferred_height = wjsizebin_get_preferred_height; wclass->get_preferred_width_for_height = wjsizebin_get_preferred_width_for_height; wclass->get_preferred_height_for_width = wjsizebin_get_preferred_height_for_width; /* !!! Leave my bin alone */ wclass->style_updated = NULL; } static void wjsizebin_init(wjsizebin *sbin) { gtk_widget_set_has_window(GTK_WIDGET(sbin), FALSE); } GtkWidget *wjsizebin_new(GCallback get_size, GCallback size_alloc, gpointer user_data) { GtkWidget *w = g_object_new(wjsizebin_get_type(), NULL); wjsizebin *sbin = WJSIZEBIN(w); sbin->get_size = (get_size_f)get_size; sbin->size_alloc = (size_alloc_f)size_alloc; sbin->udata = user_data; return (w); } #else /* #if GTK_MAJOR_VERSION <= 2 */ // Box widget with customizable size handling /* There exist no way to override builtin handlers for GTK_RUN_FIRST signals, * such as size-request and size-allocate; so instead of building multiple * custom widget classes with different resize handling, it's better to build * one with no builtin sizing at all - WJ */ GtkWidget *wj_size_box() { static GtkType size_box_type; GtkWidget *widget; if (!size_box_type) { static const GtkTypeInfo info = { "WJSizeBox", sizeof(GtkBox), sizeof(GtkBoxClass), NULL /* class init */, NULL /* instance init */, NULL, NULL, NULL }; GtkWidgetClass *wc; size_box_type = gtk_type_unique(GTK_TYPE_BOX, &info); wc = gtk_type_class(size_box_type); wc->size_request = NULL; wc->size_allocate = NULL; } widget = gtk_widget_new(size_box_type, NULL); GTK_WIDGET_SET_FLAGS(widget, GTK_NO_WINDOW); #if GTK_MAJOR_VERSION == 2 gtk_widget_set_redraw_on_allocate(widget, FALSE); #endif gtk_widget_show(widget); return (widget); } // Disable visual updates while tweaking container's contents /* This is an evil hack, and isn't guaranteed to work in future GTK+ versions; * still, not providing such a function is a design mistake in GTK+, and it'll * be easier to update this code if it becomes broken sometime in dim future, * than deal with premature updates right here and now - WJ */ typedef struct { int flags, pf, mode; } lock_state; gpointer toggle_updates(GtkWidget *widget, gpointer unlock) { lock_state *state; GtkContainer *cont = GTK_CONTAINER(widget); if (!unlock) /* Locking... */ { state = calloc(1, sizeof(lock_state)); state->mode = cont->resize_mode; cont->resize_mode = GTK_RESIZE_IMMEDIATE; state->flags = GTK_WIDGET_FLAGS(widget); #if GTK_MAJOR_VERSION == 1 GTK_WIDGET_UNSET_FLAGS(widget, GTK_VISIBLE); state->pf = GTK_WIDGET_IS_OFFSCREEN(widget); GTK_PRIVATE_SET_FLAG(widget, GTK_IS_OFFSCREEN); #else /* if GTK_MAJOR_VERSION == 2 */ GTK_WIDGET_UNSET_FLAGS(widget, GTK_VISIBLE | GTK_MAPPED); #endif } else /* Unlocking... */ { state = unlock; cont->resize_mode = state->mode; #if GTK_MAJOR_VERSION == 1 GTK_WIDGET_SET_FLAGS(widget, state->flags & GTK_VISIBLE); if (!state->pf) GTK_PRIVATE_UNSET_FLAG(widget, GTK_IS_OFFSCREEN); #else /* if GTK_MAJOR_VERSION == 2 */ GTK_WIDGET_SET_FLAGS(widget, state->flags & (GTK_VISIBLE | GTK_MAPPED)); #endif free(state); state = NULL; } return (state); } #endif // Maximized & iconified states #if GTK_MAJOR_VERSION == 1 static Atom netwm[4]; static int netwm_set; static int init_netwm(GdkWindow *w) { static char *nm[4] = { "_NET_WM_STATE", "_NET_WM_STATE_MAXIMIZED_VERT", "_NET_WM_STATE_MAXIMIZED_HORZ", "_NET_WM_STATE_HIDDEN" }; return (XInternAtoms(GDK_WINDOW_XDISPLAY(w), nm, 4, FALSE, netwm)); } int is_maximized(GtkWidget *window) { Atom type, *atoms; int format, vh = 0; unsigned long i, nitems, after; unsigned char *data; GdkWindow *w = window->window; if (!netwm_set) netwm_set = init_netwm(w); gdk_error_trap_push(); XGetWindowProperty(GDK_WINDOW_XDISPLAY(w), GDK_WINDOW_XWINDOW(w), netwm[0], 0, G_MAXLONG, False, XA_ATOM, &type, &format, &nitems, &after, &data); gdk_error_trap_pop(); atoms = (void *)data; for (i = 0; i < nitems; i++) { if (atoms[i] == netwm[1]) vh |= 1; else if (atoms[i] == netwm[2]) vh |= 2; } XFree(atoms); return (vh == 3); } static void do_wm_state(GdkWindow *w, int add, int i1, int i2) { XEvent xev; if (!netwm_set) netwm_set = init_netwm(w); xev.xclient.type = ClientMessage; xev.xclient.serial = 0; xev.xclient.send_event = True; xev.xclient.window = GDK_WINDOW_XWINDOW(w); xev.xclient.message_type = netwm[0]; xev.xclient.format = 32; xev.xclient.data.l[0] = add ? 1 : 0; /* _NET_WM_STATE_ADD : _REMOVE */ xev.xclient.data.l[1] = netwm[i1]; xev.xclient.data.l[2] = i2 ? netwm[i2] : 0; xev.xclient.data.l[3] = 0; xev.xclient.data.l[4] = 0; XSendEvent(GDK_WINDOW_XDISPLAY(w), DefaultRootWindow(GDK_WINDOW_XDISPLAY(w)), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev); } void set_maximized(GtkWidget *window) { do_wm_state(window->window, TRUE, 1, 2); } void set_iconify(GtkWidget *window, int state) { GdkWindow *w = window->window; if (!GTK_WIDGET_MAPPED(window)) return; if (state) XIconifyWindow(GDK_WINDOW_XDISPLAY(w), GDK_WINDOW_XWINDOW(w), DefaultScreen(GDK_WINDOW_XDISPLAY(w))); else { gdk_window_show(w); do_wm_state(w, FALSE, 3, 0); } } #else /* if GTK_MAJOR_VERSION >= 2 */ void set_iconify(GtkWidget *window, int state) { (state ? gdk_window_iconify : gdk_window_deiconify)(gtk_widget_get_window(window)); } #endif // Drawable to RGB /* This code exists to read back both windows and pixmaps. In GTK+1 pixmap * handling capabilities are next to nonexistent, so a GdkWindow must always * be passed in, to serve as source of everything but actual pixels. * The only exception is when the pixmap passed in is definitely a bitmap. * Parsing GdkImage pixels loosely follows the example of convert_real_slow() * in GTK+2 (gdk/gdkpixbuf-drawable.c) - WJ */ #if GTK_MAJOR_VERSION == 1 unsigned char *wj_get_rgb_image(GdkWindow *window, GdkPixmap *pixmap, unsigned char *buf, int x, int y, int width, int height) { GdkImage *img; GdkColormap *cmap; GdkVisual *vis, fake_vis; GdkColor bw[2], *cols = NULL; unsigned char *dest, *wbuf = NULL; guint32 rmask, gmask, bmask, pix; int mode, rshift, gshift, bshift; int i, j; if (!window) /* No window - we got us a bitmap */ { vis = &fake_vis; vis->type = GDK_VISUAL_STATIC_GRAY; vis->depth = 1; cmap = NULL; } else if (window == (GdkWindow *)&gdk_root_parent) /* Not a proper window */ { vis = gdk_visual_get_system(); cmap = gdk_colormap_get_system(); } else { vis = gdk_window_get_visual(window); cmap = gdk_window_get_colormap(window); } if (!vis) return (NULL); mode = vis->type; if (cmap) cols = cmap->colors; else if ((mode != GDK_VISUAL_TRUE_COLOR) && (vis->depth != 1)) return (NULL); /* Can't handle other types w/o colormap */ if (!buf) buf = wbuf = malloc(width * height * 3); if (!buf) return (NULL); img = gdk_image_get(pixmap ? pixmap : window, x, y, width, height); if (!img) { free(wbuf); return (NULL); } rmask = vis->red_mask; gmask = vis->green_mask; bmask = vis->blue_mask; rshift = vis->red_shift; gshift = vis->green_shift; bshift = vis->blue_shift; if (mode == GDK_VISUAL_TRUE_COLOR) { /* !!! Unlikely to happen, but it's cheap to be safe */ if (vis->red_prec > 8) rshift += vis->red_prec - 8; if (vis->green_prec > 8) gshift += vis->green_prec - 8; if (vis->blue_prec > 8) bshift += vis->blue_prec - 8; } else if (!cmap && (vis->depth == 1)) /* Bitmap */ { /* Make a palette for it */ mode = GDK_VISUAL_PSEUDO_COLOR; bw[0].red = bw[0].green = bw[0].blue = 0; bw[1].red = bw[1].green = bw[1].blue = 65535; cols = bw; } dest = buf; for (i = 0; i < height; i++) for (j = 0; j < width; j++ , dest += 3) { pix = gdk_image_get_pixel(img, j, i); if (mode == GDK_VISUAL_TRUE_COLOR) { dest[0] = (pix & rmask) >> rshift; dest[1] = (pix & gmask) >> gshift; dest[2] = (pix & bmask) >> bshift; } else if (mode == GDK_VISUAL_DIRECT_COLOR) { dest[0] = cols[(pix & rmask) >> rshift].red >> 8; dest[1] = cols[(pix & gmask) >> gshift].green >> 8; dest[2] = cols[(pix & bmask) >> bshift].blue >> 8; } else /* Paletted */ { dest[0] = cols[pix].red >> 8; dest[1] = cols[pix].green >> 8; dest[2] = cols[pix].blue >> 8; } } /* Now extend the precision to 8 bits where necessary */ if (mode == GDK_VISUAL_TRUE_COLOR) { unsigned char xlat[128], *dest; int i, j, k, l = width * height; for (i = 0; i < 3; i++) { k = !i ? vis->red_prec : i == 1 ? vis->green_prec : vis->blue_prec; if (k >= 8) continue; set_xlate(xlat, k); dest = buf + i; for (j = 0; j < l; j++ , dest += 3) *dest = xlat[*dest]; } } gdk_image_destroy(img); return (buf); } #elif GTK_MAJOR_VERSION == 2 unsigned char *wj_get_rgb_image(GdkWindow *window, GdkPixmap *pixmap, unsigned char *buf, int x, int y, int width, int height) { GdkColormap *cmap = NULL; GdkPixbuf *pix, *res; unsigned char *wbuf = NULL; if (!buf) buf = wbuf = malloc(width * height * 3); if (!buf) return (NULL); if (pixmap && window) { cmap = gdk_drawable_get_colormap(pixmap); if (!cmap) cmap = gdk_drawable_get_colormap(window); } pix = gdk_pixbuf_new_from_data(buf, GDK_COLORSPACE_RGB, FALSE, 8, width, height, width * 3, NULL, NULL); if (pix) { res = gdk_pixbuf_get_from_drawable(pix, pixmap ? pixmap : window, cmap, x, y, 0, 0, width, height); g_object_unref(pix); if (res) return (buf); } free(wbuf); return (NULL); } #else /* if GTK_MAJOR_VERSION == 3 */ unsigned char *wj_get_rgb_image(GdkWindow *window, cairo_surface_t *s, unsigned char *buf, int x, int y, int width, int height) { GdkPixbuf *pix; if (s) pix = gdk_pixbuf_get_from_surface(s, x, y, width, height); else pix = gdk_pixbuf_get_from_window(window, x, y, width, height); if (!pix) return (NULL); if (!buf) buf = calloc(1, width * height * 3); if (buf) /* Copy data to 3bpp continuous buffer */ { unsigned char *dest, *src; int x, y, d, ww, wh, nc, stride; ww = gdk_pixbuf_get_width(pix); wh = gdk_pixbuf_get_height(pix); nc = gdk_pixbuf_get_n_channels(pix); stride = gdk_pixbuf_get_rowstride(pix); /* If result is somehow larger (scaling?), clip it */ if (ww > width) ww = width; if (wh > height) wh = height; src = gdk_pixbuf_get_pixels(pix); dest = buf; stride -= nc * ww; d = (width - ww) * 3; for (y = 0; y < wh; y++) { for (x = 0; x < ww; x++) { *dest++= src[0]; *dest++= src[1]; *dest++= src[2]; src += nc; } src += stride; dest += d; } } g_object_unref(pix); return (buf); } #endif // Clipboard #ifdef GDK_WINDOWING_WIN32 /* Detect if current clipboard belongs to something in the program itself; * on Windows, GDK is purposely lying to us about it, so use WinAPI instead */ int internal_clipboard(int which) { DWORD pid; if (which) return (TRUE); // No "PRIMARY" clipboard exists on Windows GetWindowThreadProcessId(GetClipboardOwner(), &pid); return (pid == GetCurrentProcessId()); } #elif defined GDK_WINDOWING_QUARTZ /* Detect if current clipboard belongs to something in the program itself; * on Quartz, GDK is halfbaked, so use a workaround instead */ int internal_clipboard(int which) { return (!!gtk_clipboard_get_owner(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD))); } #else /* Detect if current clipboard belongs to something in the program itself */ int internal_clipboard(int which) { gpointer widget = NULL; GdkWindow *win = gdk_selection_owner_get( gdk_atom_intern(which ? "PRIMARY" : "CLIPBOARD", FALSE)); if (!win) return (FALSE); // Unknown window gdk_window_get_user_data(win, &widget); return (!!widget); // Real widget or foreign window? } #endif // Clipboard pixmaps #ifdef HAVE_PIXMAPS /* Make code not compile if unthinkable happens */ typedef char Mismatched_XID_type[2 * (sizeof(Pixmap) == sizeof(XID_type)) - 1]; /* It's unclear who should free clipboard pixmaps and when, so I do the same * thing Qt does, destroying the next-to-last allocated pixmap each time a new * one is allocated - WJ */ #if GTK_MAJOR_VERSION == 3 int export_pixmap(pixmap_info *p, int w, int h) { static cairo_surface_t *exported[2]; cairo_surface_t *s = gdk_window_create_similar_surface( gtk_widget_get_window(main_window), CAIRO_CONTENT_COLOR, w, h); if (cairo_surface_get_type(s) != CAIRO_SURFACE_TYPE_XLIB) { cairo_surface_destroy(s); return (FALSE); } if (exported[0]) { if (exported[1]) { /* Someone might have destroyed the X pixmap already, * so get ready to live through an X error */ GdkDisplay *d = gtk_widget_get_display(main_window); gdk_x11_display_error_trap_push(d); cairo_surface_destroy(exported[1]); gdk_x11_display_error_trap_pop_ignored(d); } exported[1] = exported[0]; } exported[0] = p->pm = s; p->w = w; p->h = h; p->depth = -1; p->xid = cairo_xlib_surface_get_drawable(s); return (TRUE); } void pixmap_put_rows(pixmap_info *p, unsigned char *src, int y, int cnt) { cairo_surface_t *s; cairo_t *cr; s = cairo_upload_rgb(p->pm, NULL, src, p->w, cnt, p->w * 3); cr = cairo_create(p->pm); cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); cairo_set_source_surface(cr, s, 0, y); cairo_rectangle(cr, 0, y, p->w, cnt); cairo_fill(cr); cairo_destroy(cr); cairo_surface_fdestroy(s); } #else /* if GTK_MAJOR_VERSION <= 2 */ int export_pixmap(pixmap_info *p, int w, int h) { static GdkPixmap *exported[2]; if (exported[0]) { if (exported[1]) { /* Someone might have destroyed the X pixmap already, * so get ready to live through an X error */ gdk_error_trap_push(); gdk_pixmap_unref(exported[1]); gdk_error_trap_pop(); } exported[1] = exported[0]; } exported[0] = p->pm = gdk_pixmap_new(main_window->window, w, h, -1); if (!exported[0]) return (FALSE); p->w = w; p->h = h; p->depth = -1; p->xid = GDK_WINDOW_XWINDOW(exported[0]); return (TRUE); } void pixmap_put_rows(pixmap_info *p, unsigned char *src, int y, int cnt) { gdk_draw_rgb_image(p->pm, main_window->style->black_gc, 0, y, p->w, cnt, GDK_RGB_DITHER_NONE, src, p->w * 3); } #endif #endif /* HAVE_PIXMAPS */ int import_pixmap(pixmap_info *p, XID_type *xid) { if (xid) // Pixmap by ID { /* This ugly code imports X Window System's pixmaps; this allows mtPaint to * receive images from programs such as XPaint */ #if (GTK_MAJOR_VERSION == 3) && defined GDK_WINDOWING_X11 cairo_surface_t *s; GdkDisplay *d = gtk_widget_get_display(main_window); Display *disp = GDK_DISPLAY_XDISPLAY(d); XWindowAttributes attr; Window root; unsigned int x, y, w, h, bor, depth; int res; gdk_x11_display_error_trap_push(d); // No guarantee that we got a valid pixmap res = XGetGeometry(disp, *xid, &root, &x, &y, &w, &h, &bor, &depth); if (res) res = XGetWindowAttributes(disp, root, &attr); gdk_x11_display_error_trap_pop_ignored(d); if (!res) return (FALSE); s = cairo_xlib_surface_create(disp, *xid, attr.visual, w, h); if (cairo_surface_get_type(s) == CAIRO_SURFACE_TYPE_XLIB) { p->xid = *xid; p->pm = s; p->w = w; p->h = h; p->depth = depth; return (TRUE); } cairo_surface_destroy(s); #elif (GTK_MAJOR_VERSION == 1) || defined GDK_WINDOWING_X11 int w, h, d, dd; gdk_error_trap_push(); // No guarantee that we got a valid pixmap p->pm = gdk_pixmap_foreign_new(p->xid = *xid); gdk_error_trap_pop(); // The above call returns NULL on failure anyway if (!p->pm) return (FALSE); dd = gdk_visual_get_system()->depth; #if GTK_MAJOR_VERSION == 1 gdk_window_get_geometry(p->pm, NULL, NULL, &w, &h, &d); #else /* #if GTK_MAJOR_VERSION == 2 */ gdk_drawable_get_size(p->pm, &w, &h); d = gdk_drawable_get_depth(p->pm); #endif if ((d == 1) || (d == dd)) { p->w = w; p->h = h; p->depth = d; return (TRUE); } drop_pixmap(p); #endif return (FALSE); } else // NULL means a screenshot { // !!! Should be the screen where gdk_get_default_root_window() is p->w = gdk_screen_width(); p->h = gdk_screen_height(); p->depth = 3; p->pm = NULL; p->xid = 0; } return (TRUE); } void drop_pixmap(pixmap_info *p) { #if (GTK_MAJOR_VERSION == 3) && defined GDK_WINDOWING_X11 if (!p->pm) return; cairo_surface_destroy(p->pm); #elif (GTK_MAJOR_VERSION == 1) || defined GDK_WINDOWING_X11 if (!p->pm) return; #if GTK_MAJOR_VERSION == 1 /* Don't let gdk_pixmap_unref() destroy another process's pixmap - * implement freeing the GdkPixmap structure here instead */ gdk_xid_table_remove(((GdkWindowPrivate *)p->pm)->xwindow); g_dataset_destroy(p->pm); g_free(p->pm); #else /* #if GTK_MAJOR_VERSION == 2 */ gdk_pixmap_unref(p->pm); #endif #endif } int pixmap_get_rows(pixmap_info *p, unsigned char *dest, int y, int cnt) { return (!!wj_get_rgb_image(p->depth == 1 ? NULL : #if GTK_MAJOR_VERSION == 1 (GdkWindow *)&gdk_root_parent, #else /* #if GTK_MAJOR_VERSION >= 2 */ gdk_get_default_root_window(), #endif p->pm, dest, 0, y, p->w, cnt)); } // Render stock icons to pixmaps #if GTK_MAJOR_VERSION == 3 /* Actually loads a named icon, not stock */ static GdkPixbuf *render_stock_pixbuf(GtkWidget *widget, const gchar *stock_id) { GtkIconTheme *theme; gint w, h; // !!! The theme need be modifiable by theme file loaded from prefs theme = gtk_icon_theme_get_for_screen(gtk_style_context_get_screen( gtk_widget_get_style_context(widget))); if (!theme) return (NULL); // Paranoia gtk_icon_size_lookup(GTK_ICON_SIZE_SMALL_TOOLBAR, &w, &h); return (gtk_icon_theme_load_icon(theme, stock_id, (w < h ? w : h), GTK_ICON_LOOKUP_USE_BUILTIN, NULL)); } #elif GTK_MAJOR_VERSION == 2 static GdkPixbuf *render_stock_pixbuf(GtkWidget *widget, const gchar *stock_id) { GtkIconSet *icon_set; /* !!! Doing this for widget itself in some cases fails (!) */ icon_set = gtk_style_lookup_icon_set(main_window->style, stock_id); if (!icon_set) return (NULL); // !!! Is this "widget" here at all useful, or is "main_window" good enough? gtk_widget_ensure_style(widget); return (gtk_icon_set_render_icon(icon_set, widget->style, gtk_widget_get_direction(widget), GTK_WIDGET_STATE(widget), GTK_ICON_SIZE_SMALL_TOOLBAR, widget, NULL)); } GdkPixmap *render_stock_pixmap(GtkWidget *widget, const gchar *stock_id, GdkBitmap **mask) { GdkPixmap *pmap; GdkPixbuf *buf; buf = render_stock_pixbuf(widget, stock_id); if (!buf) return (NULL); gdk_pixbuf_render_pixmap_and_mask_for_colormap(buf, gtk_widget_get_colormap(widget), &pmap, mask, 127); g_object_unref(buf); return (pmap); } #endif // Image widget /* !!! GtkImage is broken on GTK+ 2.12.9 at least, with regard to pixmaps - * background gets corrupted when widget is made insensitive, so GtkPixmap is * the only choice in that case - WJ */ #if GTK_MAJOR_VERSION == 2 /* Guard against different depth visuals */ static void xpm_realize(GtkWidget *widget, gpointer user_data) { if (gdk_drawable_get_depth(widget->window) != gdk_drawable_get_depth(GTK_PIXMAP(widget)->pixmap)) { GdkPixmap *icon, *mask; icon = gdk_pixmap_create_from_xpm_d(widget->window, &mask, NULL, user_data); gtk_pixmap_set(GTK_PIXMAP(widget), icon, mask); gdk_pixmap_unref(icon); gdk_pixmap_unref(mask); } } #endif GtkWidget *xpm_image(XPM_TYPE xpm) { GtkWidget *widget; #if GTK_MAJOR_VERSION >= 2 GdkPixbuf *buf; char name[256]; snprintf(name, sizeof(name), "mtpaint_%s", (char *)xpm[0]); buf = render_stock_pixbuf(main_window, name); if (buf) /* Found a themed icon - use it */ { widget = gtk_image_new_from_pixbuf(buf); g_object_unref(buf); gtk_widget_show(widget); return (widget); } #endif /* Fall back to builtin XPM icon */ #if GTK_MAJOR_VERSION == 3 buf = gdk_pixbuf_new_from_xpm_data((const char **)xpm[1]); widget = gtk_image_new_from_pixbuf(buf); g_object_unref(buf); #else /* if GTK_MAJOR_VERSION <= 2 */ { GdkPixmap *icon, *mask; icon = gdk_pixmap_create_from_xpm_d(main_window->window, &mask, #if GTK_MAJOR_VERSION == 2 NULL, (char **)xpm[1]); #else /* if GTK_MAJOR_VERSION == 1 */ NULL, xpm); #endif widget = gtk_pixmap_new(icon, mask); gdk_pixmap_unref(icon); gdk_pixmap_unref(mask); } #endif gtk_widget_show(widget); #if GTK_MAJOR_VERSION == 2 gtk_signal_connect(GTK_OBJECT(widget), "realize", GTK_SIGNAL_FUNC(xpm_realize), (char **)xpm[1]); #endif return (widget); } // Release outstanding pointer grabs #if GTK_MAJOR_VERSION == 3 int release_grab() { GdkDisplay *dp = gdk_display_get_default(); GList *l, *ll; int res = FALSE; ll = gdk_device_manager_list_devices(gdk_display_get_device_manager(dp), GDK_DEVICE_TYPE_MASTER); for (l = ll; l; l = l->next) { GdkDevice *dev = l->data; if ((gdk_device_get_source(dev) == GDK_SOURCE_MOUSE) && gdk_display_device_is_grabbed(dp, dev)) { gdk_device_ungrab(dev, GDK_CURRENT_TIME); res = TRUE; } } g_list_free(ll); return (res); } #else /* if GTK_MAJOR_VERSION <= 2 */ int release_grab() { if (!gdk_pointer_is_grabbed()) return (FALSE); gdk_pointer_ungrab(GDK_CURRENT_TIME); return (TRUE); } #endif // Frame widget with passthrough scrolling #if GTK_MAJOR_VERSION == 3 #define WJFRAME(obj) G_TYPE_CHECK_INSTANCE_CAST(obj, wjframe_get_type(), wjframe) #define IS_WJFRAME(obj) G_TYPE_CHECK_INSTANCE_TYPE(obj, wjframe_get_type()) typedef struct { GtkBin bin; // Parent class GtkAdjustment *adjustments[2]; GtkAllocation inside; } wjframe; typedef struct { GtkBinClass parent_class; } wjframeClass; G_DEFINE_TYPE_WITH_CODE(wjframe, wjframe, GTK_TYPE_BIN, G_IMPLEMENT_INTERFACE(GTK_TYPE_SCROLLABLE, NULL)) #define WJFRAME_SHADOW 1 /* Line width, limited only by common sense */ static gboolean wjframe_draw(GtkWidget *widget, cairo_t *cr) { wjframe *frame = WJFRAME(widget); /* !!! Using deprecated struct to avoid recalculating the colors */ GtkStyle *style = gtk_widget_get_style(widget); GtkAllocation alloc; double dxy = WJFRAME_SHADOW * 0.5; int x, y, x1, y1; gtk_widget_get_allocation(widget, &alloc); x1 = (x = frame->inside.x - alloc.x) + frame->inside.width - 1; y1 = (y = frame->inside.y - alloc.y) + frame->inside.height - 1; cairo_save(cr); cairo_set_line_width(cr, WJFRAME_SHADOW); cairo_set_line_cap(cr, CAIRO_LINE_CAP_SQUARE); gdk_cairo_set_source_color(cr, style->light + GTK_STATE_NORMAL); cairo_move_to(cr, x1 + dxy, y - dxy); cairo_line_to(cr, x1 + dxy, y1 + dxy); // Right cairo_line_to(cr, x - dxy, y1 + dxy); // Bottom cairo_stroke(cr); gdk_cairo_set_source_color(cr, style->dark + GTK_STATE_NORMAL); cairo_move_to(cr, x1 + dxy, y - dxy); cairo_line_to(cr, x - dxy, y - dxy); // Top cairo_line_to(cr, x - dxy, y1 + dxy); // Left cairo_stroke(cr); cairo_restore(cr); /* To draw child widget */ GTK_WIDGET_CLASS(wjframe_parent_class)->draw(widget, cr); return (FALSE); } static void wjframe_size_allocate(GtkWidget *widget, GtkAllocation *allocation) { wjframe *frame = WJFRAME(widget); GtkWidget *child = gtk_bin_get_child(GTK_BIN(widget)); int border = gtk_container_get_border_width(GTK_CONTAINER(widget)) + WJFRAME_SHADOW; GtkAllocation now_inside; gtk_widget_set_allocation(widget, allocation); now_inside.x = allocation->x + border; now_inside.y = allocation->y + border; now_inside.width = MAX(allocation->width - border * 2, 1); now_inside.height = MAX(allocation->height - border * 2, 1); /* Redraw if inside moved while visible */ if (gtk_widget_get_mapped(widget) && ((frame->inside.x ^ now_inside.x) | (frame->inside.y ^ now_inside.y) | (frame->inside.width ^ now_inside.width) | (frame->inside.height ^ now_inside.height))) gdk_window_invalidate_rect(gtk_widget_get_window(widget), allocation, FALSE); frame->inside = now_inside; if (child && gtk_widget_get_visible(child)) gtk_widget_size_allocate(child, &now_inside); } static void wjframe_get_size(GtkWidget *widget, gint vert, gint *min, gint *nat) { GtkWidget *child = gtk_bin_get_child(GTK_BIN(widget)); int border = gtk_container_get_border_width(GTK_CONTAINER(widget)) + WJFRAME_SHADOW; gint cmin = 0, cnat = 0; if (child && gtk_widget_get_visible(child)) (vert ? gtk_widget_get_preferred_height : gtk_widget_get_preferred_width)(child, &cmin, &cnat); *min = cmin + border * 2; *nat = cnat + border * 2; } static void wjframe_get_preferred_width(GtkWidget *widget, gint *min, gint *nat) { wjframe_get_size(widget, FALSE, min, nat); } static void wjframe_get_preferred_height(GtkWidget *widget, gint *min, gint *nat) { wjframe_get_size(widget, TRUE, min, nat); } static void wjframe_get_preferred_width_for_height(GtkWidget *widget, gint h, gint *min, gint *nat) { wjframe_get_size(widget, FALSE, min, nat); } /* Specialcase only height-for-width, same as GtkFrame does */ static void wjframe_get_preferred_height_for_width(GtkWidget *widget, gint w, gint *min, gint *nat) { GtkWidget *child = gtk_bin_get_child(GTK_BIN(widget)); int border = gtk_container_get_border_width(GTK_CONTAINER(widget)) + WJFRAME_SHADOW; gint cmin = 0, cnat = 0; if (child && gtk_widget_get_visible(child)) gtk_widget_get_preferred_height_for_width(child, w - border * 2, &cmin, &cnat); *min = cmin + border * 2; *nat = cnat + border * 2; } static void wjframe_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { wjframe *frame = WJFRAME(object); GtkWidget *child = gtk_bin_get_child(GTK_BIN(object)); if ((prop_id == P_HADJ) || (prop_id == P_VADJ)) { /* Cache the object */ GtkAdjustment *adj, **slot = frame->adjustments + prop_id - P_HADJ; adj = g_value_get_object(value); if (adj) g_object_ref(adj); if (*slot) g_object_unref(*slot); *slot = adj; } // !!! React to "*scroll-policy" as an invalid ID when empty else if (child && ((prop_id == P_HSCP) || (prop_id == P_VSCP))); else { G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); return; } /* Send the thing to child to handle */ if (child) g_object_set_property(G_OBJECT(child), scroll_pnames[prop_id], value); } static void wjframe_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { wjframe *frame = WJFRAME(object); if ((prop_id == P_HADJ) || (prop_id == P_VADJ)) /* Returning cached object */ g_value_set_object(value, frame->adjustments[prop_id - P_HADJ]); else if ((prop_id == P_HSCP) || (prop_id == P_VSCP)) { /* Proxying for child */ GtkWidget *child = gtk_bin_get_child(GTK_BIN(object)); if (child) g_object_get_property(G_OBJECT(child), scroll_pnames[prop_id], value); else g_value_set_enum(value, GTK_SCROLL_NATURAL); // Default } else G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); } static void wjframe_add(GtkContainer *container, GtkWidget *child) { wjframe *frame = WJFRAME(container); if (gtk_bin_get_child(GTK_BIN(container))) return; GTK_CONTAINER_CLASS(wjframe_parent_class)->add(container, child); /* Set only existing adjustments */ if (frame->adjustments[0] || frame->adjustments[1]) g_object_set(child, "hadjustment", frame->adjustments[0], "vadjustment", frame->adjustments[1], NULL); } static void wjframe_remove(GtkContainer *container, GtkWidget *child) { wjframe *frame = WJFRAME(container); GtkWidget *child0 = gtk_bin_get_child(GTK_BIN(container)); if (!child || (child0 != child)) return; /* Remove only existing adjustments */ if (frame->adjustments[0] || frame->adjustments[1]) g_object_set(child, "hadjustment", NULL, "vadjustment", NULL, NULL); GTK_CONTAINER_CLASS(wjframe_parent_class)->remove(container, child); } static void wjframe_destroy(GtkWidget *widget) { wjframe *frame = WJFRAME(widget); if (frame->adjustments[0]) g_object_unref(frame->adjustments[0]); if (frame->adjustments[1]) g_object_unref(frame->adjustments[1]); frame->adjustments[0] = frame->adjustments[1] = NULL; GTK_WIDGET_CLASS(wjframe_parent_class)->destroy(widget); } static void wjframe_class_init(wjframeClass *class) { GtkContainerClass *cclass = GTK_CONTAINER_CLASS(class); GtkWidgetClass *wclass = GTK_WIDGET_CLASS(class); GObjectClass *oclass = G_OBJECT_CLASS(class); oclass->set_property = wjframe_set_property; oclass->get_property = wjframe_get_property; wclass->destroy = wjframe_destroy; wclass->draw = wjframe_draw; wclass->size_allocate = wjframe_size_allocate; wclass->get_preferred_width = wjframe_get_preferred_width; wclass->get_preferred_height = wjframe_get_preferred_height; wclass->get_preferred_width_for_height = wjframe_get_preferred_width_for_height; wclass->get_preferred_height_for_width = wjframe_get_preferred_height_for_width; /* !!! Leave my frame alone */ wclass->style_updated = NULL; cclass->add = wjframe_add; cclass->remove = wjframe_remove; g_object_class_override_property(oclass, P_HADJ, "hadjustment"); g_object_class_override_property(oclass, P_VADJ, "vadjustment"); g_object_class_override_property(oclass, P_HSCP, "hscroll-policy"); g_object_class_override_property(oclass, P_VSCP, "vscroll-policy"); } static void wjframe_init(wjframe *frame) { // gtk_widget_set_has_window(GTK_WIDGET(frame), FALSE); // GtkBin done it frame->adjustments[0] = frame->adjustments[1] = NULL; } #else /* if GTK_MAJOR_VERSION <= 2 */ /* !!! Windows builds of GTK+ are made with G_ENABLE_DEBUG, which means also * marshallers checking what passes through. Since "OBJECT" is, from their * point of view, not "POINTER", we need our own marshaller without the checks, * or our "set-scroll-adjustments" handlers won't receive anything but NULLs. * Just in case someone does the same on Unix, we use our marshaller with GTK+2 * regardless of the host OS - WJ */ /* #if defined GDK_WINDOWING_WIN32 */ #if GTK_MAJOR_VERSION == 2 /* Function autogenerated by "glib-genmarshal" utility, then improved a bit - WJ */ #define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer static void unchecked_gtk_marshal_VOID__POINTER_POINTER(GClosure *closure, GValue *return_value, guint n_param_values, const GValue *param_values, gpointer invocation_hint, gpointer marshal_data) { void (*callback)(gpointer data1, gpointer arg1, gpointer arg2, gpointer data2); gpointer data1, data2; if (n_param_values != 3) return; data1 = data2 = g_value_peek_pointer(param_values + 0); if (G_CCLOSURE_SWAP_DATA(closure)) data1 = closure->data; else data2 = closure->data; callback = marshal_data ? marshal_data : ((GCClosure *)closure)->callback; callback(data1, g_marshal_value_peek_pointer(param_values + 1), g_marshal_value_peek_pointer(param_values + 2), data2); } #undef gtk_marshal_NONE__POINTER_POINTER #define gtk_marshal_NONE__POINTER_POINTER unchecked_gtk_marshal_VOID__POINTER_POINTER #endif #define WJFRAME(obj) GTK_CHECK_CAST(obj, wjframe_get_type(), wjframe) #define IS_WJFRAME(obj) GTK_CHECK_TYPE(obj, wjframe_get_type()) typedef struct { GtkBin bin; // Parent class GtkAdjustment *adjustments[2]; } wjframe; typedef struct { GtkBinClass parent_class; void (*set_scroll_adjustments)(wjframe *frame, GtkAdjustment *hadjustment, GtkAdjustment *vadjustment); } wjframeClass; static GtkBinClass *bin_class; static GtkType wjframe_type; #define WJFRAME_SHADOW 1 static GtkType wjframe_get_type(); static void wjframe_realize(GtkWidget *widget) { GdkWindowAttr attrs; int border = GTK_CONTAINER(widget)->border_width; GTK_WIDGET_SET_FLAGS(widget, GTK_REALIZED); /* Make widget window */ attrs.x = widget->allocation.x + border; attrs.y = widget->allocation.y + border; attrs.width = widget->allocation.width - 2 * border; attrs.height = widget->allocation.height - 2 * border; attrs.window_type = GDK_WINDOW_CHILD; attrs.wclass = GDK_INPUT_OUTPUT; attrs.visual = gtk_widget_get_visual(widget); attrs.colormap = gtk_widget_get_colormap(widget); // Window exists only to render the shadow attrs.event_mask = gtk_widget_get_events(widget) | GDK_EXPOSURE_MASK; widget->window = gdk_window_new(gtk_widget_get_parent_window(widget), &attrs, GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP); gdk_window_set_user_data(widget->window, widget); widget->style = gtk_style_attach(widget->style, widget->window); /* Background clear is for wimps :-) */ gdk_window_set_back_pixmap(widget->window, NULL, FALSE); // !!! Do this instead if the widget is ever used for non-canvaslike stuff // gtk_style_set_background(widget->style, widget->window, GTK_STATE_NORMAL); } static void wjframe_paint(GtkWidget *widget, GdkRectangle *area) { GdkWindow *window = widget->window; GdkGC *light, *dark; gint w, h; int x1, y1; if (!window || !widget->style) return; gdk_window_get_size(window, &w, &h); #if 0 /* !!! Useless with canvaslike widgets */ if ((w > WJFRAME_SHADOW * 2) && (h > WJFRAME_SHADOW * 2)) gtk_paint_flat_box(widget->style, window, widget->state, GTK_SHADOW_NONE, area, widget, NULL, WJFRAME_SHADOW, WJFRAME_SHADOW, w - WJFRAME_SHADOW * 2, h - WJFRAME_SHADOW * 2); #endif /* State, shadow, and widget type are hardcoded */ light = widget->style->light_gc[GTK_STATE_NORMAL]; dark = widget->style->dark_gc[GTK_STATE_NORMAL]; gdk_gc_set_clip_rectangle(light, area); gdk_gc_set_clip_rectangle(dark, area); x1 = w - 1; y1 = h - 1; gdk_draw_line(window, light, 0, y1, x1, y1); gdk_draw_line(window, light, x1, 0, x1, y1); gdk_draw_line(window, dark, 0, 0, x1, 0); gdk_draw_line(window, dark, 0, 0, 0, y1); gdk_gc_set_clip_rectangle(light, NULL); gdk_gc_set_clip_rectangle(dark, NULL); } #if GTK_MAJOR_VERSION == 1 static void wjframe_draw(GtkWidget *widget, GdkRectangle *area) { GdkRectangle tmp, child; GtkBin *bin = GTK_BIN(widget); int border = GTK_CONTAINER(widget)->border_width; if (!area || !GTK_WIDGET_DRAWABLE(widget)) return; tmp = *area; tmp.x -= border; tmp.y -= border; wjframe_paint(widget, &tmp); if (bin->child && gtk_widget_intersect(bin->child, &tmp, &child)) gtk_widget_draw(bin->child, &child); } static gboolean wjframe_expose(GtkWidget *widget, GdkEventExpose *event) { GtkBin *bin = GTK_BIN(widget); if (!GTK_WIDGET_DRAWABLE(widget)) return (FALSE); wjframe_paint(widget, &event->area); if (bin->child && GTK_WIDGET_NO_WINDOW(bin->child)) { GdkEventExpose tmevent = *event; if (gtk_widget_intersect(bin->child, &event->area, &tmevent.area)) gtk_widget_event(bin->child, (GdkEvent *)&tmevent); } return (FALSE); } #else /* if GTK_MAJOR_VERSION == 2 */ static gboolean wjframe_expose(GtkWidget *widget, GdkEventExpose *event) { if (!GTK_WIDGET_DRAWABLE(widget)) return (FALSE); wjframe_paint(widget, &event->area); GTK_WIDGET_CLASS(bin_class)->expose_event(widget, event); return (FALSE); } #endif static void wjframe_size_request(GtkWidget *widget, GtkRequisition *requisition) { GtkRequisition req; GtkBin *bin = GTK_BIN(widget); int border = GTK_CONTAINER(widget)->border_width; requisition->width = requisition->height = (WJFRAME_SHADOW + border) * 2; if (bin->child && GTK_WIDGET_VISIBLE(bin->child)) { gtk_widget_size_request(bin->child, &req); requisition->width += req.width; requisition->height += req.height; } } static void wjframe_size_allocate(GtkWidget *widget, GtkAllocation *allocation) { GtkAllocation alloc; GtkBin *bin = GTK_BIN(widget); int border = GTK_CONTAINER(widget)->border_width; widget->allocation = *allocation; alloc.x = alloc.y = WJFRAME_SHADOW; alloc.width = MAX(allocation->width - (WJFRAME_SHADOW + border) * 2, 0); alloc.height = MAX(allocation->height - (WJFRAME_SHADOW + border) * 2, 0); if (GTK_WIDGET_REALIZED(widget)) gdk_window_move_resize(widget->window, allocation->x + border, allocation->y + border, allocation->width - border * 2, allocation->height - border * 2); if (bin->child) gtk_widget_size_allocate(bin->child, &alloc); } static void wjframe_set_adjustments(wjframe *frame, GtkAdjustment *hadjustment, GtkAdjustment *vadjustment) { if (hadjustment) gtk_object_ref(GTK_OBJECT(hadjustment)); if (frame->adjustments[0]) gtk_object_unref(GTK_OBJECT(frame->adjustments[0])); frame->adjustments[0] = hadjustment; if (vadjustment) gtk_object_ref(GTK_OBJECT(vadjustment)); if (frame->adjustments[1]) gtk_object_unref(GTK_OBJECT(frame->adjustments[1])); frame->adjustments[1] = vadjustment; } static void wjframe_set_scroll_adjustments(wjframe *frame, GtkAdjustment *hadjustment, GtkAdjustment *vadjustment) { GtkBin *bin = GTK_BIN(frame); if ((hadjustment == frame->adjustments[0]) && (vadjustment == frame->adjustments[1])) return; wjframe_set_adjustments(frame, hadjustment, vadjustment); if (bin->child) gtk_widget_set_scroll_adjustments(bin->child, hadjustment, vadjustment); } static void wjframe_add(GtkContainer *container, GtkWidget *child) { wjframe *frame = WJFRAME(container); GtkBin *bin = GTK_BIN(container); GtkWidget *widget = GTK_WIDGET(container); if (bin->child) return; bin->child = child; gtk_widget_set_parent(child, widget); /* Set only existing adjustments */ if (frame->adjustments[0] || frame->adjustments[1]) gtk_widget_set_scroll_adjustments(child, frame->adjustments[0], frame->adjustments[1]); #if GTK_MAJOR_VERSION == 1 if (GTK_WIDGET_REALIZED(widget)) gtk_widget_realize(child); if (GTK_WIDGET_VISIBLE(widget) && GTK_WIDGET_VISIBLE(child)) { if (GTK_WIDGET_MAPPED(widget)) gtk_widget_map(child); gtk_widget_queue_resize(child); } #endif } static void wjframe_remove(GtkContainer *container, GtkWidget *child) { wjframe *frame = WJFRAME(container); GtkBin *bin = GTK_BIN(container); if (!child || (bin->child != child)) return; /* Remove only existing adjustments */ if (frame->adjustments[0] || frame->adjustments[1]) gtk_widget_set_scroll_adjustments(child, NULL, NULL); GTK_CONTAINER_CLASS(bin_class)->remove(container, child); } static void wjframe_destroy(GtkObject *object) { wjframe_set_adjustments(WJFRAME(object), NULL, NULL); GTK_OBJECT_CLASS(bin_class)->destroy(object); } static void wjframe_class_init(wjframeClass *class) { GtkWidgetClass *wclass = GTK_WIDGET_CLASS(class); GtkContainerClass *cclass = GTK_CONTAINER_CLASS(class); bin_class = gtk_type_class(GTK_TYPE_BIN); GTK_OBJECT_CLASS(class)->destroy = wjframe_destroy; #if GTK_MAJOR_VERSION == 1 wclass->draw = wjframe_draw; #endif wclass->realize = wjframe_realize; wclass->expose_event = wjframe_expose; wclass->size_request = wjframe_size_request; wclass->size_allocate = wjframe_size_allocate; // !!! Default "style_set" handler can reenable background clear wclass->style_set = NULL; cclass->add = wjframe_add; cclass->remove = wjframe_remove; class->set_scroll_adjustments = wjframe_set_scroll_adjustments; wclass->set_scroll_adjustments_signal = gtk_signal_new( "set_scroll_adjustments", GTK_RUN_LAST, wjframe_type, GTK_SIGNAL_OFFSET(wjframeClass, set_scroll_adjustments), gtk_marshal_NONE__POINTER_POINTER, GTK_TYPE_NONE, 2, GTK_TYPE_ADJUSTMENT, GTK_TYPE_ADJUSTMENT); } static void wjframe_init(wjframe *frame) { GTK_WIDGET_UNSET_FLAGS(frame, GTK_NO_WINDOW); #if GTK_MAJOR_VERSION == 2 // !!! Would only waste time, with canvaslike child widgets GTK_WIDGET_UNSET_FLAGS(frame, GTK_DOUBLE_BUFFERED); #endif frame->adjustments[0] = frame->adjustments[1] = NULL; } static GtkType wjframe_get_type() { if (!wjframe_type) { static const GtkTypeInfo wjframe_info = { "wjFrame", sizeof(wjframe), sizeof(wjframeClass), (GtkClassInitFunc)wjframe_class_init, (GtkObjectInitFunc)wjframe_init, NULL, NULL, NULL }; wjframe_type = gtk_type_unique(GTK_TYPE_BIN, &wjframe_info); } return (wjframe_type); } #endif /* GTK+1&2 */ GtkWidget *wjframe_new() { return (gtk_widget_new(wjframe_get_type(), NULL)); } // Scrollable canvas widget #if GTK_MAJOR_VERSION == 3 #define WCACHE_STEP 64 /* Dimensions are multiples of this */ #define WCACHE_FRAC 2 /* Can be this larger than necessary */ typedef struct { cairo_surface_t *s; // Surface int xy[4]; // Viewport int dx; // X offset int dy; // Y offset int w; // Cache line width int h; // Cache height including boundary rows int scale; // Window scale factor } wcache; // Create cache for viewport static void wcache_init(wcache *cache, int *vport, GdkWindow *win) { cache->w = vport[2] - vport[0] + WCACHE_STEP - 1; cache->h = vport[3] - vport[1] + WCACHE_STEP - 1; cache->w -= cache->w % WCACHE_STEP; cache->h -= cache->h % WCACHE_STEP; copy4(cache->xy, vport); cache->dx = cache->dy = 0; cache->scale = gdk_window_get_scale_factor(win); cache->s = gdk_window_create_similar_surface(win, CAIRO_CONTENT_COLOR, cache->w, cache->h); } // Check if cache need be replaced, align it to vport if not static int wcache_check(wcache *cache, int *vport, int empty) { int tw = vport[2] - vport[0], th = vport[3] - vport[1]; if (!cache->s) return (TRUE); while ((tw <= cache->w) && (th <= cache->h)) { tw += WCACHE_STEP - 1; tw -= tw % WCACHE_STEP; th += WCACHE_STEP - 1; th -= th % WCACHE_STEP; if (tw * th * WCACHE_FRAC < cache->w * cache->h) break; /* Adjust for new vport */ if (empty) { cache->dx = 0; cache->dy = 0; } else if (memcmp(cache->xy, vport, sizeof(cache->xy))) { cache->dx = floor_mod(cache->dx + vport[0] - cache->xy[0], cache->w); cache->dy = floor_mod(cache->dy + vport[1] - cache->xy[1], cache->h); } copy4(cache->xy, vport); return (FALSE); // Leave be } /* Drop the cache if no data inside */ if (empty) { cairo_surface_fdestroy(cache->s); cache->s = NULL; } return (TRUE); } // Move data from old cache to new static void wcache_move(wcache *new, wcache *old) { int rxy[4]; cairo_t *cr; if (!old->s) return; /* Copy matching part of old's spans into new */ if (clip(rxy, old->xy[0], old->xy[1], old->xy[2], old->xy[3], new->xy)) { cr = cairo_create(new->s); cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); cairo_set_source_surface(cr, old->s, old->xy[0] - new->xy[0] - old->dx, old->xy[1] - new->xy[1] - old->dy); cairo_pattern_set_extend(cairo_get_source(cr), CAIRO_EXTEND_REPEAT); cairo_rectangle(cr, rxy[0] - new->xy[0], rxy[1] - new->xy[1], rxy[2] - rxy[0], rxy[3] - rxy[1]); cairo_fill(cr); cairo_destroy(cr); } /* Drop the old cache */ cairo_surface_fdestroy(old->s); old->s = NULL; } static void wcache_render(wcache *cache, cairo_t *cr) { int h = cache->xy[3] - cache->xy[1], w = cache->xy[2] - cache->xy[0]; cairo_save(cr); cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); cairo_set_source_surface(cr, cache->s, -cache->dx, -cache->dy); cairo_pattern_set_extend(cairo_get_source(cr), CAIRO_EXTEND_REPEAT); cairo_rectangle(cr, 0, 0, w, h); cairo_fill(cr); cairo_restore(cr); } #define WJCANVAS(obj) G_TYPE_CHECK_INSTANCE_CAST(obj, wjcanvas_get_type(), wjcanvas) #define IS_WJCANVAS(obj) G_TYPE_CHECK_INSTANCE_TYPE(obj, wjcanvas_get_type()) typedef void (*wjc_expose_f)(GtkWidget *widget, cairo_region_t *clip, gpointer user_data); typedef struct { GtkWidget widget; // Parent class GtkAdjustment *adjustments[2]; cairo_region_t *r; // Cached region int xy[4]; // Viewport int size[2]; // Requested (virtual) size int resize; // Resize was requested int resizing; // Requested resize is happening guint32 scrolltime; // For autoscroll rate-limiting wcache cache; // Pixel cache wjc_expose_f expose; // Drawing function gpointer udata; // Link to slot } wjcanvas; typedef struct { GtkWidgetClass parent_class; } wjcanvasClass; G_DEFINE_TYPE_WITH_CODE(wjcanvas, wjcanvas, GTK_TYPE_WIDGET, G_IMPLEMENT_INTERFACE(GTK_TYPE_SCROLLABLE, NULL)) static gboolean wjcanvas_draw(GtkWidget *widget, cairo_t *cr) { wjcanvas *canvas = WJCANVAS(widget); cairo_region_t *clip; cairo_rectangle_list_t *rl; cairo_rectangle_int_t re; wcache ncache; int i; doom_tick = 0; // Redraw is happening /* Check if anything useful remains in cache */ if (canvas->r) { cairo_rectangle_int_t vport = { canvas->xy[0], canvas->xy[1], canvas->xy[2] - canvas->xy[0], canvas->xy[3] - canvas->xy[1] }; cairo_region_intersect_rectangle(canvas->r, &vport); if (cairo_region_is_empty(canvas->r)) { cairo_region_destroy(canvas->r); canvas->r = NULL; } } /* Check if need a new cache */ if (wcache_check(&canvas->cache, canvas->xy, !canvas->r)) { wcache_init(&ncache, canvas->xy, gtk_widget_get_window(widget)); // Create it wcache_move(&ncache, &canvas->cache); // Move contents if needed canvas->cache = ncache; } /* Convert clip to image-space region */ clip = cairo_region_create(); rl = cairo_copy_clip_rectangle_list(cr); if (rl->status != CAIRO_STATUS_SUCCESS) // Paranoia fallback { // The two rectangle types documented as identical in GTK+3 docs if (gdk_cairo_get_clip_rectangle(cr, (GdkRectangle*)&re)) cairo_region_union_rectangle(clip, &re); } else for (i = 0; i < rl->num_rectangles; i++) { cairo_rectangle_t *rd = rl->rectangles + i; // GTK+3 assumes the values are converted ints re.x = rd->x; re.y = rd->y; re.width = rd->width; re.height = rd->height; cairo_region_union_rectangle(clip, &re); } cairo_rectangle_list_destroy(rl); cairo_region_translate(clip, canvas->xy[0], canvas->xy[1]); /* Check if we need draw anything anew */ if (canvas->r) cairo_region_subtract(clip, canvas->r); if (!cairo_region_is_empty(clip) && canvas->expose) // Do nothing if unset canvas->expose((GtkWidget *)canvas, clip, canvas->udata); cairo_region_destroy(clip); wcache_render(&canvas->cache, cr); return (FALSE); } static void wjcanvas_send_configure(GtkWidget *widget, GtkAllocation *alloc) { GdkEvent *event = gdk_event_new(GDK_CONFIGURE); event->configure.window = g_object_ref(gtk_widget_get_window(widget)); event->configure.send_event = TRUE; event->configure.x = alloc->x; event->configure.y = alloc->y; event->configure.width = alloc->width; event->configure.height = alloc->height; gtk_widget_event(widget, event); gdk_event_free(event); } static void wjcanvas_realize(GtkWidget *widget) { // static const GdkRGBA black = { 0, 0, 0, 0 }; GdkWindow *win; GdkWindowAttr attrs; GtkAllocation alloc; gtk_widget_set_realized(widget, TRUE); gtk_widget_get_allocation(widget, &alloc); attrs.x = alloc.x; attrs.y = alloc.y; attrs.width = alloc.width; attrs.height = alloc.height; attrs.window_type = GDK_WINDOW_CHILD; attrs.wclass = GDK_INPUT_OUTPUT; attrs.visual = gtk_widget_get_visual(widget); /* !!! GtkViewport also sets GDK_TOUCH_MASK and GDK_SMOOTH_SCROLL_MASK, * but the latter blocks non-smooth scroll events if device sends * smooth ones, and the former, I do not (yet?) handle anyway - WJ */ attrs.event_mask = gtk_widget_get_events(widget) | GDK_SCROLL_MASK; /* !!! GDK_EXPOSURE_MASK seems really not be needed (as advertised), * despite GtkDrawingArea still having it */ win = gdk_window_new(gtk_widget_get_parent_window(widget), &attrs, GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL); /* !!! Versions without this (below 3.12) are useless */ gdk_window_set_event_compression(win, FALSE); gtk_widget_register_window(widget, win); gtk_widget_set_window(widget, win); // gdk_window_set_background_rgba(win, &black); // !!! In hope this (parent's bkg) isn't drawn twice gdk_window_set_background_pattern(win, NULL); /* Replicate behaviour of GtkDrawingCanvas */ wjcanvas_send_configure(widget, &alloc); } static int wjcanvas_readjust(wjcanvas *canvas, int which, GtkAllocation *alloc) { GtkAdjustment *adj = canvas->adjustments[which]; int sz, wp; double oldv, newv; oldv = gtk_adjustment_get_value(adj); wp = which ? alloc->height : alloc->width; sz = canvas->size[which]; if (sz < wp) sz = wp; newv = oldv < 0.0 ? 0.0 : oldv > sz - wp ? sz - wp : oldv; gtk_adjustment_configure(adj, newv, 0, sz, wp * 0.1, wp * 0.9, wp); return (newv != oldv); } static void wjcanvas_set_extents(wjcanvas *canvas, GtkAllocation *alloc) { canvas->xy[2] = alloc->width + (canvas->xy[0] = (int)rint(gtk_adjustment_get_value(canvas->adjustments[0]))); canvas->xy[3] = alloc->height + (canvas->xy[1] = (int)rint(gtk_adjustment_get_value(canvas->adjustments[1]))); } static void wjcanvas_size_allocate(GtkWidget *widget, GtkAllocation *allocation) { wjcanvas *canvas = WJCANVAS(widget); GtkAllocation alloc0; int conf; /* Don't send useless configure events */ gtk_widget_get_allocation(widget, &alloc0); conf = canvas->resize | (allocation->width ^ alloc0.width) | (allocation->height ^ alloc0.height); canvas->resizing = canvas->resize; canvas->resize = FALSE; gtk_widget_set_allocation(widget, allocation); g_object_freeze_notify(G_OBJECT(canvas->adjustments[0])); g_object_freeze_notify(G_OBJECT(canvas->adjustments[1])); wjcanvas_readjust(canvas, 0, allocation); wjcanvas_readjust(canvas, 1, allocation); wjcanvas_set_extents(canvas, allocation); if (gtk_widget_get_realized(widget)) { /* In GTK+3 this'll do whole window redraw for any change */ gdk_window_move_resize(gtk_widget_get_window(widget), allocation->x, allocation->y, allocation->width, allocation->height); /* Replicate behaviour of GtkDrawingCanvas */ if (conf) wjcanvas_send_configure(widget, allocation); } g_object_thaw_notify(G_OBJECT(canvas->adjustments[0])); g_object_thaw_notify(G_OBJECT(canvas->adjustments[1])); canvas->resizing = FALSE; } static void wjcanvas_get_preferred_width(GtkWidget *widget, gint *min, gint *nat) { *min = 1; *nat = WJCANVAS(widget)->size[0]; } static void wjcanvas_get_preferred_height(GtkWidget *widget, gint *min, gint *nat) { *min = 1; *nat = WJCANVAS(widget)->size[1]; } #if 0 /* Direct descendants of GtkWidget can let it redirect these two */ static void wjcanvas_get_preferred_width_for_height(GtkWidget *widget, gint h, gint *min, gint *nat) { *min = 1; *nat = WJCANVAS(widget)->size[0]; } static void wjcanvas_get_preferred_height_for_width(GtkWidget *widget, gint w, gint *min, gint *nat) { *min = 1; *nat = WJCANVAS(widget)->size[1]; } #endif /* We do scrolling in both directions at once if possible, to avoid ultimately * useless repaint ops and associated flickers - WJ */ static void wjcanvas_adjustment_value_changed(GtkAdjustment *adjustment, gpointer data) { GtkWidget *widget = data; wjcanvas *canvas = data; GtkAllocation alloc; int oxy[4]; if (!GTK_IS_ADJUSTMENT(adjustment) || !IS_WJCANVAS(data)) return; gtk_widget_get_allocation(widget, &alloc); copy4(oxy, canvas->xy); wjcanvas_set_extents(data, &alloc); // Set new window extents /* No scrolling in GTK+3, rely on caching */ if (!gtk_widget_get_mapped(widget)) return; if ((oxy[0] ^ canvas->xy[0]) | (oxy[1] ^ canvas->xy[1])) // If moved gtk_widget_queue_draw(widget); } static void wjcanvas_drop_adjustment(wjcanvas *canvas, int which) { GtkAdjustment **slot = canvas->adjustments + which; if (!*slot) return; g_signal_handlers_disconnect_by_func(*slot, wjcanvas_adjustment_value_changed, canvas); g_object_unref(*slot); *slot = NULL; } static GtkAdjustment *wjcanvas_prepare_adjustment(wjcanvas *canvas, int which, GtkAdjustment *adjustment) { GtkAdjustment **slot = canvas->adjustments + which; if (adjustment && (adjustment == *slot)) return (NULL); // Leave alone if (!adjustment) adjustment = gtk_adjustment_new(0, 0, 0, 0, 0, 0); wjcanvas_drop_adjustment(canvas, which); g_object_ref_sink(*slot = adjustment); g_signal_connect(adjustment, "value-changed", G_CALLBACK(wjcanvas_adjustment_value_changed), canvas); return (adjustment); } static void wjcanvas_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { if ((prop_id == P_HADJ) || (prop_id == P_VADJ)) { wjcanvas *canvas = WJCANVAS(object); GtkAllocation alloc; GtkAdjustment *adj; int which = prop_id - P_HADJ; gtk_widget_get_allocation(GTK_WIDGET(canvas), &alloc); adj = wjcanvas_prepare_adjustment( canvas, which, g_value_get_object(value)); if (adj && !wjcanvas_readjust(canvas, which, &alloc)) wjcanvas_adjustment_value_changed(adj, canvas); // Readjust anyway } // !!! React to "*scroll-policy" as an invalid ID if trying to set else G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); } static void wjcanvas_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { wjcanvas *canvas = WJCANVAS(object); if ((prop_id == P_HADJ) || (prop_id == P_VADJ)) g_value_set_object(value, canvas->adjustments[prop_id - P_HADJ]); else if ((prop_id == P_HSCP) || (prop_id == P_VSCP)) g_value_set_enum(value, GTK_SCROLL_NATURAL); else G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); } static void wjcanvas_drop_cache(wjcanvas *canvas) { cairo_region_destroy(canvas->r); canvas->r = NULL; if (canvas->cache.s) { cairo_surface_fdestroy(canvas->cache.s); canvas->cache.s = NULL; } } static void wjcanvas_scale_change(GObject *object, GParamSpec *pspec, gpointer user_data) { wjcanvas *canvas = WJCANVAS(object); if (canvas->cache.s && (canvas->cache.scale != gtk_widget_get_scale_factor(GTK_WIDGET(canvas)))) wjcanvas_drop_cache(canvas); } static void wjcanvas_unmap(GtkWidget *widget) { wjcanvas *canvas = WJCANVAS(widget); GTK_WIDGET_CLASS(wjcanvas_parent_class)->unmap(widget); wjcanvas_drop_cache(canvas); } static void wjcanvas_destroy(GtkWidget *widget) { wjcanvas *canvas = WJCANVAS(widget); wjcanvas_drop_adjustment(canvas, 0); wjcanvas_drop_adjustment(canvas, 1); wjcanvas_drop_cache(canvas); GTK_WIDGET_CLASS(wjcanvas_parent_class)->destroy(widget); } static void wjcanvas_class_init(wjcanvasClass *class) { GtkWidgetClass *wclass = GTK_WIDGET_CLASS(class); GObjectClass *oclass = G_OBJECT_CLASS(class); oclass->set_property = wjcanvas_set_property; oclass->get_property = wjcanvas_get_property; wclass->destroy = wjcanvas_destroy; wclass->realize = wjcanvas_realize; wclass->unmap = wjcanvas_unmap; wclass->draw = wjcanvas_draw; wclass->size_allocate = wjcanvas_size_allocate; wclass->get_preferred_width = wjcanvas_get_preferred_width; wclass->get_preferred_height = wjcanvas_get_preferred_height; /* Default handlers in GtkWidget redirect these two anyway */ // wclass->get_preferred_width_for_height = wjcanvas_get_preferred_width_for_height; // wclass->get_preferred_height_for_width = wjcanvas_get_preferred_height_for_width; /* !!! Do not disturb my circles */ wclass->style_updated = NULL; g_object_class_override_property(oclass, P_HADJ, "hadjustment"); g_object_class_override_property(oclass, P_VADJ, "vadjustment"); g_object_class_override_property(oclass, P_HSCP, "hscroll-policy"); g_object_class_override_property(oclass, P_VSCP, "vscroll-policy"); } static void wjcanvas_init(wjcanvas *canvas) { gtk_widget_set_has_window(GTK_WIDGET(canvas), TRUE); gtk_widget_set_redraw_on_allocate(GTK_WIDGET(canvas), FALSE); /* Ensure 1x1 at least */ canvas->size[0] = canvas->size[1] = 1; /* Install fake adjustments */ canvas->adjustments[0] = canvas->adjustments[1] = NULL; wjcanvas_prepare_adjustment(canvas, 0, NULL); wjcanvas_prepare_adjustment(canvas, 1, NULL); /* No cached things yet */ canvas->r = NULL; /* And no cache, too */ memset(&canvas->cache, 0, sizeof(canvas->cache)); /* Track scale */ g_signal_connect(canvas, "notify::scale-factor", G_CALLBACK(wjcanvas_scale_change), NULL); } void wjcanvas_draw_rgb(GtkWidget *widget, int x, int y, int w, int h, unsigned char *rgb, int step, int fill, int repaint) { wjcanvas *canvas; wcache *cache; cairo_surface_t *s = NULL; cairo_t *cr; cairo_rectangle_int_t re; int y1, x1, rxy[4]; if (!IS_WJCANVAS(widget)) return; canvas = WJCANVAS(widget); cache = &canvas->cache; if (!cache->s) return; // Not visible yet, draw it later if (!clip(rxy, x, y, x + w, y + h, cache->xy)) return; if (rgb) s = cairo_upload_rgb(cache->s, NULL, rgb + (rxy[1] - y) * step + (rxy[0] - x) * 3, rxy[2] - rxy[0], rxy[3] - rxy[1], step); /* Find out whether area wraps around on X */ x = (cache->dx + rxy[0] - cache->xy[0]) % cache->w; w = rxy[2] - rxy[0]; x1 = (x + w) % cache->w; if (x1 < w) w -= x1; else x1 = 0; /* Same thing on Y */ y = (cache->dy + rxy[1] - cache->xy[1]) % cache->h; h = rxy[3] - rxy[1]; y1 = (y + h) % cache->h; if (y1 < h) h -= y1; else y1 = 0; cr = cairo_create(cache->s); cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); if (!s) cairo_set_rgb(cr, fill); // If no bitmap, fill by color /* Paint the area into cache, in up to 4 pieces */ if (s) cairo_set_source_surface(cr, s, x, y); cairo_unfilter(cr); cairo_rectangle(cr, x, y, w, h); cairo_fill(cr); if (y1) { if (s) { cairo_set_source_surface(cr, s, x, -h); cairo_unfilter(cr); } cairo_rectangle(cr, x, 0, w, y1); cairo_fill(cr); } if (x1) { if (s) { cairo_set_source_surface(cr, s, -w, y); cairo_unfilter(cr); } cairo_rectangle(cr, 0, y, x1, h); cairo_fill(cr); if (y1) { if (s) { cairo_set_source_surface(cr, s, -w, -h); cairo_unfilter(cr); } cairo_rectangle(cr, 0, 0, x1, y1); cairo_fill(cr); } } cairo_destroy(cr); if (s) cairo_surface_fdestroy(s); /* Remember this part is up to date */ if (!canvas->r) canvas->r = cairo_region_create(); re.width = rxy[2] - (re.x = rxy[0]); re.height = rxy[3] - (re.y = rxy[1]); cairo_region_union_rectangle(canvas->r, &re); /* Invalidate part of window if asked to */ if (repaint) { re.x -= canvas->xy[0]; re.y -= canvas->xy[1]; // The two rectangle types documented as identical in GTK+3 docs gdk_window_invalidate_rect(gtk_widget_get_window(widget), (GdkRectangle*)&re, FALSE); doom_tick |= 1; // Awaiting redraw } } void wjcanvas_redraw(GtkWidget *widget, int *rxy) { wjcanvas *canvas = WJCANVAS(widget); int wxy[4]; if (!canvas->r); // Nothing in cache else if (!rxy) // Total clear { cairo_region_destroy(canvas->r); canvas->r = NULL; } else // Partial clear { cairo_rectangle_int_t re = { rxy[0], rxy[1], rxy[2] - rxy[0], rxy[3] - rxy[1] }; cairo_region_subtract_rectangle(canvas->r, &re); } if (!rxy) gtk_widget_queue_draw(widget); else if (!clip(wxy, rxy[0], rxy[1], rxy[2], rxy[3], canvas->xy)) return; else gtk_widget_queue_draw_area(widget, wxy[0] - canvas->xy[0], wxy[1] - canvas->xy[1], wxy[2] - wxy[0], wxy[3] - wxy[1]); doom_tick |= 1; // Awaiting redraw } void wjcanvas_set_expose(GtkWidget *widget, GCallback handler, gpointer user_data) { wjcanvas *canvas; if (!IS_WJCANVAS(widget)) return; canvas = WJCANVAS(widget); canvas->expose = (wjc_expose_f)handler; canvas->udata = user_data; } void wjcanvas_size(GtkWidget *widget, int width, int height) { wjcanvas *canvas; if (!IS_WJCANVAS(widget)) return; canvas = WJCANVAS(widget); if ((canvas->size[0] == width) && (canvas->size[1] == height)) return; canvas->size[0] = width; canvas->size[1] = height; canvas->resize = TRUE; /* Forget cached rectangles */ cairo_region_destroy(canvas->r); canvas->r = NULL; gtk_widget_queue_resize(widget); } static int wjcanvas_offset(GtkAdjustment *adj, int dv) { double nv, up, v; int step, dw = dv; step = (int)(gtk_adjustment_get_step_increment(adj) + 0.5); if (step) { dw = abs(dw) + step - 1; dw -= dw % step; if (dv < 0) dw = -dw; } up = gtk_adjustment_get_upper(adj) - gtk_adjustment_get_page_size(adj); nv = (v = gtk_adjustment_get_value(adj)) + dw; if (nv > up) nv = up; if (nv < 0.0) nv = 0.0; gtk_adjustment_set_value(adj, nv); return (v != nv); } int wjcanvas_scroll_in(GtkWidget *widget, int x, int y) { wjcanvas *canvas = WJCANVAS(widget); int dx = 0, dy = 0; if (!canvas->adjustments[0] || !canvas->adjustments[1]) return (FALSE); if (x < canvas->xy[0]) dx = (x < 0 ? 0 : x) - canvas->xy[0]; else if (x >= canvas->xy[2]) dx = (x >= canvas->size[0] ? canvas->size[0] : x + 1) - canvas->xy[2]; if (y < canvas->xy[1]) dy = (y < 0 ? 0 : y) - canvas->xy[1]; else if (y >= canvas->xy[3]) dy = (y >= canvas->size[1] ? canvas->size[1] : y + 1) - canvas->xy[3]; if (!(dx | dy)) return (FALSE); g_object_freeze_notify(G_OBJECT(canvas->adjustments[0])); g_object_freeze_notify(G_OBJECT(canvas->adjustments[1])); dx = wjcanvas_offset(canvas->adjustments[0], dx); dy = wjcanvas_offset(canvas->adjustments[1], dy); g_object_thaw_notify(G_OBJECT(canvas->adjustments[0])); g_object_thaw_notify(G_OBJECT(canvas->adjustments[1])); return (dx | dy); } #define WJCANVAS_SCROLL_LIMIT 333 /* 3 steps/second */ /* If mouse moved outside canvas, scroll canvas & warp cursor back in */ int wjcanvas_bind_mouse(GtkWidget *widget, GdkEventMotion *event, int x, int y) { wjcanvas *canvas = WJCANVAS(widget); int oldv[4]; copy4(oldv, canvas->xy); x += oldv[0]; y += oldv[1]; if ((x >= oldv[0]) && (x < oldv[2]) && (y >= oldv[1]) && (y < oldv[3])) return (FALSE); /* Limit scrolling rate for absolute pointing devices */ if ((gdk_device_get_source(event->device) != GDK_SOURCE_MOUSE) && (event->time < canvas->scrolltime + WJCANVAS_SCROLL_LIMIT)) return (FALSE); if (!wjcanvas_scroll_in(widget, x, y)) return (FALSE); canvas->scrolltime = event->time; return (move_mouse_relative(oldv[0] - canvas->xy[0], oldv[1] - canvas->xy[1])); } #else /* if GTK_MAJOR_VERSION <= 2 */ #define WJCANVAS(obj) GTK_CHECK_CAST(obj, wjcanvas_get_type(), wjcanvas) #define IS_WJCANVAS(obj) GTK_CHECK_TYPE(obj, wjcanvas_get_type()) typedef struct { GtkWidget widget; // Parent class GtkAdjustment *adjustments[2]; GdkGC *scroll_gc; // For scrolling in GTK+1 int xy[4]; // Viewport int size[2]; // Requested (virtual) size int resize; // Resize was requested int resizing; // Requested resize is happening guint32 scrolltime; // For autoscroll rate-limiting } wjcanvas; typedef struct { GtkWidgetClass parent_class; void (*set_scroll_adjustments)(wjcanvas *canvas, GtkAdjustment *hadjustment, GtkAdjustment *vadjustment); } wjcanvasClass; static GtkWidgetClass *widget_class; static GtkType wjcanvas_type; static GtkType wjcanvas_get_type(); static void wjcanvas_send_configure(GtkWidget *widget) { #if GTK2VERSION >= 2 /* GTK+ 2.2+ */ GdkEvent *event = gdk_event_new(GDK_CONFIGURE); event->configure.window = g_object_ref(widget->window); event->configure.send_event = TRUE; event->configure.x = widget->allocation.x; event->configure.y = widget->allocation.y; event->configure.width = widget->allocation.width; event->configure.height = widget->allocation.height; gtk_widget_event(widget, event); gdk_event_free(event); #else /* GTK+ 1.x or 2.0 */ GdkEventConfigure event; event.type = GDK_CONFIGURE; event.window = widget->window; event.send_event = TRUE; event.x = widget->allocation.x; event.y = widget->allocation.y; event.width = widget->allocation.width; event.height = widget->allocation.height; gdk_window_ref(event.window); gtk_widget_event(widget, (GdkEvent *)&event); gdk_window_unref(event.window); #endif } static void wjcanvas_realize(GtkWidget *widget) { GdkWindowAttr attrs; GTK_WIDGET_SET_FLAGS(widget, GTK_REALIZED); attrs.x = widget->allocation.x; attrs.y = widget->allocation.y; attrs.width = widget->allocation.width; attrs.height = widget->allocation.height; attrs.window_type = GDK_WINDOW_CHILD; attrs.wclass = GDK_INPUT_OUTPUT; attrs.visual = gtk_widget_get_visual(widget); attrs.colormap = gtk_widget_get_colormap(widget); // Add the same events as GtkViewport does attrs.event_mask = gtk_widget_get_events(widget) | GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK; widget->window = gdk_window_new(gtk_widget_get_parent_window(widget), &attrs, GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP); gdk_window_set_user_data(widget->window, widget); #if GTK_MAJOR_VERSION == 1 fix_gdk_events(widget->window); WJCANVAS(widget)->scroll_gc = gdk_gc_new(widget->window); gdk_gc_set_exposures(WJCANVAS(widget)->scroll_gc, TRUE); #endif widget->style = gtk_style_attach(widget->style, widget->window); gdk_window_set_back_pixmap(widget->window, NULL, FALSE); /* Replicate behaviour of GtkDrawingCanvas */ wjcanvas_send_configure(widget); } #if GTK_MAJOR_VERSION == 1 static void wjcanvas_unrealize(GtkWidget *widget) { wjcanvas *canvas = WJCANVAS(widget); gdk_gc_destroy(canvas->scroll_gc); canvas->scroll_gc = NULL; if (widget_class->unrealize) widget_class->unrealize(widget); } #endif static int wjcanvas_readjust(wjcanvas *canvas, int which) { GtkWidget *widget = GTK_WIDGET(canvas); GtkAdjustment *adj = canvas->adjustments[which]; int sz, wp; double oldv, newv; oldv = adj->value; wp = which ? widget->allocation.height : widget->allocation.width; sz = canvas->size[which]; if (sz < wp) sz = wp; adj->page_size = wp; adj->step_increment = wp * 0.1; adj->page_increment = wp * 0.9; adj->lower = 0; adj->upper = sz; adj->value = newv = oldv < 0.0 ? 0.0 : oldv > sz - wp ? sz - wp : oldv; return (newv != oldv); } static void wjcanvas_set_extents(wjcanvas *canvas) { GtkWidget *widget = GTK_WIDGET(canvas); canvas->xy[2] = (canvas->xy[0] = ADJ2INT(canvas->adjustments[0])) + widget->allocation.width; canvas->xy[3] = (canvas->xy[1] = ADJ2INT(canvas->adjustments[1])) + widget->allocation.height; } #if GTK_MAJOR_VERSION == 1 static void wjcanvas_send_expose(GtkWidget *widget, int x, int y, int w, int h) { GdkEventExpose event; event.type = GDK_EXPOSE; event.send_event = TRUE; event.window = widget->window; event.area.x = x; event.area.y = y; event.area.width = w; event.area.height = h; event.count = 0; gdk_window_ref(event.window); gtk_widget_event(widget, (GdkEvent *)&event); gdk_window_unref(event.window); } #endif static void wjcanvas_scroll(GtkWidget *widget, int *oxy) { wjcanvas *canvas = WJCANVAS(widget); int nxy[4], rxy[4], fulldraw; if (!GTK_WIDGET_DRAWABLE(widget)) return; // No use if (canvas->resizing) return; // No reason copy4(nxy, canvas->xy); if (!((oxy[0] ^ nxy[0]) | (oxy[1] ^ nxy[1]))) return; // No scrolling /* Scroll or redraw? */ fulldraw = !clip(rxy, nxy[0], nxy[1], nxy[2], nxy[3], oxy); #if GTK_MAJOR_VERSION == 1 /* Check for resize - GTK+1 operates with ForgetGravity */ if ((oxy[2] - oxy[0] - nxy[2] + nxy[0]) | (oxy[3] - oxy[1] - nxy[3] + nxy[1])) return; // A full expose event should be queued anyway /* Check for in-flight draw ops */ if (GTK_WIDGET_FULLDRAW_PENDING(widget)) return; fulldraw |= GTK_WIDGET_REDRAW_PENDING(widget); // Updating draws in queue might be possible, but sure is insanely hard #endif if (fulldraw) gtk_widget_queue_draw(widget); // Just redraw everything else // Scroll { #if GTK_MAJOR_VERSION == 1 GdkEvent *event; gdk_window_copy_area(widget->window, canvas->scroll_gc, rxy[0] - nxy[0], rxy[1] - nxy[1], widget->window, rxy[0] - oxy[0], rxy[1] - oxy[1], rxy[2] - rxy[0], rxy[3] - rxy[1]); /* Have to process GraphicsExpose events before next scrolling */ while ((event = gdk_event_get_graphics_expose(widget->window))) { gtk_widget_event(widget, event); if (event->expose.count == 0) { gdk_event_free(event); break; } gdk_event_free(event); } /* Now draw the freed-up part(s) */ if (rxy[1] > nxy[1]) wjcanvas_send_expose(widget, 0, 0, nxy[2] - nxy[0], rxy[1] - nxy[1]); if (rxy[3] < nxy[3]) wjcanvas_send_expose(widget, 0, rxy[3] - nxy[1], nxy[2] - nxy[0], nxy[3] - rxy[3]); if (rxy[0] > nxy[0]) wjcanvas_send_expose(widget, 0, rxy[1] - nxy[1], rxy[0] - nxy[0], rxy[3] - rxy[1]); if (rxy[2] < nxy[2]) wjcanvas_send_expose(widget, rxy[2] - nxy[0], rxy[1] - nxy[1], nxy[2] - rxy[2], rxy[3] - rxy[1]); #elif defined GDK_WINDOWING_WIN32 /* !!! On Windows, gdk_window_scroll() had been badly broken in * GTK+ 2.6.5, then fixed in 2.8.10, but with changed behaviour * with regard to screen updates. * Unlike all that, my own window scrolling code here behaves * consistently :-) - WJ */ GdkRegion *tmp; int dx = oxy[0] - nxy[0], dy = oxy[1] - nxy[1]; /* Adjust the pending update region, let system add the rest * through WM_PAINT (but, in Wine WM_PAINTs can lag behind) */ if ((tmp = gdk_window_get_update_area(widget->window))) { gdk_region_offset(tmp, dx, dy); gdk_window_invalidate_region(widget->window, tmp, FALSE); gdk_region_destroy(tmp); } /* Tell Windows to scroll window AND send us invalidations */ ScrollWindowEx(GDK_WINDOW_HWND(widget->window), dx, dy, NULL, NULL, NULL, NULL, SW_INVALIDATE); /* Catch the invalidations; this cures Wine, while on Windows * just improves render consistency a bit. * And needs by-region expose to not waste a lot of work - WJ */ while (TRUE) { GdkEvent *event = gdk_event_get_graphics_expose(widget->window); if (!event) break; /* !!! The above function is buggy in GTK+2/Win32: it * doesn't ref the window, so we must do it here - WJ */ gdk_window_ref(widget->window); gdk_window_invalidate_region(widget->window, event->expose.region, FALSE); gdk_event_free(event); } /* And tell GTK+ to redraw it */ gdk_window_process_updates(widget->window, FALSE); #else gdk_window_scroll(widget->window, oxy[0] - nxy[0], oxy[1] - nxy[1]); #endif } /* !!! _Maybe_ we need gdk_window_process_updates(widget->window, FALSE) here * in GTK+2 - but then, maybe we don't; only practice will tell. * Rule of thumb is, you need atrociously slow render to make forced updates * useful - otherwise, they just create a slowdown. - WJ */ } static void wjcanvas_size_allocate(GtkWidget *widget, GtkAllocation *allocation) { wjcanvas *canvas = WJCANVAS(widget); int hchg, vchg, conf, oxy[4]; /* Don't send useless configure events */ conf = canvas->resize | (allocation->width ^ widget->allocation.width) | (allocation->height ^ widget->allocation.height); canvas->resizing = canvas->resize; canvas->resize = FALSE; copy4(oxy, canvas->xy); widget->allocation = *allocation; hchg = wjcanvas_readjust(canvas, 0); vchg = wjcanvas_readjust(canvas, 1); wjcanvas_set_extents(canvas); if (GTK_WIDGET_REALIZED(widget)) { gdk_window_move_resize(widget->window, allocation->x, allocation->y, allocation->width, allocation->height); wjcanvas_scroll(widget, oxy); /* Replicate behaviour of GtkDrawingCanvas */ if (conf) wjcanvas_send_configure(widget); } gtk_adjustment_changed(canvas->adjustments[0]); gtk_adjustment_changed(canvas->adjustments[1]); if (hchg) gtk_adjustment_value_changed(canvas->adjustments[0]); if (vchg) gtk_adjustment_value_changed(canvas->adjustments[1]); canvas->resizing = FALSE; } /* We do scrolling in both directions at once if possible, to avoid ultimately * useless repaint ops and associated flickers - WJ */ static void wjcanvas_adjustment_value_changed(GtkAdjustment *adjustment, gpointer data) { GtkWidget *widget = data; wjcanvas *canvas; int oxy[4]; if (!GTK_IS_ADJUSTMENT(adjustment) || !IS_WJCANVAS(data)) return; canvas = WJCANVAS(data); copy4(oxy, canvas->xy); wjcanvas_set_extents(canvas); // Set new window extents wjcanvas_scroll(widget, oxy); } static void wjcanvas_drop_adjustment(wjcanvas *canvas, int which) { GtkAdjustment **slot = canvas->adjustments + which; if (*slot) { GtkObject *adj = GTK_OBJECT(*slot); gtk_signal_disconnect_by_func(adj, GTK_SIGNAL_FUNC(wjcanvas_adjustment_value_changed), canvas); gtk_object_unref(adj); *slot = NULL; } } static GtkAdjustment *wjcanvas_prepare_adjustment(wjcanvas *canvas, GtkAdjustment *adjustment) { GtkObject *adj; if (!adjustment) adjustment = GTK_ADJUSTMENT(gtk_adjustment_new(0, 0, 0, 0, 0, 0)); adj = GTK_OBJECT(adjustment); gtk_object_ref(adj); gtk_object_sink(adj); gtk_signal_connect(adj, "value_changed", GTK_SIGNAL_FUNC(wjcanvas_adjustment_value_changed), (gpointer)canvas); return (adjustment); } static void wjcanvas_set_adjustment(wjcanvas *canvas, int which, GtkAdjustment *adjustment) { int changed; wjcanvas_drop_adjustment(canvas, which); adjustment = wjcanvas_prepare_adjustment(canvas, adjustment); canvas->adjustments[which] = adjustment; changed = wjcanvas_readjust(canvas, which); gtk_adjustment_changed(adjustment); if (changed) gtk_adjustment_value_changed(adjustment); else wjcanvas_adjustment_value_changed(adjustment, canvas); // Readjust anyway } static void wjcanvas_set_scroll_adjustments(wjcanvas *canvas, GtkAdjustment *hadjustment, GtkAdjustment *vadjustment) { if (canvas->adjustments[0] != hadjustment) wjcanvas_set_adjustment(canvas, 0, hadjustment); if (canvas->adjustments[1] != vadjustment) wjcanvas_set_adjustment(canvas, 1, vadjustment); } static void wjcanvas_destroy(GtkObject *object) { wjcanvas *canvas = WJCANVAS(object); wjcanvas_drop_adjustment(canvas, 0); wjcanvas_drop_adjustment(canvas, 1); GTK_OBJECT_CLASS(widget_class)->destroy(object); } static void wjcanvas_class_init(wjcanvasClass *class) { GtkWidgetClass *wclass = GTK_WIDGET_CLASS(class); widget_class = gtk_type_class(GTK_TYPE_WIDGET); GTK_OBJECT_CLASS(class)->destroy = wjcanvas_destroy; wclass->realize = wjcanvas_realize; #if GTK_MAJOR_VERSION == 1 wclass->unrealize = wjcanvas_unrealize; #endif wclass->size_allocate = wjcanvas_size_allocate; // !!! Default "style_set" handler can reenable background clear wclass->style_set = NULL; class->set_scroll_adjustments = wjcanvas_set_scroll_adjustments; wclass->set_scroll_adjustments_signal = gtk_signal_new( "set_scroll_adjustments", GTK_RUN_LAST, wjcanvas_type, GTK_SIGNAL_OFFSET(wjcanvasClass, set_scroll_adjustments), gtk_marshal_NONE__POINTER_POINTER, GTK_TYPE_NONE, 2, GTK_TYPE_ADJUSTMENT, GTK_TYPE_ADJUSTMENT); } static void wjcanvas_init(wjcanvas *canvas) { GTK_WIDGET_UNSET_FLAGS(canvas, GTK_NO_WINDOW); #if GTK_MAJOR_VERSION == 2 GTK_WIDGET_UNSET_FLAGS(canvas, GTK_DOUBLE_BUFFERED); gtk_widget_set_redraw_on_allocate(GTK_WIDGET(canvas), FALSE); #endif /* Install fake adjustments */ canvas->adjustments[0] = wjcanvas_prepare_adjustment(canvas, NULL); canvas->adjustments[1] = wjcanvas_prepare_adjustment(canvas, NULL); } static GtkType wjcanvas_get_type() { if (!wjcanvas_type) { static const GtkTypeInfo wjcanvas_info = { "wjCanvas", sizeof(wjcanvas), sizeof(wjcanvasClass), (GtkClassInitFunc)wjcanvas_class_init, (GtkObjectInitFunc)wjcanvas_init, NULL, NULL, NULL }; wjcanvas_type = gtk_type_unique(GTK_TYPE_WIDGET, &wjcanvas_info); } return (wjcanvas_type); } void wjcanvas_redraw(GtkWidget *widget, int *rxy) { wjcanvas *canvas = WJCANVAS(widget); int wxy[4]; if (!rxy) gtk_widget_queue_draw(widget); else if (clip(wxy, rxy[0], rxy[1], rxy[2], rxy[3], canvas->xy)) gtk_widget_queue_draw_area(widget, wxy[0] - canvas->xy[0], wxy[1] - canvas->xy[1], wxy[2] - wxy[0], wxy[3] - wxy[1]); } void wjcanvas_set_expose(GtkWidget *widget, GtkSignalFunc handler, gpointer user_data) { gtk_signal_connect(GTK_OBJECT(widget), "expose_event", handler, user_data); } void wjcanvas_size(GtkWidget *widget, int width, int height) { wjcanvas *canvas; if (!IS_WJCANVAS(widget)) return; canvas = WJCANVAS(widget); if ((canvas->size[0] == width) && (canvas->size[1] == height)) return; canvas->size[0] = width; canvas->size[1] = height; canvas->resize = TRUE; #if GTK_MAJOR_VERSION == 1 /* !!! The fields are limited to 16-bit signed, and the values aren't */ widget->requisition.width = MIN(width, 32767); widget->requisition.height = MIN(height, 32767); #else /* if GTK_MAJOR_VERSION == 2 */ widget->requisition.width = width; widget->requisition.height = height; #endif gtk_widget_queue_resize(widget); } static int wjcanvas_offset(GtkAdjustment *adj, int dv) { double nv, up; int step, dw = dv; step = (int)(adj->step_increment + 0.5); if (step) { dw = abs(dw) + step - 1; dw -= dw % step; if (dv < 0) dw = -dw; } up = adj->upper - adj->page_size; nv = adj->value + dw; if (nv > up) nv = up; if (nv < 0.0) nv = 0.0; up = adj->value; adj->value = nv; return (up != nv); } int wjcanvas_scroll_in(GtkWidget *widget, int x, int y) { wjcanvas *canvas = WJCANVAS(widget); int dx = 0, dy = 0; if (!canvas->adjustments[0] || !canvas->adjustments[1]) return (FALSE); if (x < canvas->xy[0]) dx = (x < 0 ? 0 : x) - canvas->xy[0]; else if (x >= canvas->xy[2]) dx = (x >= canvas->size[0] ? canvas->size[0] : x + 1) - canvas->xy[2]; if (y < canvas->xy[1]) dy = (y < 0 ? 0 : y) - canvas->xy[1]; else if (y >= canvas->xy[3]) dy = (y >= canvas->size[1] ? canvas->size[1] : y + 1) - canvas->xy[3]; if (!(dx | dy)) return (FALSE); dx = wjcanvas_offset(canvas->adjustments[0], dx); dy = wjcanvas_offset(canvas->adjustments[1], dy); if (dx) gtk_adjustment_value_changed(canvas->adjustments[0]); if (dy) gtk_adjustment_value_changed(canvas->adjustments[1]); return (dx | dy); } #define WJCANVAS_SCROLL_LIMIT 333 /* 3 steps/second */ /* If mouse moved outside canvas, scroll canvas & warp cursor back in */ int wjcanvas_bind_mouse(GtkWidget *widget, GdkEventMotion *event, int x, int y) { wjcanvas *canvas = WJCANVAS(widget); int oldv[4]; copy4(oldv, canvas->xy); x += oldv[0]; y += oldv[1]; if ((x >= oldv[0]) && (x < oldv[2]) && (y >= oldv[1]) && (y < oldv[3])) return (FALSE); /* Limit scrolling rate for absolute pointing devices */ #if GTK_MAJOR_VERSION == 1 if ((event->source != GDK_SOURCE_MOUSE) && #else /* if GTK_MAJOR_VERSION == 2 */ if ((event->device->source != GDK_SOURCE_MOUSE) && #endif (event->time < canvas->scrolltime + WJCANVAS_SCROLL_LIMIT)) return (FALSE); if (!wjcanvas_scroll_in(widget, x, y)) return (FALSE); canvas->scrolltime = event->time; return (move_mouse_relative(oldv[0] - canvas->xy[0], oldv[1] - canvas->xy[1])); } #endif /* GTK+1&2 */ GtkWidget *wjcanvas_new() { return (gtk_widget_new(wjcanvas_get_type(), NULL)); } void wjcanvas_get_vport(GtkWidget *widget, int *vport) { copy4(vport, WJCANVAS(widget)->xy); } #if GTK_MAJOR_VERSION == 3 // Focusable pixmap widget (on Cairo surfaces, but whatever) #define WJPIXMAP(obj) G_TYPE_CHECK_INSTANCE_CAST(obj, wjpixmap_get_type(), wjpixmap) #define IS_WJPIXMAP(obj) G_TYPE_CHECK_INSTANCE_TYPE(obj, wjpixmap_get_type()) typedef struct { GtkWidget widget; // Parent class GdkWindow *pixwindow; cairo_surface_t *pixmap; cairo_surface_t *cursor; GdkRectangle pm, cr; // pm is allocation relative, unlike in GTK+1&2 int width, height; // Requested pixmap size int xc, yc; int focused_cursor; } wjpixmap; typedef struct { GtkWidgetClass parent_class; } wjpixmapClass; G_DEFINE_TYPE(wjpixmap, wjpixmap, GTK_TYPE_WIDGET) #define WJPIXMAP_FRAME 1 /* Line width, limited only by common sense */ static gboolean wjpixmap_draw(GtkWidget *widget, cairo_t *cr) { wjpixmap *pix = WJPIXMAP(widget); GtkStyleContext *ctx = gtk_widget_get_style_context(widget); GtkAllocation alloc; cairo_save(cr); gtk_widget_get_allocation(widget, &alloc); /* Outer window */ if (gtk_cairo_should_draw_window(cr, gtk_widget_get_window(widget))) { gtk_render_background(ctx, cr, 0, 0, alloc.width, alloc.height); // !!! Maybe render pixmap frame here: _before_ focus, as in GTK+1/2? /* Focus frame */ if (gtk_widget_has_visible_focus(widget)) { /* !!! Is inside-the-border the right place? */ GtkBorder border; get_padding_and_border(ctx, NULL, &border, NULL); gtk_render_focus(ctx, cr, border.left, border.top, alloc.width - border.left - border.right, alloc.height - border.top - border.bottom); } /* Pixmap frame */ cairo_set_line_width(cr, WJPIXMAP_FRAME); cairo_set_line_cap(cr, CAIRO_LINE_CAP_SQUARE); cairo_set_source_rgb(cr, 0, 0, 0); // Black cairo_rectangle(cr, pix->pm.x - WJPIXMAP_FRAME * 0.5, pix->pm.y - WJPIXMAP_FRAME * 0.5, pix->pm.width + WJPIXMAP_FRAME, pix->pm.height + WJPIXMAP_FRAME); cairo_stroke(cr); } /* Pixmap window */ while (gtk_cairo_should_draw_window(cr, pix->pixwindow)) { /* This widget may get moved to differently-scaled monitor while * retaining the buffer surfaces, so cairo_unfilter() to at least * prevent blurring if that happens */ gtk_cairo_transform_to_window(cr, widget, pix->pixwindow); cairo_set_source_surface(cr, pix->pixmap, 0, 0); cairo_unfilter(cr); cairo_rectangle(cr, 0, 0, pix->pm.width, pix->pm.height); // cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); cairo_fill(cr); // Hope Cairo won't waste much time on clipped-out parts /* Cursor pixmap */ if (!pix->cursor) break; if (pix->focused_cursor && !gtk_widget_has_focus(widget)) break; cairo_set_source_surface(cr, pix->cursor, pix->cr.x, pix->cr.y); cairo_unfilter(cr); // cairo_set_operator(cr, CAIRO_OPERATOR_OVER); cairo_rectangle(cr, pix->cr.x, pix->cr.y, pix->cr.width, pix->cr.height); cairo_fill(cr); // Hope Cairo won't waste time if outside of clip break; } cairo_restore(cr); return (FALSE); } static void wjpixmap_position(wjpixmap *pix, GtkAllocation *alloc) { int x, y, w, h; GtkBorder border; get_padding_and_border(gtk_widget_get_style_context(GTK_WIDGET(pix)), NULL, NULL, &border); x = alloc->width - border.left - border.right; pix->pm.width = w = pix->width <= x ? pix->width : x; pix->pm.x = (x - w) / 2 + border.left; y = alloc->height - border.top - border.bottom; pix->pm.height = h = pix->height <= y ? pix->height : y; pix->pm.y = (y - h) / 2 + border.top; } static void wjpixmap_realize(GtkWidget *widget) { wjpixmap *pix = WJPIXMAP(widget); GdkWindow *win; GdkWindowAttr attrs; GtkAllocation alloc; gtk_widget_set_realized(widget, TRUE); gtk_widget_get_allocation(widget, &alloc); win = gtk_widget_get_parent_window(widget); gtk_widget_set_window(widget, win); g_object_ref(win); wjpixmap_position(pix, &alloc); attrs.x = pix->pm.x + alloc.x; attrs.y = pix->pm.y + alloc.y; attrs.width = pix->pm.width; attrs.height = pix->pm.height; attrs.window_type = GDK_WINDOW_CHILD; attrs.wclass = GDK_INPUT_OUTPUT; attrs.visual = gtk_widget_get_visual(widget); // Add the same events as GtkEventBox does attrs.event_mask = gtk_widget_get_events(widget) | GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK; /* !!! GDK_EXPOSURE_MASK seems really not be needed (as advertised), * despite GtkDrawingArea still having it */ pix->pixwindow = win = gdk_window_new(win, &attrs, GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL); /* !!! Versions without this (below 3.12) are useless */ gdk_window_set_event_compression(win, FALSE); gtk_widget_register_window(widget, win); } static void wjpixmap_unrealize(GtkWidget *widget) { wjpixmap *pix = WJPIXMAP(widget); if (pix->pixwindow) { gtk_widget_unregister_window(widget, pix->pixwindow); gdk_window_destroy(pix->pixwindow); pix->pixwindow = NULL; } GTK_WIDGET_CLASS(wjpixmap_parent_class)->unrealize(widget); } static void wjpixmap_map(GtkWidget *widget) { wjpixmap *pix = WJPIXMAP(widget); GTK_WIDGET_CLASS(wjpixmap_parent_class)->map(widget); if (pix->pixwindow) gdk_window_show(pix->pixwindow); } static void wjpixmap_unmap(GtkWidget *widget) { wjpixmap *pix = WJPIXMAP(widget); if (pix->pixwindow) gdk_window_hide(pix->pixwindow); GTK_WIDGET_CLASS(wjpixmap_parent_class)->unmap(widget); } static void wjpixmap_size_allocate(GtkWidget *widget, GtkAllocation *allocation) { wjpixmap *pix = WJPIXMAP(widget); gtk_widget_set_allocation(widget, allocation); wjpixmap_position(pix, allocation); if (gtk_widget_get_realized(widget)) gdk_window_move_resize(pix->pixwindow, pix->pm.x + allocation->x, pix->pm.y + allocation->y, pix->pm.width, pix->pm.height); } static void wjpixmap_get_size(GtkWidget *widget, gint vert, gint *min, gint *nat) { wjpixmap *pix = WJPIXMAP(widget); GtkBorder border; get_padding_and_border(gtk_widget_get_style_context(widget), NULL, NULL, &border); *min = *nat = (vert ? border.top + border.bottom + pix->height : border.left + border.right + pix->width) + WJPIXMAP_FRAME * 2; } static void wjpixmap_get_preferred_width(GtkWidget *widget, gint *min, gint *nat) { wjpixmap_get_size(widget, FALSE, min, nat); } static void wjpixmap_get_preferred_height(GtkWidget *widget, gint *min, gint *nat) { wjpixmap_get_size(widget, TRUE, min, nat); } static void wjpixmap_destroy(GtkWidget *widget) { wjpixmap *pix = WJPIXMAP(widget); if (pix->pixmap) { cairo_surface_fdestroy(pix->pixmap); pix->pixmap = NULL; } if (pix->cursor) { cairo_surface_fdestroy(pix->cursor); pix->cursor = NULL; } GTK_WIDGET_CLASS(wjpixmap_parent_class)->destroy(widget); } static void wjpixmap_class_init(wjpixmapClass *class) { GtkWidgetClass *wclass = GTK_WIDGET_CLASS(class); // wclass->screen_changed = wjpixmap_screen_changed; // as proxy for changing visual? wclass->destroy = wjpixmap_destroy; wclass->realize = wjpixmap_realize; wclass->unrealize = wjpixmap_unrealize; wclass->map = wjpixmap_map; wclass->unmap = wjpixmap_unmap; wclass->draw = wjpixmap_draw; wclass->size_allocate = wjpixmap_size_allocate; wclass->get_preferred_width = wjpixmap_get_preferred_width; wclass->get_preferred_height = wjpixmap_get_preferred_height; /* Default handlers in GtkWidget redirect these two anyway */ // wclass->get_preferred_width_for_height = wjpixmap_get_preferred_width_for_height; // wclass->get_preferred_height_for_width = wjpixmap_get_preferred_height_for_width; /* !!! Do not disturb my circles */ // wclass->style_updated = NULL; } static void wjpixmap_init(wjpixmap *pix) { gtk_widget_set_has_window(GTK_WIDGET(pix), FALSE); pix->pixwindow = NULL; pix->pixmap = pix->cursor = NULL; add_css_class(GTK_WIDGET(pix), "wjpixmap"); } GtkWidget *wjpixmap_new(int width, int height) { GtkWidget *widget = gtk_widget_new(wjpixmap_get_type(), NULL); wjpixmap *pix = WJPIXMAP(widget); gtk_widget_set_can_focus(widget, TRUE); pix->width = width; pix->height = height; return (widget); } /* Must be called first to init, and afterwards to access pixmap */ cairo_surface_t *wjpixmap_pixmap(GtkWidget *widget) { wjpixmap *pix = WJPIXMAP(widget); if (!pix->pixmap) { GdkWindow *win = pix->pixwindow; if (!win) win = gdk_screen_get_root_window(gtk_widget_get_screen(widget)); pix->pixmap = gdk_window_create_similar_surface(win, CAIRO_CONTENT_COLOR, pix->width, pix->height); } return (pix->pixmap); } void wjpixmap_draw_rgb(GtkWidget *widget, int x, int y, int w, int h, unsigned char *rgb, int step) { wjpixmap *pix = WJPIXMAP(widget); cairo_surface_t *s; cairo_t *cr; if (!pix->pixmap) return; s = cairo_upload_rgb(pix->pixmap, NULL, rgb, w, h, step); cr = cairo_create(pix->pixmap); cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); cairo_set_source_surface(cr, s, x, y); cairo_unfilter(cr); cairo_rectangle(cr, x, y, w, h); cairo_fill(cr); cairo_destroy(cr); cairo_surface_fdestroy(s); if (pix->pixwindow) { GdkRectangle wr = { x, y, w, h }; gdk_window_invalidate_rect(pix->pixwindow, &wr, FALSE); } } void wjpixmap_move_cursor(GtkWidget *widget, int x, int y) { wjpixmap *pix = WJPIXMAP(widget); GdkRectangle pm, ocr, tcr1, tcr2, *rcr = NULL; int dx = x - pix->xc, dy = y - pix->yc; if (!(dx | dy)) return; ocr = pix->cr; pix->cr.x += dx; pix->cr.y += dy; pix->xc = x; pix->yc = y; if (!pix->pixmap || !pix->cursor) return; if (pix->focused_cursor && !gtk_widget_has_focus(widget)) return; /* Anything visible? */ if (!gtk_widget_get_visible(widget)) return; pm = pix->pm; pm.x = pm.y = 0; if (gdk_rectangle_intersect(&ocr, &pm, &tcr1)) rcr = &tcr1; if (gdk_rectangle_intersect(&pix->cr, &pm, &tcr2)) { if (rcr) gdk_rectangle_union(&tcr1, &tcr2, rcr = &ocr); else rcr = &tcr2; } if (!rcr) return; /* Both positions invisible */ if (pix->pixwindow) gdk_window_invalidate_rect(pix->pixwindow, rcr, FALSE); } /* Input is two compiled-in XBMs */ void wjpixmap_set_cursor(GtkWidget *widget, char *image, char *mask, int width, int height, int hot_x, int hot_y, int focused) { wjpixmap *pix = WJPIXMAP(widget); if (pix->cursor) { cairo_surface_fdestroy(pix->cursor); pix->cursor = NULL; } pix->focused_cursor = focused; if (image) { GdkWindow *win = pix->pixwindow; cairo_surface_t *s; cairo_t *cr; if (!win) win = gdk_screen_get_root_window(gtk_widget_get_screen(widget)); pix->cursor = gdk_window_create_similar_surface(win, CAIRO_CONTENT_COLOR_ALPHA, width, height); s = xbms_to_surface(image, mask, width, height); cr = cairo_create(pix->cursor); cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); cairo_set_source_surface(cr, s, 0, 0); cairo_paint(cr); cairo_destroy(cr); cairo_surface_fdestroy(s); pix->cr.x = pix->xc - hot_x; pix->cr.y = pix->yc - hot_y; pix->cr.width = width; pix->cr.height = height; } /* Optimizing redraw in a rare operation is useless */ if (pix->pixmap) gtk_widget_queue_draw(widget); } /* Translate allocation-relative coords to pixmap-relative */ int wjpixmap_rxy(GtkWidget *widget, int x, int y, int *xr, int *yr) { wjpixmap *pix = WJPIXMAP(widget); if (!pix->pixmap) return (FALSE); x -= pix->pm.x; y -= pix->pm.y; *xr = x; *yr = y; return ((x >= 0) && (x < pix->pm.width) && (y >= 0) && (y < pix->pm.height)); } #else /* if GTK_MAJOR_VERSION <= 2 */ // Focusable pixmap widget #define WJPIXMAP(obj) GTK_CHECK_CAST(obj, wjpixmap_get_type(), wjpixmap) #define IS_WJPIXMAP(obj) GTK_CHECK_TYPE(obj, wjpixmap_get_type()) typedef struct { GtkWidget widget; // Parent class GdkWindow *pixwindow; int width, height; // Requested pixmap size int xc, yc; int focused_cursor; GdkRectangle pm, cr; GdkPixmap *pixmap, *cursor; GdkBitmap *cmask; } wjpixmap; static GtkType wjpixmap_type; static GtkType wjpixmap_get_type(); static void wjpixmap_position(wjpixmap *pix) { int x, y, w, h; x = pix->widget.allocation.width; pix->pm.width = w = pix->width <= x ? pix->width : x; pix->pm.x = (x - w) / 2 + pix->widget.allocation.x; y = pix->widget.allocation.height; pix->pm.height = h = pix->height <= y ? pix->height : y; pix->pm.y = (y - h) / 2 + pix->widget.allocation.y; } static void wjpixmap_realize(GtkWidget *widget) { wjpixmap *pix = WJPIXMAP(widget); GdkWindowAttr attrs; GTK_WIDGET_SET_FLAGS(widget, GTK_REALIZED); widget->window = gtk_widget_get_parent_window(widget); gdk_window_ref(widget->window); wjpixmap_position(pix); attrs.x = pix->pm.x; attrs.y = pix->pm.y; attrs.width = pix->pm.width; attrs.height = pix->pm.height; attrs.window_type = GDK_WINDOW_CHILD; attrs.wclass = GDK_INPUT_OUTPUT; attrs.visual = gtk_widget_get_visual(widget); attrs.colormap = gtk_widget_get_colormap(widget); // Add the same events as GtkEventBox does attrs.event_mask = gtk_widget_get_events(widget) | GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_EXPOSURE_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK; pix->pixwindow = gdk_window_new(widget->window, &attrs, GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP); gdk_window_set_user_data(pix->pixwindow, widget); #if GTK_MAJOR_VERSION == 1 fix_gdk_events(pix->pixwindow); #endif gdk_window_set_back_pixmap(pix->pixwindow, NULL, FALSE); widget->style = gtk_style_attach(widget->style, widget->window); } static void wjpixmap_unrealize(GtkWidget *widget) { wjpixmap *pix = WJPIXMAP(widget); if (pix->pixwindow) { gdk_window_set_user_data(pix->pixwindow, NULL); gdk_window_destroy(pix->pixwindow); pix->pixwindow = NULL; } if (widget_class->unrealize) widget_class->unrealize(widget); } static void wjpixmap_map(GtkWidget *widget) { wjpixmap *pix = WJPIXMAP(widget); if (widget_class->map) widget_class->map(widget); if (pix->pixwindow) gdk_window_show(pix->pixwindow); } static void wjpixmap_unmap(GtkWidget *widget) { wjpixmap *pix = WJPIXMAP(widget); if (pix->pixwindow) gdk_window_hide(pix->pixwindow); if (widget_class->unmap) widget_class->unmap(widget); } static void wjpixmap_size_request(GtkWidget *widget, GtkRequisition *requisition) { wjpixmap *pix = WJPIXMAP(widget); gint xp, yp; #if GTK_MAJOR_VERSION == 1 xp = widget->style->klass->xthickness * 2 + 4; yp = widget->style->klass->ythickness * 2 + 4; #else gtk_widget_style_get(GTK_WIDGET (widget), "focus-line-width", &xp, "focus-padding", &yp, NULL); yp = (xp + yp) * 2 + 2; xp = widget->style->xthickness * 2 + yp; yp = widget->style->ythickness * 2 + yp; #endif requisition->width = pix->width + xp; requisition->height = pix->height + yp; } static void wjpixmap_size_allocate(GtkWidget *widget, GtkAllocation *allocation) { wjpixmap *pix = WJPIXMAP(widget); widget->allocation = *allocation; wjpixmap_position(pix); if (GTK_WIDGET_REALIZED(widget)) gdk_window_move_resize(pix->pixwindow, pix->pm.x, pix->pm.y, pix->pm.width, pix->pm.height); } static void wjpixmap_paint(GtkWidget *widget, int inner, GdkRectangle *area) { wjpixmap *pix = WJPIXMAP(widget); GdkRectangle cdest; #if GTK_MAJOR_VERSION == 1 /* Preparation */ gdk_gc_set_clip_rectangle(widget->style->black_gc, area); #endif if (!inner) // Drawing borders { #if GTK_MAJOR_VERSION == 1 gdk_window_clear_area(widget->window, area->x, area->y, area->width, area->height); #endif /* Frame */ gdk_draw_rectangle(widget->window, widget->style->black_gc, FALSE, pix->pm.x - 1, pix->pm.y - 1, pix->pm.width + 1, pix->pm.height + 1); /* Focus rectangle */ if (GTK_WIDGET_HAS_FOCUS(widget)) gtk_paint_focus(widget->style, widget->window, #if GTK_MAJOR_VERSION == 2 GTK_WIDGET_STATE(widget), #endif area, widget, NULL, widget->allocation.x, widget->allocation.y, widget->allocation.width - 1, widget->allocation.height - 1); } while (inner) // Drawing pixmap & cursor { /* Contents pixmap */ gdk_draw_pixmap(pix->pixwindow, widget->style->black_gc, pix->pixmap, area->x, area->y, area->x, area->y, area->width, area->height); /* Cursor pixmap */ if (!pix->cursor) break; if (pix->focused_cursor && !GTK_WIDGET_HAS_FOCUS(widget)) break; if (!gdk_rectangle_intersect(&pix->cr, area, &cdest)) break; if (pix->cmask) { gdk_gc_set_clip_mask(widget->style->black_gc, pix->cmask); gdk_gc_set_clip_origin(widget->style->black_gc, pix->cr.x, pix->cr.y); } gdk_draw_pixmap(pix->pixwindow, widget->style->black_gc, pix->cursor, cdest.x - pix->cr.x, cdest.y - pix->cr.y, cdest.x, cdest.y, cdest.width, cdest.height); if (pix->cmask) { gdk_gc_set_clip_mask(widget->style->black_gc, NULL); gdk_gc_set_clip_origin(widget->style->black_gc, 0, 0); } break; } #if GTK_MAJOR_VERSION == 1 /* Cleanup */ gdk_gc_set_clip_rectangle(widget->style->black_gc, NULL); #endif } static gboolean wjpixmap_expose(GtkWidget *widget, GdkEventExpose *event) { if (GTK_WIDGET_DRAWABLE(widget)) wjpixmap_paint(widget, event->window != widget->window, &event->area); return (FALSE); } #if GTK_MAJOR_VERSION == 1 static void wjpixmap_draw(GtkWidget *widget, GdkRectangle *area) { wjpixmap *pix = WJPIXMAP(widget); GdkRectangle ir; if (!GTK_WIDGET_DRAWABLE(widget)) return; /* If inner window is touched */ if (gdk_rectangle_intersect(area, &pix->pm, &ir)) { ir.x -= pix->pm.x; ir.y -= pix->pm.y; wjpixmap_paint(widget, TRUE, &ir); /* If outer window isn't */ if (!((area->width - ir.width) | (area->height - ir.height))) return; } wjpixmap_paint(widget, FALSE, area); } static void wjpixmap_draw_focus(GtkWidget *widget) { gtk_widget_draw(widget, NULL); } static gint wjpixmap_focus_event(GtkWidget *widget, GdkEventFocus *event) { if (event->in) GTK_WIDGET_SET_FLAGS(widget, GTK_HAS_FOCUS); else GTK_WIDGET_UNSET_FLAGS(widget, GTK_HAS_FOCUS); gtk_widget_draw_focus(widget); return (FALSE); } #endif static void wjpixmap_destroy(GtkObject *object) { wjpixmap *pix = WJPIXMAP(object); if (pix->pixmap) gdk_pixmap_unref(pix->pixmap); if (pix->cursor) gdk_pixmap_unref(pix->cursor); if (pix->cmask) gdk_bitmap_unref(pix->cmask); /* !!! Unlike attached handler, default handler can get called twice */ pix->pixmap = pix->cursor = pix->cmask = NULL; GTK_OBJECT_CLASS(widget_class)->destroy(object); } static void wjpixmap_class_init(GtkWidgetClass *class) { widget_class = gtk_type_class(GTK_TYPE_WIDGET); GTK_OBJECT_CLASS(class)->destroy = wjpixmap_destroy; class->realize = wjpixmap_realize; class->unrealize = wjpixmap_unrealize; class->map = wjpixmap_map; class->unmap = wjpixmap_unmap; #if GTK_MAJOR_VERSION == 1 class->draw = wjpixmap_draw; class->draw_focus = wjpixmap_draw_focus; class->focus_in_event = class->focus_out_event = wjpixmap_focus_event; #endif class->expose_event = wjpixmap_expose; class->size_request = wjpixmap_size_request; class->size_allocate = wjpixmap_size_allocate; } static GtkType wjpixmap_get_type() { if (!wjpixmap_type) { static const GtkTypeInfo wjpixmap_info = { "wjPixmap", sizeof(wjpixmap), sizeof(GtkWidgetClass), (GtkClassInitFunc)wjpixmap_class_init, // (GtkObjectInitFunc)wjpixmap_init, NULL, /* No instance init */ NULL, NULL, NULL }; wjpixmap_type = gtk_type_unique(GTK_TYPE_WIDGET, &wjpixmap_info); } return (wjpixmap_type); } GtkWidget *wjpixmap_new(int width, int height) { GtkWidget *widget = gtk_widget_new(wjpixmap_get_type(), NULL); wjpixmap *pix = WJPIXMAP(widget); GTK_WIDGET_SET_FLAGS(widget, GTK_CAN_FOCUS | GTK_NO_WINDOW); pix->width = width; pix->height = height; return (widget); } /* Must be called first to init, and afterwards to access pixmap */ GdkPixmap *wjpixmap_pixmap(GtkWidget *widget) { wjpixmap *pix = WJPIXMAP(widget); if (!pix->pixmap) { GdkWindow *win = NULL; int depth = -1; if (GTK_WIDGET_REALIZED(widget)) win = widget->window; else depth = gtk_widget_get_visual(widget)->depth; pix->pixmap = gdk_pixmap_new(win, pix->width, pix->height, depth); } return (pix->pixmap); } void wjpixmap_draw_rgb(GtkWidget *widget, int x, int y, int w, int h, unsigned char *rgb, int step) { wjpixmap *pix = WJPIXMAP(widget); if (!pix->pixmap) return; gdk_draw_rgb_image(pix->pixmap, widget->style->black_gc, x, y, w, h, GDK_RGB_DITHER_NONE, rgb, step); #if GTK_MAJOR_VERSION == 1 gtk_widget_queue_draw_area(widget, x + pix->pm.x, y + pix->pm.y, w, h); #else /* if GTK_MAJOR_VERSION == 2 */ if (pix->pixwindow) { GdkRectangle wr = { x, y, w, h }; gdk_window_invalidate_rect(pix->pixwindow, &wr, FALSE); } #endif } void wjpixmap_move_cursor(GtkWidget *widget, int x, int y) { wjpixmap *pix = WJPIXMAP(widget); GdkRectangle pm, ocr, tcr1, tcr2, *rcr = NULL; int dx = x - pix->xc, dy = y - pix->yc; if (!(dx | dy)) return; ocr = pix->cr; pix->cr.x += dx; pix->cr.y += dy; pix->xc = x; pix->yc = y; if (!pix->pixmap || !pix->cursor) return; if (pix->focused_cursor && !GTK_WIDGET_HAS_FOCUS(widget)) return; /* Anything visible? */ if (!GTK_WIDGET_VISIBLE(widget)) return; pm = pix->pm; pm.x = pm.y = 0; if (gdk_rectangle_intersect(&ocr, &pm, &tcr1)) rcr = &tcr1; if (gdk_rectangle_intersect(&pix->cr, &pm, &tcr2)) { if (rcr) gdk_rectangle_union(&tcr1, &tcr2, rcr = &ocr); else rcr = &tcr2; } if (!rcr) return; /* Both positions invisible */ #if GTK_MAJOR_VERSION == 1 gtk_widget_queue_draw_area(widget, rcr->x + pix->pm.x, rcr->y + pix->pm.y, rcr->width, rcr->height); #else /* if GTK_MAJOR_VERSION == 2 */ if (pix->pixwindow) gdk_window_invalidate_rect(pix->pixwindow, rcr, FALSE); #endif } void wjpixmap_set_cursor(GtkWidget *widget, char *image, char *mask, int width, int height, int hot_x, int hot_y, int focused) { wjpixmap *pix = WJPIXMAP(widget); if (pix->cursor) gdk_pixmap_unref(pix->cursor); if (pix->cmask) gdk_bitmap_unref(pix->cmask); pix->cursor = pix->cmask = NULL; pix->focused_cursor = focused; if (image) { GdkWindow *win = NULL; int depth = -1; if (GTK_WIDGET_REALIZED(widget)) win = widget->window; else depth = gtk_widget_get_visual(widget)->depth; pix->cursor = gdk_pixmap_create_from_data(win, image, width, height, depth, &widget->style->white, &widget->style->black); pix->cr.x = pix->xc - hot_x; pix->cr.y = pix->yc - hot_y; pix->cr.width = width; pix->cr.height = height; if (mask) pix->cmask = gdk_bitmap_create_from_data(win, mask, width, height); } /* Optimizing redraw in a rare operation is useless */ if (pix->pixmap) gtk_widget_queue_draw(widget); } /* Translate allocation-relative coords to pixmap-relative */ int wjpixmap_rxy(GtkWidget *widget, int x, int y, int *xr, int *yr) { wjpixmap *pix = WJPIXMAP(widget); if (!pix->pixmap) return (FALSE); x -= pix->pm.x - widget->allocation.x; y -= pix->pm.y - widget->allocation.y; *xr = x; *yr = y; return ((x >= 0) && (x < pix->pm.width) && (y >= 0) && (y < pix->pm.height)); } #endif /* GTK+1&2 */ // Type of pathname int path_type(char *path) { #ifdef WIN32 return ((path[0] == '/') || (path[0] == '\\') ? PT_DRIVE_ABS : path[1] != ':' ? PT_REL : (path[2] != '/') && (path[2] != '\\') ? PT_DRIVE_REL : PT_ABS); #else return (path[0] != '/' ? PT_REL : PT_ABS); #endif } // Convert pathname to absolute char *resolve_path(char *buf, int buflen, char *path) { char wbuf[PATHBUF], *tmp, *src, *dest, *tm2 = ""; int ch, dot, dots, pt; pt = path_type(path); wbuf[0] = '\0'; /* Relative name to absolute */ if (pt != PT_ABS) { getcwd(wbuf, PATHBUF - 1); tm2 = DIR_SEP_STR; } #ifdef WIN32 /* Drive-absolute pathname needs current drive */ if (pt == PT_DRIVE_ABS) wbuf[2] = '\0'; /* Drive-relative pathname needs drive's current directory */ else if (pt == PT_DRIVE_REL) { char tbuf[PATHBUF]; tbuf[0] = path[0]; tbuf[1] = ':'; tbuf[2] = '\0'; if (!chdir(tbuf)) getcwd(tbuf, PATHBUF - 1); chdir(wbuf); memcpy(wbuf, tbuf, PATHBUF); path += 2; } #endif tmp = wjstrcat(NULL, 0, "", 0, wbuf, tm2, path, NULL); /* Canonicalize path the way "realpath -s" does, i.e., symlinks * followed by ".." will get resolved wrong - WJ */ src = dest = tmp; dots = dot = 0; while (TRUE) { ch = *src++; #ifdef WIN32 if (ch == '/') ch = DIR_SEP; #endif if (ch == '.') dots += dot; else if (!ch || (ch == DIR_SEP)) { if ((dots > 0) && (dots < 4)) /* // /./ /../ */ { dest -= dots; if (dots == 3) /* /../ */ { *dest = '\0'; if ((tm2 = strrchr(tmp, DIR_SEP))) dest = tm2; } /* Do not lose trailing separator */ if (!ch) *dest++ = DIR_SEP; } dots = dot = 1; } else dots = dot = 0; *dest++ = ch; if (!ch) break; } /* Return the result */ if (buf) { strncpy(buf, tmp, buflen); buf[buflen - 1] = 0; free(tmp); tmp = buf; } return (tmp); } // A (better) substitute for fnmatch(), in case one is needed /* One is necessary in case of Win32 or GTK+ 2.0/2.2 */ #if defined(WIN32) || ((GTK_MAJOR_VERSION == 2) && (GTK2VERSION < 4)) #ifdef WIN32 /* Convert everything to lowercase */ static gunichar nxchar(const char **str) { gunichar c = g_utf8_get_char(*str); *str = g_utf8_next_char(*str); return (g_unichar_tolower(c)); } /* Slash isn't an escape char in Windows */ #define UNQUOTE_CHAR(C,P) #else static gunichar nxchar(const char **str) { gunichar c = g_utf8_get_char(*str); *str = g_utf8_next_char(*str); return (c); } #define UNQUOTE_CHAR(C,P) if ((C) == '\\') (C) = nxchar(P) #endif static int match_char_set(const char **maskp, gunichar cs) { const char *mask = *maskp; gunichar ch, cstart, cend; int inv; ch = *mask; if ((inv = (ch == '^') | (ch == '!'))) mask++; ch = nxchar(&mask); while (TRUE) { UNQUOTE_CHAR(ch, &mask); if (!ch) return (0); // Failed cstart = cend = ch; if ((*mask == '-') && (mask[1] != ']')) { mask++; ch = nxchar(&mask); UNQUOTE_CHAR(ch, &mask); if (!ch) return (0); // Failed cend = ch; } if ((cs >= cstart) && (cs <= cend)) { if (inv) return (-1); // Didn't match while ((ch = nxchar(&mask)) != ']') { UNQUOTE_CHAR(ch, &mask); if (!ch) return (0); // Failed } break; } ch = nxchar(&mask); if (ch != ']') continue; if (!inv) return (-1); // Didn't match break; } *maskp = mask; return (1); // Matched } /* The limiting of recursion to one level in this algorithm is based on the * observation that in case of a "*X*Y" subsequence, moving a match for "X" to * the right can not improve the outcome - so only the part after the last * encountered star may ever need to be rematched at another position - WJ */ int wjfnmatch(const char *mask, const char *str, int utf) { char *xmask, *xstr; const char *nstr, *omask, *wmask, *tstr = NULL, *tmask = NULL; gunichar ch, cs, cw; int res, ret = FALSE; /* Convert locale to utf8 */ if (!utf) { mask = xmask = g_locale_to_utf8((gchar *)mask, -1, NULL, NULL, NULL); str = xstr = g_locale_to_utf8((gchar *)str, -1, NULL, NULL, NULL); // Fail the match if conversion failed if (!xmask || !xstr) return (FALSE); } while (TRUE) { nstr = str; cs = nxchar(&nstr); if (!cs) break; omask = mask; ch = nxchar(&mask); if ((cs == DIR_SEP) && (ch != cs)) goto nomatch; if (ch == '?') { str = nstr; continue; } if (ch == '[') { str = nstr; res = match_char_set(&mask, cs); if (res < 0) goto nomatch; if (!res) goto fail; continue; } if (ch == '*') { while (TRUE) { omask = mask; ch = nxchar(&mask); if (!ch) { ret = !strchr(str, DIR_SEP); goto fail; } if (ch == '*') continue; if (ch != '?') break; cs = nxchar(&str); if (!cs || (cs == DIR_SEP)) goto fail; } } else { str = nstr; UNQUOTE_CHAR(ch, &mask); if (ch == cs) continue; nomatch: if (!tmask) goto fail; omask = mask = tmask; str = tstr; ch = nxchar(&mask); } cw = ch; UNQUOTE_CHAR(ch, &mask); if (!ch) goto fail; // Escape char at end of mask wmask = mask; while (TRUE) { cs = nxchar(&str); if (!cs || ((cs == DIR_SEP) && (ch != cs))) goto fail; if (cw == '[') { res = match_char_set(&mask, cs); if (res > 0) break; if (!res) goto fail; mask = wmask; } else if (ch == cs) break; } tmask = omask; tstr = str; } while ((ch = nxchar(&mask)) == '*'); ret = !ch; fail: if (!utf) { g_free(xmask); g_free(xstr); } return (ret); } #endif // Replace '/' path separators #ifdef WIN32 void reseparate(char *str) { while ((str = strchr(str, '/'))) *str++ = DIR_SEP; } #endif // Process event queue void handle_events() { int i = 20; /* To prevent endless waiting */ while ((i-- > 0) && gtk_events_pending()) gtk_main_iteration(); } // Make GtkEntry accept Ctrl+Enter as a character static gboolean convert_ctrl_enter(GtkWidget *widget, GdkEventKey *event, gpointer user_data) { if (((event->keyval == KEY(Return)) || (event->keyval == KEY(KP_Enter))) && (event->state & GDK_CONTROL_MASK)) { #if GTK_MAJOR_VERSION == 1 GtkEditable *edit = GTK_EDITABLE(widget); gint pos = edit->current_pos; gtk_editable_delete_selection(edit); gtk_editable_insert_text(edit, "\n", 1, &pos); edit->current_pos = pos; #else /* if GTK_MAJOR_VERSION >= 2 */ gtk_signal_emit_by_name(GTK_OBJECT(widget), "insert_at_cursor", "\n"); #endif return (TRUE); } return (FALSE); } void accept_ctrl_enter(GtkWidget *entry) { gtk_signal_connect(GTK_OBJECT(entry), "key_press_event", GTK_SIGNAL_FUNC(convert_ctrl_enter), NULL); } // Grab/ungrab input #define GRAB_KEY "mtPaint.grab" /* !!! Widget is expected to have window visible & w/appropriate event masks */ int do_grab(int mode, GtkWidget *widget, GdkCursor *cursor) { int owner_events = mode != GRAB_FULL; #if GTK_MAJOR_VERSION == 1 if (!widget->window) return (FALSE); if (gdk_keyboard_grab(widget->window, owner_events, GDK_CURRENT_TIME)) return (FALSE); if (gdk_pointer_grab(widget->window, owner_events, GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK, NULL, cursor, GDK_CURRENT_TIME)) { gdk_keyboard_ungrab(GDK_CURRENT_TIME); return (FALSE); } if (mode != GRAB_PROGRAM) gtk_grab_add(widget); #elif GTK_MAJOR_VERSION == 2 guint32 time; if (!widget->window) return (FALSE); time = gtk_get_current_event_time(); if (gdk_keyboard_grab(widget->window, owner_events, time) != GDK_GRAB_SUCCESS) return (FALSE); if (gdk_pointer_grab(widget->window, owner_events, GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK, NULL, cursor, time) != GDK_GRAB_SUCCESS) { gdk_display_keyboard_ungrab(gtk_widget_get_display(widget), time); return (FALSE); } if (mode != GRAB_PROGRAM) gtk_grab_add(widget); #else /* #if GTK_MAJOR_VERSION == 3 */ guint32 time; GdkDevice *kbd, *mouse, *dev; GdkWindow *win = gtk_widget_get_window(widget); if (!win) return (FALSE); // Lose time = gtk_get_current_event_time(); mouse = dev = gtk_get_current_event_device(); if (!dev) return (FALSE); // If called out of the blue by mistake kbd = gdk_device_get_associated_device(dev); if (gdk_device_get_source(dev) == GDK_SOURCE_KEYBOARD) // Missed the guess mouse = kbd , kbd = dev; if (gdk_device_grab(kbd, win, GDK_OWNERSHIP_APPLICATION, owner_events, GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK, NULL, time) != GDK_GRAB_SUCCESS) return (FALSE); if (gdk_device_grab(mouse, win, GDK_OWNERSHIP_APPLICATION, owner_events, GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK, cursor, time) != GDK_GRAB_SUCCESS) { gdk_device_ungrab(kbd, time); return (FALSE); } if (mode != GRAB_PROGRAM) gtk_device_grab_add(widget, mouse, TRUE); g_object_set_data(G_OBJECT(widget), GRAB_KEY, mouse); #endif return (TRUE); } void undo_grab(GtkWidget *widget) { #if GTK_MAJOR_VERSION == 1 gdk_keyboard_ungrab(GDK_CURRENT_TIME); gdk_pointer_ungrab(GDK_CURRENT_TIME); gtk_grab_remove(widget); #elif GTK_MAJOR_VERSION == 2 guint32 time = gtk_get_current_event_time(); GdkDisplay *display = gtk_widget_get_display(widget); gdk_display_keyboard_ungrab(display, time); gdk_display_pointer_ungrab(display, time); gtk_grab_remove(widget); #else /* #if GTK_MAJOR_VERSION == 3 */ /* !!! Only removes what do_grab() set, here */ guint32 time = gtk_get_current_event_time(); GdkDevice *mouse = g_object_get_data(G_OBJECT(widget), GRAB_KEY); if (!mouse) return; gdk_device_ungrab(gdk_device_get_associated_device(mouse), time); // kbd gdk_device_ungrab(mouse, time); gtk_device_grab_remove(widget, mouse); g_object_set_data(G_OBJECT(widget), GRAB_KEY, NULL); #endif } #if GTK_MAJOR_VERSION == 1 // Workaround for crazy GTK+1 resize handling /* !!! GTK+1 may "short-circuit" a resize just redoing an existing allocation - * unless resize is queued on a toplevel and NOT from within its check_resize * handler. As all size_request and size_allocate handlers ARE called from * within it, here is a way to postpone queuing till after it finishes - WJ */ #define RESIZE_KEY "mtPaint.resize" static guint resize_key; static void repeat_resize(GtkContainer *cont, gpointer user_data) { GtkObject *obj = GTK_OBJECT(cont); if (gtk_object_get_data_by_id(obj, resize_key) != (gpointer)2) return; gtk_object_set_data_by_id(obj, resize_key, (gpointer)1); gtk_widget_queue_resize(GTK_WIDGET(cont)); } void force_resize(GtkWidget *widget) { GtkObject *obj = GTK_OBJECT(gtk_widget_get_toplevel(widget)); if (!resize_key) resize_key = g_quark_from_static_string(RESIZE_KEY); if (!gtk_object_get_data_by_id(obj, resize_key)) gtk_signal_connect_after(obj, "check_resize", GTK_SIGNAL_FUNC(repeat_resize), NULL); gtk_object_set_data_by_id(obj, resize_key, (gpointer)2); } // Workaround for broken GTK_SHADOW_NONE viewports in GTK+1 /* !!! gtk_viewport_draw() adjusts for shadow thickness even with shadow * disabled, resulting in lower right boundary left undrawn; easiest fix is * to set thickness to 0 for such widgets - WJ */ void vport_noshadow_fix(GtkWidget *widget) { static GtkStyle *defstyle; GtkStyleClass *class; if (!defstyle) { defstyle = gtk_style_new(); class = g_malloc(sizeof(GtkStyleClass)); memcpy(class, defstyle->klass, sizeof(GtkStyleClass)); defstyle->klass = class; class->xthickness = class->ythickness = 0; } gtk_widget_set_style(widget, defstyle); } #endif // Helper for accessing scrollbars void get_scroll_adjustments(GtkWidget *win, GtkAdjustment **h, GtkAdjustment **v) { GtkScrolledWindow *scroll = GTK_SCROLLED_WINDOW(win); *h = gtk_scrolled_window_get_hadjustment(scroll); *v = gtk_scrolled_window_get_vadjustment(scroll); } // Helper for widget show/hide void widget_showhide(GtkWidget *widget, int what) { (what ? gtk_widget_show : gtk_widget_hide)(widget); } // Color name to value int parse_color(char *what) { #if GTK_MAJOR_VERSION == 3 GdkRGBA col; if (!gdk_rgba_parse(&col, what)) return (-1); return (RGB_2_INT(((int)(col.red * 65535) + 128) / 257, ((int)(col.green * 65535) + 128) / 257, ((int)(col.blue * 65535) + 128) / 257)); #else /* if GTK_MAJOR_VERSION <= 2 */ GdkColor col; if (!gdk_color_parse(what, &col)) return (-1); return (RGB_2_INT(((int)col.red + 128) / 257, ((int)col.green + 128) / 257, ((int)col.blue + 128) / 257)); #endif } // DPI value double window_dpi(GtkWidget *win) { #if GTK_MAJOR_VERSION == 3 GValue v; GdkScreen *sc = gtk_widget_get_screen(win); double d = gdk_screen_get_resolution(sc); if (d > 0) return (d); // Seems good memset(&v, 0, sizeof(v)); g_value_init(&v, G_TYPE_INT); if (gdk_screen_get_setting(sc, "gtk-xft-dpi", &v)) return (g_value_get_int(&v) / (double)1024.0); #ifdef GDK_WINDOWING_X11 { /* Get DPI from Xft */ char *e, *v = XGetDefault(GDK_SCREEN_XDISPLAY(sc), "Xft", "dpi"); if (v) { d = g_strtod(v, &e); if (e != v) return (d); // Seems good } } #endif return ((gdk_screen_get_height(sc) * (double)25.4) / gdk_screen_get_height_mm(sc)); #else /* if GTK_MAJOR_VERSION <= 2 */ #if GTK2VERSION >= 10 double d = gdk_screen_get_resolution(gdk_drawable_get_screen(win->window)); if (d > 0) return (d); // Seems good #endif #if GTK2VERSION >= 4 { GValue v; memset(&v, 0, sizeof(v)); g_value_init(&v, G_TYPE_INT); if (gdk_screen_get_setting(gdk_drawable_get_screen(win->window), "gtk-xft-dpi", &v)) return (g_value_get_int(&v) / (double)1024.0); } #endif #if defined(U_MTK) || defined(GDK_WINDOWING_X11) /* GTK+2/X */ { /* Get DPI from Xft */ char *e, *v = XGetDefault(GDK_WINDOW_XDISPLAY(win->window), "Xft", "dpi"); if (v) { double d = g_strtod(v, &e); if (e != v) return (d); // Seems good } } #endif #if GTK2VERSION >= 2 { GdkScreen *sc = gdk_drawable_get_screen(win->window); return ((gdk_screen_get_height(sc) * (double)25.4) / gdk_screen_get_height_mm(sc)); } #else return ((gdk_screen_height() * (double)25.4) / gdk_screen_height_mm()); #endif #endif /* GTK+1&2 */ } // Memory size (Mb) #ifndef WIN32 #ifndef _SC_PHYS_PAGES #include #include #include #endif #endif unsigned sys_mem_size() { #ifdef WIN32 MEMORYSTATUS mem; mem.dwLength = sizeof(mem); GlobalMemoryStatus(&mem); return (mem.dwTotalPhys / (1024 * 1024)); #elif defined _SC_PHYS_PAGES size_t n; #ifdef _SC_PAGESIZE n = sysconf(_SC_PAGESIZE); #else n = sysconf(_SC_PAGE_SIZE); #endif return (((n / 1024) * sysconf(_SC_PHYS_PAGES)) / 1024); #elif defined CTL_HW #undef FAIL int mib[2] = { CTL_HW }; size_t n; #ifdef HW_MEMSIZE uint64_t v; mib[1] = HW_MEMSIZE; #elif defined HW_PHYSMEM64 uint64_t v; mib[1] = HW_PHYSMEM64; #elif defined HW_REALMEM unsigned long v; mib[1] = HW_REALMEM; #elif defined HW_PHYSMEM unsigned long v; mib[1] = HW_PHYSMEM; #else #define FAIL #endif #ifndef FAIL n = sizeof(v); if (!sysctl(mib, 2, &v, &n, NULL, 0) && (n == sizeof(v))) return ((unsigned)(v / (1024 * 1024))); #endif #endif return (0); // Fail } // Threading helpers #if 0 /* Not needed for now - GTK+/Win32 still isn't thread-safe anyway */ //#ifdef U_THREADS /* The following is a replacement for gdk_threads_add_*() functions - which are * useful, but hadn't been implemented before GTK+ 2.12 - WJ */ #if GTK_MAJOR_VERSION == 1 /* With GLib 1.2, a g_source_is_destroyed()-like check cannot be done from * outside GLib, so thread-safety is limited (see GTK+ bug #321866) */ typedef struct { GSourceFunc callback; gpointer user_data; } dispatch_info; static gboolean do_dispatch(dispatch_info *info) { gboolean res; gdk_threads_enter(); res = info->callback(info->user_data); gdk_threads_leave(); return (res); } guint threads_idle_add_priority(gint priority, GtkFunction function, gpointer data) { dispatch_info *disp = g_malloc(sizeof(dispatch_info)); disp->callback = function; disp->user_data = data; return (g_idle_add_full(priority, (GSourceFunc)do_dispatch, disp, (GDestroyNotify)g_free)); } guint threads_timeout_add(guint32 interval, GSourceFunc function, gpointer data) { dispatch_info *disp = g_malloc(sizeof(dispatch_info)); disp->callback = function; disp->user_data = data; return (g_timeout_add_full(G_PRIORITY_DEFAULT, interval, (GSourceFunc)do_dispatch, disp, (GDestroyNotify)g_free)); } #else /* if GTK_MAJOR_VERSION == 2 */ static GSourceFuncs threads_timeout_funcs, threads_idle_funcs; static gboolean threads_timeout_dispatch(GSource *source, GSourceFunc callback, gpointer user_data) { gboolean res = FALSE; gdk_threads_enter(); /* The test below is what g_source_is_destroyed() in GLib 2.12+ does */ if (source->flags & G_HOOK_FLAG_ACTIVE) res = g_timeout_funcs.dispatch(source, callback, user_data); gdk_threads_leave(); return (res); } static gboolean threads_idle_dispatch(GSource *source, GSourceFunc callback, gpointer user_data) { gboolean res = FALSE; gdk_threads_enter(); /* The test below is what g_source_is_destroyed() in GLib 2.12+ does */ if (source->flags & G_HOOK_FLAG_ACTIVE) res = g_idle_funcs.dispatch(source, callback, user_data); gdk_threads_leave(); return (res); } guint threads_timeout_add(guint32 interval, GSourceFunc function, gpointer data) { GSource *source = g_timeout_source_new(interval); guint id; if (!threads_timeout_funcs.dispatch) { threads_timeout_funcs = g_timeout_funcs; threads_timeout_funcs.dispatch = threads_timeout_dispatch; } source->source_funcs = &threads_timeout_funcs; g_source_set_callback(source, function, data, NULL); id = g_source_attach(source, NULL); g_source_unref(source); return (id); } guint threads_idle_add_priority(gint priority, GtkFunction function, gpointer data) { GSource *source = g_idle_source_new(); guint id; if (!threads_idle_funcs.dispatch) { threads_idle_funcs = g_idle_funcs; threads_idle_funcs.dispatch = threads_idle_dispatch; } source->source_funcs = &threads_idle_funcs; if (priority != G_PRIORITY_DEFAULT_IDLE) g_source_set_priority(source, priority); g_source_set_callback(source, function, data, NULL); id = g_source_attach(source, NULL); g_source_unref(source); return (id); } #endif #endif mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/mygtk.h000066400000000000000000000375641471325446300222650ustar00rootroot00000000000000/* mygtk.h Copyright (C) 2004-2024 Mark Tyler and Dmitry Groshev This file is part of mtPaint. mtPaint 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. mtPaint 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 mtPaint in the file COPYING. */ #include #include #include #include #include #include #include #include #include #include #include /// GTK+2 version to use #if GTK_MAJOR_VERSION == 2 #ifndef GTK2VERSION #define GTK2VERSION GTK_MINOR_VERSION #endif #endif /// GTK+3 version to use #if GTK_MAJOR_VERSION == 3 #ifndef GTK3VERSION #define GTK3VERSION GTK_MINOR_VERSION #endif #endif /// List widgets to use #if GTK_MAJOR_VERSION == 1 #undef U_LISTS_GTK1 #define U_LISTS_GTK1 #elif GTK_MAJOR_VERSION == 2 #if GTK2VERSION < 18 #undef U_LISTS_GTK1 #define U_LISTS_GTK1 #endif #else /* GTK_MAJOR_VERSION == 3 */ #undef U_LISTS_GTK1 #endif /// Meaningless differences to hide #if GTK_MAJOR_VERSION == 3 #define g_thread_init(A) /* Not needed anymore */ #define GtkSignalFunc GCallback #define GTK_SIGNAL_FUNC(A) G_CALLBACK(A) #define GTK_OBJECT(A) G_OBJECT(A) #define gtk_signal_connect(A,B,C,D) g_signal_connect(A,B,C,D) #define gtk_signal_connect_object(A,B,C,D) g_signal_connect_swapped(A,B,C,D) #define gtk_signal_disconnect_by_data(A,B) g_signal_handlers_disconnect_by_data(A,B) #define gtk_signal_emit_by_name g_signal_emit_by_name #define KEY(A) GDK_KEY_##A /* Only one target backend */ #ifdef GDK_WINDOWING_X11 #undef GDK_WINDOWING_QUARTZ #endif #else #define gtk_widget_get_parent(A) ((A)->parent) #define gtk_widget_get_window(A) ((A)->window) #define gdk_device_get_name(A) ((A)->name) #define gdk_device_get_n_axes(A) ((A)->num_axes) #define gdk_device_get_mode(A) ((A)->mode) #define KEY(A) GDK_##A #endif #ifndef G_GNUC_BEGIN_IGNORE_DEPRECATIONS #define G_GNUC_BEGIN_IGNORE_DEPRECATIONS #define G_GNUC_END_IGNORE_DEPRECATIONS #endif /// Icon descriptor type typedef void *xpm_icon_desc[2]; #if GTK_MAJOR_VERSION == 1 #define XPM_TYPE char** #else /* if GTK_MAJOR_VERSION >= 2 */ #define XPM_TYPE void** #endif /// Generic RGB buffer typedef struct { int xy[4]; unsigned char *rgb; } rgbcontext; /// Main toplevel, for anchoring dialogs and rendering pixmaps GtkWidget *main_window; /// Generic Widget Primitives GtkWidget *add_a_window(GtkWindowType type, char *title, GtkWindowPosition pos); GtkWidget *add_a_spin( int value, int min, int max ); int user_break; void progress_init(char *text, int canc); // Initialise progress window int progress_update(float val); // Update progress window void progress_end(); // Close progress window int alert_box(char *title, char *message, char *text1, ...); // Tablet handling #if GTK_MAJOR_VERSION == 1 GdkDeviceInfo *tablet_device; #else /* #if GTK_MAJOR_VERSION >= 2 */ GdkDevice *tablet_device; #endif void init_tablet(); void conf_tablet(void **slot); void conf_done(void *cause); // GTK+3 specific support code #if GTK_MAJOR_VERSION == 3 void cairo_surface_fdestroy(cairo_surface_t *s); cairo_surface_t *cairo_upload_rgb(cairo_surface_t *ref, GdkWindow *win, unsigned char *src, int w, int h, int len); void cairo_set_rgb(cairo_t *cr, int c); /* Prevent color bleed on HiDPI */ void cairo_unfilter(cairo_t *cr); void css_restyle(GtkWidget *w, char *css, char *class, char *name); void add_css_class(GtkWidget *w, char *class); /* Add CSS, builtin and user-provided, to default screen */ void init_css(char *cssfile); /* Find button widget of a GtkComboBox with entry */ GtkWidget *combobox_button(GtkWidget *cbox); void get_padding_and_border(GtkStyleContext *ctx, GtkBorder *pad, GtkBorder *bor, GtkBorder *both); /* Find out which set of bugs & breakages is active */ int gtk3version; #else #define add_css_class(A,B) #endif // Slider-spin combo (a decorated spinbutton) GtkWidget *mt_spinslide_new(int swidth, int sheight); #define ADJ2INT(a) ((int)rint((a)->value)) // Self-contained package of radio buttons GtkWidget *wj_radio_pack(char **names, int cnt, int vnum, int idx, void **r, GtkSignalFunc handler); int wj_radio_pack_get_active(GtkWidget *widget); // Easier way with spinbuttons int read_spin(GtkWidget *spin); double read_float_spin(GtkWidget *spin); GtkWidget *add_float_spin(double value, double min, double max); void spin_connect(GtkWidget *spin, GtkSignalFunc handler, gpointer user_data); #if GTK_MAJOR_VERSION == 1 void spin_set_range(GtkWidget *spin, int min, int max); #else #define spin_set_range(spin, min, max) \ gtk_spin_button_set_range(GTK_SPIN_BUTTON(spin), (min), (max)) #endif // Box unpacking macros #if GTK_MAJOR_VERSION <= 2 #define BOX_CHILD_0(box) \ (((GtkBoxChild*)GTK_BOX(box)->children->data)->widget) #define BOX_CHILD_1(box) \ (((GtkBoxChild*)GTK_BOX(box)->children->next->data)->widget) #define BOX_CHILD_2(box) \ (((GtkBoxChild*)GTK_BOX(box)->children->next->next->data)->widget) #define BOX_CHILD(box, n) \ (((GtkBoxChild *)g_list_nth_data(GTK_BOX(box)->children, (n)))->widget) #endif // Wrapper for utf8->C and C->utf8 translation char *gtkxncpy(char *dest, const char *src, int cnt, int u); #define gtkncpy(dest, src, cnt) gtkxncpy(dest, src, cnt, FALSE) #define gtkuncpy(dest, src, cnt) gtkxncpy(dest, src, cnt, TRUE) // Generic wrapper for strncpy(), ensuring NUL termination #define strncpy0(A,B,C) (strncpy((A), (B), (C))[(C) - 1] = 0) // A more sane replacement for strncat() char *strnncat(char *dest, const char *src, int max); // Add C strings to a string with explicit length char *wjstrcat(char *dest, int max, const char *s0, int l, ...); // Add directory to filename char *file_in_dir(char *dest, const char *dir, const char *file, int cnt); char *file_in_homedir(char *dest, const char *file, int cnt); // Add extension to filename, making sure result is not the same file char *tailed_name(char *dest, const char *file, const char *tail, int max); // Set minimum size for a widget void widget_set_minsize(GtkWidget *widget, int width, int height); GtkWidget *widget_align_minsize(GtkWidget *widget, int width, int height); // Make widget request no less size than before (in one direction) void widget_set_keepsize(GtkWidget *widget, int keep_height); // Workaround for GtkCList reordering bug in GTK2 void clist_enable_drag(GtkWidget *clist); // Most common use of boxes GtkWidget *pack(GtkWidget *box, GtkWidget *widget); GtkWidget *xpack(GtkWidget *box, GtkWidget *widget); GtkWidget *pack_end(GtkWidget *box, GtkWidget *widget); // Put vbox into container GtkWidget *add_vbox(GtkWidget *cont); // Fix for paned widgets losing focus in GTK+1 #if GTK_MAJOR_VERSION == 1 void paned_mouse_fix(GtkWidget *widget); #else #define paned_mouse_fix(X) #endif // Init-time bugfixes void gtk_init_bugfixes(); // Moving mouse cursor int move_mouse_relative(int dx, int dy); // Mapping keyval to key guint real_key(GdkEventKey *event); guint low_key(GdkEventKey *event); guint keyval_key(guint keyval); // Interpreting arrow keys int arrow_key_(unsigned key, unsigned state, int *dx, int *dy, int mult); #define arrow_key(E,X,Y,M) arrow_key_((E)->keyval, (E)->state, (X), (Y), (M)) // Create pixmap cursor GdkCursor *make_cursor(char *icon, char *mask, int w, int h, int tip_x, int tip_y); // Menu-like combo box GtkWidget *wj_combo_box(char **names, int cnt, int u, int idx, void **r, GtkSignalFunc handler); int wj_combo_box_get_history(GtkWidget *combobox); #if GTK_MAJOR_VERSION == 3 // Bin widget with customizable size handling GtkWidget *wjsizebin_new(GCallback get_size, GCallback size_alloc, gpointer user_data); #else // Box widget with customizable size handling GtkWidget *wj_size_box(); #endif // Disable visual updates while tweaking container's contents gpointer toggle_updates(GtkWidget *widget, gpointer unlock); // Maximized & iconified states #if GTK_MAJOR_VERSION == 1 int is_maximized(GtkWidget *window); void set_maximized(GtkWidget *window); #elif GTK_MAJOR_VERSION == 2 #define is_maximized(W) \ (!!(gdk_window_get_state((W)->window) & GDK_WINDOW_STATE_MAXIMIZED)) #define set_maximized(W) gtk_window_maximize(W) #else /* if GTK_MAJOR_VERSION == 3 */ #define is_maximized(W) gtk_window_is_maximized(GTK_WINDOW(W)) #define set_maximized(W) gtk_window_maximize(W) #endif void set_iconify(GtkWidget *window, int state); // Drawable to RGB #if GTK_MAJOR_VERSION == 3 unsigned char *wj_get_rgb_image(GdkWindow *window, cairo_surface_t *s, unsigned char *buf, int x, int y, int width, int height); #else /* if GTK_MAJOR_VERSION <= 2 */ unsigned char *wj_get_rgb_image(GdkWindow *window, GdkPixmap *pixmap, unsigned char *buf, int x, int y, int width, int height); #endif // Clipboard int internal_clipboard(int which); // Clipboard pixmaps typedef unsigned long XID_type; typedef struct { int w, h, depth; XID_type xid; #if GTK_MAJOR_VERSION == 3 cairo_surface_t *pm; #else /* if GTK_MAJOR_VERSION <= 2 */ GdkPixmap *pm; #endif } pixmap_info; #if (GTK_MAJOR_VERSION == 1) || defined GDK_WINDOWING_X11 #define HAVE_PIXMAPS int export_pixmap(pixmap_info *p, int w, int h); void pixmap_put_rows(pixmap_info *p, unsigned char *src, int y, int cnt); #endif int import_pixmap(pixmap_info *p, XID_type *xid); // xid = NULL for a screenshot void drop_pixmap(pixmap_info *p); int pixmap_get_rows(pixmap_info *p, unsigned char *dest, int y, int cnt); // Image widget GtkWidget *xpm_image(XPM_TYPE xpm); // Render stock icons to pixmaps /* !!! Mask needs be zeroed before the call - especially with GTK+1 :-) */ #if GTK_MAJOR_VERSION == 1 #define render_stock_pixmap(X,Y,Z) NULL #elif GTK_MAJOR_VERSION == 2 GdkPixmap *render_stock_pixmap(GtkWidget *widget, const gchar *stock_id, GdkBitmap **mask); #endif // Release outstanding pointer grabs int release_grab(); // Frame widget with passthrough scrolling GtkWidget *wjframe_new(); // Scrollable canvas widget GtkWidget *wjcanvas_new(); void wjcanvas_set_expose(GtkWidget *widget, GtkSignalFunc handler, gpointer user_data); void wjcanvas_size(GtkWidget *widget, int width, int height); void wjcanvas_get_vport(GtkWidget *widget, int *vport); void wjcanvas_redraw(GtkWidget *widget, int *rxy); // Rectangle, or entire int wjcanvas_scroll_in(GtkWidget *widget, int x, int y); int wjcanvas_bind_mouse(GtkWidget *widget, GdkEventMotion *event, int x, int y); #if GTK_MAJOR_VERSION == 3 void wjcanvas_draw_rgb(GtkWidget *widget, int x, int y, int w, int h, unsigned char *rgb, int step, int fill, int repaint); #endif // Focusable pixmap widget GtkWidget *wjpixmap_new(int width, int height); #if GTK_MAJOR_VERSION == 3 cairo_surface_t *wjpixmap_pixmap(GtkWidget *widget); #else /* if GTK_MAJOR_VERSION <= 2 */ GdkPixmap *wjpixmap_pixmap(GtkWidget *widget); #endif void wjpixmap_draw_rgb(GtkWidget *widget, int x, int y, int w, int h, unsigned char *rgb, int step); void wjpixmap_move_cursor(GtkWidget *widget, int x, int y); void wjpixmap_set_cursor(GtkWidget *widget, char *image, char *mask, int width, int height, int hot_x, int hot_y, int focused); int wjpixmap_rxy(GtkWidget *widget, int x, int y, int *xr, int *yr); // Type of pathname #define PT_ABS 0 /* Absolute */ #define PT_REL 1 /* Relative */ #define PT_DRIVE_ABS 2 /* On Windows: absolute w/o drive (\DIR\FILE) */ #define PT_DRIVE_REL 3 /* On Windows: relative with drive (C:FILE) */ int path_type(char *path); // Convert pathname to absolute char *resolve_path(char *buf, int buflen, char *path); // A (better) substitute for fnmatch(), in case one is needed #if defined(WIN32) || ((GTK_MAJOR_VERSION == 2) && (GTK2VERSION < 4)) int wjfnmatch(const char *mask, const char *str, int utf); #endif // Replace '/' path separators #ifdef WIN32 void reseparate(char *str); #endif // Process event queue void handle_events(); // Make GtkEntry accept Ctrl+Enter as a character void accept_ctrl_enter(GtkWidget *entry); // Grab/ungrab input #define GRAB_FULL 0 /* Redirect everything */ #define GRAB_WIDGET 1 /* Redirect everything outside widget */ #define GRAB_PROGRAM 2 /* Redirect everything outside program's windows */ int do_grab(int mode, GtkWidget *widget, GdkCursor *cursor); void undo_grab(GtkWidget *widget); // Workaround for crazy GTK+1 resize handling #if GTK_MAJOR_VERSION == 1 void force_resize(GtkWidget *widget); #endif // Workaround for broken GTK_SHADOW_NONE viewports in GTK+1 #if GTK_MAJOR_VERSION == 1 void vport_noshadow_fix(GtkWidget *widget); #else #define vport_noshadow_fix(X) #endif // Helper for accessing scrollbars void get_scroll_adjustments(GtkWidget *win, GtkAdjustment **h, GtkAdjustment **v); // Helper for widget show/hide void widget_showhide(GtkWidget *widget, int what); // Color name to value int parse_color(char *what); // DPI value double window_dpi(GtkWidget *win); // Interface scale #if GTK_MAJOR_VERSION == 3 #define window_scale(W) gtk_widget_get_scale_factor(W) #else /* if GTK_MAJOR_VERSION <= 2 */ #define window_scale(W) 1 #endif // Memory size (Mb) unsigned sys_mem_size(); // Filtering bogus xine-ui "keypresses" (Linux only) #ifdef WIN32 #define XINE_FAKERY(key) 0 #else #define XINE_FAKERY(key) (((key) == KEY(Shift_L)) || ((key) == KEY(Control_L)) \ || ((key) == KEY(Scroll_Lock)) || ((key) == KEY(Num_Lock))) #endif // Workaround for stupid GTK1 typecasts #if GTK_MAJOR_VERSION == 1 #define GTK_RADIO_BUTTON_0(X) (GtkRadioButton *)(X) #else #define GTK_RADIO_BUTTON_0(X) GTK_RADIO_BUTTON(X) #endif // Path separator char #ifdef WIN32 #define DIR_SEP '\\' #define DIR_SEP_STR "\\" #else #define DIR_SEP '/' #define DIR_SEP_STR "/" #endif // Path string sizes /* If path is longer than this, it is user's own problem */ #define SANE_PATH_LEN 2048 #ifdef WIN32 #define PATHBUF 260 /* MinGW defines PATH_MAX to not include terminating NUL */ #elif defined MAXPATHLEN #define PATHBUF MAXPATHLEN /* MAXPATHLEN includes the NUL */ #elif defined PATH_MAX #define PATHBUF PATH_MAX /* POSIXly correct PATH_MAX does too */ #else #define PATHBUF SANE_PATH_LEN /* Arbitrary limit for GNU Hurd and the like */ #endif #if PATHBUF > SANE_PATH_LEN /* Force a sane limit */ #undef PATHBUF #define PATHBUF SANE_PATH_LEN #endif #if GTK_MAJOR_VERSION == 1 /* Same encoding in GTK+1 */ #define PATHTXT PATHBUF #else /* Allow for expansion when converting from codepage to UTF8 */ #define PATHTXT (PATHBUF * 2) #endif // Filename string size #ifdef WIN32 #define NAMEBUF 256 /* MinGW doesn't define MAXNAMLEN nor NAME_MAX */ #elif defined MAXNAMLEN #define NAMEBUF (MAXNAMLEN + 1) #elif defined NAME_MAX #define NAMEBUF (NAME_MAX + 1) #else #define NAMEBUF 256 /* Most filesystems limit filenames to 255 bytes or less */ #endif // Threading helpers #if 0 /* Not needed for now - GTK+/Win32 still isn't thread-safe anyway */ //#ifdef U_THREADS guint threads_idle_add_priority(gint priority, GtkFunction function, gpointer data); guint threads_timeout_add(guint32 interval, GSourceFunc function, gpointer data); #define THREADS_ENTER() gdk_threads_enter() #define THREADS_LEAVE() gdk_threads_leave() #else #if GTK_MAJOR_VERSION == 3 #define GTK_PRIORITY_REDRAW GDK_PRIORITY_REDRAW #define GtkFunction GSourceFunc #define threads_idle_add_priority(X,Y,Z) g_idle_add_full(X,Y,Z,NULL) #define gtk_idle_remove(A) g_source_remove(A) #else #define threads_idle_add_priority(X,Y,Z) gtk_idle_add_priority(X,Y,Z) #endif #define threads_timeout_add(X,Y,Z) g_timeout_add(X,Y,Z) #define THREADS_ENTER() #define THREADS_LEAVE() #endif // Workaround for broken glibc's #if (__GLIBC__ == 2) && ((__GLIBC_MINOR__ == 15) || (__GLIBC_MINOR__ == 16)) static inline int strncasecmp_fix(const char *s1, const char *s2, size_t n) { return (!*s1 && !*s2 ? 0 : strncasecmp(s1, s2, n)); } #define strncasecmp(A, B, C) strncasecmp_fix(A, B, C) #endif mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/otherwindow.c000066400000000000000000002345611471325446300234720ustar00rootroot00000000000000/* otherwindow.c Copyright (C) 2004-2021 Mark Tyler and Dmitry Groshev This file is part of mtPaint. mtPaint 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. mtPaint 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 mtPaint in the file COPYING. */ #include "global.h" #undef _ #define _(X) X #include "mygtk.h" #include "memory.h" #include "vcode.h" #include "otherwindow.h" #include "ani.h" #include "png.h" #include "mainwindow.h" #include "viewer.h" #include "inifile.h" #include "canvas.h" #include "layer.h" #include "wu.h" #include "channels.h" #include "toolbar.h" #include "csel.h" #include "font.h" #include "icons.h" /// NEW IMAGE WINDOW void reset_tools() { if (!mem_img[mem_channel]) mem_channel = CHN_IMAGE; // Safety first pressed_select(FALSE); // To prevent automatic paste change_to_tool(DEFAULT_TOOL_ICON); init_istate(&mem_state, &mem_image); memset(channel_col_A, 255, NUM_CHANNELS); memset(channel_col_B, 0, NUM_CHANNELS); tool_opacity = 255; // Set opacity to 100% to start with if (inifile_get_gboolean("zoomToggle", FALSE)) can_zoom = 1; // Always start at 100% update_stuff(UPD_RESET | UPD_ALL); } void do_new_chores(int undo) { set_new_filename(layer_selected, NULL); if (layers_total) layers_notify_changed(); // No reason to reset tools in undoable mode if (!undo) reset_tools(); else update_stuff(UPD_ALL); } int do_new_one(int nw, int nh, int nc, png_color *pal, int bpp, int undo) { int res = 0; nw = nw < MIN_WIDTH ? MIN_WIDTH : nw > MAX_WIDTH ? MAX_WIDTH : nw; nh = nh < MIN_HEIGHT ? MIN_HEIGHT : nh > MAX_HEIGHT ? MAX_HEIGHT : nh; mem_cols = nc < 2 ? 2 : nc > 256 ? 256 : nc; /* Check memory for undo */ if (undo) undo = !undo_next_core(UC_CREATE | UC_GETMEM, nw, nh, bpp, CMASK_IMAGE); /* Create undo frame if requested */ if (undo) { undo_next_core(UC_DELETE, nw, nh, bpp, CMASK_ALL); undo = !!(mem_img[CHN_IMAGE] = calloc(1, nw * nh * bpp)); } /* Create image anew if all else fails */ if (!undo) { res = mem_new( nw, nh, bpp, CMASK_IMAGE ); if (res) memory_errors(1); // Not enough memory! } /* *Now* prepare and update palette */ if (pal) mem_pal_copy(mem_pal, pal); else mem_bw_pal(mem_pal, 0, nc - 1); update_undo(&mem_image); do_new_chores(undo); return (res); } static int clip_to_layer(int layer) { image_info *img; image_state *state; int cmask, undo = undo_load; cmask = cmask_from(mem_clip.img); if (layer == layer_selected) { if (undo) undo = !undo_next_core(UC_CREATE | UC_GETMEM, mem_clip_w, mem_clip_h, mem_clip_bpp, cmask); if (undo) undo_next_core(UC_DELETE, mem_clip_w, mem_clip_h, mem_clip_bpp, CMASK_ALL); else mem_free_image(&mem_image, FREE_IMAGE); img = &mem_image; state = &mem_state; } else { img = &layer_table[layer].image->image_; state = &layer_table[layer].image->state_; *state = mem_state; mem_free_image(img, FREE_IMAGE); mem_pal_copy(img->pal, mem_pal); img->cols = mem_cols; img->trans = mem_xpm_trans; } if (!mem_alloc_image(AI_COPY, img, 0, 0, 0, 0, &mem_clip)) return (0); update_undo(img); state->channel = CHN_IMAGE; return (1); } typedef struct { int type, w, h, c, undo, delay, im_type; } newwin_dd; static void create_new(newwin_dd *dt, void **wdata) { png_color *pal; int im_type, new_window_type = dt->type; int nw, nh, nc, err = 1, bpp; run_query(wdata); im_type = dt->im_type; pal = im_type == 1 ? NULL : mem_pal_def; nw = dt->w; nh = dt->h; nc = dt->c; if (!new_window_type) undo_load = dt->undo; if (im_type == 4) /* Screenshot */ { // Ensure that both this window and the main one are offscreen cmd_setv(wdata, (void *)(TRUE), WINDOW_DISAPPEAR); if (dt->delay) sleep(dt->delay); // Use current layer if (!new_window_type) { err = load_image(NULL, FS_PNG_LOAD, undo_load ? FT_PIXMAP | FTM_UNDO : FT_PIXMAP); if (err == 1) { do_new_chores(undo_load); notify_changed(); } } // Add new layer else if (layer_add(0, 0, 1, 0, mem_pal_def, 0)) { err = load_image(NULL, FS_LAYER_LOAD, FT_PIXMAP); if (err == 1) layer_show_new(); else layer_delete(layers_total); } // Let main window onscreen again cmd_setv(main_window_, (void *)(FALSE), WINDOW_DISAPPEAR); } if (im_type == 3) /* Clipboard */ { // Use current layer if (!new_window_type) { err = import_clipboard(FS_PNG_LOAD); if ((err != 1) && mem_clipboard) err = clip_to_layer(layer_selected); if (err == 1) { do_new_chores(undo_load); notify_changed(); } } // Add new layer else if (layer_add(0, 0, 1, 0, mem_pal_def, 0)) { err = import_clipboard(FS_LAYER_LOAD); if ((err != 1) && mem_clipboard) err = clip_to_layer(layers_total); if (err == 1) layer_show_new(); else layer_delete(layers_total); } } /* Fallthrough if error */ if (err != 1) im_type = 0; /* RGB / Greyscale / Indexed */ bpp = im_type == 0 ? 3 : 1; if (im_type > 2); // Successfully done above else if (new_window_type == 1) // Layer layer_new(nw, nh, bpp, nc, pal, CMASK_IMAGE); else // Image { /* Nothing to undo if image got deleted already */ err = do_new_one(nw, nh, nc, pal, bpp, undo_load && mem_img[CHN_IMAGE]); if (err > 0) { /* System was unable to allocate memory for * image, using 8x8 instead */ nw = mem_width; nh = mem_height; } inifile_set_gint32("lastnewWidth", nw ); inifile_set_gint32("lastnewHeight", nh ); inifile_set_gint32("lastnewCols", nc ); inifile_set_gint32("lastnewType", im_type ); } run_destroy(wdata); } static char *newwin_txt[] = { _("24 bit RGB"), _("Greyscale"), _("Indexed Palette"), _("From Clipboard"), _("Grab Screenshot") }; #define WBbase newwin_dd static void *newwin_code[] = { IF(type), WINDOWm(_("New Layer")), // modal UNLESS(type), WINDOWm(_("New Image")), // modal TABLE2(3), OPNAME0, TSPIN(_("Width"), w, MIN_WIDTH, MAX_WIDTH), TSPIN(_("Height"), h, MIN_HEIGHT, MAX_HEIGHT), TSPIN(_("Colours"), c, 2, 256), WDONE, BORDER(RPACK, 0), // !!! Commandline mode leaves GDK uninitialized, but screenshot needs it UNLESSv(cmd_mode), RPACK(newwin_txt, 5, 0, im_type), IFv(cmd_mode), RPACK(newwin_txt, 4, 0, im_type), OPNAME(""), uSPIN(delay, 0, 100), OPNAME("Delay"), // For screenshots from scripts UNLESS(type), CHECK(_("Undoable"), undo), HSEPl(200), OKBOXB(_("Create"), create_new, _("Cancel"), NULL), WSHOW }; #undef WBbase void generic_new_window(int type) // 0=New image, 1=New layer { newwin_dd tdata = { type, mem_width, mem_height, mem_cols, undo_load, 0 }; int im_type = 3 - mem_img_bpp; if (!type) { if ((!script_cmds || !undo_load) && (check_for_changes() == 1)) return; tdata.w = inifile_get_gint32("lastnewWidth", DEFAULT_WIDTH); tdata.h = inifile_get_gint32("lastnewHeight", DEFAULT_HEIGHT); tdata.c = inifile_get_gint32("lastnewCols", 256); im_type = inifile_get_gint32("lastnewType", 2); if ((im_type < 0) || (im_type > 2)) im_type = 0; } tdata.im_type = im_type; run_create_(newwin_code, &tdata, sizeof(tdata), script_cmds); } /// PATTERN & BRUSH CHOOSER WINDOW static void **pat_window; typedef struct { int mode; int wh[3]; int xs, ys, xw, max; unsigned char *rgb; } pattern_dd; #define PAL_SLOT_SIZE 10 static void make_crgb(unsigned char *tmp, int channel) { int col, k, r, g, b; if (channel <= CHN_IMAGE) /* Palette as such */ { pal2rgb(tmp, mem_pal, mem_cols, 256); return; } if (channel < NUM_CHANNELS) /* Utility */ { r = channel_rgb[channel][0]; g = channel_rgb[channel][1]; b = channel_rgb[channel][2]; } else r = g = b = 255; /* Opacity */ for (col = 0; col < 256; col++) { k = r * col; *tmp++ = (k + (k >> 8) + 1) >> 8; k = g * col; *tmp++ = (k + (k >> 8) + 1) >> 8; k = b * col; *tmp++ = (k + (k >> 8) + 1) >> 8; } } static void render_color_grid(unsigned char *rgb, int w, int h, int cellsize, unsigned char *pp) { unsigned char *tmp; int i, j, k, row = w * 3; for (i = 0; i < h; i += cellsize) { tmp = rgb + i * row; for (j = 0; j < row; j += cellsize * 3 , pp += 3) { tmp[j + 0] = pp[0]; tmp[j + 1] = pp[1]; tmp[j + 2] = pp[2]; for (k = j + 3; k < j + cellsize * 3 - 3; k++) tmp[k] = tmp[k - 3]; } for (j = i + 1; j < i + cellsize - 1; j++) memcpy(rgb + j * row, tmp, row); } } static int delete_pat(pattern_dd *dt, void **wdata) { run_destroy(wdata); pat_window = NULL; return (FALSE); } static int key_pat(pattern_dd *dt, void **wdata, int what, void **where, key_ext *key) { /* xine-ui sends bogus keypresses so don't delete on this */ if (!XINE_FAKERY(key->key)) delete_pat(dt, wdata); return (TRUE); } static int click_pat(pattern_dd *dt, void **wdata, int what, void **where, mouse_ext *mouse) { int pat_no, mx = mouse->x, my = mouse->y; pat_no = mx / dt->xs + dt->xw * (my / dt->ys); pat_no = pat_no < 0 ? 0 : pat_no > dt->max ? dt->max : pat_no; // if (mouse->count != 1) return (FALSE); // only single click if (dt->mode == CHOOSE_COLOR) { int ab; if (!(ab = mouse->button == 3) && (mouse->button != 1)) return (FALSE); // Only left or right click mem_col_[ab] = pat_no; mem_col_24[ab] = mem_pal[pat_no]; update_stuff(UPD_AB); } else if (dt->mode == CHOOSE_PATTERN) { if (mouse->button == 1) mem_tool_pat = pat_no; // Left else if (pattern_B && (mouse->button == 3)) // Right mem_tool_pat_B = pat_no; else return (FALSE); update_stuff(UPD_PAT); } else if (mouse->button != 1) return (FALSE); // Left click only else /* if (dt->mode == CHOOSE_BRUSH) */ { mem_set_brush(pat_no); change_to_tool(TTB_PAINT); update_stuff(UPD_BRUSH); } return (TRUE); } #define WBbase pattern_dd void *pattern_code[] = { BORDER(POPUP, 4), WPMOUSE, POPUP(_("Pattern Chooser")), EVENT(KEY, key_pat), /* !!! Given the window is modal, this makes it closeable by button * release anywhere over mtPaint's main window - WJ */ EVENT(RMOUSE, delete_pat), TALLOC(rgb, wh[2]), RGBIMAGE(rgb, wh), EVENT(MOUSE, click_pat), WEND }; #undef WBbase void choose_pattern(int typ) // Bring up pattern chooser (0) or brush (1) { unsigned char pp[768]; pattern_dd tdata, *dt; if (pat_window) return; // Already displayed tdata.mode = typ; tdata.wh[2] = 3; // bpp if (typ == CHOOSE_PATTERN) { tdata.wh[0] = patterns_grid_w * PATTERN_CELL; tdata.wh[1] = patterns_grid_h * PATTERN_CELL; tdata.xs = tdata.ys = PATTERN_CELL; tdata.xw = patterns_grid_w; tdata.max = patterns_grid_w * patterns_grid_h - 1; } else if (typ == CHOOSE_BRUSH) { tdata.rgb = mem_brushes; tdata.wh[0] = PATCH_WIDTH; tdata.wh[1] = PATCH_HEIGHT; tdata.wh[2] = 0; // no allocation tdata.xs = tdata.ys = BRUSH_CELL; tdata.xw = BRUSH_GRID_W; tdata.max = NUM_BRUSHES - 1; } else /* if (typ == CHOOSE_COLOR) */ { tdata.wh[0] = tdata.wh[1] = 16 * PAL_SLOT_SIZE - 1; tdata.xs = tdata.ys = PAL_SLOT_SIZE; tdata.xw = 16; tdata.max = mem_cols - 1; } tdata.wh[2] *= tdata.wh[0] * tdata.wh[1]; // alloc size pat_window = run_create(pattern_code, &tdata, sizeof(tdata)); /* Prepare image */ dt = GET_DDATA(pat_window); if (typ == CHOOSE_PATTERN) render_patterns(dt->rgb); else if (typ == CHOOSE_COLOR) { make_crgb(pp, CHN_IMAGE); render_color_grid(dt->rgb, dt->wh[0], dt->wh[1], PAL_SLOT_SIZE, pp); } cmd_showhide(pat_window, TRUE); } /// ADD COLOURS TO PALETTE WINDOW static int do_add_cols(spin1_dd *dt, void **wdata) { int i; run_query(wdata); i = dt->n[0]; if (i != mem_cols) { spot_undo(UNDO_PAL); if (i > mem_cols) memset(mem_pal + mem_cols, 0, (i - mem_cols) * sizeof(png_color)); mem_cols = i; update_stuff(UPD_PAL); } return (TRUE); } void pressed_add_cols() { static spin1_dd tdata = { { _("Set Palette Size"), spin1_code, FW_FN(do_add_cols) }, { 256, 2, 256 } }; run_create_(filterwindow_code, &tdata, sizeof(tdata), script_cmds); } /* Generic code to handle UI needs of common image transform tasks */ static void do_filterwindow(filterwindow_dd *dt, void **wdata) { if (dt->evt(dt, wdata) || script_cmds) run_destroy(wdata); update_stuff(UPD_IMG); } #define WBbase filterwindow_dd void *filterwindow_code[] = { WINDOWpm(name), // modal DEFW(300), HSEP, CALLp(code), HSEP, OKBOX(_("Apply"), do_filterwindow, _("Cancel"), NULL), WSHOW }; #undef WBbase #define WBbase spin1_dd void *spin1_code[] = { SPINa(n), RET }; #undef WBbase /// BACTERIA EFFECT static int do_bacteria(spin1_dd *dt, void **wdata) { run_query(wdata); spot_undo(UNDO_FILT); mem_bacteria(dt->n[0]); mem_undo_prepare(); return (FALSE); } void pressed_bacteria() { static spin1_dd tdata = { { _("Bacteria Effect"), spin1_code, FW_FN(do_bacteria) }, { 10, 1, 100 } }; run_create_(filterwindow_code, &tdata, sizeof(tdata), script_cmds); } /// SORT PALETTE COLOURS int spal_mode; typedef struct { int rgb, rev, start[3], end[3]; } spal_dd; static void spal_evt(spal_dd *dt, void **wdata, int what) { int index1, index2; run_query(wdata); index1 = dt->start[0]; index2 = dt->end[0]; if (index1 != index2) { spot_undo(UNDO_XPAL); mem_pal_sort(spal_mode, index1, index2, dt->rev); mem_undo_prepare(); update_stuff(UPD_TPAL); } if (what == op_EVT_OK) run_destroy(wdata); } static char *spal_txt[] = { _("Hue"), _("Saturation"), _("Luminance"), _("Brightness"), _("Distance to A"), _("Red"), _("Green"), _("Blue"), _("Projection to A->B"), _("Frequency") }; #define WBbase spal_dd static void *spal_code[] = { WINDOWm(_("Sort Palette Colours")), // modal TABLE2(2), OPNAME0, TSPINa(_("Start Index"), start), TSPINa(_("End Index"), end), WDONE, BORDER(RPACK, 0), IF(rgb), RPACKv(spal_txt, 9, 5, spal_mode), UNLESS(rgb), RPACKv(spal_txt, 10, 5, spal_mode), OPNAME(""), // default CHECKb(_("Reverse Order"), rev, "palrevSort"), HSEPl(200), OKBOX3B(_("OK"), spal_evt, _("Cancel"), NULL, _("Apply"), spal_evt), WSHOW }; #undef WBbase void pressed_sort_pal() { spal_dd tdata = { mem_img_bpp == 3, FALSE, { 0, 0, mem_cols - 1 }, { mem_cols - 1, 0, mem_cols - 1 } }; run_create_(spal_code, &tdata, sizeof(tdata), script_cmds); } /// BRIGHTNESS-CONTRAST-SATURATION WINDOW transform_state def_bcsp = { { 0, 0, 0, 8, 100, 0 }, { TRUE, TRUE, TRUE } }; int mem_preview, mem_preview_clip, brcosa_auto; typedef struct { transform_state t; int rgb, show, tmode; int rgbclip, pflag; int c01[3 * 2]; void **xb; // Transform mode toggle void **sss[BRCOSA_ITEMS]; // Spinsliders void **buttons[4]; // Preview/Reset/Apply/OK void **xtra; // "Details" area png_color pal[256]; } brcosa_dd; static int check_transform_defaults(transform_state *t) { int i; for (i = 0; i < BRCOSA_ITEMS; i++) if (t->bcsp[i] != (i != BRCOSA_POSTERIZE ? def_bcsp.bcsp[i] : DEF_POSTERIZE(t->pmode))) return (TRUE); return (FALSE); } static void brcosa_preview(brcosa_dd *dt, void *cause) { int j, update = UPD_PAL; int do_pal = TRUE; // palette processing mem_pal_copy(mem_pal, dt->pal); // Get back normal palette mem_bcsp[0] = dt->t; if (mem_img_bpp == 3) { update = UPD_RENDER | UPD_PAL; do_pal = dt->pflag; // Unless user has just cleared toggle if (!do_pal && (cause != &dt->pflag)) update = UPD_RENDER; } if (do_pal) { j = dt->c01[0] > dt->c01[3] ? 3 : 0; transform_pal(mem_pal, dt->pal, dt->c01[j], dt->c01[j ^ 3]); } update_stuff(update); } static void brcosa_changed(brcosa_dd *dt, void **wdata, int what, void **where) { brcosa_preview(dt, cmd_read(where, dt)); // Update everything } static void brcosa_moved(brcosa_dd *dt, void **wdata, int what, void **where) { int i, state; void *cause = cmd_read(where, dt); if (script_cmds) return; // Useless in scripted mode if (brcosa_auto) brcosa_preview(dt, NULL); if (cause == &brcosa_auto) cmd_showhide(dt->buttons[0], !brcosa_auto); // Set 3 brcosa button as sensitive if the user has assigned changes state = check_transform_defaults(&dt->t); for (i = 1; i < 4; i++) cmd_sensitive(dt->buttons[i], state); } static void brcosa_btn(brcosa_dd *dt, void **wdata, int what) { unsigned char *mask, *mask0, *tmp, *xbuf; int i; mem_pal_copy(mem_pal, dt->pal); if (what == op_EVT_CANCEL); else if (!dt->tmode) // OK/Apply { // !!! Buttons disabled for default values spot_undo(UNDO_COL); run_query(wdata); // This may modify palette if preview active brcosa_preview(dt, NULL); // This definitely modifies it while (mem_preview && (mem_img_bpp == 3)) // This modifies image { mask = malloc(mem_width * 4); if (!mask) break; xbuf = mask + mem_width; mask0 = NULL; if (!channel_dis[CHN_MASK]) mask0 = mem_img[CHN_MASK]; tmp = mem_img[CHN_IMAGE]; for (i = 0; i < mem_height; i++) { prep_mask(0, 1, mem_width, mask, mask0, tmp); do_transform(0, 1, mem_width, mask, xbuf, tmp, 255); process_img(0, 1, mem_width, mask, tmp, tmp, xbuf, NULL, 3, BLENDF_SET | BLENDF_INVM); if (mask0) mask0 += mem_width; tmp += mem_width * 3; } free(mask); break; } if (mem_preview_clip && (mem_img_bpp == 3) && (mem_clip_bpp == 3)) { // This modifies clipboard do_transform(0, 1, mem_clip_w * mem_clip_h, NULL, mem_clipboard, mem_clipboard, 0); } mem_undo_prepare(); } else // OK/Apply for transform mode { run_query(wdata); // May modify palette, through preview mem_bcsp[1] = dt->t; // Safe: buttons disabled for default values mem_pal_copy(mem_pal, dt->pal); // Restore palette if (mem_blend) update_stuff(UPD_MODE); } // Disable preview for final update if (what != op_EVT_CLICK) mem_preview = mem_preview_clip = FALSE; update_stuff(UPD_PAL); if (what != op_EVT_CLICK) // OK/Cancel { void **xb = dt->xb; run_destroy(wdata); if (xb) // Transform mode { // Toggle transform off if still uninitialized if (!mem_bcsp[1].bcsp[BRCOSA_POSTERIZE]) cmd_set(xb, FALSE); // Show its dialog cmd_showhide(GET_WINDOW(wdata_slot(xb)), TRUE); } } else if (!dt->tmode) // Apply { // Reload palette and redo preview mem_pal_copy(dt->pal, mem_pal); brcosa_preview(dt, NULL); } } static void click_brcosa_show_toggle(brcosa_dd *dt, void **wdata, int what, void **where) { cmd_read(where, dt); cmd_showhide(dt->xtra, dt->show); } static void click_brcosa_reset(brcosa_dd *dt) { int i; mem_pal_copy(mem_pal, dt->pal); for (i = 0; i < BRCOSA_ITEMS; i++) cmd_set(dt->sss[i], i != BRCOSA_POSTERIZE ? def_bcsp.bcsp[i] : DEF_POSTERIZE(dt->t.pmode)); update_stuff(UPD_PAL); } static void brcosa_posterize_changed(brcosa_dd *dt, void **wdata, int what, void **where) { int vvv[3]; int i, v, m; cmd_read(where, dt); m = dt->t.pmode; if (!def_bcsp.pmode ^ !m) // From/to bitwise { cmd_read(dt->sss[BRCOSA_POSTERIZE], dt); v = dt->t.bcsp[BRCOSA_POSTERIZE]; if (!m) // To bitwise { for (i = 0 , v -= 1; v ; i++ , v >>= 1); vvv[0] = i; vvv[1] = 1; vvv[2] = 8; } else // From bitwise { vvv[0] = 1 << v; vvv[1] = 2; vvv[2] = 256; } cmd_setv(dt->sss[BRCOSA_POSTERIZE], vvv, SPIN_ALL); } else if (brcosa_auto) brcosa_preview(dt, NULL); def_bcsp.pmode = m; // Remember } static char *pos_txt[] = { _("Bitwise"), _("Truncated"), _("Rounded") }; #define WBbase brcosa_dd static void *brcosa_code[] = { WPMOUSE, WINDOWm(_("Transform Colour")), NORESIZE, BORDER(TABLE, 10), BORDER(SPINSLIDE, 0), TABLE2(6), OPNAME0, REF(sss[4]), TSPINSLIDE(_("Gamma"), t.bcsp[4], 20, 500), EVENT(CHANGE, brcosa_moved), REF(sss[0]), TSPINSLIDE(_("Brightness"), t.bcsp[0], -255, 255), EVENT(CHANGE, brcosa_moved), REF(sss[1]), TSPINSLIDE(_("Contrast"), t.bcsp[1], -100, 100), EVENT(CHANGE, brcosa_moved), REF(sss[2]), TSPINSLIDE(_("Saturation"), t.bcsp[2], -100, 100), EVENT(CHANGE, brcosa_moved), REF(sss[5]), TSPINSLIDE(_("Hue"), t.bcsp[5], -1529, 1529), EVENT(CHANGE, brcosa_moved), TLABEL(_("Posterize")), REF(sss[3]), UNLESS(t.pmode), T1SPINSLIDE(t.bcsp[3], 1, 8), IF(t.pmode), T1SPINSLIDE(t.bcsp[3], 2, 256), EVENT(CHANGE, brcosa_moved), WDONE, /// MIDDLE SECTION HSEP, HBOX, CHECKb(_("Show Detail"), show, "transcol_show"), UNNAME, EVENT(CHANGE, click_brcosa_show_toggle), TRIGGER, WDONE, BORDER(TABLE, 0), REF(xtra), TABLEr(4, 4), TLABEL(_("Posterize type")), BORDER(OPT, 0), TLOPTle(pos_txt, 3, t.pmode, brcosa_posterize_changed, 1, 0, 2), UNLESSx(tmode, 1), UNLESS(rgb), TLLABEL(_("Palette"), 0, 2), IFx(rgb, 2), TLCHECK(_("Palette"), pflag, 0, 2), EVENT(CHANGE, brcosa_changed), TLCHECKv(_("Image"), mem_preview, 0, 1), EVENT(CHANGE, brcosa_changed), IFx(rgbclip, 3), TLCHECKvl(_("Clipboard"), mem_preview_clip, 1, 1, 2), EVENT(CHANGE, brcosa_changed), ENDIF(3), ENDIF(2), TLHBOXl(1, 2, 2), BORDER(SPIN, 0), XSPINa(c01[0]), EVENT(CHANGE, brcosa_changed), OPNAME("from"), XSPINa(c01[3]), EVENT(CHANGE, brcosa_changed), OPNAME("to"), WDONE, ENDIF(1), TLCHECKv(_("Auto-Preview"), brcosa_auto, 0, 3), UNNAME, EVENT(CHANGE, brcosa_moved), TRIGGER, TLCHECK(_("Red"), t.allow[0], 1, 3), EVENT(CHANGE, brcosa_changed), TLCHECK(_("Green"), t.allow[1], 2, 3), EVENT(CHANGE, brcosa_changed), TLCHECK(_("Blue"), t.allow[2], 3, 3), EVENT(CHANGE, brcosa_changed), WDONE, /// BOTTOM AREA HSEP, EQBOXB, BORDER(BUTTON, 4), CANCELBTN(_("Cancel"), brcosa_btn), REF(buttons[0]), BUTTON(_("Preview"), brcosa_changed), REF(buttons[1]), BUTTON(_("Reset"), click_brcosa_reset), REF(buttons[2]), BUTTON(_("Apply"), brcosa_btn), REF(buttons[3]), OKBTN(_("OK"), brcosa_btn), WSHOW }; #undef WBbase void pressed_brcosa(void **xb) { brcosa_dd tdata = { def_bcsp, mem_img_bpp == 3, FALSE, !!xb, mem_clipboard && (mem_clip_bpp == 3), FALSE, { 0, 0, mem_cols - 1, mem_cols - 1, 0, mem_cols - 1 }, xb }; tdata.t.bcsp[BRCOSA_POSTERIZE] = DEF_POSTERIZE(tdata.t.pmode); /* Remember settings for transform mode if initialized */ if (xb && mem_bcsp[1].bcsp[BRCOSA_POSTERIZE]) tdata.t = mem_bcsp[1]; mem_pal_copy(tdata.pal, mem_pal); // Remember original palette mem_bcsp[0] = tdata.t; // !!! In case a redraw happens inside run_create() mem_preview = TRUE; // Enable live preview in RGB mode run_create_(brcosa_code, &tdata, sizeof(tdata), script_cmds); } /// RESIZE/RESCALE WINDOWS typedef struct { int script, mode, rgb; int fix, gamma; int w, h, x, y; void **spin[4]; // w, h, x, y void **book; } sisca_dd; static void sisca_moved(sisca_dd *dt, void **wdata, int what, void **where) { int w, h, nw, idx; idx = cmd_read(where, dt) != &dt->h; // _other_ spin index: w/h if (!dt->fix) return; w = dt->w; h = dt->h; if (!idx) { nw = (h * mem_width * 2 + mem_height) / (mem_height * 2); nw = nw < 1 ? 1 : nw > MAX_WIDTH ? MAX_WIDTH : nw; if (nw == w) return; } else { nw = (w * mem_height * 2 + mem_width) / (mem_width * 2); nw = nw < 1 ? 1 : nw > MAX_HEIGHT ? MAX_HEIGHT : nw; if (nw == h) return; } dt->fix = FALSE; // Prevent readjusting the original cmd_set(dt->spin[idx], nw); /* Other coordinate */ dt->fix = TRUE; } static void alert_same_geometry() { alert_box(_("Error"), _("New geometry is the same as now - nothing to do."), NULL); } static int scale_mode = 6; static int resize_mode = 0; static int boundary_mode = BOUND_MIRROR; int sharper_reduce; static void click_sisca_ok(sisca_dd *dt, void **wdata) { int nw, nh, ox, oy, res, scale_type = 0, gcor = FALSE; run_query(wdata); nw = dt->w; nh = dt->h; ox = dt->x; oy = dt->y; if (!((nw ^ mem_width) | (nh ^ mem_height) | ox | oy)) { if (!script_cmds) alert_same_geometry(); else // Allow a noop in script mode { spot_undo(UNDO_PAL); run_destroy(wdata); } return; } if (dt->mode) { if (mem_img_bpp == 3) { scale_type = scale_mode; gcor = dt->gamma; } res = mem_image_scale(nw, nh, scale_type, gcor, sharper_reduce, boundary_mode); } else res = mem_image_resize(nw, nh, ox, oy, resize_mode); if (!res) { update_stuff(UPD_GEOM); run_destroy(wdata); } else memory_errors(res); } void memory_errors(int type) { if ( type == 1 ) alert_box(_("Error"), _("The operating system cannot allocate the memory for this operation."), NULL); if ( type == 2 ) alert_box(_("Error"), _("You have not allocated enough memory in the Preferences window for this operation."), NULL); } static void click_sisca_centre(sisca_dd *dt, void **wdata) { int nw = dt->w, nh = dt->h; // !!! sisca_moved() keeps these updated cmd_set(dt->spin[2], (nw - mem_width) / 2); cmd_set(dt->spin[3], (nh - mem_height) / 2); } static char *bound_modes[] = { _("Mirror"), _("Tile"), _("Void") }; static char *resize_modes[] = { _("Clear"), _("Tile"), _("Mirror tile"), NULL }; static char *scale_modes[] = { _("Nearest Neighbour"), _("Bilinear / Area Mapping"), _("Bicubic"), _("Bicubic edged"), _("Bicubic better"), _("Bicubic sharper"), _("Blackman-Harris"), NULL }; #define WBbase sisca_dd static void *sisca_code[] = { IF(mode), WINDOWm(_("Scale Canvas")), UNLESS(mode), WINDOWm(_("Resize Canvas")), TABLE(3, 3), // !!! in fact 5 rows in resize mode BORDER(LABEL, 0), TLLABEL(_("Original "), 0, 1), TLNOSPIN(w, 1, 1), TLNOSPIN(h, 2, 1), TLABEL(_("New")), TLLABEL(_("Width "), 1, 0), REF(spin[0]), UNLESS(script), TLSPIN(w, 1, MAX_WIDTH, 1, 2), IF(script), uSCALE(w, 1, MAX_WIDTH), EVENT(CHANGE, sisca_moved), TLLABEL(_("Height "), 2, 0), REF(spin[1]), UNLESS(script), TLSPIN(h, 1, MAX_HEIGHT, 2, 2), IF(script), uSCALE(h, 1, MAX_HEIGHT), EVENT(CHANGE, sisca_moved), UNLESSx(mode, 1), TLABEL(_("Offset")), REF(spin[2]), TLSPIN(x, -MAX_WIDTH, MAX_WIDTH, 1, 3), OPNAME("X"), REF(spin[3]), TLSPIN(y, -MAX_HEIGHT, MAX_HEIGHT, 2, 3), OPNAME("Y"), TLBUTTONs(_("Centre"), click_sisca_centre, 0, 4), ENDIF(1), WDONE, HSEP, BORDER(RPACK, 0), IF(rgb), HBOX, IF(rgb), VBOX, IFx(mode, 1), CHECKb(_("Fix Aspect Ratio"), fix, "scaleAspect"), EVENT(CHANGE, sisca_moved), ENDIF(1), IFx(rgb, 1), CHECK(_("Gamma corrected"), gamma), WDONE, EVBOX, BOOKBTN(_("Settings"), book), WDONE, WDONE, HSEP, REF(book), PLAINBOOK, // pages 0 and 1 are both stacked RPACKv(scale_modes, 0, 0, scale_mode), OPNAME(""), HSEP, WDONE, // page 0 CHECKv(_("Sharper image reduction"), sharper_reduce), FRPACKv(_("Boundary extension"), bound_modes, 3, 0, boundary_mode), WDONE, // page 1 ENDIF(1), UNLESSx(mode, 1), CHECKb(_("Fix Aspect Ratio"), fix, "resizeAspect"), EVENT(CHANGE, sisca_moved), HSEP, RPACKv(resize_modes, 0, 0, resize_mode), OPNAME(""), ENDIF(1), UNLESS(rgb), HSEP, OKBOXB(_("OK"), click_sisca_ok, _("Cancel"), NULL), WSHOW }; #undef WBbase void pressed_scale_size(int mode) { sisca_dd tdata = { !!script_cmds, mode, mode && (mem_img_bpp == 3), TRUE, use_gamma, mem_width, mem_height, 0, 0 }; run_create_(sisca_code, &tdata, sizeof(tdata), script_cmds); } /// PALETTE EDITOR WINDOW enum { CHOOK_CANCEL = 0, CHOOK_PREVIEW, CHOOK_OK, CHOOK_SELECT, CHOOK_SET, CHOOK_UNVIEW, CHOOK_CHANGE }; typedef struct { unsigned char rgb[768]; // everything needs it unsigned char opac[256]; // only EDIT_OVERLAYS uses it int AB[4][NUM_CHANNELS]; // for EDIT_AB int csrange, csinv, csmode; // for EDIT_CSEL int cgrid, tgrid, grid_min, tgrid_dx, tgrid_dy; // for GRID } csdata_dd; typedef struct colsel_dd colsel_dd; typedef void (*colsel_fn)(colsel_dd *dt, int what); struct colsel_dd { colsel_fn select; char *name, **cnames; int opflag, mpflag; int cnt, idx; int preview; int rflag; // recursion int color[2]; void **clist, **csel; int is_pal; int n0, n1, scale; void **fbutton, **fspin, **tspin; int is_AB; int pos_AB, v_AB[NUM_CHANNELS]; void **xtbox, **pspin_AB, **spin_AB[NUM_CHANNELS]; int is_csel; void **fspin_csel; int is_grid; csdata_dd v, v0; // primary and backup }; /* Put current color in list into selector */ static void colsel_show_idx(colsel_dd *dt) { unsigned char *c = dt->v.rgb + dt->idx * 3; int color[4]; color[2] = color[0] = MEM_2_INT(c, 0); color[3] = color[1] = dt->v.opac[dt->idx]; dt->rflag = TRUE; // prevent recursion cmd_setv(dt->csel, color, COLOR_ALL); dt->rflag = FALSE; } static void color_refresh(colsel_dd *dt) { colsel_show_idx(dt); cmd_repaint(dt->clist); } static void do_allcol(csdata_dd *v) { rgb2pal(mem_pal, v->rgb, mem_cols); update_stuff(UPD_PAL); } static void do_allover(csdata_dd *v) { unsigned char *rgb = v->rgb; int i; for (i = 0; i < NUM_CHANNELS; i++) { channel_rgb[i][0] = rgb[0]; channel_rgb[i][1] = rgb[1]; channel_rgb[i][2] = rgb[2]; channel_opacity[i] = v->opac[i]; rgb += 3; } update_stuff(UPD_RENDER); } static void do_AB(csdata_dd *v) { png_color *A0, *B0; A0 = mem_img_bpp == 1 ? &mem_pal[mem_col_A] : &mem_col_A24; B0 = mem_img_bpp == 1 ? &mem_pal[mem_col_B] : &mem_col_B24; A0->red = v->rgb[0]; A0->green = v->rgb[1]; A0->blue = v->rgb[2]; B0->red = v->rgb[3]; B0->green = v->rgb[4]; B0->blue = v->rgb[5]; mem_pal_ab_c = MEM_2_INT(v->rgb, 6); mem_pal_id_c = MEM_2_INT(v->rgb, 9); update_stuff(mem_img_bpp == 1 ? UPD_PAL : UPD_AB); } static void set_csel(csdata_dd *v) { unsigned char *rgb = v->rgb; csel_data->center = MEM_2_INT(rgb, 0); csel_data->limit = MEM_2_INT(rgb, 3); csel_preview = MEM_2_INT(rgb, 6); /* !!! Disabled for now - later will be opacity */ // csel_preview_a = v->opac[2]; csel_data->mode = v->csmode; csel_data->range = v->csrange / 100.0; csel_data->invert = v->csinv; } static void set_grid(csdata_dd *v) { unsigned char *rgb = v->rgb; int i; for (i = 0; i < GRID_MAX; i++) { grid_rgb[i] = MEM_2_INT(rgb, 0); rgb += 3; } color_grid = v->cgrid; show_tile_grid = v->tgrid; mem_grid_min = v->grid_min; tgrid_dx = v->tgrid_dx; tgrid_dy = v->tgrid_dy; } static void select_colour(colsel_dd *dt, int what) { switch (what) { case CHOOK_UNVIEW: /* Disable preview */ case CHOOK_CANCEL: /* Cancel */ do_allcol(&dt->v0); break; case CHOOK_SET: /* Set */ if (!dt->preview) break; case CHOOK_PREVIEW: /* Preview */ do_allcol(&dt->v); break; case CHOOK_OK: /* OK */ do_allcol(&dt->v0); spot_undo(UNDO_PAL); do_allcol(&dt->v); break; } } static void click_colour(colsel_dd *dt, void **wdata, int what, void **where, colorlist_ext *xdata) { /* Middle click sets "from" */ if (xdata->button == 2) cmd_set(dt->fspin, xdata->idx); /* Right click sets "to" */ if (xdata->button == 3) cmd_set(dt->tspin, xdata->idx); } static void set_range_spin(colsel_dd *dt, void **wdata, int what, void **where) { cmd_set(origin_slot(where) == dt->fbutton ? dt->fspin : dt->tspin, dt->idx); } static void make_cscale(colsel_dd *dt, void **wdata) { int i, n, start, stop, start0, mode; unsigned char *c0, *c1, *lc; double d; run_query(wdata); mode = dt->scale; start = start0 = dt->n0; stop = dt->n1; if (mode <= 2) /* RGB/sRGB/HSV */ { if (start > stop) { i = start; start = stop; stop = i; } if (stop < start + 2) return; } else if (stop == start) return; /* Gradient */ c0 = lc = dt->v.rgb + start * 3; c1 = dt->v.rgb + stop * 3; d = n = stop - start; switch (mode) { case 0: /* RGB */ { double r0, g0, b0, dr, dg, db; dr = ((int)c1[0] - c0[0]) / d; r0 = c0[0]; dg = ((int)c1[1] - c0[1]) / d; g0 = c0[1]; db = ((int)c1[2] - c0[2]) / d; b0 = c0[2]; for (i = 1; i < n; i++) { lc += 3; lc[0] = rint(r0 + dr * i); lc[1] = rint(g0 + dg * i); lc[2] = rint(b0 + db * i); } break; } case 1: /* sRGB */ { double r0, g0, b0, dr, dg, db, rr, gg, bb; dr = (gamma256[c1[0]] - (r0 = gamma256[c0[0]])) / d; dg = (gamma256[c1[1]] - (g0 = gamma256[c0[1]])) / d; db = (gamma256[c1[2]] - (b0 = gamma256[c0[2]])) / d; for (i = 1; i < n; i++) { lc += 3; rr = r0 + dr * i; lc[0] = UNGAMMA256(rr); gg = g0 + dg * i; lc[1] = UNGAMMA256(gg); bb = b0 + db * i; lc[2] = UNGAMMA256(bb); } break; } case 2: /* HSV */ { int t; double h0, dh, s0, ds, v0, dv, hsv[6], hh, ss, vv; rgb2hsv(c0, hsv + 0); rgb2hsv(c1, hsv + 3); /* Grey has no hue */ if (hsv[1] == 0.0) hsv[0] = hsv[3]; if (hsv[4] == 0.0) hsv[3] = hsv[0]; /* Always go from 1st to 2nd hue in ascending order */ t = start == start0 ? 0 : 3; if (hsv[t] > hsv[t ^ 3]) hsv[t] -= 6.0; dh = (hsv[3] - hsv[0]) / d; h0 = hsv[0]; ds = (hsv[4] - hsv[1]) / d; s0 = hsv[1]; dv = (hsv[5] - hsv[2]) / d; v0 = hsv[2]; for (i = 1; i < n; i++) { vv = v0 + dv * i; ss = vv - vv * (s0 + ds * i); hh = h0 + dh * i; if (hh < 0.0) hh += 6.0; t = hh; hh = (hh - t) * (vv - ss); if (t & 1) { vv -= hh; hh += vv; } else hh += ss; t >>= 1; lc += 3; lc[t] = rint(vv); lc[(t + 1) % 3] = rint(hh); lc[(t + 2) % 3] = rint(ss); } break; } default: /* Gradient */ { int j, op, c[NUM_CHANNELS + 3]; j = start < stop ? 1 : -1; for (i = 0; i != n + j; i += j , lc += j * 3) { op = grad_value(c, 0, i / d); /* Zero opacity - empty slot */ if (!op) lc[0] = lc[1] = lc[2] = 0; else { lc[0] = (c[0] + 128) >> 8; lc[1] = (c[1] + 128) >> 8; lc[2] = (c[2] + 128) >> 8; } } break; } } color_refresh(dt); select_colour(dt, CHOOK_SET); } static void select_overlay(colsel_dd *dt, int what) { char txt[64]; int i, j; switch (what) { case CHOOK_UNVIEW: /* Disable preview */ case CHOOK_CANCEL: /* Cancel */ do_allover(&dt->v0); // Restore original values break; case CHOOK_SET: /* Set */ if (!dt->preview) break; case CHOOK_PREVIEW: /* Preview */ do_allover(&dt->v); break; case CHOOK_OK: /* OK */ do_allover(&dt->v); for (i = 0; i < NUM_CHANNELS; i++) // Save all settings to ini file { for (j = 0; j < 4; j++) { sprintf(txt, "overlay%i%i", i, j); inifile_set_gint32(txt, j < 3 ? channel_rgb[i][j] : channel_opacity[i]); } } break; } } static void select_AB(colsel_dd *dt, int what) { int i, *v; switch (what) { case CHOOK_UNVIEW: /* Disable preview */ case CHOOK_CANCEL: /* Cancel */ do_AB(&dt->v0); break; case CHOOK_OK: /* OK */ do_AB(&dt->v0); /* Palette gets modified in indexed mode */ if (mem_img_bpp == 1) spot_undo(UNDO_PAL); for (i = CHN_ALPHA; i < NUM_CHANNELS; i++) { channel_col_A[i] = dt->v.AB[0][i]; channel_col_B[i] = dt->v.AB[1][i]; } do_AB(&dt->v); break; case CHOOK_SET: /* Set */ if (!dt->preview) break; case CHOOK_PREVIEW: /* Preview */ do_AB(&dt->v); break; case CHOOK_SELECT: /* Select */ v = dt->v.AB[dt->idx]; for (i = CHN_ALPHA; i < NUM_CHANNELS; i++) cmd_set(dt->spin_AB[i], v[i]); cmd_sensitive(dt->xtbox, dt->idx < 2); break; } } static void AB_spin_moved(colsel_dd *dt, void **wdata, int what, void **where) { int *w = cmd_read(where, dt); dt->v.AB[dt->idx][w - dt->v_AB] = *w; } static void posterize_AB(colsel_dd *dt, void **wdata) { static const int posm[8] = {0, 0xFF00, 0x5500, 0x2480, 0x1100, 0x0840, 0x0410, 0x0204}; unsigned char *lc = dt->v.rgb; int i, pm, ps; cmd_read(dt->pspin_AB, dt); inifile_set_gint32("posterizeInt", ps = dt->pos_AB); if (ps >= 8) return; pm = posm[ps]; ps = 8 - ps; for (i = 0; i < 6; i++) lc[i] = ((lc[i] >> ps) * pm) >> 8; color_refresh(dt); select_AB(dt, CHOOK_SET); } static void select_csel(colsel_dd *dt, int what) { int old_over = csel_overlay; switch (what) { case CHOOK_CANCEL: /* Cancel */ set_csel(&dt->v0); csel_reset(csel_data); case CHOOK_UNVIEW: /* Disable preview */ csel_overlay = 0; if (old_over) update_stuff(UPD_RENDER); break; case CHOOK_PREVIEW: /* Preview */ csel_overlay = 1; case CHOOK_CHANGE: /* Range/mode/invert controls changed */ if (!csel_overlay) break; // No preview case CHOOK_OK: /* OK */ set_csel(&dt->v); csel_reset(csel_data); if (what == CHOOK_OK) { csel_overlay = 0; update_stuff(UPD_RENDER | UPD_MODE); } else update_stuff(UPD_RENDER); break; case CHOOK_SET: /* Set */ set_csel(&dt->v); if (dt->idx == 1) /* Limit color changed */ { // This triggers CHOOK_CHANGE which will redraw cmd_set(dt->fspin_csel, rint(csel_eval(csel_data->mode, csel_data->center, csel_data->limit) * 100)); } else if (csel_overlay) { /* Center color changed */ if (!dt->idx) csel_reset(csel_data); /* Else, overlay color changed */ update_stuff(UPD_RENDER); } break; } } static void csel_controls_changed(colsel_dd *dt, void **wdata, int what, void **where) { if (cmd_read(where, dt) == &dt->v.csmode) { set_csel(&dt->v); // This triggers CHOOK_CHANGE which will redraw cmd_set(dt->fspin_csel, rint(csel_eval(csel_data->mode, csel_data->center, csel_data->limit) * 100)); } else select_csel(dt, CHOOK_CHANGE); } static void select_grid(colsel_dd *dt, int what) { switch (what) { case CHOOK_UNVIEW: /* Disable preview */ case CHOOK_CANCEL: /* Cancel */ // Restore original values set_grid(&dt->v0); break; case CHOOK_CHANGE: /* Grid controls changed */ case CHOOK_SET: /* Set */ if (!dt->preview) return; case CHOOK_PREVIEW: /* Preview */ case CHOOK_OK: /* OK */ set_grid(&dt->v); break; default: return; } update_stuff(UPD_RENDER); } static void grid_controls_changed(colsel_dd *dt, void **wdata, int what, void **where) { cmd_read(where, dt); select_grid(dt, CHOOK_CHANGE); } static void colsel_evt(colsel_dd *dt, void **wdata, int what, void **where) { void *cause; if (dt->rflag) return; // skip recursive calls cause = cmd_read(where, dt); if (cause == &dt->idx) { colsel_show_idx(dt); // Set selected color dt->select(dt, CHOOK_SELECT); } else if (cause == &dt->color) { unsigned char *c = dt->v.rgb + dt->idx * 3; int col = dt->color[0]; /* Opacity */ dt->v.opac[dt->idx] = dt->color[1]; /* Color */ c[0] = INT_2_R(col); c[1] = INT_2_G(col); c[2] = INT_2_B(col); cmd_setv(dt->clist, (void *)dt->idx, COLORLIST_RESET_ROW); dt->select(dt, CHOOK_SET); } else if (cause == &dt->preview) dt->select(dt, dt->preview ? CHOOK_PREVIEW : CHOOK_UNVIEW); else if (what == op_EVT_OK) { run_query(wdata); // for final updating, and for extra part dt->select(dt, CHOOK_OK); run_destroy(wdata); } else if (what == op_EVT_CANCEL) { dt->select(dt, CHOOK_CANCEL); run_destroy(wdata); } } static int colsel_pick_pixel(colsel_dd *dt, void **wdata, int what, void **where, multi_ext *mx) { int pix, *row = mx->rows[0] + 1; /* Sanity check */ if ((mx->ncols != 2) || (mx->nrows != 1) || (mx->fractcol >= 0)) return (0); if ((row[0] < 0) || (row[1] < 0) || (row[0] >= mem_width) || (row[1] >= mem_height)) pix = mem_background * 0x010101; // Grey outside image else pix = get_pixel_RGB(row[0], row[1]); cmd_set(origin_slot(where), pix); return (1); } static char *scales_txt[] = { _("RGB"), _("sRGB"), _("HSV"), _("Gradient") }; static char *AB_txt[] = { "A", "B", _("Highlight"), _("Index"), NULL }; static char *csel_txt[] = { _("Centre"), _("Limit"), _("Preview"), NULL }; static char *csel_modes[] = { _("Sphere"), _("Angle"), _("Cube"), NULL }; static char *grid_txt[GRID_MAX + 1] = { _("Opaque"), _("Border"), _("Transparent"), _("Tile "), _("Segment"), NULL }; /* !!! "Tile " has a trailing space to be distinct from "Tile" in "Resize Canvas" */ #if NUM_CHANNELS > CHN_MASK + 1 #error "Not all channels listed in dialog" #endif #define WBbase colsel_dd static void *colsel_code[] = { IF(mpflag), WPMOUSE, WINDOWpm(name), BORDER(SCROLL, 0), BORDER(BUTTON, 4), REF(clist), IFx(is_pal, 1), // long-list form - for now only palette needs it XHBOXS, SCROLL(0, 1), // never/auto COLORLISTN(cnt, idx, v.rgb, colsel_evt, click_colour), XVBOXBS, ENDIF(1), UNLESSx(is_pal, 1), // short-list form (6 items or less) XVBOXBS, XHBOXbp(10, 0, 0), SCROLL(0, 1), // never/auto COLORLIST(cnames, idx, v.rgb, colsel_evt, NULL), ENDIF(1), TRIGGER, // colorlist SELECT REF(csel), IF(opflag), TCOLOR(color), // with opacity UNLESS(opflag), COLOR(color), // solid colors EVENT(CHANGE, colsel_evt), OPNAME("Colour"), EVENT(MULTI, colsel_pick_pixel), UNLESS(is_pal), WDONE, /* Task-specific part */ BORDER(TABLE, 0), IFx(is_pal, 1), BORDER(SPIN, 0), BORDER(LABEL, 0), HBOX, MLABEL(_("Scale")), REF(fbutton), BUTTON(_("From"), set_range_spin), REF(fspin), SPIN(n0, 0, 255), BUTTON(_("To"), set_range_spin), REF(tspin), SPIN(n1, 0, 255), BORDER(OPT, 0), XVBOXbp(0, 4, 0), OPT(scales_txt, 4, scale), EVENT(SCRIPT, make_cscale), OPNAME("Scale"), WDONE, BUTTON(_("Create"), make_cscale), WDONE, ENDIF(1), IFx(is_AB, 1), BORDER(SPINSLIDE, 0), BORDER(LABEL, 0), REF(xtbox), VBOXr, HBOX, BUTTON(_("Posterize"), posterize_AB), REF(pspin_AB), SPIN(pos_AB, 1, 8), EVENT(SCRIPT, posterize_AB), WDONE, TABLE(3, 2), TXLABEL(_("Alpha"), 0, 0), REF(spin_AB[CHN_ALPHA]), TLSPINSLIDEx(v_AB[CHN_ALPHA], 0, 255, 0, 1), EVENT(CHANGE, AB_spin_moved), TXLABEL(_("Selection"), 1, 0), REF(spin_AB[CHN_SEL]), TLSPINSLIDEx(v_AB[CHN_SEL], 0, 255, 1, 1), EVENT(CHANGE, AB_spin_moved), TXLABEL(_("Mask"), 2, 0), REF(spin_AB[CHN_MASK]), TLSPINSLIDEx(v_AB[CHN_MASK], 0, 255, 2, 1), EVENT(CHANGE, AB_spin_moved), WDONE, WDONE, // VBOXr ENDIF(1), IFx(is_csel, 1), BORDER(SPIN, 0), BORDER(LABEL, 0), BORDER(RPACK, 0), HBOX, MLABEL(_("Range")), REF(fspin_csel), FSPIN(v.csrange, 0, 76500), EVENT(CHANGE, csel_controls_changed), CHECK(_("Inverse"), v.csinv), EVENT(CHANGE, csel_controls_changed), RPACKe(csel_modes, 0, 1, v.csmode, csel_controls_changed), FLATTEN, OPNAME("Mode"), WDONE, ENDIF(1), IFx(is_grid, 1), BORDER(SPIN, 0), TABLE(6, 2), TLCHECK(_("Smart grid"), v.cgrid, 0, 0), EVENT(CHANGE, grid_controls_changed), TLCHECKl(_("Tile grid"), v.tgrid, 1, 0, 2), EVENT(CHANGE, grid_controls_changed), TLLABEL(_("Minimum grid zoom"), 0, 1), TLXSPIN(v.grid_min, 2, 12, 1, 1), EVENT(CHANGE, grid_controls_changed), TLLABEL(_("Tile width"), 2, 1), TLXSPIN(v.tgrid_dx, 2, MAX_WIDTH, 3, 1), EVENT(CHANGE, grid_controls_changed), TLLABEL(_("Tile height"), 4, 1), TLXSPIN(v.tgrid_dy, 2, MAX_HEIGHT, 5, 1), EVENT(CHANGE, grid_controls_changed), WDONE, ENDIF(1), HBOX, MINWIDTH(260), EEQBOX, DEFBORDER(BUTTON), CANCELBTN(_("Cancel"), colsel_evt), TOGGLE(_("Preview"), preview, colsel_evt), OKBTN(_("OK"), colsel_evt), WSHOW }; #undef WBbase void colour_selector(int cs_type) { colsel_dd tdata; unsigned char *rgb = tdata.v.rgb; int i; memset(&tdata, 0, sizeof(tdata)); if (cs_type >= COLSEL_EDIT_ALL) { tdata.select = select_colour; tdata.name = _("Palette Editor"); tdata.mpflag = TRUE; tdata.cnt = mem_cols; tdata.idx = cs_type - COLSEL_EDIT_ALL; tdata.is_pal = TRUE; pal2rgb(rgb, mem_pal, mem_cols, 0); // Opacity (unused) // memset(tdata.v.opac, 255, mem_cols); } else if (cs_type == COLSEL_OVERLAYS) { tdata.select = select_overlay; tdata.name = _("Configure Overlays"); tdata.cnames = channames_; tdata.opflag = TRUE; tdata.cnt = NUM_CHANNELS; for (i = 0; i < NUM_CHANNELS; i++) { tdata.v.opac[i] = channel_opacity[i]; rgb[0] = channel_rgb[i][0]; rgb[1] = channel_rgb[i][1]; rgb[2] = channel_rgb[i][2]; rgb += 3; } } else if (cs_type == COLSEL_EDIT_AB) { png_color *A0 = &mem_col_A24, *B0 = &mem_col_B24; tdata.select = select_AB; tdata.name = _("Colour Editor"); tdata.cnames = AB_txt; tdata.mpflag = TRUE; // at cursor tdata.cnt = 4; tdata.is_AB = TRUE; tdata.pos_AB = inifile_get_gint32("posterizeInt", 1); if (mem_img_bpp == 1) A0 = &mem_pal[mem_col_A] , B0 = &mem_pal[mem_col_B]; rgb[0] = A0->red; rgb[1] = A0->green; rgb[2] = A0->blue; rgb[3] = B0->red; rgb[4] = B0->green; rgb[5] = B0->blue; rgb[6] = INT_2_R(mem_pal_ab_c); rgb[7] = INT_2_G(mem_pal_ab_c); rgb[8] = INT_2_B(mem_pal_ab_c); rgb[9] = INT_2_R(mem_pal_id_c); rgb[10] = INT_2_G(mem_pal_id_c); rgb[11] = INT_2_B(mem_pal_id_c); for (i = CHN_ALPHA; i < NUM_CHANNELS; i++) { tdata.v.AB[0][i] = tdata.v_AB[i] = channel_col_A[i]; tdata.v.AB[1][i] = channel_col_B[i]; } // Opacity (unused) // tdata.v.opac[0] = tdata.v.opac[1] = 255; } else if (cs_type == COLSEL_EDIT_CSEL) { if (!csel_data) { csel_init(); if (!csel_data) return; } tdata.select = select_csel; tdata.name = _("Colour-Selective Mode"); tdata.cnames = csel_txt; tdata.cnt = 3; tdata.is_csel = TRUE; tdata.v.csrange = rint(csel_data->range * 100); tdata.v.csinv = csel_data->invert; tdata.v.csmode = csel_data->mode; rgb[0] = INT_2_R(csel_data->center); rgb[1] = INT_2_G(csel_data->center); rgb[2] = INT_2_B(csel_data->center); rgb[3] = INT_2_R(csel_data->limit); rgb[4] = INT_2_G(csel_data->limit); rgb[5] = INT_2_B(csel_data->limit); rgb[6] = INT_2_R(csel_preview); rgb[7] = INT_2_G(csel_preview); rgb[8] = INT_2_B(csel_preview); // Opacity (unused) // tdata.v.opac[0] = tdata.v.opac[1] = 255; // tdata.v.opac[2] = csel_preview_a; } else if (cs_type == COLSEL_GRID) { tdata.select = select_grid; tdata.name = _("Configure Grid"); tdata.cnames = grid_txt; tdata.cnt = GRID_MAX; tdata.is_grid = TRUE; tdata.v.cgrid = color_grid; tdata.v.tgrid = show_tile_grid; tdata.v.grid_min = mem_grid_min; tdata.v.tgrid_dx = tgrid_dx; tdata.v.tgrid_dy = tgrid_dy; for (i = 0; i < GRID_MAX; i++) { rgb[0] = INT_2_R(grid_rgb[i]); rgb[1] = INT_2_G(grid_rgb[i]); rgb[2] = INT_2_B(grid_rgb[i]); // Opacity (unused) // tdata.v.opac[i] = 255; rgb += 3; } } tdata.v0 = tdata.v; // Save original values run_create_(colsel_code, &tdata, sizeof(tdata), script_cmds); } /// QUANTIZE WINDOW #define QUAN_EXACT 0 #define QUAN_CURRENT 1 #define QUAN_PNN 2 #define QUAN_WU 3 #define QUAN_MAXMIN 4 #define QUAN_MAX 5 #define DITH_NONE 0 #define DITH_FS 1 #define DITH_STUCKI 2 #define DITH_ORDERED 3 #define DITH_DUMBFS 4 #define DITH_OLDDITHER 5 #define DITH_OLDSCATTER 6 #define DITH_MAX 7 typedef struct { int pflag; int cols, cols0; int err; png_color newpal[256]; char **qtxt; void **dith, **colspin, **errspin; void **book, **qbook; } quantize_dd; /* Quantization & dither settings - persistent */ static int quantize_mode = -1, dither_mode = -1; static int quantize_tp; static int dither_cspace = CSPACE_SRGB, dither_dist = DIST_L2, dither_limit; static int dither_scan = TRUE, dither_8b, dither_sel; static int dither_pfract[2] = { 100, 85 }; static void click_quantize_radio(quantize_dd *dt, void **wdata, int what, void **where) { int vvv[3] = { 1, 1, 256 }, n; cmd_read(where, dt); n = quantize_mode; cmd_set(dt->qbook, (n == QUAN_PNN) || (n == QUAN_WU) ? 2 : n == QUAN_CURRENT ? 1 : 0); if (n == QUAN_EXACT) vvv[1] = vvv[2] = dt->cols0; else if (n == QUAN_CURRENT) vvv[2] = mem_cols; cmd_read(dt->colspin, dt); vvv[0] = dt->cols; // !!! gets bounded when setting cmd_setv(dt->colspin, vvv, SPIN_ALL); /* No dither for exact conversion */ if (!dt->pflag) cmd_sensitive(dt->dith, n != QUAN_EXACT); } static void click_quantize_ok(quantize_dd *dt, void **wdata) { int i, dither, new_cols, have_image = !dt->pflag, err = 0; int quantize_cols = dt->cols0, efrac = 0; png_color newpal[256]; unsigned char *old_image = mem_img[CHN_IMAGE]; /* Dithering filters */ /* Floyd-Steinberg dither */ static short fs_dither[16] = { 16, 0, 0, 0, 7, 0, 0, 3, 5, 1, 0, 0, 0, 0, 0, 0 }; /* Stucki dither */ static short s_dither[16] = { 42, 0, 0, 0, 8, 4, 2, 4, 8, 4, 2, 1, 2, 4, 2, 1 }; run_query(wdata); dither = quantize_mode != QUAN_EXACT ? dither_mode : DITH_NONE; new_cols = dt->cols; mem_pal_copy(newpal, dt->newpal); if (have_image) /* Work on image */ dither_pfract[dither_sel ? 1 : 0] = efrac = dt->err; /* !!! No touching dt past this point */ run_destroy(wdata); /* Paranoia */ if ((quantize_mode >= QUAN_MAX) || (dither >= DITH_MAX)) return; if (!have_image && (quantize_mode == QUAN_CURRENT)) return; i = undo_next_core(UC_NOCOPY, mem_width, mem_height, have_image ? 1 : mem_img_bpp, have_image ? CMASK_IMAGE : CMASK_NONE); if (i) { memory_errors(i); return; } switch (quantize_mode) { case QUAN_EXACT: /* Use image colours */ new_cols = quantize_cols; if (have_image) err = mem_convert_indexed(mem_img[CHN_IMAGE], old_image, mem_width * mem_height, new_cols, newpal); dither = DITH_MAX; break; default: case QUAN_CURRENT: /* Use current palette */ break; case QUAN_PNN: /* PNN quantizer */ err = pnnquan(old_image, mem_width, mem_height, new_cols, newpal); break; case QUAN_WU: /* Wu quantizer */ err = wu_quant(old_image, mem_width, mem_height, new_cols, newpal); break; case QUAN_MAXMIN: /* Max-Min quantizer */ err = maxminquan(old_image, mem_width, mem_height, new_cols, newpal); break; } if (err) dither = DITH_MAX; else if (quantize_mode != QUAN_CURRENT) { memcpy(mem_pal, newpal, new_cols * sizeof(*mem_pal)); mem_cols = new_cols; } else if (quantize_tp) mem_cols = new_cols; // Truncate palette if (!have_image) /* Palette only */ { if (err < 0) memory_errors(1); update_stuff(UPD_PAL | CF_MENU); return; } switch (dither) { case DITH_NONE: case DITH_FS: case DITH_STUCKI: err = mem_dither(old_image, new_cols, dither == DITH_NONE ? NULL : dither == DITH_FS ? fs_dither : s_dither, dither_cspace, dither_dist, dither_limit, dither_sel, dither_scan, dither_8b, efrac * 0.01); break; // !!! No code yet - temporarily disabled !!! // case DITH_ORDERED: case DITH_DUMBFS: err = mem_dumb_dither(old_image, mem_img[CHN_IMAGE], mem_pal, mem_width, mem_height, new_cols, TRUE); break; case DITH_OLDDITHER: err = mem_quantize(old_image, new_cols, 2); break; case DITH_OLDSCATTER: err = mem_quantize(old_image, new_cols, 3); break; case DITH_MAX: /* Stay silent unless a memory error happened */ err = err < 0; break; } if (err) memory_errors(1); /* Image was converted */ mem_col_A = mem_cols > 1 ? 1 : 0; mem_col_B = 0; update_stuff(UPD_2IDX); } static void choose_selective(quantize_dd *dt, void **wdata, int what, void **where) { int i = dither_sel; cmd_read(where, dt); /* Selectivity state toggled */ if ((i = !i) ^ !dither_sel) { cmd_read(dt->errspin, dt); dither_pfract[i ^ 1] = dt->err; cmd_set(dt->errspin, dither_pfract[i]); } } static char *quan_txt[] = { _("Exact Conversion"), _("Use Current Palette"), _("PNN Quantize (slow, better quality)"), _("Wu Quantize (fast)"), _("Max-Min Quantize (best for small palettes and dithering)"), NULL }; static char *dith_txt[] = { _("None"), _("Floyd-Steinberg"), _("Stucki"), // !!! "Ordered" not done yet !!! /* _("Ordered") */ "", _("Floyd-Steinberg (quick)"), _("Dithered (effect)"), _("Scattered (effect)"), NULL }; static char *clamp_txt[] = { _("Gamut"), _("Weakly"), _("Strongly") }; static char *err_txt[] = { _("Off"), _("Separate/Sum"), _("Separate/Split"), _("Length/Sum"), _("Length/Split"), NULL }; static char *dist_txt[] = { _("Largest (Linf)"), _("Sum (L1)"), _("Euclidean (L2)") }; #define WBbase quantize_dd static void *quantize_code[] = { IF(pflag), WINDOWm(_("Create Quantized")), UNLESS(pflag), WINDOWm(_("Convert To Indexed")), BORDER(RPACK, 0), BORDER(LABEL, 0), HBOXbp(5, 10, 0), MLABEL(_("Indexed Colours To Use")), DEFBORDER(LABEL), BORDER(SPIN, 0), REF(colspin), XSPIN(cols, 1, 256), DEFBORDER(SPIN), UNLESS(pflag), BOOKBTN(_("Settings"), book), WDONE, REF(book), UNLESS(pflag), PLAINBOOK, /* Main page - Palette frame */ FVBOX(_("Palette")), RPACKDve(qtxt, 0, quantize_mode, click_quantize_radio), TRIGGER, REF(qbook), PLAINBOOKn(3), WDONE, // empty page 0 CHECKv(_("Truncate palette"), quantize_tp), WDONE, // page 1 CHECKv(_("Diameter based weighting"), quan_sqrt), WDONE, // page 2 WDONE, UNLESSx(pflag, 1), /* Main page - Dither frame */ REF(dith), FRPACKv(_("Dither"), dith_txt, 0, DITH_MAX / 2, dither_mode), WDONE, /* Settings page */ FRPACKv(_("Colour space"), cspnames_, NUM_CSPACES, 1, dither_cspace), FRPACKv(_("Difference measure"), dist_txt, 3, 1, dither_dist), FRPACKv(_("Reduce colour bleed"), clamp_txt, 3, 1, dither_limit), CHECKv(_("Serpentine scan"), dither_scan), TABLE2(2), REF(errspin), TSPIN(_("Error propagation, %"), err, 0, 100), TLABEL(_("Selective error propagation")), BORDER(OPT, 0), TLOPTve(err_txt, 0, dither_sel, choose_selective, 1, 1), WDONE, CHECKv(_("Full error precision"), dither_8b), WDONE, ENDIF(1), /* OK / Cancel */ OKBOX(_("OK"), click_quantize_ok, _("Cancel"), NULL), WSHOW }; #undef WBbase void pressed_quantize(int palette) { char *qnames[sizeof(quan_txt) / sizeof(quan_txt[0])]; quantize_dd tdata; tdata.pflag = palette; tdata.cols = tdata.cols0 = mem_cols_used(tdata.newpal); tdata.qtxt = qnames; memcpy(qnames, quan_txt, sizeof(qnames)); /* No exact transfer if too many colours */ if (tdata.cols > 256) qnames[QUAN_EXACT] = ""; if (palette) qnames[QUAN_CURRENT] = ""; if ((quantize_mode < 0) || !qnames[quantize_mode][0]) // Use default mode { quantize_mode = palette || (tdata.cols > 256) ? QUAN_WU : QUAN_EXACT; if (!palette) dither_mode = -1; // Reset dither too } if (!palette) { if (dither_mode < 0) dither_mode = tdata.cols > 256 ? DITH_DUMBFS : DITH_NONE; tdata.err = dither_pfract[dither_sel ? 1 : 0]; } run_create_(quantize_code, &tdata, sizeof(tdata), script_cmds); } /// GRADIENT WINDOW #define PPAD_SLOT 11 #define PPAD_XSZ 32 #define PPAD_YSZ 8 #define PPAD_WIDTH (PPAD_XSZ * PPAD_SLOT - 1) #define PPAD_HEIGHT (PPAD_YSZ * PPAD_SLOT - 1) #define PPAD_C ((PPAD_SLOT >> 1) - 1) #define NUM_GTYPES 7 #define NUM_OTYPES 3 typedef struct { int pmouse; int channel, nchan; int len, rep, ofs; int type, bound, opac; int gtype, grev; int otype, orev; void **opt, **gbut, **obut, **group; char **gpp, *gp[NUM_GTYPES + 1]; grad_info temps[NUM_CHANNELS]; grad_map tmaps[NUM_CHANNELS + 1]; grad_store tbytes; } grad_dd; typedef struct { void **xw; // parent widget-map int lock; // prevent nested calls int interp, crgb[4], cidx[3]; int cnt, slot, mode; int gsize[3], gxy[2]; void **ppad; void **col, **opt; void **spin, **chk; void **pspin, **gbar; unsigned char *pgrid; unsigned char rgb[768]; unsigned char pad[GRAD_POINTS * 3], mpad[GRAD_POINTS]; } ged_dd; static void ged_event(ged_dd *dt, void **wdata, int what, void **where) { int slot, *cause; if (what == op_EVT_OK) { grad_dd *gdt = GET_DDATA(dt->xw); int idx = (gdt->channel == CHN_IMAGE) && (mem_img_bpp == 3) ? 0 : gdt->channel + 1; run_query(wdata); if (dt->mode > NUM_CHANNELS) /* Opacity */ { memcpy(gdt->tbytes + GRAD_CUSTOM_OPAC(idx), dt->pad, GRAD_POINTS); memcpy(gdt->tbytes + GRAD_CUSTOM_OMAP(idx), dt->mpad, GRAD_POINTS); gdt->tmaps[idx].coplen = dt->cnt; } else /* Gradient */ { memcpy(gdt->tbytes + GRAD_CUSTOM_DATA(idx), dt->pad, idx ? GRAD_POINTS : GRAD_POINTS * 3); memcpy(gdt->tbytes + GRAD_CUSTOM_DMAP(idx), dt->mpad, GRAD_POINTS); gdt->tmaps[idx].cvslen = dt->cnt; } run_destroy(wdata); return; } cause = cmd_read(where, dt); if (dt->lock) return; dt->lock = TRUE; /* Block circular signal calls */ slot = dt->slot; if (cause == &dt->slot) /* Select slot */ { if (slot >= dt->cnt) goto done; /* Empty slot */ if (!dt->mode) /* RGB */ { unsigned char *gp = dt->pad + slot * 3; dt->crgb[0] = dt->crgb[2] = MEM_2_INT(gp, 0); cmd_setv(dt->col, dt->crgb, COLOR_ALL); cmd_set(dt->opt, dt->mpad[slot]); } else /* Indexed / utility / opacity */ { cmd_set(dt->chk, dt->mpad[slot] == GRAD_TYPE_CONST); dt->lock = FALSE; cmd_set(dt->spin, dt->pad[slot]); } } else if (cause == &dt->cnt) /* Set length */ cmd_repaint(dt->gbar); else { int n = *cause; if (cause == &dt->interp) /* Select mode */ { if (dt->mode) n = n ? GRAD_TYPE_CONST : GRAD_TYPE_RGB; dt->mpad[slot] = n; } else if (cause == dt->cidx) { int xy[2]; xy[0] = (n % PPAD_XSZ) * PPAD_SLOT + PPAD_C; xy[1] = (n / PPAD_XSZ) * PPAD_SLOT + PPAD_C; cmd_setv(dt->ppad, xy, FCIMAGE_XY); if (!dt->mode) /* RGB */ { dt->crgb[0] = MEM_2_INT(dt->rgb, n * 3); cmd_setv(dt->col, dt->crgb, COLOR_RGBA); } else dt->pad[slot] = n; /* Indexed / utility / opacity */ } if (!dt->mode) /* RGB */ { unsigned char *gp = dt->pad + slot * 3; int rgb = dt->crgb[0]; gp[0] = INT_2_R(rgb); gp[1] = INT_2_G(rgb); gp[2] = INT_2_B(rgb); } if (dt->cnt <= slot) // Extend as needed cmd_set(dt->pspin, dt->cnt = slot + 1); cmd_repaint(dt->gbar); } done: dt->lock = FALSE; } static int ged_pkey(ged_dd *dt, void **wdata, int what, void **where, key_ext *key) { int x, y; if (!arrow_key_(key->key, key->state, &x, &y, 0)) return (FALSE); x += dt->gxy[0] / PPAD_SLOT; y += dt->gxy[1] / PPAD_SLOT; y = y < 0 ? 0 : y >= PPAD_YSZ ? PPAD_YSZ - 1 : y; y = y * PPAD_XSZ + x; y = y < 0 ? 0 : y > 255 ? 255 : y; cmd_set(dt->spin, y); return (TRUE); } static int ged_pclick(ged_dd *dt, void **wdata, int what, void **where, mouse_ext *mouse) { int x, y; /* Only single clicks */ if (mouse->count != 1) return (TRUE); x = mouse->x / PPAD_SLOT; y = mouse->y / PPAD_SLOT; y = y * PPAD_XSZ + x; cmd_set(dt->spin, y); return (TRUE); } static char *interp_txt[] = { _("RGB"), _("sRGB"), _("HSV"), _("Backward HSV"), _("Constant") }; #define WBbase ged_dd static void *ged_code[] = { ONTOP(xw), WINDOWm(_("Edit Gradient")), XVBOXBS, // !!! Originally the main vbox was that way /* Palette pad */ TALLOC(pgrid, gsize[2]), REF(ppad), FCIMAGEP(pgrid, gxy, gsize), EVENT(KEY, ged_pkey), EVENT(MOUSE, ged_pclick), HSEP, /* Editor widgets */ BORDER(SPINSLIDE, 0), REF(spin), IF(mode), SPINSLIDEa(cidx), UNLESS(mode), uSPINa(cidx), EVENT(CHANGE, ged_event), OPNAME("Value"), UNLESSx(mode, 1), /* RGB */ REF(col), COLOR(crgb), EVENT(CHANGE, ged_event), OPNAME("Colour"), EVENT(MULTI, colsel_pick_pixel), EQBOXS, BORDER(OPT, 0), REF(opt), XOPTe(interp_txt, 5, interp, ged_event), OPNAME("Type"), ENDIF(1), IFx(mode, 1), /* Indexed / utility / opacity */ EQBOXS, REF(chk), XCHECK(_("Constant"), interp), EVENT(CHANGE, ged_event), ENDIF(1), BORDER(LABEL, 0), XHBOXS, MLABEL(_("Points:")), REF(pspin), SPIN(cnt, 2, GRAD_POINTS), EVENT(CHANGE, ged_event), WDONE, WDONE, /* Gradient bar */ uSPIN(slot, 0, GRAD_POINTS - 1), EVENT(CHANGE, ged_event), TRIGGER, OPNAME(""), REF(gbar), GRADBAR(mode, slot, cnt, GRAD_POINTS, pad, rgb, ged_event), OKBOX(_("OK"), ged_event, _("Cancel"), NULL), WEND }; #undef WBbase static void grad_edit(void **wdata, int opac) { ged_dd tdata, *ddt; grad_dd *dt = GET_DDATA(wdata); void **dd; int idx; memset(&tdata, 0, sizeof(tdata)); tdata.xw = wdata; idx = (dt->channel == CHN_IMAGE) && (mem_img_bpp == 3) ? 0 : dt->channel + 1; /* Copy to temp */ if (opac) { memcpy(tdata.pad, dt->tbytes + GRAD_CUSTOM_OPAC(idx), GRAD_POINTS); memcpy(tdata.mpad, dt->tbytes + GRAD_CUSTOM_OMAP(idx), GRAD_POINTS); tdata.cnt = dt->tmaps[idx].coplen; tdata.mode = NUM_CHANNELS + 1; } else { memcpy(tdata.pad, dt->tbytes + GRAD_CUSTOM_DATA(idx), idx ? GRAD_POINTS : GRAD_POINTS * 3); memcpy(tdata.mpad, dt->tbytes + GRAD_CUSTOM_DMAP(idx), GRAD_POINTS); tdata.cnt = dt->tmaps[idx].cvslen; tdata.mode = idx; } if (tdata.cnt < 2) tdata.cnt = 2; tdata.crgb[1] = tdata.crgb[3] = 255; tdata.cidx[2] = tdata.mode <= CHN_IMAGE + 1 ? mem_cols - 1 : 255; make_crgb(tdata.rgb, tdata.mode - 1); if (!script_cmds) { tdata.gsize[2] = (tdata.gsize[0] = PPAD_WIDTH) * (tdata.gsize[1] = PPAD_HEIGHT) * 3; tdata.gxy[0] = tdata.gxy[1] = PPAD_C; } dd = run_create_(ged_code, &tdata, sizeof(tdata), script_cmds); if (!script_cmds) { ddt = GET_DDATA(dd); render_color_grid(ddt->pgrid, PPAD_WIDTH, PPAD_HEIGHT, PPAD_SLOT, ddt->rgb); } cmd_showhide(dd, TRUE); } static const char gtmap[NUM_GTYPES * 2] = { GRAD_TYPE_RGB, 1, GRAD_TYPE_RGB, 2, GRAD_TYPE_SRGB, 2, GRAD_TYPE_HSV, 2, GRAD_TYPE_BK_HSV, 2, GRAD_TYPE_CONST, 3, GRAD_TYPE_CUSTOM, 3 }; static const char opmap[NUM_OTYPES] = { GRAD_TYPE_RGB, GRAD_TYPE_CONST, GRAD_TYPE_CUSTOM }; static void store_channel_gradient(grad_dd *dt) { int channel = dt->channel; grad_info *grad = dt->temps + channel; grad_map *gmap = dt->tmaps + channel + 1; if ((channel == CHN_IMAGE) && (mem_img_bpp == 3)) gmap = dt->tmaps; grad->len = dt->len; grad->gmode = dt->type + GRAD_MODE_LINEAR; grad->rep = dt->rep; grad->rmode = dt->bound; grad->ofs = dt->ofs; gmap->gtype = gtmap[2 * dt->gtype]; gmap->grev = dt->grev; gmap->otype = opmap[dt->otype]; gmap->orev = dt->orev; } static char *gradtypes_txt[NUM_GTYPES]; static void show_channel_gradient(grad_dd *dt, void **wdata) { int channel = dt->channel; grad_info *grad = dt->temps + channel; grad_map *gmap; int i, j, k, idx = channel + 1, bpp = BPP(channel); if (bpp == 3) --idx; gmap = dt->tmaps + idx; /* Reconfigure gradient selector */ dt->gpp = dt->gp; i = bpp == 1 ? 1 : 2; for (k = -1 , j = 0; j < NUM_GTYPES; j++) { dt->gp[j] = ""; // hide if (!(gtmap[j * 2 + 1] & i)) continue; dt->gp[j] = gradtypes_txt[j]; // show if ((gtmap[j * 2] == gmap->gtype) || (k < 0)) k = j; // select } dt->gtype = k; /* Opacity gradient */ for (i = NUM_OTYPES - 1; (i >= 0) && (opmap[i] != gmap->otype); i--); dt->otype = i; /* Parameters */ dt->len = grad->len; dt->rep = grad->rep; dt->ofs = grad->ofs; dt->type = grad->gmode - GRAD_MODE_LINEAR; dt->bound = grad->rmode; dt->grev = gmap->grev; dt->orev = gmap->orev; /* Display all that */ cmd_reset(dt->group, dt); } static void grad_evt(grad_dd *dt, void **wdata, int what, void **where) { run_query(wdata); if (what == op_EVT_SELECT) // channel { /* If same channel, it means doing a reset */ if (dt->nchan != dt->channel) store_channel_gradient(dt); dt->channel = dt->nchan; show_channel_gradient(dt, wdata); return; } where = origin_slot(where); // button if ((where == dt->gbut) || (where == dt->obut)) grad_edit(wdata, where == dt->obut); // value / opacity else // OK/Apply { int i; store_channel_gradient(dt); memcpy(gradient, dt->temps, sizeof(dt->temps)); memcpy(graddata, dt->tmaps, sizeof(dt->tmaps)); memcpy(gradbytes, dt->tbytes, sizeof(dt->tbytes)); grad_opacity = dt->opac; for (i = 0; i < NUM_CHANNELS; i++) grad_update(gradient + i); for (i = 0; i <= NUM_CHANNELS; i++) gmap_setup(graddata + i, gradbytes, i); update_stuff(UPD_GRAD); } if (what == op_EVT_OK) run_destroy(wdata); } static char *gtypes_txt[] = {_("Linear"), _("Bilinear"), _("Radial"), _("Square"), _("Angular"), _("Conical")}; static char *rtypes_txt[] = {_("None"), _("Level "), _("Repeat"), _("Mirror")}; static char *gradtypes_txt[NUM_GTYPES] = {_("A to B"), _("A to B (RGB)"), _("A to B (sRGB)"), _("A to B (HSV)"), _("A to B (backward HSV)"), _("A only"), _("Custom")}; static char *optypes_txt[NUM_OTYPES] = {_("Current to 0"), _("Current only"), _("Custom")}; #define WBbase grad_dd static void *grad_code[] = { IF(pmouse), WPMOUSE, WINDOWm(_("Configure Gradient")), /* Channel box */ BORDER(RPACK, 0), FRPACKe(_("Channel"), channames_, NUM_CHANNELS, 1, nchan, grad_evt), TRIGGER, /* Setup block */ TABLE(4, 4), REF(group), GROUPR, TSPIN(_("Length"), len, 0, MAX_GRAD), TSPIN(_("Repeat length"), rep, 0, MAX_GRAD), TSPIN(_("Offset"), ofs, -MAX_GRAD, MAX_GRAD), TLLABEL(_("Gradient type"), 2, 0), TLOPT(gtypes_txt, 6, type, 3, 0), TLLABEL(_("Extension type"), 2, 1), TLOPT(rtypes_txt, 4, bound, 3, 1), TLLABEL(_("Distance type"), 2, 2), TLOPTv(dist_txt, 3, sb_dist, 3, 2), TLABEL(_("Preview opacity")), MINWIDTH(200), TLSPINSLIDExl(opac, 0, 255, 1, 3, 3), UNNAME, WDONE, /* Select page */ EQBOX, BORDER(OPT, 0), FXVBOX(_("Gradient")), VBOXB, REF(opt), OPTD(gpp, gtype), WDONE, GROUPN, EQBOX, CHECK(_("Reverse"), grev), REF(gbut), BUTTONs(_("Edit Custom"), grad_evt), WDONE, GROUP0, WDONE, FXVBOX(_("Opacity")), VBOXB, OPT(optypes_txt, NUM_OTYPES, otype), WDONE, GROUPN, EQBOX, CHECK(_("Reverse"), orev), REF(obut), BUTTONs(_("Edit Custom"), grad_evt), WDONE, GROUP0, WDONE, WDONE, /* Cancel / Apply / OK */ OKBOX3(_("OK"), grad_evt, _("Cancel"), NULL, _("Apply"), grad_evt), WSHOW }; #undef WBbase void gradient_setup(int mode) { grad_dd tdata; memset(&tdata, 0, sizeof(tdata)); tdata.pmouse = !mode && !inifile_get_gboolean("centerSettings", TRUE); tdata.channel = tdata.nchan = mem_channel; tdata.opac = grad_opacity; tdata.gpp = tdata.gp; // Gradient menu is empty initially memcpy(tdata.temps, gradient, sizeof(tdata.temps)); memcpy(tdata.tmaps, graddata, sizeof(tdata.tmaps)); memcpy(tdata.tbytes, gradbytes, sizeof(tdata.tbytes)); run_create_(grad_code, &tdata, sizeof(tdata), script_cmds); } /// GRADIENT PICKER static int pickg_grad = GRAD_TYPE_RGB, pickg_cspace = CSPACE_LXN; static int do_pick_gradient(filterwindow_dd *dt, void **wdata) { unsigned char buf[256]; int len; run_query(wdata); len = mem_pick_gradient(buf, pickg_cspace, pickg_grad); mem_clip_new(len, 1, 1, CMASK_IMAGE, NULL); if (mem_clipboard) memcpy(mem_clipboard, buf, len); update_stuff(UPD_XCOPY); pressed_paste(TRUE); return TRUE; } #define WBbase filterwindow_dd static void *gp_code[] = { TABLE2(2), OPNAME0, TOPTv(_("Gradient"), interp_txt, 4, pickg_grad), TOPTv(_("Colour space"), cspnames_, NUM_CSPACES, pickg_cspace), WDONE, RET }; #undef WBbase void pressed_pick_gradient() { static filterwindow_dd tdata = { _("Pick Gradient"), gp_code, FW_FN(do_pick_gradient) }; run_create_(filterwindow_code, &tdata, sizeof(tdata), script_cmds); } /// SKEW WINDOW typedef struct { int rgb, gamma; int angle[2], ofs[2], dist[2]; int angles, lock; char **ftxt; void **aspin[2], **ospin[2]; } skew_dd; static int skew_mode = 6; static void click_skew_ok(skew_dd *dt, void **wdata) { double xskew, yskew; int res; run_query(wdata); if (dt->angles & 1) xskew = tan(dt->angle[0] * (M_PI / 18000.0)); else xskew = dt->ofs[0] / (double)(dt->dist[0] * 100); if (dt->angles & 2) yskew = tan(dt->angle[1] * (M_PI / 18000.0)); else yskew = dt->ofs[1] / (double)(dt->dist[1] * 100); if (!xskew && !yskew) { alert_same_geometry(); return; } res = mem_skew(xskew, yskew, skew_mode, dt->gamma); if (!res) { update_stuff(UPD_GEOM); run_destroy(wdata); } else memory_errors(res); } static void skew_moved(skew_dd *dt, void **wdata, int what, void **where) { void *cause = cmd_read(where, dt); int i; if (dt->lock) return; // Avoid recursion dt->lock = TRUE; for (i = 0; i < 2; i++) { /* Offset for angle */ if (cause == &dt->angle[i]) { cmd_set(dt->ospin[i], rint(dt->dist[i] * 100 * tan(dt->angle[i] * (M_PI / 18000.0)))); dt->angles |= 1 << i; } /* Angle for offset */ else if ((cause == &dt->ofs[i]) || (cause == &dt->dist[i])) { cmd_set(dt->aspin[i], rint(atan(dt->ofs[i] / (dt->dist[i] * 100)) * (18000.0 / M_PI))); dt->angles &= ~(1 << i); } } dt->lock = FALSE; } #define WBbase skew_dd static void *skew_code[] = { WINDOWm(_("Skew")), TABLE(4, 3), BORDER(LABEL, 0), TLLABEL(_("Horizontal "), 0, 1), GROUPN, REF(aspin[0]), TLFSPIN(angle[0], -8999, 8999, 1, 1), EVENT(CHANGE, skew_moved), TLLABEL(_("Angle"), 1, 0), REF(ospin[0]), TLFSPIN(ofs[0], -MAX_WIDTH * 100, MAX_WIDTH * 100, 2, 1), EVENT(CHANGE, skew_moved), TLLABEL(_("Offset"), 2, 0), TLSPIN(dist[0], 1, MAX_HEIGHT, 3, 1), EVENT(CHANGE, skew_moved), TLLABEL(_("At distance"), 3, 0), TLLABEL(_("Vertical"), 0, 2), GROUPN, REF(aspin[1]), TLFSPIN(angle[1], -8999, 8999, 1, 2), EVENT(CHANGE, skew_moved), OPNAME("Angle"), REF(ospin[1]), TLFSPIN(ofs[1], -MAX_HEIGHT * 100, MAX_HEIGHT * 100, 2, 2), EVENT(CHANGE, skew_moved), OPNAME("Offset"), TLSPIN(dist[1], 1, MAX_WIDTH, 3, 2), EVENT(CHANGE, skew_moved), OPNAME("At distance"), WDONE, GROUP0, HSEP, IFx(rgb, 1), CHECK(_("Gamma corrected"), gamma), HSEP, BORDER(RPACK, 0), RPACKDv(ftxt, 0, skew_mode), OPNAME(""), HSEP, ENDIF(1), OKBOXB(_("OK"), click_skew_ok, _("Cancel"), NULL), WSHOW }; #undef WBbase void pressed_skew() { char *fnames[sizeof(scale_modes) / sizeof(scale_modes[0])]; skew_dd tdata; memcpy(fnames, scale_modes, sizeof(fnames)); fnames[1] = _("Bilinear"); memset(&tdata, 0, sizeof(tdata)); tdata.rgb = mem_img_bpp == 3; tdata.gamma = use_gamma; tdata.dist[0] = mem_height; tdata.dist[1] = mem_width; tdata.ftxt = fnames; run_create_(skew_code, &tdata, sizeof(tdata), script_cmds); } /// TRACING IMAGE WINDOW typedef struct { int src; int w, h; int x, y; int scale, state; void **wspin, **hspin; } bkg_dd; static void bkg_evt(bkg_dd *dt, void **wdata, int what) { run_query(wdata); if (what == op_EVT_SELECT) // set source { int w = 0, h = 0; switch (dt->src) { case 0: w = bkg_w; h = bkg_h; break; case 1: break; case 2: w = mem_width; h = mem_height; break; case 3: if (mem_clipboard) w = mem_clip_w , h = mem_clip_h; break; } cmd_set(dt->wspin, w); cmd_set(dt->hspin, h); } else // OK/Apply { bkg_x = dt->x; bkg_y = dt->y; bkg_scale = dt->scale; bkg_flag = dt->state; if (!config_bkg(dt->src)) memory_errors(1); update_stuff(UPD_RENDER); } if (what == op_EVT_OK) run_destroy(wdata); } static char *srcs_txt[4] = { _("Unchanged"), _("None"), _("Image"), _("Clipboard") }; #define WBbase bkg_dd static void *bkg_code[] = { WINDOWm(_("Tracing Image")), TABLE(3, 4), TLABEL(_("Source")), TLOPTle(srcs_txt, 4, src, bkg_evt, 1, 0, 2), TRIGGER, TLABEL(_("Size")), REF(wspin), TLNOSPINr(w, 1, 1), REF(hspin), TLNOSPINr(h, 2, 1), TLABEL(_("Origin")), TLSPIN(x, -MAX_WIDTH, MAX_WIDTH, 1, 2), TLSPIN(y, -MAX_HEIGHT, MAX_HEIGHT, 2, 2), TLABEL(_("Relative scale")), TLSPIN(scale, 1, MAX_ZOOM, 1, 3), WDONE, CHECK(_("Display"), state), HSEP, OKBOX3B(_("OK"), bkg_evt, _("Cancel"), NULL, _("Apply"), bkg_evt), WSHOW }; #undef WBbase void bkg_setup() { bkg_dd tdata = { 0, 0, 0, bkg_x, bkg_y, bkg_scale, bkg_flag }; run_create(bkg_code, &tdata, sizeof(tdata)); } /// SEGMENTATION WINDOW seg_state *seg_preview; typedef struct { int cspace, dist; int threshold, rank, size[3]; int preview, progress; int step; void **tspin, **pbutton; seg_state *s; } seg_dd; static int seg_cspace = CSPACE_LXN, seg_dist = DIST_LINF; static int seg_rank = 4, seg_minsize = 1; static guint seg_idle; /* Change colorspace or distance measure, causing full recalculation */ static void seg_mode_toggled(seg_dd *dt, void **wdata, int what, void **where) { cmd_read(where, dt); mem_seg_prepare(dt->s, mem_img[CHN_IMAGE], mem_width, mem_height, dt->progress, dt->cspace, dt->dist); /* Disable preview if cancelled, change threshold if not */ if (!dt->s->phase) cmd_set(dt->pbutton, FALSE); else cmd_set(dt->tspin, rint(mem_seg_threshold(dt->s) * 100)); } /* Do phase 2 (segmentation) in the background */ static gboolean seg_process_idle(void **wdata) { seg_dd *dt = GET_DDATA(wdata); if (seg_preview && (dt->s->phase == 1)) { #define SEG_STEP 100000 dt->step = mem_seg_process_chunk(dt->step, SEG_STEP, dt->s); #undef SEG_STEP if (!(dt->s->phase & 2)) return (TRUE); // Not yet completed cmd_cursor(GET_WINDOW(wdata), NULL); seg_idle = 0; // In case update_stuff() ever calls main loop update_stuff(UPD_RENDER); } seg_idle = 0; return (FALSE); } /* Change segmentation limits, causing phase 2 restart */ static void seg_spin_changed(seg_dd *dt, void **wdata, int what, void **where) { void *cause = cmd_read(where, dt); seg_state *s = dt->s; if (cause == &dt->threshold) s->threshold = dt->threshold * 0.01; else if (cause == &dt->rank) s->minrank = dt->rank; else s->minsize = dt->size[0]; s->phase &= 1; // Need phase 2 rerun dt->step = 0; // Restart phase 2 afresh if (seg_preview) { if (dt->progress) cmd_cursor(GET_WINDOW(wdata), busy_cursor); if (!seg_idle) seg_idle = threads_idle_add_priority( GTK_PRIORITY_REDRAW + 5, (GtkFunction)seg_process_idle, wdata); } } /* Finish all calculations (preparation and segmentation) */ static int seg_process(seg_dd *dt) { /* Run phase 1 if necessary */ if (!dt->s->phase) mem_seg_prepare(dt->s, mem_img[CHN_IMAGE], mem_width, mem_height, dt->progress, dt->cspace, dt->dist); /* Run phase 2 if possible & necessary */ if (dt->s->phase == 1) mem_seg_process(dt->s); /* Return whether job is done */ return (dt->s->phase > 1); } static void seg_evt(seg_dd *dt, void **wdata, int what, void **where) { seg_state *oldp = seg_preview; int update = 0; if (what == op_EVT_CHANGE) // Toggle preview { cmd_read(where, dt); if (dt->preview ^ !oldp) return; // Nothing to do if (!oldp) // Enable { /* Do segmentation conspicuously at first */ if (!seg_process(dt)) cmd_set(dt->pbutton, FALSE); else seg_preview = dt->s; if (seg_preview) update_stuff(UPD_RENDER); return; } } /* First, disable preview */ if (oldp) { if (seg_idle) gtk_idle_remove(seg_idle); seg_idle = 0; seg_preview = NULL; update = UPD_RENDER; } if (what == op_EVT_OK) { /* Update parameters */ run_query(wdata); seg_cspace = dt->cspace; seg_dist = dt->dist; seg_rank = dt->rank; seg_minsize = dt->size[0]; /* Now, finish segmentation & render results */ if (seg_process(dt)) { spot_undo(UNDO_FILT); mem_seg_render(mem_img[CHN_IMAGE], dt->s); mem_undo_prepare(); update |= UPD_IMG; } } if (what != op_EVT_CHANGE) // Finished { oldp = dt->s; run_destroy(wdata); free(oldp); } // !!! Maybe better to add & use an integrated progressbar? else cmd_cursor(GET_WINDOW(wdata), NULL); update_stuff(update); } #define WBbase seg_dd static void *seg_code[] = { WINDOWm(_("Segment Image")), BORDER(RPACK, 0), FRPACKe(_("Colour space"), cspnames_, NUM_CSPACES, 1, cspace, seg_mode_toggled), FRPACKe(_("Difference measure"), dist_txt, 3, 1, dist, seg_mode_toggled), TABLE2(3), REF(tspin), TFSPIN(_("Threshold"), threshold, 0, 500000), EVENT(CHANGE, seg_spin_changed), TSPIN(_("Level"), rank, 0, 30), EVENT(CHANGE, seg_spin_changed), TSPINa(_("Minimum size"), size), EVENT(CHANGE, seg_spin_changed), WDONE, EQBOX, CANCELBTN(_("Cancel"), seg_evt), REF(pbutton), TOGGLE(_("Preview"), preview, seg_evt), OKBTN(_("Apply"), seg_evt), WSHOW }; #undef WBbase void pressed_segment() { seg_dd tdata; seg_state *s; int progress = 0, sz = mem_width * mem_height; if (sz == 1) return; /* 1 pixel in image is trivial - do nothing */ if (sz >= 1024 * 1024) progress = SEG_PROGRESS; s = mem_seg_prepare(NULL, mem_img[CHN_IMAGE], mem_width, mem_height, progress, seg_cspace, seg_dist); if (!s) { memory_errors(1); return; } if (!s->phase) return; // Terminated by user s->threshold = mem_seg_threshold(s); tdata.s = s; tdata.progress = progress; tdata.cspace = seg_cspace; tdata.dist = seg_dist; tdata.threshold = rint(s->threshold * 100); tdata.rank = s->minrank = seg_rank; tdata.size[0] = s->minsize = seg_minsize; tdata.size[1] = 1; tdata.size[2] = sz; tdata.preview = FALSE; tdata.step = 0; run_create_(seg_code, &tdata, sizeof(tdata), script_cmds); } /// THRESHOLDING WINDOW int xhold_preview; typedef struct { int lo[3], hi[3], mode, preview; int rgb; void **lspin, **hspin, **pbutton; } xhold_dd; static void xhold_changed(xhold_dd *dt, void **wdata, int what, void **where) { void *cause = cmd_read(where, dt); if (dt->lo[0] > dt->hi[0]) // Inversion tried to happen { if (cause == dt->hspin) cmd_set(dt->lspin, dt->hi[0]); else cmd_set(dt->hspin, dt->lo[0]); return; // Changed slider did the update } mem_ts.lo = dt->lo[0]; mem_ts.hi = dt->hi[0]; mem_ts.mode = dt->mode; if (xhold_preview) update_stuff(UPD_RENDER); } static void xhold_evt(xhold_dd *dt, void **wdata, int what, void **where) { int update = 0; if (what == op_EVT_CHANGE) // Toggle preview { cmd_read(where, dt); if (dt->preview ^ !xhold_preview) return; // Nothing to do xhold_preview = dt->preview; update_stuff(UPD_RENDER); return; } /* First, disable preview */ if (xhold_preview) update = UPD_RENDER; xhold_preview = FALSE; while (what == op_EVT_OK) { unsigned char *dest, *xbuf, *mask; int i, bpp = MEM_BPP; run_query(wdata); // Update parameters mask = malloc(mem_width * (bpp + 1)); if (!mask) break; spot_undo(UNDO_FILT); xbuf = mask + mem_width; for (i = 0; i < mem_height; i++) { row_protected(0, i, mem_width, mask); dest = mem_img[mem_channel] + i * mem_width * bpp; do_xhold(0, 1, mem_width, mask, xbuf, dest); process_img(0, 1, mem_width, mask, dest, dest, xbuf, NULL, bpp, BLENDF_SET | BLENDF_INVM); } free(mask); mem_undo_prepare(); update |= UPD_IMG; break; } run_destroy(wdata); // Finished update_stuff(update); } static char *xh_txt[] = {_("Max"), _("Min"), _("Red"), _("Green"), _("Blue")}; #define WBbase xhold_dd static void *xhold_code[] = { WINDOWm(_("Threshold Image")), DEFW(300), TABLE2(2), OPNAME0, REF(lspin), TSPINSLIDEa(_("From"), lo), EVENT(CHANGE, xhold_changed), TRIGGER, REF(hspin), TSPINSLIDEa(_("To"), hi), EVENT(CHANGE, xhold_changed), WDONE, IFx(rgb, 1), BORDER(RPACK, 0), RPACKe(xh_txt, XHOLD_NMODES, 0, mode, xhold_changed), OPNAME(""), // default ENDIF(1), HSEP, EQBOX, CANCELBTN(_("Cancel"), xhold_evt), REF(pbutton), TOGGLE(_("Preview"), preview, xhold_evt), OKBTN(_("OK"), xhold_evt), WSHOW }; #undef WBbase void pressed_xhold() { xhold_dd tdata = { { 128, 0, 255 }, { 255, 0, 255 }, 0, FALSE, MEM_BPP == 3 }; if (IS_INDEXED) { tdata.lo[0] = mem_cols / 2; tdata.hi[0] = tdata.hi[2] = tdata.lo[2] = mem_cols - 1; } run_create_(xhold_code, &tdata, sizeof(tdata), script_cmds); } /// NOISE WINDOW int noise_preview; static int noise_seed, noise_map; static int noise_xs = 256, noise_ys = 256, noise_lvl = 1; typedef struct { int xs, ys, lvl, seed, map, preview; int rgb; char **ncp, *nc[5]; void **sspin, **xspin, **yspin, **lspin, **copt, **pbutton; } noise_dd; static void noise_changed(noise_dd *dt, void **wdata, int what, void **where) { cmd_read(where, dt); if (!noise_preview) return; init_perlin(dt->seed, dt->xs, dt->ys, dt->lvl, dt->map); update_stuff(UPD_RENDER); } static void noise_evt(noise_dd *dt, void **wdata, int what, void **where) { int update = 0; if (what == op_EVT_OK) { /* Update parameters */ run_query(wdata); noise_seed = dt->seed; noise_map = dt->map; noise_xs = dt->xs; noise_ys = dt->ys; noise_lvl = dt->lvl; } if (what != op_EVT_CANCEL) init_perlin(dt->seed, dt->xs, dt->ys, dt->lvl, dt->map); if (what == op_EVT_CHANGE) // Toggle preview { cmd_read(where, dt); if (dt->preview ^ !noise_preview) return; // Nothing to do noise_preview = dt->preview; update_stuff(UPD_RENDER); return; } /* First, disable preview */ if (noise_preview) update = UPD_RENDER; noise_preview = FALSE; while (what == op_EVT_OK) { spot_undo(UNDO_FILT); mem_perlin(); mem_undo_prepare(); update |= UPD_IMG; break; } run_destroy(wdata); // Finished update_stuff(update); } #define WBbase noise_dd static void *noise_code[] = { WINDOWm(_("Solid Noise")), DEFW(300), TABLE2(5), REF(sspin), TSPIN(_("Seed"), seed, 0, INT_MAX), EVENT(CHANGE, noise_changed), TRIGGER, REF(xspin), TSPIN(_("X span"), xs, 1, MAX_WIDTH), EVENT(CHANGE, noise_changed), REF(yspin), TSPIN(_("Y span"), ys, 1, MAX_HEIGHT), EVENT(CHANGE, noise_changed), REF(lspin), TSPIN(_("Octaves"), lvl, 1, 8), EVENT(CHANGE, noise_changed), IFx(rgb, 1), REF(copt), TOPTDe(_("Colours"), ncp, map, noise_changed), ENDIF(1), WDONE, HSEP, EQBOX, CANCELBTN(_("Cancel"), noise_evt), REF(pbutton), TOGGLE(_("Preview"), preview, noise_evt), OKBTN(_("OK"), noise_evt), WSHOW }; #undef WBbase void pressed_noise() { noise_dd tdata = { noise_xs, noise_ys, noise_lvl, noise_seed, noise_map, FALSE, MEM_BPP == 3, tdata.nc, { _("Greyscale"), _("Gradient"), _("Palette"), mem_clipboard ? _("Clipboard") : "", NULL } }; run_create_(noise_code, &tdata, sizeof(tdata), script_cmds); } mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/otherwindow.h000066400000000000000000000041311471325446300234630ustar00rootroot00000000000000/* otherwindow.h Copyright (C) 2004-2020 Mark Tyler and Dmitry Groshev This file is part of mtPaint. mtPaint 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. mtPaint 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 mtPaint in the file COPYING. */ #define COLSEL_OVERLAYS 1 #define COLSEL_EDIT_AB 2 #define COLSEL_EDIT_CSEL 3 #define COLSEL_GRID 4 #define COLSEL_EDIT_ALL 256 #define CHOOSE_PATTERN 0 #define CHOOSE_BRUSH 1 #define CHOOSE_COLOR 2 /// Generic V-code to handle UI needs of common image transform tasks typedef int (*filterwindow_fn)(void *ddata, void **wdata); #define FW_FN(X) (filterwindow_fn)(X) typedef struct { char *name; void **code; filterwindow_fn evt; } filterwindow_dd; extern void *filterwindow_code[]; typedef struct { filterwindow_dd fw; int n[3]; } spin1_dd; extern void *spin1_code[]; int mem_preview, mem_preview_clip, brcosa_auto; transform_state def_bcsp; int sharper_reduce; int spal_mode; seg_state *seg_preview; int xhold_preview; int noise_preview; void generic_new_window(int type); void pressed_add_cols(); void pressed_brcosa(void **xb); void pressed_bacteria(); void pressed_scale_size(int mode); void pressed_sort_pal(); void pressed_quantize(int palette); void pressed_pick_gradient(); void choose_pattern(int typ); // Bring up pattern chooser void colour_selector( int cs_type ); // Bring up GTK+ colour wheel int do_new_one(int nw, int nh, int nc, png_color *pal, int bpp, int undo); void do_new_chores(int undo); void reset_tools(); void memory_errors(int type); void gradient_setup(int mode); void pressed_skew(); void bkg_setup(); void pressed_segment(); void pressed_xhold(); void pressed_noise(); mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/png.c000066400000000000000000010343441471325446300217030ustar00rootroot00000000000000/* png.c Copyright (C) 2004-2024 Mark Tyler and Dmitry Groshev This file is part of mtPaint. mtPaint 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. mtPaint 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 mtPaint in the file COPYING. */ /* Rewritten for version 3.10 by Dmitry Groshev */ #include #include #define PNG_READ_PACK_SUPPORTED #include #include #ifdef U_JPEG #define NEED_CMYK /* !!! libjpeg 9 headers conflict with these */ #undef TRUE #undef FALSE #include /* !!! Since libjpeg 7, this conflicts with ; with libjpeg 8a, * conflict can be avoided if windows.h is included BEFORE this - WJ */ #endif #ifdef U_JP2 #if U_JP2 < 2 #define NEED_FILE2MEM #endif #define HANDLE_JP2 #include #endif #ifdef U_JASPER #define HANDLE_JP2 #include #endif #ifdef U_TIFF #define NEED_CMYK #include #endif #ifdef U_WEBP #include #include #endif #if U_LCMS == 2 #include /* For version 1.x compatibility */ #define icSigCmykData cmsSigCmykData #define icSigRgbData cmsSigRgbData #define icHeader cmsICCHeader #elif defined U_LCMS #include #endif #include "global.h" #undef _ #define _(X) X #include "mygtk.h" #include "memory.h" #include "ani.h" #include "png.h" #include "canvas.h" #include "toolbar.h" #include "layer.h" #include "spawn.h" #include "thread.h" /* Compatibility defines will be added when they ARE needed, not beforehand */ G_GNUC_BEGIN_IGNORE_DEPRECATIONS /* Make fseek() and ftell() on Win64 have the same limits as on 64-bit Unix */ #ifdef _WIN64 /* LLP64 */ #define F_LONG_MAX LLONG_MAX /* What can be handled - including allocated */ typedef long long f_long; #define ftell(A) _ftelli64(A) #define fseek(A,B,C) _fseeki64(A, B, C) #else /* LP64 or ILP32 */ #define F_LONG_MAX LONG_MAX /* What can be handled - including allocated */ typedef long f_long; #endif #include #if F_LONG_MAX > SIZE_MAX #error "File offset limit exceeds allocation limit" #endif /* Macro for big-endian tags (IFF and BMP) */ #define TAG4B(A,B,C,D) (((A) << 24) + ((B) << 16) + ((C) << 8) + (D)) /* All-in-one transport container for animation save/load */ typedef struct { frameset fset; ls_settings settings; int mode; /* Explode frames mode */ int desttype; int error, miss, cnt; int lastzero; char *destdir; } ani_settings; int silence_limit, jpeg_quality, png_compression; int tga_RLE, tga_565, tga_defdir, jp2_rate; int lzma_preset, zstd_level, tiff_predictor, tiff_rtype, tiff_itype, tiff_btype; int webp_preset, webp_quality, webp_compression; int lbm_mask, lbm_untrans, lbm_pack, lbm_pbm; int apply_icc; fformat file_formats[NUM_FTYPES] = { { "", "", "", 0}, { "PNG", "png", "apng", FF_256 | FF_RGB | FF_ANIM | FF_ALPHA | FF_MULTI | FF_MEM, XF_TRANS | XF_COMPZ }, #ifdef U_JPEG { "JPEG", "jpg", "jpeg", FF_RGB, XF_COMPJ }, #else { "", "", "", 0}, #endif #ifdef HANDLE_JP2 { "JPEG2000", "jp2", "", FF_RGB | FF_ALPHA, XF_COMPJ2 }, { "J2K", "j2k", "jpc", FF_RGB | FF_ALPHA, XF_COMPJ2 }, #else { "", "", "", 0}, { "", "", "", 0}, #endif #ifdef U_TIFF #define TIFF0FLAGS FF_LAYER | FF_MEM #define TIFFLAGS (FF_BW | FF_256 | FF_RGB | FF_ALPHA | TIFF0FLAGS) { "TIFF", "tif", "tiff", TIFFLAGS, XF_COMPT }, #else { "", "", "", 0}, #endif { "GIF", "gif", "", FF_256 | FF_ANIM, XF_TRANS }, { "BMP", "bmp", "", FF_256 | FF_RGB | FF_ALPHAR | FF_MEM }, { "XPM", "xpm", "", FF_256 | FF_RGB, XF_TRANS | XF_SPOT }, { "XBM", "xbm", "", FF_BW, XF_SPOT }, { "LSS16", "lss", "", FF_16 }, { "TGA", "tga", "", FF_256 | FF_RGB | FF_ALPHAR, XF_TRANS | XF_COMPR }, { "PCX", "pcx", "", FF_256 | FF_RGB }, { "PBM", "pbm", "", FF_BW | FF_LAYER }, { "PGM", "pgm", "", FF_256 | FF_LAYER | FF_NOSAVE }, { "PPM", "ppm", "pnm", FF_RGB | FF_LAYER }, { "PAM", "pam", "", FF_BW | FF_RGB | FF_ALPHA | FF_LAYER }, { "GPL", "gpl", "", FF_PALETTE }, { "TXT", "txt", "", FF_PALETTE }, { "PAL", "pal", "", FF_PALETTE }, { "ACT", "act", "", FF_PALETTE }, { "LAYERS", "txt", "", FF_LAYER }, /* !!! No 2nd layers format yet */ { "", "", "", 0}, /* An X pixmap - not a file at all */ { "PIXMAP", "", "", FF_RGB | FF_NOSAVE }, /* SVG image - import only */ { "SVG", "svg", "svgz", FF_RGB | FF_ALPHA | FF_SCALE | FF_NOSAVE }, /* mtPaint's own format - extended PAM */ { "* PMM *", "pmm", "", FF_256 | FF_RGB | FF_ANIM | FF_ALPHA | FF_MULTI | FF_LAYER | FF_PALETTE | FF_MEM, XF_TRANS }, #ifdef U_WEBP { "WEBP", "webp", "", FF_RGB | FF_ANIM | FF_ALPHA, XF_COMPW }, #else { "", "", "", 0}, #endif { "LBM", "lbm", "ilbm", FF_256 | FF_RGB | FF_ALPHA, XF_TRANS | XF_COMPRL }, }; #ifndef U_TIFF tiff_format tiff_formats[] = { { NULL } }; #endif #ifndef U_WEBP char *webp_presets[] = { NULL }; #endif int file_type_by_ext(char *name, guint32 mask) { char *ext; int i, l = LONGEST_EXT; ext = strrchr(name, '.'); if (!ext || !ext[0]) return (FT_NONE); /* Special case for exploded frames (*.gif.000 etc.) */ if (!ext[strspn(ext, ".0123456789")] && memchr(name, '.', ext - name)) { char *tmp = ext; while (*(--ext) != '.'); if (tmp - ext - 1 < LONGEST_EXT) l = tmp - ext - 1; } ext++; for (i = 0; i < NUM_FTYPES; i++) { unsigned int flags = file_formats[i].flags; if ((flags & FF_NOSAVE) || !(flags & mask)) continue; if (!strncasecmp(ext, file_formats[i].ext, l)) return (i); if (!file_formats[i].ext2[0]) continue; if (!strncasecmp(ext, file_formats[i].ext2, l)) return (i); } return (FT_NONE); } /* Which of 2 palette colors is more like black */ static int get_bw(ls_settings *settings) { return (pal2B(settings->pal + 0) > pal2B(settings->pal + 1)); } /* Set palette to white and black */ static void set_bw(ls_settings *settings) { static const png_color wb[2] = { { 255, 255, 255 }, { 0, 0, 0 } }; settings->colors = 2; memcpy(settings->pal, wb, sizeof(wb)); } /* Set palette to grayscale */ static void set_gray(ls_settings *settings) { settings->colors = 256; mem_bw_pal(settings->pal, 0, 255); } /* Map RGB transparency to indexed */ static void map_rgb_trans(ls_settings *settings) { int i; if ((settings->rgb_trans < 0) || (settings->bpp < 3)) return; // Look for transparent colour in palette for (i = 0; i < settings->colors; i++) { if (PNG_2_INT(settings->pal[i]) != settings->rgb_trans) continue; settings->xpm_trans = i; return; } // Colour not in palette so force it into last entry settings->pal[255].red = INT_2_R(settings->rgb_trans); settings->pal[255].green = INT_2_G(settings->rgb_trans); settings->pal[255].blue = INT_2_B(settings->rgb_trans); settings->xpm_trans = 255; settings->colors = 256; } static int check_next_frame(frameset *fset, int mode, int anim) { int lim = mode != FS_LAYER_LOAD ? FRAMES_MAX : anim ? MAX_LAYERS - 1 : MAX_LAYERS; return (fset->cnt < lim); } static int write_out_frame(char *file_name, ani_settings *ani, ls_settings *f_set); static int process_page_frame(char *file_name, ani_settings *ani, ls_settings *w_set) { image_frame *frame; if (ani->settings.mode == FS_EXPLODE_FRAMES) return (write_out_frame(file_name, ani, w_set)); /* Store a new frame */ // !!! Currently, frames are allocated without checking any limits if (!mem_add_frame(&ani->fset, w_set->width, w_set->height, w_set->bpp, CMASK_NONE, w_set->pal)) return (FILE_MEM_ERROR); frame = ani->fset.frames + (ani->fset.cnt - 1); frame->cols = w_set->colors; frame->trans = w_set->xpm_trans; frame->delay = w_set->gif_delay > 0 ? w_set->gif_delay : 0; frame->x = w_set->x; frame->y = w_set->y; memcpy(frame->img, w_set->img, sizeof(chanlist)); return (0); } /* Receives struct with image parameters, and channel flags; * returns 0 for success, or an error code; * success doesn't mean that anything was allocated, loader must check that; * loader may call this multiple times - say, for each channel */ static int allocate_image(ls_settings *settings, int cmask) { size_t sz, l; int i, j, oldmask, wbpp, mode = settings->mode; if ((settings->width < 1) || (settings->height < 1)) return (-1); if ((settings->width > MAX_WIDTH) || (settings->height > MAX_HEIGHT)) return (TOO_BIG); /* Don't show progress bar where there's no need */ if (settings->width * settings->height <= (1 << silence_limit)) settings->silent = TRUE; if (mode == FS_PATTERN_LOAD) settings->silent = TRUE; /* Reduce cmask according to mode */ if (mode == FS_CLIP_FILE) cmask &= CMASK_CLIP; else if (mode == FS_CLIPBOARD) cmask &= CMASK_RGBA; else if ((mode == FS_CHANNEL_LOAD) || (mode == FS_PATTERN_LOAD)) cmask &= CMASK_IMAGE; /* Overwriting is allowed */ oldmask = cmask_from(settings->img); cmask &= ~oldmask; if (!cmask) return (0); // Already allocated /* No utility channels without image */ oldmask |= cmask; if (!(oldmask & CMASK_IMAGE)) return (-1); /* Can ask for RGBA-capable image channel */ wbpp = settings->bpp; if (wbpp > 3) settings->bpp = 3; j = TRUE; // For FS_LAYER_LOAD sz = (size_t)settings->width * settings->height; switch (mode) { case FS_PNG_LOAD: /* Regular image */ /* Reserve memory */ j = undo_next_core(UC_CREATE | UC_GETMEM, settings->width, settings->height, settings->bpp, oldmask); /* Drop current image if not enough memory for undo */ if (j) mem_free_image(&mem_image, FREE_IMAGE); case FS_EXPLODE_FRAMES: /* Frames' temporaries */ case FS_LAYER_LOAD: /* Layers */ /* Allocate, or at least try to */ for (i = 0; i < NUM_CHANNELS; i++) { if (!(cmask & CMASK_FOR(i))) continue; l = i == CHN_IMAGE ? sz * wbpp : sz; settings->img[i] = j ? malloc(l) : mem_try_malloc(l); if (!settings->img[i]) return (FILE_MEM_ERROR); } break; case FS_CLIP_FILE: /* Clipboard */ case FS_CLIPBOARD: /* Allocate the entire batch at once */ if (cmask & CMASK_IMAGE) { j = mem_clip_new(settings->width, settings->height, settings->bpp, cmask, NULL); if (j) return (FILE_MEM_ERROR); memcpy(settings->img, mem_clip.img, sizeof(chanlist)); break; } /* Try to extend image channel to RGBA if asked */ if (wbpp > 3) { unsigned char *w = realloc(mem_clipboard, sz * wbpp); if (!w) return (FILE_MEM_ERROR); settings->img[CHN_IMAGE] = mem_clipboard = w; } /* Try to add clipboard alpha and/or mask */ for (i = 0; i < NUM_CHANNELS; i++) { if (!(cmask & CMASK_FOR(i))) continue; if (!(settings->img[i] = mem_clip.img[i] = malloc(sz))) return (FILE_MEM_ERROR); } break; case FS_CHANNEL_LOAD: /* Current channel */ /* Dimensions & depth have to be the same */ if ((settings->width != mem_width) || (settings->height != mem_height) || (settings->bpp != MEM_BPP)) return (-1); /* Reserve memory */ j = undo_next_core(UC_CREATE | UC_GETMEM, settings->width, settings->height, settings->bpp, CMASK_CURR); if (j) return (FILE_MEM_ERROR); /* Allocate */ settings->img[CHN_IMAGE] = mem_try_malloc(sz * wbpp); if (!settings->img[CHN_IMAGE]) return (FILE_MEM_ERROR); break; case FS_PATTERN_LOAD: /* Patterns */ /* Check dimensions & depth */ if (!set_patterns(settings)) return (-1); /* Allocate temp memory */ settings->img[CHN_IMAGE] = calloc(1, sz * wbpp); if (!settings->img[CHN_IMAGE]) return (FILE_MEM_ERROR); break; case FS_PALETTE_LOAD: /* Palette */ case FS_PALETTE_DEF: return (-1); // Should not arrive here if palette is present } return (0); } /* Receives struct with image parameters, and which channels to deallocate */ static void deallocate_image(ls_settings *settings, int cmask) { int i; /* No deallocating image channel */ if (!(cmask &= ~CMASK_IMAGE)) return; for (i = 0; i < NUM_CHANNELS; i++) { if (!(cmask & CMASK_FOR(i))) continue; if (!settings->img[i]) continue; free(settings->img[i]); settings->img[i] = NULL; /* Clipboard */ if ((settings->mode == FS_CLIP_FILE) || (settings->mode == FS_CLIPBOARD)) mem_clip.img[i] = NULL; } } /* Deallocate alpha channel if useless; namely, all filled with given value */ static void delete_alpha(ls_settings *settings, int v) { if (settings->img[CHN_ALPHA] && is_filled(settings->img[CHN_ALPHA], v, settings->width * settings->height)) deallocate_image(settings, CMASK_ALPHA); } typedef struct { FILE *file; // for traditional use memx2 m; // data int top; // end of data } memFILE; #define MEMFILE_MAX INT_MAX /* How much it can hold */ #if MEMFILE_MAX != MEMX2_MAX #error "Mismatched max sizes" #endif static size_t mfread(void *ptr, size_t size, size_t nmemb, memFILE *mf) { size_t l, m; if (mf->file) return (fread(ptr, size, nmemb, mf->file)); if ((mf->m.here < 0) || (mf->m.here > mf->top)) return (0); l = size * nmemb; m = mf->top - mf->m.here; if (l > m) l = m , nmemb = m / size; memcpy(ptr, mf->m.buf + mf->m.here, l); mf->m.here += l; return (nmemb); } static size_t mfwrite(void *ptr, size_t size, size_t nmemb, memFILE *mf) { size_t l; if (mf->file) return (fwrite(ptr, size, nmemb, mf->file)); if (mf->m.here < 0) return (0); l = getmemx2(&mf->m, size * nmemb); nmemb = l / size; memcpy(mf->m.buf + mf->m.here, ptr, l); mf->m.here += l; if (mf->top < mf->m.here) mf->top = mf->m.here; return (nmemb); } static int mfseek(memFILE *mf, f_long offset, int mode) { // !!! For operating on tarballs, adjust fseek() params here if (mf->file) return (fseek(mf->file, offset, mode)); if (mode == SEEK_SET); else if (mode == SEEK_CUR) offset += mf->m.here; else if (mode == SEEK_END) offset += mf->top; else return (-1); if ((offset < 0) || (offset > MEMFILE_MAX)) return (-1); mf->m.here = offset; return (0); } static char *mfgets(char *s, int size, memFILE *mf) { size_t m; char *t, *v; if (mf->file) return (fgets(s, size, mf->file)); if (size < 1) return (NULL); if ((mf->m.here < 0) || (mf->m.here > mf->top)) return (NULL); m = mf->top - mf->m.here; if (m >= (unsigned)size) m = size - 1; t = memchr(v = mf->m.buf + mf->m.here, '\n', m); if (t) m = t - v + 1; memcpy(s, v, m); s[m] = '\0'; mf->m.here += m; return (s); } static int mfputs(const char *s, memFILE *mf) { size_t l; if (mf->file) return (fputs(s, mf->file)); l = strlen(s); return (!l || mfwrite((void *)s, l, 1, mf) ? 0 : EOF); } static int mfputss(memFILE *mf, const char *s, ...) { va_list args; size_t l; int m = 0; va_start(args, s); while (s) { if (mf->file) m = fputs(s, mf->file); else { l = strlen(s); m = !l || mfwrite((void *)s, l, 1, mf) ? 0 : EOF; } if (m < 0) break; s = va_arg(args, const char *); } va_end(args); return (m); } static void copy_run(unsigned char *dest, unsigned char *src, int len, int dstep, int sstep, int bgr) { if (bgr) bgr = 2; while (len-- > 0) { dest[0] = src[bgr]; dest[1] = src[1]; dest[2] = src[bgr ^ 2]; dest += dstep; src += sstep; } } /* Fills temp buffer row, or returns image row if no buffer */ static unsigned char *prepare_row(unsigned char *buf, ls_settings *settings, int bpp, int y) { unsigned char *tmp, *tmi, *tma, *tms; int i, j, w = settings->width, h = y * w; int bgr = (settings->ftype == FT_BMP) || (settings->ftype == FT_TGA) ? 2 : 0; tmi = settings->img[CHN_IMAGE] + h * settings->bpp; if (bpp < (bgr ? 3 : 4)) /* Return/copy image row */ { if (!buf) return (tmi); memcpy(buf, tmi, w * bpp); return (buf); } /* Produce BGR / BGRx / RGBx */ tmp = buf; if (settings->bpp == 1) // Indexed { png_color *pal = settings->pal; for (i = 0; i < w; tmp += bpp , i++) { png_color *col = pal + *tmi++; tmp[bgr] = col->red; tmp[1] = col->green; tmp[bgr ^ 2] = col->blue; } } else copy_run(tmp, tmi, w, bpp, 3, bgr); // RGB /* Add alpha to the mix */ tmp = buf + 3; tma = settings->img[CHN_ALPHA] + h; if (bpp == 3); // No alpha - all done else if ((settings->mode != FS_CLIPBOARD) || !settings->img[CHN_SEL]) { // Only alpha here for (i = 0; i < w; tmp += bpp , i++) *tmp = *tma++; } else { // Merge alpha and selection tms = settings->img[CHN_SEL] + h; for (i = 0; i < w; tmp += bpp , i++) { j = *tma++ * *tms++; *tmp = (j + (j >> 8) + 1) >> 8; } } return (buf); } /* Converts palette-based transparency to color transparency or alpha channel */ static int palette_trans(ls_settings *settings, unsigned char ttb[256]) { int i, n, res; /* Count transparent colors */ for (i = n = 0; i < 256; i++) n += ttb[i] < 255; /* None means no transparency */ settings->xpm_trans = -1; if (!n) return (0); /* One fully transparent color means color transparency */ if (n == 1) { for (i = 0; i < 256; i++) { if (ttb[i]) continue; settings->xpm_trans = i; return (0); } } /* Anything else means alpha transparency */ res = allocate_image(settings, CMASK_ALPHA); if (!res && settings->img[CHN_ALPHA]) { unsigned char *src, *dest; size_t i = (size_t)settings->width * settings->height; src = settings->img[CHN_IMAGE]; dest = settings->img[CHN_ALPHA]; while (i-- > 0) *dest++ = ttb[*src++]; } return (res); } static void ls_init(char *what, int save) { what = g_strdup_printf(save ? __("Saving %s image") : __("Loading %s image"), what); progress_init(what, 0); g_free(what); } static void ls_progress(ls_settings *settings, int n, int steps) { int h = settings->height; if (!settings->silent && ((n * steps) % h >= h - steps)) progress_update((float)n / h); } #if PNG_LIBPNG_VER >= 10400 /* 1.4+ */ #define png_set_gray_1_2_4_to_8(X) png_set_expand_gray_1_2_4_to_8(X) #endif /* !!! libpng 1.2.17-1.2.24 was losing extra chunks if there was no callback */ static int buggy_libpng_handler() { return (0); } static void png_memread(png_structp png_ptr, png_bytep data, png_size_t length) { memFILE *mf = (memFILE *)png_get_io_ptr(png_ptr); // memFILE *mf = (memFILE *)png_ptr->io_ptr; size_t l = mf->top - mf->m.here; if (l > length) l = length; memcpy(data, mf->m.buf + mf->m.here, l); mf->m.here += l; if (l < length) png_error(png_ptr, "Read Error"); } static void png_memwrite(png_structp png_ptr, png_bytep data, png_size_t length) { memFILE *mf = (memFILE *)png_get_io_ptr(png_ptr); // memFILE *mf = (memFILE *)png_ptr->io_ptr; if (getmemx2(&mf->m, length) < length) png_error(png_ptr, "Write Error"); else { memcpy(mf->m.buf + mf->m.here, data, length); mf->top = mf->m.here += length; } } static void png_memflush(png_structp png_ptr) { /* Does nothing */ } #define PNG_BYTES_TO_CHECK 8 #define PNG_HANDLE_CHUNK_NEVER 1 #define PNG_HANDLE_CHUNK_ALWAYS 3 static const char *chunk_names[NUM_CHANNELS] = { "", "alPh", "seLc", "maSk" }; static int load_png(char *file_name, ls_settings *settings, memFILE *mf, int frame) { /* Description of PNG interlacing passes as X0, DX, Y0, DY */ static const unsigned char png_interlace[8][4] = { {0, 1, 0, 1}, /* One pass for non-interlaced */ {0, 8, 0, 8}, /* Seven passes for Adam7 interlaced */ {4, 8, 0, 8}, {0, 4, 4, 8}, {2, 4, 0, 4}, {0, 2, 2, 4}, {1, 2, 0, 2}, {0, 1, 1, 2} }; static png_bytep *row_pointers; static char *msg; png_structp png_ptr; png_infop info_ptr; png_unknown_chunkp uk_p; png_uint_32 pwidth, pheight; char buf[PNG_BYTES_TO_CHECK + 1]; unsigned char trans[256], *src, *dest, *dsta; long dest_len; FILE *fp = NULL; int i, j, k, bit_depth, color_type, interlace_type, num_uk, res = -1; int maxpass, x0, dx, y0, dy, n, nx, height, width, itrans = FALSE, anim = FALSE; if (!mf) { if ((fp = fopen(file_name, "rb")) == NULL) return -1; i = fread(buf, 1, PNG_BYTES_TO_CHECK, fp); } else i = mfread(buf, 1, PNG_BYTES_TO_CHECK, mf); if (i != PNG_BYTES_TO_CHECK) goto fail; if (png_sig_cmp(buf, 0, PNG_BYTES_TO_CHECK)) goto fail; png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) goto fail; row_pointers = NULL; msg = NULL; info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) goto fail2; if (setjmp(png_jmpbuf(png_ptr))) { res = settings->width ? FILE_LIB_ERROR : -1; goto fail2; } /* Frame pseudo-files have wrong CRCs */ if (frame) png_set_crc_action(png_ptr, PNG_CRC_QUIET_USE, PNG_CRC_QUIET_USE); /* !!! libpng 1.2.17-1.2.24 needs this to read extra channels */ else png_set_read_user_chunk_fn(png_ptr, NULL, buggy_libpng_handler); if (!mf) png_init_io(png_ptr, fp); else png_set_read_fn(png_ptr, mf, png_memread); png_set_sig_bytes(png_ptr, PNG_BYTES_TO_CHECK); /* Stupid libpng handles private chunks on all-or-nothing basis */ png_set_keep_unknown_chunks(png_ptr, frame ? PNG_HANDLE_CHUNK_NEVER : PNG_HANDLE_CHUNK_ALWAYS, NULL, 0); png_read_info(png_ptr, info_ptr); /* Check whether the file is APNG */ num_uk = png_get_unknown_chunks(png_ptr, info_ptr, &uk_p); for (i = 0; i < num_uk; i++) { if (strcmp(uk_p[i].name, "acTL")) continue; anim = TRUE; /* mtPaint does not write APNGs with extra channels, and * no reason to waste memory on APNG frames now */ png_set_keep_unknown_chunks(png_ptr, PNG_HANDLE_CHUNK_NEVER, NULL, 0); png_set_read_user_chunk_fn(png_ptr, NULL, NULL); } png_get_IHDR(png_ptr, info_ptr, &pwidth, &pheight, &bit_depth, &color_type, &interlace_type, NULL, NULL); if (png_get_valid(png_ptr, info_ptr, PNG_INFO_PLTE)) { png_colorp png_palette; png_get_PLTE(png_ptr, info_ptr, &png_palette, &settings->colors); memcpy(settings->pal, png_palette, settings->colors * sizeof(png_color)); /* If palette is all we need */ res = 1; if ((settings->mode == FS_PALETTE_LOAD) || (settings->mode == FS_PALETTE_DEF)) goto fail3; } res = TOO_BIG; if ((pwidth > MAX_WIDTH) || (pheight > MAX_HEIGHT)) goto fail2; /* Call allocator for image data */ settings->width = width = (int)pwidth; settings->height = height = (int)pheight; settings->bpp = 1; if ((color_type != PNG_COLOR_TYPE_PALETTE) || (bit_depth > 8)) settings->bpp = 3; i = CMASK_IMAGE; if ((color_type == PNG_COLOR_TYPE_RGB_ALPHA) || (color_type == PNG_COLOR_TYPE_GRAY_ALPHA)) i = CMASK_RGBA; if ((res = allocate_image(settings, i))) goto fail2; res = FILE_MEM_ERROR; i = sizeof(png_bytep) * height; row_pointers = malloc(i + width * 4); if (!row_pointers) goto fail2; row_pointers[0] = (char *)row_pointers + i; if (!settings->silent) { switch(settings->mode) { case FS_PNG_LOAD: msg = "PNG"; break; case FS_CLIP_FILE: case FS_CLIPBOARD: msg = __("Clipboard"); break; } } if (msg) ls_init(msg, 0); res = -1; /* RGB PNG file */ if (settings->bpp == 3) { png_set_strip_16(png_ptr); png_set_gray_1_2_4_to_8(png_ptr); png_set_palette_to_rgb(png_ptr); png_set_gray_to_rgb(png_ptr); /* Is there a transparent color? */ settings->rgb_trans = -1; if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { png_color_16p trans_rgb; png_get_tRNS(png_ptr, info_ptr, NULL, NULL, &trans_rgb); if (color_type == PNG_COLOR_TYPE_GRAY) { i = trans_rgb->gray; switch (bit_depth) { case 1: i *= 0xFF; break; case 2: i *= 0x55; break; case 4: i *= 0x11; break; case 8: default: break; /* Hope libpng compiled w/o accurate transform */ case 16: i >>= 8; break; } settings->rgb_trans = RGB_2_INT(i, i, i); } else settings->rgb_trans = RGB_2_INT(trans_rgb->red, trans_rgb->green, trans_rgb->blue); } if (settings->img[CHN_ALPHA]) /* RGBA */ { nx = height; /* Have to do deinterlacing myself */ if (interlace_type == PNG_INTERLACE_NONE) { k = 0; maxpass = 1; } else if (interlace_type == PNG_INTERLACE_ADAM7) { k = 1; maxpass = 8; nx = (nx + 7) & ~7; nx += 7 * (nx >> 3); } else goto fail2; /* Unknown type */ for (n = 0; k < maxpass; k++) { x0 = png_interlace[k][0]; dx = png_interlace[k][1]; y0 = png_interlace[k][2]; dy = png_interlace[k][3]; for (i = y0; i < height; i += dy , n++) { png_read_rows(png_ptr, &row_pointers[0], NULL, 1); src = row_pointers[0]; dest = settings->img[CHN_IMAGE] + (i * width + x0) * 3; dsta = settings->img[CHN_ALPHA] + i * width; for (j = x0; j < width; j += dx) { dest[0] = src[0]; dest[1] = src[1]; dest[2] = src[2]; dsta[j] = src[3]; src += 4; dest += 3 * dx; } if (msg && ((n * 20) % nx >= nx - 20)) progress_update((float)n / nx); } } } else /* RGB */ { png_set_strip_alpha(png_ptr); for (i = 0; i < height; i++) { row_pointers[i] = settings->img[CHN_IMAGE] + i * width * 3; } png_read_image(png_ptr, row_pointers); } } /* Paletted PNG file */ else { /* Is there a transparent index? */ if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { png_bytep ptrans; int ltrans; png_get_tRNS(png_ptr, info_ptr, &ptrans, <rans, NULL); memset(trans, 255, 256); memcpy(trans, ptrans, ltrans); itrans = TRUE; } png_set_strip_16(png_ptr); png_set_strip_alpha(png_ptr); png_set_packing(png_ptr); if ((color_type == PNG_COLOR_TYPE_GRAY) && (bit_depth < 8)) png_set_gray_1_2_4_to_8(png_ptr); for (i = 0; i < height; i++) { row_pointers[i] = settings->img[CHN_IMAGE] + i * width; } png_read_image(png_ptr, row_pointers); } if (msg) progress_update(1.0); png_read_end(png_ptr, info_ptr); res = 0; /* Apply palette transparency */ if (itrans) res = palette_trans(settings, trans); num_uk = png_get_unknown_chunks(png_ptr, info_ptr, &uk_p); if (num_uk) /* File contains mtPaint's private chunks */ { for (i = 0; i < num_uk; i++) /* Examine each chunk */ { for (j = CHN_ALPHA; j < NUM_CHANNELS; j++) { if (!strcmp(uk_p[i].name, chunk_names[j])) break; } if (j >= NUM_CHANNELS) continue; /* Try to allocate a channel */ if ((res = allocate_image(settings, CMASK_FOR(j)))) break; /* Skip if not allocated */ if (!settings->img[j]) continue; dest_len = width * height; uncompress(settings->img[j], &dest_len, uk_p[i].data, uk_p[i].size); } /* !!! Is this call really needed? */ png_free_data(png_ptr, info_ptr, PNG_FREE_UNKN, -1); } if (!res) res = anim ? FILE_HAS_FRAMES : 1; #ifdef U_LCMS #ifdef PNG_iCCP_SUPPORTED /* Extract ICC profile if it's of use */ if (!settings->icc_size) { #if PNG_LIBPNG_VER >= 10600 /* 1.6+ */ png_bytep icc; #else png_charp icc; #endif png_charp name; png_uint_32 len; int comp; if (png_get_iCCP(png_ptr, info_ptr, &name, &comp, &icc, &len) && (len < INT_MAX) && (settings->icc = malloc(len))) { settings->icc_size = len; memcpy(settings->icc, icc, len); } } #endif #endif fail2: if (msg) progress_end(); free(row_pointers); fail3: png_destroy_read_struct(&png_ptr, &info_ptr, NULL); fail: if (fp) fclose(fp); return (res); } #ifndef PNG_AFTER_IDAT #define PNG_AFTER_IDAT 8 #endif static int save_png(char *file_name, ls_settings *settings, memFILE *mf) { png_unknown_chunk unknown0; png_structp png_ptr; png_infop info_ptr; FILE *fp = NULL; int h = settings->height, w = settings->width, bpp = settings->bpp; int i, j, res = -1; long uninit_(dest_len), res_len; char *mess = NULL; unsigned char trans[256], *tmp, *rgba_row = NULL; png_color_16 trans_rgb; /* Baseline PNG format does not support alpha for indexed images, so * we have to convert them to RGBA for clipboard export - WJ */ if (((settings->mode == FS_CLIPBOARD) || (bpp == 3)) && settings->img[CHN_ALPHA]) { rgba_row = malloc(w * 4); if (!rgba_row) return (-1); bpp = 4; } if (!settings->silent) switch(settings->mode) { case FS_PNG_SAVE: mess = "PNG"; break; case FS_CLIP_FILE: case FS_CLIPBOARD: mess = __("Clipboard"); break; case FS_COMPOSITE_SAVE: mess = __("Layer"); break; case FS_CHANNEL_SAVE: mess = __("Channel"); break; default: settings->silent = TRUE; break; } if (!mf && ((fp = fopen(file_name, "wb")) == NULL)) goto exit0; png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, NULL, NULL); if (!png_ptr) goto exit1; info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) goto exit2; res = 0; if (!mf) png_init_io(png_ptr, fp); else png_set_write_fn(png_ptr, mf, png_memwrite, png_memflush); png_set_compression_level(png_ptr, settings->png_compression); if (bpp == 1) { png_set_IHDR(png_ptr, info_ptr, w, h, 8, PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); png_set_PLTE(png_ptr, info_ptr, settings->pal, settings->colors); /* Transparent index in use */ if ((settings->xpm_trans > -1) && (settings->xpm_trans < 256)) { memset(trans, 255, 256); trans[settings->xpm_trans] = 0; png_set_tRNS(png_ptr, info_ptr, trans, settings->colors, 0); } } else { png_set_IHDR(png_ptr, info_ptr, w, h, 8, bpp == 4 ? PNG_COLOR_TYPE_RGB_ALPHA : PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); if (settings->pal) png_set_PLTE(png_ptr, info_ptr, settings->pal, settings->colors); /* Transparent index in use */ if ((settings->rgb_trans > -1) && !settings->img[CHN_ALPHA]) { trans_rgb.red = INT_2_R(settings->rgb_trans); trans_rgb.green = INT_2_G(settings->rgb_trans); trans_rgb.blue = INT_2_B(settings->rgb_trans); png_set_tRNS(png_ptr, info_ptr, 0, 1, &trans_rgb); } } png_write_info(png_ptr, info_ptr); if (mess) ls_init(mess, 1); for (j = 0; j < h; j++) { tmp = prepare_row(rgba_row, settings, bpp, j); png_write_row(png_ptr, (png_bytep)tmp); ls_progress(settings, j, 20); } /* Save private chunks into PNG file if we need to */ /* !!! Uncomment if default setting ever gets inadequate (in 1.7+) */ // png_set_keep_unknown_chunks(png_ptr, PNG_HANDLE_CHUNK_ALWAYS, NULL, 0); tmp = NULL; i = bpp == 1 ? CHN_ALPHA : CHN_ALPHA + 1; if (settings->mode == FS_CLIPBOARD) i = NUM_CHANNELS; // Disable extensions for (j = 0; i < NUM_CHANNELS; i++) { if (!settings->img[i]) continue; if (!tmp) { /* Get size required for each zlib compress */ w = settings->width * settings->height; #if ZLIB_VERNUM >= 0x1200 dest_len = compressBound(w); #else dest_len = w + (w >> 8) + 32; #endif res = -1; tmp = malloc(dest_len); // Temporary space for compression if (!tmp) break; res = 0; } res_len = dest_len; if (compress2(tmp, &res_len, settings->img[i], w, settings->png_compression) != Z_OK) continue; strncpy(unknown0.name, chunk_names[i], 5); unknown0.data = tmp; unknown0.size = res_len; unknown0.location = PNG_AFTER_IDAT; png_set_unknown_chunks(png_ptr, info_ptr, &unknown0, 1); #if PNG_LIBPNG_VER < 10600 /* before 1.6 */ png_set_unknown_chunk_location(png_ptr, info_ptr, j++, PNG_AFTER_IDAT); #endif } free(tmp); png_write_end(png_ptr, info_ptr); if (mess) progress_end(); /* Tidy up */ exit2: png_destroy_write_struct(&png_ptr, &info_ptr); exit1: if (fp) fclose(fp); exit0: free(rgba_row); return (res); } /* *** PREFACE *** * Contrary to what GIF89 docs say, all contemporary browser implementations * always render background in an animated GIF as transparent. So does mtPaint, * for some GIF animations depend on this rule. * An inter-frame delay of 0 normally means that the two (or more) frames * are parts of same animation frame and should be rendered as one resulting * frame; but some (ancient) GIFs have all delays set to 0, but still contain * animation sequences. So the handling of zero-delay frames is user-selectable * in mtPaint. */ /* Animation state */ typedef struct { unsigned char lmap[MAX_DIM]; image_frame prev; int prev_idx; // Frame index+1, so that 0 means None int have_frames; // Set after first int defw, defh, bk_rect[4]; int mode; /* Extra fields for paletted images */ int global_cols, newcols, newtrans; png_color global_pal[256], newpal[256]; unsigned char xlat[513]; /* Extra fields for RGBA images */ int blend; unsigned char bkg[4]; } ani_status; /* Initialize palette remapping table */ static void ani_init_xlat(ani_status *stat) { int i; for (i = 0; i < 256; i++) stat->xlat[i] = stat->xlat[i + 256] = i; stat->xlat[512] = stat->newtrans; } /* Calculate new frame dimensions, and point-in-area bitmap */ static void ani_map_frame(ani_status *stat, ls_settings *settings) { unsigned char *lmap; int i, j, w, h; /* Calculate the new dimensions */ // !!! Offsets considered nonnegative (as in GIF, WebP and APNG) w = settings->x + settings->width; h = settings->y + settings->height; if (!stat->have_frames) // Resize screen to fit the first frame { if (w > MAX_WIDTH) w = MAX_WIDTH; if (h > MAX_HEIGHT) h = MAX_HEIGHT; if (stat->defw < w) stat->defw = w; if (stat->defh < h) stat->defh = h; stat->have_frames = TRUE; } else // Clip all frames past the first to screen size { if (stat->defw < w) w = stat->defw; if (stat->defh < h) h = stat->defh; } /* The bitmap works this way: "Xth byte & (Yth byte >> 4)" tells which * area(s) the pixel (X,Y) is in: bit 0 is for image (the new one), * bit 1 is for underlayer (the previous composited frame), and bit 2 * is for hole in it (if "restore to background" was last) */ j = stat->defw > stat->defh ? stat->defw : stat->defh; memset(lmap = stat->lmap, 0, j); // Mark new frame for (i = settings->x; i < w; i++) lmap[i] |= 0x01; // Image bit for (i = settings->y; i < h; i++) lmap[i] |= 0x10; // Image mask bit // Mark previous frame if (stat->prev_idx) { for (i = stat->prev.x , j = i + stat->prev.width; i < j; i++) lmap[i] |= 0x02; // Underlayer bit for (i = stat->prev.y , j = i + stat->prev.height; i < j; i++) lmap[i] |= 0x20; // Underlayer mask bit } // Mark disposal area if (clip(stat->bk_rect, 0, 0, stat->defw, stat->defh, stat->bk_rect)) { for (i = stat->bk_rect[0] , j = stat->bk_rect[2]; i < j; i++) lmap[i] |= 0x04; // Background bit for (i = stat->bk_rect[1] , j = stat->bk_rect[3]; i < j; i++) lmap[i] |= 0x40; // Background mask bit } } /* Allowed bpp: 0 - move, 1 - indexed, 3 - RGB, 4 - RGBA * Indexed+alpha not supported nor should be: cannot be saved as standard PNG */ static int add_frame(ani_settings *ani, ani_status *stat, ls_settings *settings, int bpp, int disposal) { int cmask = !bpp ? CMASK_NONE : bpp > 3 ? CMASK_RGBA : CMASK_IMAGE; int fbpp = !bpp ? settings->bpp : bpp > 3 ? 3 : bpp; image_frame *frame; /* Allocate a new frame */ if (!mem_add_frame(&ani->fset, stat->defw, stat->defh, fbpp, cmask, stat->newpal)) return (FILE_MEM_ERROR); frame = ani->fset.frames + (ani->fset.cnt - 1); frame->cols = stat->newcols; frame->trans = stat->newtrans; frame->delay = settings->gif_delay; frame->flags = disposal; // Pass to compositing /* Tag zero-delay frame for deletion if requested */ if ((ani->lastzero = (stat->mode == ANM_NOZERO) && !settings->gif_delay)) frame->flags |= FM_NUKE; if (!bpp) // Same bpp & dimensions - reassign the chanlist { memcpy(frame->img, settings->img, sizeof(chanlist)); memset(settings->img, 0, sizeof(chanlist)); } return (0); } static int done_frame(char *file_name, ani_settings *ani, int last) { int res = 1; if ((ani->settings.mode == FS_EXPLODE_FRAMES) && (!last ^ ani->lastzero)) res = write_out_frame(file_name, ani, NULL); return (res ? res : 1); } static void composite_indexed_frame(image_frame *frame, ani_status *stat, ls_settings *settings) { unsigned char *dest, *fg0, *bg0 = NULL, *lmap = stat->lmap; image_frame *bkf = &stat->prev; int w, fgw, bgw = 0, urgb = 0, tp = settings->xpm_trans; w = frame->width; dest = frame->img[CHN_IMAGE]; fgw = settings->width; fg0 = settings->img[CHN_IMAGE] ? settings->img[CHN_IMAGE] - (settings->y * fgw + settings->x) : dest; // Always indexed (1 bpp) /* Pointer to absent underlayer is no problem - it just won't get used */ bgw = bkf->width; bg0 = bkf->img[CHN_IMAGE] - (bkf->y * bgw + bkf->x) * bkf->bpp; urgb = bkf->bpp != 1; if (frame->bpp == 1) // To indexed { unsigned char *fg = fg0, *bg = bg0, *xlat = stat->xlat; int x, y; for (y = 0; y < frame->height; y++) { int bmask = lmap[y] >> 4; for (x = 0; x < w; x++) { int c0, bflag = lmap[x] & bmask; if ((bflag & 1) && ((c0 = fg[x]) != tp)) // New frame c0 += 256; else if ((bflag & 6) == 2) // Underlayer c0 = bg[x]; else c0 = 512; // Background (transparent) *dest++ = xlat[c0]; } fg += fgw; bg += bgw; } } else // To RGB { unsigned char rgb[513 * 3], *fg = fg0, *bg = bg0; int x, y, bpp = urgb + urgb + 1; /* Setup global palette map: underlayer, image, background */ if (bkf->pal) pal2rgb(rgb, bkf->pal, 256, 0); pal2rgb(rgb + 256 * 3, settings->colors ? settings->pal : stat->global_pal, 256, 257); frame->trans = -1; // No color-key transparency for (y = 0; y < frame->height; y++) { int bmask = lmap[y] >> 4; for (x = 0; x < w; x++) { unsigned char *src; int c0, bflag = lmap[x] & bmask; if ((bflag & 1) && ((c0 = fg[x]) != tp)) // New frame src = rgb + (256 * 3) + (c0 * 3); else if ((bflag & 6) == 2) // Underlayer src = urgb ? bg + x * 3 : rgb + bg[x] * 3; else src = rgb + 512 * 3; // Background (black) dest[0] = src[0]; dest[1] = src[1]; dest[2] = src[2]; dest += 3; } fg += fgw; bg += bgw * bpp; } } if (frame->img[CHN_ALPHA]) // To alpha { unsigned char *fg = fg0, *bg = NULL; int x, y, af = 0, utp = -1; dest = frame->img[CHN_ALPHA]; utp = bkf->bpp == 1 ? bkf->trans : -1; af = !!bkf->img[CHN_ALPHA]; // Underlayer has alpha bg = bkf->img[af ? CHN_ALPHA : CHN_IMAGE] - (bkf->y * bgw + bkf->x); for (y = 0; y < frame->height; y++) { int bmask = lmap[y] >> 4; for (x = 0; x < w; x++) { int c0, bflag = lmap[x] & bmask; if ((bflag & 1) && (fg[x] != tp)) // New frame c0 = 255; else if ((bflag & 6) == 2) // Underlayer { c0 = bg[x]; if (!af) c0 = c0 != utp ? 255 : 0; } else c0 = 0; // Background (transparent) *dest++ = c0; } fg += fgw; bg += bgw; } } } static void composite_rgba_frame(image_frame *frame, ani_status *stat, ls_settings *settings) { static unsigned char bkg0[4]; // Default transparent black unsigned char mask[MAX_WIDTH], alpha[MAX_WIDTH], pal[768]; unsigned char *dest, *src, *dsta, *srca, *bg, *bga, *lmap = stat->lmap; image_frame *bkf = &stat->prev; int rxy[4] = { 0, 0, frame->width, frame->height }; int x, y, w, bgw, bgoff, fgw, ww, fgoff, dstoff, bpp, tr; /* Do the mixing if source is present */ if (!settings->img[CHN_IMAGE]) return; w = frame->width; bgw = bkf->width; bgoff = bkf->y * bgw + bkf->x; bpp = bkf->bpp; if (bpp == 1) pal2rgb(pal, bkf->pal, bkf->cols, 256); /* First, generate the destination RGB */ dest = frame->img[CHN_IMAGE]; bg = bkf->img[CHN_IMAGE] - bgoff * bpp; // Won't get used if not valid for (y = 0; y < frame->height; y++) { int bmask = lmap[y] >> 4; for (x = 0; x < w; x++) { unsigned char *rgb = bkg0; // Default black int bflag = lmap[x] & bmask; if (bflag & 4) rgb = stat->bkg; // Background in the hole else if (bflag & 2) // Underlayer rgb = bpp == 1 ? pal + bg[x] * 3 : bg + x * 3; dest[0] = rgb[0]; dest[1] = rgb[1]; dest[2] = rgb[2]; dest += 3; } bg += bgw * bpp; } /* Then, destination alpha */ dsta = frame->img[CHN_ALPHA]; bga = bkf->img[CHN_ALPHA] ? bkf->img[CHN_ALPHA] - bgoff : NULL; if (dsta) for (y = 0; y < frame->height; y++) { int bmask = lmap[y] >> 4; for (x = 0; x < w; x++) { int bflag = lmap[x] & bmask, a = 0; // Default transparent if (bflag & 2) a = bga ? bga[x] : 255; // Underlayer if (bflag & 4) a = stat->bkg[3]; // Background in the hole *dsta++ = a; } if (bga) bga += bgw; } /* Then, check if the new frame is in bounds */ if (!clip(rxy, settings->x, settings->y, settings->x + settings->width, settings->y + settings->height, rxy)) return; /* Then, paste it over */ fgw = settings->width; ww = rxy[2] - rxy[0]; fgoff = (rxy[1] - settings->y) * fgw + (rxy[0] - settings->x); dstoff = rxy[1] * w + rxy[0]; memset(alpha, 255, ww); tr = settings->rgb_trans; for (y = rxy[1]; y < rxy[3]; y++) { dsta = frame->img[CHN_ALPHA] ? frame->img[CHN_ALPHA] + dstoff : NULL; srca = settings->img[CHN_ALPHA] ? settings->img[CHN_ALPHA] + fgoff : NULL; dest = frame->img[CHN_IMAGE] + dstoff * 3; src = settings->img[CHN_IMAGE] + fgoff * 3; if (stat->blend) // Do alpha blend { memset(mask, 0, ww); if (tr >= 0) mem_mask_colors(mask, src, 255, ww, 1, 3, tr, tr); process_mask(0, 1, ww, mask, dsta, dsta, alpha, srca, 255, FALSE); process_img(0, 1, ww, mask, dest, dest, src, NULL, 3, BLENDF_SET); } else // Do a copy { memcpy(dest, src, ww * 3); // Copy image if (!dsta); // No alpha else if (srca) memcpy(dsta, srca, ww); // Copy alpha else { memset(dsta, 255, ww); // Fill alpha if (tr >= 0) mem_mask_colors(dsta, src, 0, ww, 1, 3, tr, tr); } } fgoff += fgw; dstoff += w; } } static void composite_frame(frameset *fset, ani_status *stat, ls_settings *settings) { image_frame *frame = fset->frames + (fset->cnt - 1); int disposal; /* In raw mode, just store the offsets */ if (stat->mode <= ANM_RAW) { frame->x = settings->x; frame->y = settings->y; } else { /* Read & clear disposal mode */ disposal = frame->flags & FM_DISPOSAL; frame->flags ^= disposal ^ FM_DISP_REMOVE; /* For WebP and RGB[A] APNG */ if (settings->bpp == 3) composite_rgba_frame(frame, stat, settings); /* For GIF & indexed[+T] APNG */ else { /* No blend means ignoring transparent color */ if (!stat->blend) settings->xpm_trans = -1; composite_indexed_frame(frame, stat, settings); } /* Drop alpha if not used */ if (frame->img[CHN_ALPHA] && is_filled(frame->img[CHN_ALPHA], 255, frame->width * frame->height)) { free(frame->img[CHN_ALPHA]); frame->img[CHN_ALPHA] = NULL; } /* If transparent color and alpha are both present, convert the * color into alpha, as PNG does not allow combining them */ if ((frame->trans >= 0) && frame->img[CHN_ALPHA]) { /* RGBA: indexed+alpha blocked elsewhere for same reason */ /* Use palette that add_frame() assigns */ int tr = PNG_2_INT(stat->newpal[frame->trans]); mem_mask_colors(frame->img[CHN_ALPHA], frame->img[CHN_IMAGE], 0, frame->width, frame->height, 3, tr, tr); frame->trans = -1; } /* Prepare the disposal action */ if (disposal == FM_DISP_REMOVE) // Dispose to background { // Image-sized hole in underlayer stat->bk_rect[2] = (stat->bk_rect[0] = settings->x) + settings->width; stat->bk_rect[3] = (stat->bk_rect[1] = settings->y) + settings->height; } if (disposal == FM_DISP_LEAVE) // Don't dispose memset(&stat->bk_rect, 0, sizeof(stat->bk_rect)); // Clear old if ((disposal == FM_DISP_REMOVE) || (disposal == FM_DISP_LEAVE)) { stat->prev = *frame; // Current frame becomes underlayer if (!stat->prev.pal) stat->prev.pal = fset->pal; if (stat->prev_idx && (fset->frames[stat->prev_idx - 1].flags & FM_NUKE)) /* Remove the unref'd frame */ mem_remove_frame(fset, stat->prev_idx - 1); stat->prev_idx = fset->cnt; } /* if (disposal == FM_DISP_RESTORE); // Dispose to previous // Underlayer and hole stay unchanged */ } if ((fset->cnt > 1) && (stat->prev_idx != fset->cnt - 1) && (fset->frames[fset->cnt - 2].flags & FM_NUKE)) { /* Remove the next-to-last frame */ mem_remove_frame(fset, fset->cnt - 2); if (stat->prev_idx > fset->cnt) stat->prev_idx = fset->cnt; } } static int analyze_rgba_frame(ani_status *stat, ls_settings *settings) { int same_size, holes, alpha0, alpha1, alpha, bpp; if (stat->mode <= ANM_RAW) // Raw frame mode { stat->defw = settings->width; stat->defh = settings->height; return (0); // Output matches input } else if ((stat->defw > MAX_WIDTH) || (stat->defh > MAX_HEIGHT)) return (-1); // Too large ani_map_frame(stat, settings); same_size = !(settings->x | settings->y | (stat->defw ^ settings->width) | (stat->defh ^ settings->height)); holes = !same_size || stat->blend; if (same_size && !holes) return (0); // New replaces old /* Indexed with transparent color (from APNG) stay as they were: * no local palettes there, upgrade to RGB/RGBA never needed */ if ((settings->bpp == 1) && (settings->xpm_trans >= 0)) return (same_size ? 0 : 1); /* Alpha transparency on underlayer */ alpha0 = !stat->prev_idx || stat->prev.img[CHN_ALPHA]; /* Transparency from disposal to background */ if ((stat->bk_rect[0] < stat->bk_rect[2]) && (stat->bk_rect[1] < stat->bk_rect[3])) alpha0 |= stat->bkg[3] < 255; /* Alpha transparency from this layer */ alpha1 = !stat->blend && settings->img[CHN_ALPHA]; /* Result */ alpha = alpha1 | (alpha0 & holes); /* Output bpp is max of underlayer & image */ bpp = (stat->prev.bpp == 3) || (settings->bpp == 3) ? 3 : 1; /* Do not produce indexed+alpha as regular PNG does not support that */ if (alpha) bpp = 4; /* !!! composite_rgba_frame() as of now cannot handle frame == dest, so * do not return 0 even if same size, bpp & alpha, w/o rewriting that */ return (bpp); } /* In absence of library support, APNG files are read through building in memory * a regular PNG file for a frame, and then feeding that to libpng - WJ */ /* Macros for accessing values in Motorola byte order */ #define GET16B(buf) (((buf)[0] << 8) + (buf)[1]) #define GET32B(buf) (((unsigned)(buf)[0] << 24) + ((buf)[1] << 16) + \ ((buf)[2] << 8) + (buf)[3]) #define PUT16B(buf, v) (buf)[0] = (v) >> 8; (buf)[1] = (v) & 0xFF; #define PUT32B(buf, v) (buf)[0] = (v) >> 24; (buf)[1] = ((v) >> 16) & 0xFF; \ (buf)[2] = ((v) >> 8) & 0xFF; (buf)[3] = (v) & 0xFF; /* Macros for relevant PNG tags; big-endian */ #define TAG4B_IHDR TAG4B('I', 'H', 'D', 'R') #define TAG4B_IDAT TAG4B('I', 'D', 'A', 'T') #define TAG4B_IEND TAG4B('I', 'E', 'N', 'D') #define TAG4B_acTL TAG4B('a', 'c', 'T', 'L') #define TAG4B_fcTL TAG4B('f', 'c', 'T', 'L') #define TAG4B_fdAT TAG4B('f', 'd', 'A', 'T') /* PNG block header */ #define PNG_SIZE 0 /* 32b */ #define PNG_TAG 4 /* 32b */ #define PNG_HSIZE 8 /* IHDR block */ #define IHDR_W 0 /* 32b */ #define IHDR_H 4 /* 32b */ #define IHDR_SIZE 13 /* acTL block */ #define acTL_FCNT 0 /* 32b */ #define acTL_SIZE 8 /* fcTL block */ #define fcTL_SEQ 0 /* 32b */ #define fcTL_W 4 /* 32b */ #define fcTL_H 8 /* 32b */ #define fcTL_X 12 /* 32b */ #define fcTL_Y 16 /* 32b */ #define fcTL_DN 20 /* 16b */ #define fcTL_DD 22 /* 16b */ #define fcTL_DISP 24 /* 8b */ #define fcTL_BLEND 25 /* 8b */ #define fcTL_SIZE 26 typedef struct { int w, h, disp; f_long ihdr, idat0, fdat0, fdat1; unsigned frames; unsigned char fctl[fcTL_SIZE]; int phase; unsigned char *png; // Buffer for fake file size_t sz; // Buffer size memFILE mf; } pnghead; /* Build in-memory PNG from file header and frame data, ignoring CRCs */ static int assemble_png(FILE *fp, pnghead *pg) { size_t l = pg->idat0 + (pg->fdat1 - pg->fdat0) + PNG_HSIZE + 4; unsigned char *src, *dest, *wrk = pg->png; unsigned tag, tl, u, seq; /* Enlarge the buffer if needed */ if (l > pg->sz) { if (l > MEMFILE_MAX) return (FILE_MEM_ERROR); dest = realloc(pg->png, l); if (!dest) return (FILE_MEM_ERROR); pg->png = dest; pg->sz = l; } /* Read in the header on first pass */ if (!wrk) { fseek(fp, 0, SEEK_SET); if (!fread(pg->png, pg->idat0, 1, fp)) return (-1); } /* Modify the header */ wrk = pg->png + pg->ihdr; memcpy(wrk + IHDR_W, pg->fctl + fcTL_W, 4); memcpy(wrk + IHDR_H, pg->fctl + fcTL_H, 4); /* Read in body */ wrk = pg->png + pg->idat0; fseek(fp, pg->fdat0, SEEK_SET); l = pg->fdat1 - pg->fdat0; if (!fread(wrk, l, 1, fp)) return (-1); /* Reformat the body blocks if needed */ seq = GET32B(pg->fctl + fcTL_SEQ); src = dest = wrk; while (l) { tag = GET32B(src + PNG_TAG); tl = GET32B(src + PNG_SIZE); if (tl > l - PNG_HSIZE - 4) return (-1); // Paranoia l -= u = PNG_HSIZE + tl + 4; if (tag == TAG4B_fdAT) { if (tl < 4) return (-1); // Paranoia if (GET32B(src + PNG_HSIZE) != ++seq) return (-1); // Sequence tl -= 4; PUT32B(dest + PNG_SIZE, tl); memcpy(dest + PNG_TAG, "IDAT", 4); memmove(dest + PNG_HSIZE, src + PNG_HSIZE + 4, tl); } else if (src != dest) memmove(dest, src, u); src += u; dest += PNG_HSIZE + tl + 4; } /* Add IEND */ PUT32B(dest + PNG_SIZE, 0); memcpy(dest + PNG_TAG, "IEND", 4); /* Prepare file buffer */ memset(&pg->mf, 0, sizeof(pg->mf)); pg->mf.m.buf = pg->png; pg->mf.top = pg->mf.m.size = dest + PNG_HSIZE + 4 - pg->png; return (0); } static int png_scan(FILE *fp, pnghead *pg) { /* APNG disposal codes mapping */ static const unsigned short apng_disposal[3] = { FM_DISP_LEAVE, FM_DISP_REMOVE, FM_DISP_RESTORE }; unsigned char buf[256]; unsigned tag, tl, w, h; f_long p = ftell(fp); if (p <= 0) return (-1); // Sanity check /* Read block headers & see what we get */ pg->phase = 0; while (TRUE) { if (fread(buf, 1, PNG_HSIZE, fp) < PNG_HSIZE) { if (pg->phase != 2) break; // Fail pg->phase = 4; // Improper end return (0); // Done } tag = GET32B(buf + PNG_TAG); tl = GET32B(buf + PNG_SIZE); if (tl > 0x7FFFFFFFU) break; // Limit if (p > F_LONG_MAX - tl - PNG_HSIZE - 4) break; // File too large if (tag == TAG4B_IHDR) { if (tl < IHDR_SIZE) break; // Bad if (pg->ihdr) break; // There must be only one pg->ihdr = p + PNG_HSIZE; /* Get canvas dimensions */ if (!fread(buf, IHDR_SIZE, 1, fp)) break; // Fail w = GET32B(buf + IHDR_W); h = GET32B(buf + IHDR_H); if ((w > 0x7FFFFFFFU) || (h > 0x7FFFFFFFU)) break; // Limit pg->w = w; pg->h = h; } else if (tag == TAG4B_IDAT) { if (!pg->ihdr) break; // Fail if (!pg->idat0) pg->idat0 = p; if (pg->phase == 1) // Had a fcTL { pg->fdat0 = p; pg->phase = 2; } if (pg->phase > 1) { if (pg->fdat0 != pg->idat0) break; // Mixed IDAT & fdAT pg->fdat1 = p + PNG_HSIZE + tl + 4; } } else if (tag == TAG4B_acTL) { if (tl < acTL_SIZE) break; // Bad if (!fread(buf, acTL_SIZE, 1, fp)) break; // Fail /* Store frames count */ if (!pg->frames) pg->frames = GET32B(buf + acTL_FCNT); if (pg->frames > 0x7FFFFFFFU) break; // Limit if (!pg->frames) break; // Fail } else if (tag == TAG4B_fcTL) { if (pg->phase > 1) { /* End of frame data - step back & return */ fseek(fp, p, SEEK_SET); return (0); } if (tl < fcTL_SIZE) break; // Bad /* Store for later use */ if (!fread(pg->fctl, fcTL_SIZE, 1, fp)) break; // Fail if (pg->fctl[fcTL_DISP] > 2) break; // Unknown value pg->disp = apng_disposal[pg->fctl[fcTL_DISP]]; pg->phase = 1; // Ready for a new frame } else if (tag == TAG4B_fdAT) { if (!pg->ihdr) break; // Fail if (!pg->phase) break; // Fail - no fcTL if (pg->phase == 1) // Had a fcTL { pg->fdat0 = p; pg->phase = 2; } if (pg->fdat0 == pg->idat0) break; // Mixed IDAT & fdAT pg->fdat1 = p + PNG_HSIZE + tl + 4; } else if (tag == TAG4B_IEND) { if (pg->phase != 2) break; // Fail pg->phase = 3; // End return (0); // Done } /* Skip tag header, data, & CRC field */ p += PNG_HSIZE + tl + 4; if (fseek(fp, p, SEEK_SET)) break; } return (-1); // Failed } static int load_apng_frame(FILE *fp, pnghead *pg, ls_settings *settings) { unsigned char *w; int l, res; /* Try scanning the frame */ res = png_scan(fp, pg); /* Prepare fake PNG */ if (!res) res = assemble_png(fp, pg); /* Load the frame */ if (!res) res = load_png(NULL, settings, &pg->mf, TRUE); if (res != 1) return (res); // Fail on any error /* Convert indexed+alpha to RGBA, to let it be regular PNG */ w = settings->img[CHN_ALPHA]; if ((settings->bpp == 1) && w) { l = settings->width * settings->height; w = malloc((size_t)l * 3); if (!w) return (FILE_MEM_ERROR); // No memory do_convert_rgb(0, 1, l, w, settings->img[CHN_IMAGE], settings->pal); free(settings->img[CHN_IMAGE]); settings->img[CHN_IMAGE] = w; settings->bpp = 3; } /* Ensure transparent color is in palette */ else map_rgb_trans(settings); return (res); } static int load_apng_frames(char *file_name, ani_settings *ani) { char buf[PNG_BYTES_TO_CHECK + 1]; pnghead pg; ani_status stat; ls_settings w_set; unsigned wx, wy; int n, d, bpp, frames = 0, res = -1; FILE *fp; if (!(fp = fopen(file_name, "rb"))) return (-1); memset(w_set.img, 0, sizeof(chanlist)); memset(&pg, 0, sizeof(pg)); if (fread(buf, 1, PNG_BYTES_TO_CHECK, fp) != PNG_BYTES_TO_CHECK) goto fail; if (png_sig_cmp(buf, 0, PNG_BYTES_TO_CHECK)) goto fail; w_set = ani->settings; res = load_apng_frame(fp, &pg, &w_set); if (res != 1) goto fail; /* Init state structure */ memset(&stat, 0, sizeof(stat)); stat.mode = ani->mode; stat.defw = pg.w; stat.defh = pg.h; /* Use whatever palette we read */ mem_pal_copy(stat.newpal, w_set.pal); stat.newcols = w_set.colors; stat.newtrans = w_set.xpm_trans; ani_init_xlat(&stat); // Init palette remapping to 1:1 and leave at that /* Init frameset - palette in APNG is global */ res = FILE_MEM_ERROR; if (!(ani->fset.pal = malloc(SIZEOF_PALETTE))) goto fail; mem_pal_copy(ani->fset.pal, stat.newpal); /* Go through images */ while (frames++ < pg.frames) { res = FILE_TOO_LONG; if (!check_next_frame(&ani->fset, ani->settings.mode, TRUE)) goto fail; /* Get the next frame, after the first */ if (frames > 1) { w_set = ani->settings; res = load_apng_frame(fp, &pg, &w_set); if (res != 1) goto fail; } delete_alpha(&w_set, 255); stat.blend = pg.fctl[fcTL_BLEND] && (w_set.img[CHN_ALPHA] || (stat.newtrans >= 0)); /* Within mtPaint delays are 1/100s granular */ n = GET16B(pg.fctl + fcTL_DN); d = GET16B(pg.fctl + fcTL_DD); if (!d) d = 100; w_set.gif_delay = (n * 100 + d - 1) / d; // Round up wx = GET32B(pg.fctl + fcTL_X); wy = GET32B(pg.fctl + fcTL_Y); if (wx > MAX_WIDTH) wx = MAX_WIDTH; // Out is out if (wy > MAX_HEIGHT) wy = MAX_HEIGHT; // Same w_set.x = wx; w_set.y = wy; /* Analyze how we can merge the frames */ res = TOO_BIG; bpp = analyze_rgba_frame(&stat, &w_set); if (bpp < 0) goto fail; /* Allocate a new frame */ res = add_frame(ani, &stat, &w_set, bpp, pg.disp); if (res) goto fail; /* Do actual compositing, remember disposal method */ composite_frame(&ani->fset, &stat, &w_set); mem_free_chanlist(w_set.img); memset(w_set.img, 0, sizeof(chanlist)); /* Write out those frames worthy to be stored */ res = done_frame(file_name, ani, FALSE); if (res != 1) goto fail; if (pg.phase > 2) break; // End of file } /* Write out the final frame if not written before */ res = done_frame(file_name, ani, TRUE); fail: free(pg.png); mem_free_chanlist(w_set.img); fclose(fp); return (res); } static int analyze_gif_frame(ani_status *stat, ls_settings *settings) { unsigned char cmap[513], *lmap, *fg, *bg; png_color *pal, *prev; int tmpal[257], same_size, show_under; int i, k, l, x, y, ul, lpal, lprev, fgw, bgw, prevtr = -1; /* Locate the new palette */ pal = prev = stat->global_pal; lpal = lprev = stat->global_cols; if (settings->colors > 0) { pal = settings->pal; lpal = settings->colors; } /* Accept new palette as final, for now */ mem_pal_copy(stat->newpal, pal); stat->newcols = lpal; stat->newtrans = settings->xpm_trans; /* Prepare for new frame */ if (stat->mode <= ANM_RAW) // Raw frame mode { stat->defw = settings->width; stat->defh = settings->height; return (0); } else if ((stat->defw > MAX_WIDTH) || (stat->defh > MAX_HEIGHT)) return (-1); // Too large ani_map_frame(stat, settings); same_size = !(settings->x | settings->y | (stat->defw ^ settings->width) | (stat->defh ^ settings->height)); ani_init_xlat(stat); // Init palette remapping to 1:1 /* First frame is exceptional */ if (!stat->prev_idx) { // Trivial if no background gets drawn if (same_size) return (0); // Trivial if have transparent color if (settings->xpm_trans >= 0) return (1); } /* Disable transparency by default, enable when needed */ stat->newtrans = -1; /* Now scan the dest area, filling colors bitmap */ memset(cmap, 0, sizeof(cmap)); fgw = settings->width; fg = settings->img[CHN_IMAGE] - (settings->y * fgw + settings->x); // Set underlayer pointer & step (ignore bpp!) bgw = stat->prev.width; bg = stat->prev.img[CHN_IMAGE] - (stat->prev.y * bgw + stat->prev.x); lmap = stat->lmap; for (y = 0; y < stat->defh; y++) { int ww = stat->defw, tp = settings->xpm_trans; int bmask = lmap[y] >> 4; for (x = 0; x < ww; x++) { int c0, bflag = lmap[x] & bmask; if ((bflag & 1) && ((c0 = fg[x]) != tp)) // New frame c0 += 256; else if ((bflag & 6) == 2) // Underlayer c0 = bg[x]; else c0 = 512; // Background (transparency) cmap[c0] = 1; } fg += fgw; bg += bgw; } /* If we have underlayer */ show_under = 0; if (stat->prev_idx) { // Use per-frame palette if underlayer has it prev = stat->prev.pal; lprev = stat->prev.cols; prevtr = stat->prev.trans; // Move underlayer transparency to "transparent" if (prevtr >= 0) { cmap[512] |= cmap[prevtr]; cmap[prevtr] = 0; } // Check if underlayer is at all visible show_under = !!memchr(cmap, 1, 256); // Visible RGB/RGBA underlayer means RGB/RGBA frame if (show_under && (stat->prev.bpp == 3)) goto RGB; } /* Now, check if either frame's palette is enough */ ul = 2; // Default is new palette if (show_under) { l = lprev > lpal ? lprev : lpal; k = lprev > lpal ? lpal : lprev; for (ul = 3 , i = 0; ul && (i < l); i++) { int tf2 = cmap[i] * 2 + cmap[256 + i]; if (tf2 && ((i >= k) || (PNG_2_INT(prev[i]) != PNG_2_INT(pal[i])))) ul &= ~tf2; // Exclude mismatched palette(s) } if (ul == 1) // Need old palette { mem_pal_copy(stat->newpal, prev); stat->newcols = lprev; } } while (ul) // Place transparency { if (cmap[512]) // Need transparency { int i, l = prevtr, nc = stat->newcols; /* If cannot use old transparent index */ if ((l < 0) || (l >= nc) || (cmap[l] | cmap[l + 256])) l = settings->xpm_trans; /* If cannot use new one either */ if ((l < 0) || (l >= nc) || (cmap[l] | cmap[l + 256])) { /* Try to find unused palette slot */ for (l = -1 , i = 0; (l < 0) && (i < nc); i++) if (!(cmap[i] | cmap[i + 256])) l = i; } if (l < 0) /* Try to add a palette slot */ { png_color *c; if (nc >= 256) break; // Failure l = stat->newcols++; c = stat->newpal + l; c->red = c->green = c->blue = 0; } // Modify mapping if (prevtr >= 0) stat->xlat[prevtr] = l; stat->xlat[512] = stat->newtrans = l; } // Successfully mapped everything - use paletted mode return (same_size ? 0 : 1); } /* Try to build combined palette */ for (ul = i = 0; (ul < 257) && (i < 512); i++) { png_color *c; int j, v; if (!cmap[i]) continue; c = (i < 256 ? prev : pal - 256) + i; v = PNG_2_INT(*c); for (j = 0; (j < ul) && (tmpal[j] != v); j++); if (j == ul) tmpal[ul++] = v; stat->xlat[i] = j; } // Add transparent color if ((ul < 257) && cmap[512]) { // Modify mapping if (prevtr >= 0) stat->xlat[prevtr] = ul; stat->xlat[512] = stat->newtrans = ul; tmpal[ul++] = 0; } if (ul < 257) // Success! { png_color *c = stat->newpal; for (i = 0; i < ul; i++ , c++) // Build palette { int v = tmpal[i]; c->red = INT_2_R(v); c->green = INT_2_G(v); c->blue = INT_2_B(v); } stat->newcols = ul; // Use paletted mode return (same_size ? 0 : 1); } /* Tried everything in vain - fall back to RGB/RGBA */ RGB: if (stat->global_cols > 0) // Use default palette if present { mem_pal_copy(stat->newpal, stat->global_pal); stat->newcols = stat->global_cols; } stat->newtrans = -1; // No color-key transparency // RGBA if underlayer with alpha, or transparent backround, is visible if ((show_under && stat->prev.img[CHN_ALPHA]) || cmap[512]) return (4); // RGB otherwise return (3); } /* Macros for accessing values in Intel byte order */ #define GET16(buf) (((buf)[1] << 8) + (buf)[0]) #define GET32(buf) (((unsigned)(buf)[3] << 24) + ((buf)[2] << 16) + \ ((buf)[1] << 8) + (buf)[0]) #define GET32s(buf) (((signed char)(buf)[3] * 0x1000000) + ((buf)[2] << 16) + \ ((buf)[1] << 8) + (buf)[0]) #define PUT16(buf, v) (buf)[0] = (v) & 0xFF; (buf)[1] = (v) >> 8; #define PUT32(buf, v) (buf)[0] = (v) & 0xFF; (buf)[1] = ((v) >> 8) & 0xFF; \ (buf)[2] = ((v) >> 16) & 0xFF; (buf)[3] = (v) >> 24; #define GIF_ID "GIF87a" #define GIF_IDLEN 6 /* GIF header */ #define GIF_VER 4 /* Where differing version digit goes */ #define GIF_WIDTH 6 /* 16b */ #define GIF_HEIGHT 8 /* 16b */ #define GIF_GPBITS 10 #define GIF_BKG 11 #define GIF_ASPECT 12 #define GIF_HDRLEN 13 /* Global palette starts here */ #define GIF_GPFLAG 0x80 #define GIF_8BPC 0x70 /* Color resolution to write out */ /* Graphics Control Extension */ #define GIF_GC_FLAGS 0 #define GIF_GC_DELAY 1 /* 16b */ #define GIF_GC_TRANS 3 #define GIF_GC_LEN 4 #define GIF_GC_TFLAG 1 #define GIF_GC_DISP 2 /* Shift amount */ /* Application Extension */ #define GIF_AP_LEN 11 /* Image */ #define GIF_IX 0 /* 16b */ #define GIF_IY 2 /* 16b */ #define GIF_IWIDTH 4 /* 16b */ #define GIF_IHEIGHT 6 /* 16b */ #define GIF_IBITS 8 #define GIF_IHDRLEN 9 #define GIF_LPFLAG 0x80 #define GIF_ILFLAG 0x40 /* Interlace */ /* Read body of GIF block into buffer (or skip if NULL), return length */ static int getblock(unsigned char *buf, FILE *fp) { int l = getc(fp); if (l == EOF) l = -1; if (l > 0) { if (!buf) fseek(fp, l, SEEK_CUR); // Just skip else if (fread(buf, 1, l, fp) < l) l = -1; // Error } return (l); } #ifdef U_LCMS /* No other uses for it now */ /* Load a sequence of GIF blocks into memory */ static int getgifdata(FILE *fp, char **res, int *len) { unsigned char *src, *dest, *mem; f_long r, p = ftell(fp); int l, size; *res = NULL; *len = 0; if (p < 0) return (1); /* Leave 2Gb+ GIFs to systems with longer f_long */ /* Measure */ while ((l = getblock(NULL, fp)) > 0); if (l < 0) return (-1); // Error r = ftell(fp); fseek(fp, p, SEEK_SET); if (r <= p) return (1); // Paranoia if (r - p > INT_MAX) return (1); // A 2Gb+ profile is unusable anyway :-) /* Allocate */ size = r - p; mem = malloc(size); if (!mem) return (1); // No memory for this /* Read */ if (fread(mem, 1, size, fp) < size) goto fail; // Error /* Merge */ src = dest = mem; while ((l = *src++)) { if (src - mem >= size - l) goto fail; // Paranoia memmove(dest, src, l); src += l; dest += l; } size = dest - mem; // Maybe realloc? /* Done */ *res = mem; *len = size; return (0); fail: free(mem); return (-1); // Someone overwrote the file damaging it } #endif /* Space enough to hold palette, or longest block + longest decoded sequence */ #define GIF_BUFSIZE (256 + 4096) typedef struct { FILE *f; int ptr, end, tail; int lc0, lc, nxc, clear, cmask; int w, bits, prev; short nxcode[4096 + 1]; unsigned char buf[GIF_BUFSIZE], cchar[4096 + 1]; } gifbuf; static void resetlzw(gifbuf *gif) { gif->nxc = gif->clear + 2; // First usable code gif->lc = gif->lc0 + 1; // Actual code size gif->cmask = (1 << gif->lc) - 1; // Actual code mask gif->prev = -1; // Previous code } static int initlzw(gifbuf *gif, FILE *fp) { int i; gif->f = fp; gif->lc0 = i = getc(fp); // Min code size /* Enforce hard upper limit but allow wasteful encoding */ if ((i == EOF) || (i > 11)) return (FALSE); gif->clear = i = 1 << i; // Clear code /* Initial 1-char codes */ while (--i >= 0) gif->nxcode[i] = -1 , gif->cchar[i] = (unsigned char)i; resetlzw(gif); gif->w = gif->bits = 0; // Ready bits in shifter gif->ptr = gif->end = gif->tail = 0; // Ready data in buffer return (TRUE); } static int getlzw(unsigned char *dest, int cnt, gifbuf *gif) { int l, c, cx, w, bits, lc, cmask, prev, nxc, tail = gif->tail; while (TRUE) { l = tail > cnt ? cnt : tail; cnt -= l; l = tail - l; while (tail > l) *dest++ = gif->buf[GIF_BUFSIZE - tail--]; if (cnt <= 0) break; // No tail past this point w = gif->w; bits = gif->bits; lc = gif->lc; while (bits < lc) { if (gif->ptr >= gif->end) { gif->end = getblock(gif->buf, gif->f); if (gif->end <= 0) return (FALSE); // No data gif->ptr = 0; } w |= gif->buf[gif->ptr++] << bits; bits += 8; } cmask = gif->cmask; c = w & cmask; gif->w = w >> lc; gif->bits = bits - lc; if (c == gif->clear) { resetlzw(gif); continue; } if (c == gif->clear + 1) return (FALSE); // Premature EOI /* Update for next code */ prev = gif->prev; gif->prev = c; nxc = gif->nxc; gif->nxcode[nxc] = prev; if ((prev >= 0) && (nxc < 4096)) { if ((++gif->nxc > cmask) && (cmask < 4096 - 1)) gif->cmask = (1 << ++gif->lc) - 1; } /* Decode this one */ if (c > nxc) return (FALSE); // Broken code if ((c == nxc) && (prev < 0)) return (FALSE); // Too early for (cx = c; cx >= 0; cx = gif->nxcode[cx]) gif->buf[GIF_BUFSIZE - ++tail] = gif->cchar[cx]; gif->cchar[nxc] = gif->buf[GIF_BUFSIZE - tail]; /* In case c == nxc, its char was garbage till now, so reread it */ gif->buf[GIF_BUFSIZE - 1] = gif->cchar[c]; } gif->tail = tail; return (TRUE); } static int load_gif_frame(FILE *fp, ls_settings *settings) { /* GIF interlace pattern: Y0, DY, ... */ static const unsigned char interlace[10] = { 0, 1, 0, 8, 4, 8, 2, 4, 1, 2 }; unsigned char hdr[GIF_IHDRLEN]; gifbuf gif; int i, k, kx, n, w, h, dy, res; /* Read the header */ if (fread(hdr, 1, GIF_IHDRLEN, fp) < GIF_IHDRLEN) return (-1); /* Get local palette if any */ if (hdr[GIF_IBITS] & GIF_LPFLAG) { int cols = 2 << (hdr[GIF_IBITS] & 7); if (fread(gif.buf, 3, cols, fp) < cols) return (-1); rgb2pal(settings->pal, gif.buf, settings->colors = cols); } if (settings->colors < 0) return (-1); // No palette at all /* If palette is all we need */ if ((settings->mode == FS_PALETTE_LOAD) || (settings->mode == FS_PALETTE_DEF)) return (EXPLODE_FAILED); if (!initlzw(&gif, fp)) return (-1); /* Store actual image parameters */ settings->x = GET16(hdr + GIF_IX); settings->y = GET16(hdr + GIF_IY); settings->width = w = GET16(hdr + GIF_IWIDTH); settings->height = h = GET16(hdr + GIF_IHEIGHT); settings->bpp = 1; if ((res = allocate_image(settings, CMASK_IMAGE))) return (res); res = FILE_LIB_ERROR; if (!settings->silent) ls_init("GIF", 0); if (hdr[GIF_IBITS] & GIF_ILFLAG) k = 2 , kx = 10; /* Interlace */ else k = 0 , kx = 2; for (n = 0; k < kx; k += 2) { dy = interlace[k + 1]; for (i = interlace[k]; i < h; n++ , i += dy) { if (!getlzw(settings->img[CHN_IMAGE] + i * w, w, &gif)) goto fail; ls_progress(settings, n, 10); } } /* Skip data blocks till 0 */ while ((i = getblock(NULL, fp)) > 0); if (!i) res = 1; fail: if (!settings->silent) progress_end(); return (res); } static int load_gif_frames(char *file_name, ani_settings *ani) { /* GIF disposal codes mapping */ static const unsigned short gif_disposal[8] = { FM_DISP_LEAVE, FM_DISP_LEAVE, FM_DISP_REMOVE, FM_DISP_RESTORE, /* Handling (reserved) "4" same as "3" is what Mozilla does */ FM_DISP_RESTORE, FM_DISP_LEAVE, FM_DISP_LEAVE, FM_DISP_LEAVE }; unsigned char hdr[GIF_HDRLEN], buf[768]; png_color w_pal[256]; ani_status stat; ls_settings w_set, init_set; int l, id, disposal, bpp, res = -1; FILE *fp; if (!(fp = fopen(file_name, "rb"))) return (-1); memset(w_set.img, 0, sizeof(chanlist)); /* Read the header */ if (fread(hdr, 1, GIF_HDRLEN, fp) < GIF_HDRLEN) goto fail; /* Check signature */ if (hdr[GIF_VER] == '9') hdr[GIF_VER] = '7'; // Does not matter anyway if (memcmp(hdr, GIF_ID, GIF_IDLEN)) goto fail; /* Init state structure */ memset(&stat, 0, sizeof(stat)); stat.mode = ani->mode; stat.defw = GET16(hdr + GIF_WIDTH); stat.defh = GET16(hdr + GIF_HEIGHT); stat.global_cols = -1; /* Get global palette */ if (hdr[GIF_GPBITS] & GIF_GPFLAG) { int cols = 2 << (hdr[GIF_GPBITS] & 7); if (fread(buf, 3, cols, fp) < cols) goto fail; rgb2pal(stat.global_pal, buf, stat.global_cols = cols); } stat.blend = TRUE; // No other case in GIF /* Init temp container */ init_set = ani->settings; init_set.colors = 0; // Nonzero will signal local palette init_set.pal = w_pal; init_set.xpm_trans = -1; init_set.gif_delay = 0; disposal = FM_DISP_LEAVE; /* Init frameset */ if (stat.global_cols > 0) // Set default palette { res = FILE_MEM_ERROR; if (!(ani->fset.pal = malloc(SIZEOF_PALETTE))) goto fail; mem_pal_copy(ani->fset.pal, stat.global_pal); } /* Go through images */ while (TRUE) { res = -1; id = getc(fp); if (!id) continue; // Extra end-blocks do happen sometimes if (id == ';') break; // Trailer block if (id == '!') // Extension block { if ((id = getc(fp)) == EOF) goto fail; if (id == 0xF9) // Graphics control - read it { if (getblock(buf, fp) < GIF_GC_LEN) goto fail; /* !!! In practice, Graphics Control Extension * affects not only "the first block to follow" * as docs say, but EVERY following block - WJ */ init_set.xpm_trans = buf[GIF_GC_FLAGS] & GIF_GC_TFLAG ? buf[GIF_GC_TRANS] : -1; init_set.gif_delay = GET16(buf + GIF_GC_DELAY); disposal = gif_disposal[(buf[GIF_GC_FLAGS] >> GIF_GC_DISP) & 7]; } while ((l = getblock(NULL, fp)) > 0); // Skip till end if (l < 0) goto fail; } else if (id == ',') // Image { res = FILE_TOO_LONG; if (!check_next_frame(&ani->fset, ani->settings.mode, TRUE)) goto fail; w_set = init_set; res = load_gif_frame(fp, &w_set); if (res != 1) goto fail; /* Analyze how we can merge the frames */ res = TOO_BIG; bpp = analyze_gif_frame(&stat, &w_set); if (bpp < 0) goto fail; /* Allocate a new frame */ res = add_frame(ani, &stat, &w_set, bpp, disposal); if (res) goto fail; /* Do actual compositing, remember disposal method */ composite_frame(&ani->fset, &stat, &w_set); mem_free_chanlist(w_set.img); memset(w_set.img, 0, sizeof(chanlist)); /* Write out those frames worthy to be stored */ res = done_frame(file_name, ani, FALSE); if (res != 1) goto fail; } else goto fail; // Garbage or EOF } /* Write out the final frame if not written before */ res = done_frame(file_name, ani, TRUE); fail: mem_free_chanlist(w_set.img); fclose(fp); return (res); } static int load_gif(char *file_name, ls_settings *settings) { unsigned char hdr[GIF_HDRLEN], buf[768]; int trans = -1, delay = settings->gif_delay, frame = 0; int l, id, res = -1; FILE *fp; if (!(fp = fopen(file_name, "rb"))) return (-1); /* Read the header */ if (fread(hdr, 1, GIF_HDRLEN, fp) < GIF_HDRLEN) goto fail; /* Check signature */ if (hdr[GIF_VER] == '9') hdr[GIF_VER] = '7'; // Does not matter anyway if (memcmp(hdr, GIF_ID, GIF_IDLEN)) goto fail; /* Get global palette */ settings->colors = -1; if (hdr[GIF_GPBITS] & GIF_GPFLAG) { int cols = 2 << (hdr[GIF_GPBITS] & 7); if (fread(buf, 3, cols, fp) < cols) goto fail; rgb2pal(settings->pal, buf, settings->colors = cols); } /* Go read the first image */ while (TRUE) { res = frame ? FILE_LIB_ERROR : -1; id = getc(fp); if (!id) continue; // Extra end-blocks do happen sometimes if (id == ';') break; // Trailer block if (id == '!') // Extension block { if ((id = getc(fp)) == EOF) goto fail; if (id == 0xF9) // Graphics control - read it { if (getblock(buf, fp) < GIF_GC_LEN) goto fail; trans = buf[GIF_GC_FLAGS] & GIF_GC_TFLAG ? buf[GIF_GC_TRANS] : -1; delay = GET16(buf + GIF_GC_DELAY); } #ifdef U_LCMS /* Yes GIF can have a color profile - imagine that */ else if ((id == 0xFF) // Application extension && !settings->icc_size // No need of it otherwise && (getblock(buf, fp) >= GIF_AP_LEN) // Not broken && !memcmp(buf, "ICCRGBG1012", GIF_AP_LEN)) // The right ID { l = getgifdata(fp, &settings->icc, &settings->icc_size); if (l < 0) goto fail; if (!l) continue; // No trailing blocks to skip } #endif while ((l = getblock(NULL, fp)) > 0); // Skip till end if (l < 0) goto fail; } else if (id == ',') // Image { if (frame++) /* Multipage GIF - notify user */ { res = FILE_HAS_FRAMES; goto fail; } settings->gif_delay = delay; settings->xpm_trans = trans; res = load_gif_frame(fp, settings); if (res != 1) goto fail; } else goto fail; // Garbage or EOF } if (frame) res = 1; // No images is fail fail: fclose(fp); return (res); } /* Space enough to hold palette and all headers, or longest block */ #define GIF_WBUFSIZE (768 + GIF_HDRLEN + (GIF_GC_LEN + 4) + (GIF_IHDRLEN + 2)) /* A cuckoo hash would take 4x less space, but need much more code */ #define GIF_CODESSIZE ((4096 * 2 * 16) * sizeof(short)) typedef struct { FILE *f; int cnt, nxmap; int lc0, lc, nxc, clear, nxc2; int w, bits, prev; short *codes; unsigned char buf[GIF_WBUFSIZE]; } gifcbuf; static void resetclzw(gifcbuf *gif) { /* Send clear code at current length */ gif->w |= gif->clear << gif->bits; gif->bits += gif->lc; /* Reset parameters */ gif->nxc = gif->clear + 2; // First usable code gif->lc = gif->lc0 + 1; // Actual code size gif->nxc2 = 1 << gif->lc; // For next code size memset(gif->codes, 0, GIF_CODESSIZE); // Maps gif->nxmap = 1; // First usable intermediate map } static void initclzw(gifcbuf *gif, int lc0, FILE *fp) { if (lc0 < 2) lc0 = 2; // Minimum allowed gif->f = fp; gif->lc0 = lc0; fputc(lc0, fp); gif->clear = 1 << lc0; // Clear code gif->prev = -1; // No previous code gif->cnt = gif->w = gif->bits = 0; // No data yet gif->lc = gif->lc0 + 1; // Actual code size resetclzw(gif); // Initial clear } static void emitlzw(gifcbuf *gif, int c) { int bits = gif->bits, w = gif->w | (c << bits); bits += gif->lc; while (bits >= 8) { gif->buf[++gif->cnt] = (unsigned char)w; w >>= 8; bits -= 8; if (gif->cnt >= 255) { gif->buf[0] = 255; fwrite(gif->buf, 1, 256, gif->f); gif->cnt = 0; } } gif->bits = bits; gif->w = w; /* Extend code size if needed */ if (gif->nxc >= gif->nxc2) gif->nxc2 = 1 << ++gif->lc; } static void putlzw(gifcbuf *gif, unsigned char *src, int cnt) { short *codes = gif->codes; int i, j, c, prev = gif->prev; while (cnt-- > 0) { c = *src++; if (prev < 0) /* Begin */ { prev = c; continue; } /* Try compression */ i = prev * 16 + (c >> 4) + 4096 * 16; j = codes[i] * 16 + (c & 0xF); j = codes[j]; if (j) // Have match { prev = j - 4096; continue; } /* Emit the code */ emitlzw(gif, prev); prev = c; /* Do a clear if needed */ if (gif->nxc >= 4096 - 1) { resetclzw(gif); continue; } /* Add new code */ if (!codes[i]) codes[i] = gif->nxmap++; j = codes[i] * 16 + (c & 0xF); codes[j] = gif->nxc++ + 4096; } gif->prev = prev; } static void donelzw(gifcbuf *gif) /* Flush */ { emitlzw(gif, gif->prev); emitlzw(gif, gif->clear + 1); // EOD if (gif->bits) gif->buf[++gif->cnt] = gif->w; // gif->w = gif->bits = 0; gif->buf[0] = gif->cnt; gif->buf[gif->cnt + 1] = 0; // Block terminator fwrite(gif->buf, 1, gif->cnt + 2, gif->f); // gif->cnt = 0; } static int save_gif(char *file_name, ls_settings *settings) { gifcbuf gif; unsigned char *tmp; FILE *fp = NULL; int i, nc, ext = FALSE, w = settings->width, h = settings->height; /* GIF save must be on indexed image */ if (settings->bpp != 1) return WRONG_FORMAT; gif.codes = malloc(GIF_CODESSIZE); if (!gif.codes) return (-1); if (!(fp = fopen(file_name, "wb"))) { free(gif.codes); return (-1); } /* Get colormap size bits */ nc = nlog2(settings->colors) - 1; if (nc < 0) nc = 0; /* Prepare header */ tmp = gif.buf; memset(tmp, 0, GIF_HDRLEN); memcpy(tmp, GIF_ID, GIF_IDLEN); PUT16(tmp + GIF_WIDTH, w); PUT16(tmp + GIF_HEIGHT, h); tmp[GIF_GPBITS] = GIF_GPFLAG | GIF_8BPC | nc; tmp += GIF_HDRLEN; /* Prepare global palette */ i = 2 << nc; pal2rgb(tmp, settings->pal, settings->colors, i); tmp += i * 3; /* Prepare extension */ if (settings->xpm_trans >= 0) { ext = TRUE; *tmp++ = '!'; // Extension block *tmp++ = 0xF9; // Graphics control *tmp++ = GIF_GC_LEN; memset(tmp, 0, GIF_GC_LEN + 1); // W/block terminator tmp[GIF_GC_FLAGS] = GIF_GC_TFLAG; tmp[GIF_GC_TRANS] = settings->xpm_trans; tmp += GIF_GC_LEN + 1; } /* Prepare image header */ *tmp++ = ','; memset(tmp, 0, GIF_IHDRLEN); PUT16(tmp + GIF_IWIDTH, w); PUT16(tmp + GIF_IHEIGHT, h); tmp += GIF_IHDRLEN; if (ext) gif.buf[GIF_VER] = '9'; // If we use extension /* Write out all the headers */ fwrite(gif.buf, 1, tmp - gif.buf, fp); if (!settings->silent) ls_init("GIF", 1); initclzw(&gif, nc + 1, fp); // "Min code size" = palette index bits for (i = 0; i < h; i++) { putlzw(&gif, settings->img[CHN_IMAGE] + i * w, w); ls_progress(settings, i, 20); } donelzw(&gif); fputc(';', fp); // Trailer block fclose(fp); if (!settings->silent) progress_end(); free(gif.codes); return 0; } #ifdef NEED_CMYK #ifdef U_LCMS /* Guard against cmsHTRANSFORM changing into something overlong in the future */ typedef char cmsHTRANSFORM_Does_Not_Fit_Into_Pointer[2 * (sizeof(cmsHTRANSFORM) <= sizeof(char *)) - 1]; static int init_cmyk2rgb(ls_settings *settings, unsigned char *icc, int len, int inverted) { cmsHPROFILE from, to; cmsHTRANSFORM how = NULL; from = cmsOpenProfileFromMem((void *)icc, len); if (!from) return (TRUE); // Unopenable now, unopenable ever to = cmsCreate_sRGBProfile(); if (cmsGetColorSpace(from) == icSigCmykData) how = cmsCreateTransform(from, inverted ? TYPE_CMYK_8_REV : TYPE_CMYK_8, to, TYPE_RGB_8, INTENT_PERCEPTUAL, 0); if (from) cmsCloseProfile(from); cmsCloseProfile(to); if (!how) return (FALSE); // Better luck the next time settings->icc = (char *)how; settings->icc_size = -2; return (TRUE); } static void done_cmyk2rgb(ls_settings *settings) { if (settings->icc_size != -2) return; cmsDeleteTransform((cmsHTRANSFORM)settings->icc); settings->icc = NULL; settings->icc_size = -1; // Not need profiles anymore } #else /* No LCMS */ #define done_cmyk2rgb(X) #endif #endif static void cmyk2rgb(unsigned char *dest, unsigned char *src, int cnt, int inverted, ls_settings *settings) { unsigned char xb; int j, k, r, g, b; #ifdef U_LCMS /* Convert CMYK to RGB using LCMS if possible */ if (settings->icc_size == -2) { cmsDoTransform((cmsHTRANSFORM)settings->icc, src, dest, cnt); return; } #endif /* Simple CMYK->RGB conversion */ xb = inverted ? 0 : 255; for (j = 0; j < cnt; j++ , src += 4 , dest += 3) { k = src[3] ^ xb; r = (src[0] ^ xb) * k; dest[0] = (r + (r >> 8) + 1) >> 8; g = (src[1] ^ xb) * k; dest[1] = (g + (g >> 8) + 1) >> 8; b = (src[2] ^ xb) * k; dest[2] = (b + (b >> 8) + 1) >> 8; } } #ifdef U_JPEG struct my_error_mgr { struct jpeg_error_mgr pub; // "public" fields jmp_buf setjmp_buffer; // for return to caller }; typedef struct my_error_mgr *my_error_ptr; METHODDEF(void) my_error_exit (j_common_ptr cinfo) { my_error_ptr myerr = (my_error_ptr) cinfo->err; longjmp(myerr->setjmp_buffer, 1); } struct my_error_mgr jerr; static int load_jpeg(char *file_name, ls_settings *settings) { static int pr; struct jpeg_decompress_struct cinfo; unsigned char *memp, *memx = NULL; FILE *fp; int i, width, height, bpp, res = -1, inv = 0; #ifdef U_LCMS unsigned char *icc = NULL; #endif if ((fp = fopen(file_name, "rb")) == NULL) return (-1); pr = 0; jpeg_create_decompress(&cinfo); cinfo.err = jpeg_std_error(&jerr.pub); jerr.pub.error_exit = my_error_exit; if (setjmp(jerr.setjmp_buffer)) { res = settings->width ? FILE_LIB_ERROR : -1; goto fail; } jpeg_stdio_src(&cinfo, fp); #ifdef U_LCMS /* Request ICC profile aka APP2 data be preserved */ if (!settings->icc_size) jpeg_save_markers(&cinfo, JPEG_APP0 + 2, 0xFFFF); #endif jpeg_read_header(&cinfo, TRUE); jpeg_start_decompress(&cinfo); bpp = 3; switch (cinfo.out_color_space) { case JCS_RGB: break; case JCS_GRAYSCALE: set_gray(settings); bpp = 1; break; case JCS_CMYK: /* Photoshop writes CMYK data inverted */ inv = cinfo.saw_Adobe_marker; if ((memx = malloc(cinfo.output_width * 4))) break; res = FILE_MEM_ERROR; // Fallthrough default: goto fail; /* Unsupported colorspace */ } settings->width = width = cinfo.output_width; settings->height = height = cinfo.output_height; settings->bpp = bpp; if ((res = allocate_image(settings, CMASK_IMAGE))) goto fail; res = -1; pr = !settings->silent; #ifdef U_LCMS #define PARTHDR 14 while (!settings->icc_size) { jpeg_saved_marker_ptr mk; unsigned char *tmp, *parts[256]; int i, part, nparts = -1, icclen = 0, lparts[256]; /* List parts */ memset(parts, 0, sizeof(parts)); for (mk = cinfo.marker_list; mk; mk = mk->next) { if ((mk->marker != JPEG_APP0 + 2) || (mk->data_length < PARTHDR) || strcmp(mk->data, "ICC_PROFILE")) continue; part = GETJOCTET(mk->data[13]); if (nparts < 0) nparts = part; if (nparts != part) break; part = GETJOCTET(mk->data[12]); if (!part-- || (part >= nparts) || parts[part]) break; parts[part] = (unsigned char *)(mk->data + PARTHDR); icclen += lparts[part] = mk->data_length - PARTHDR; } if (nparts < 0) break; icc = tmp = malloc(icclen); if (!icc) break; /* Assemble parts */ for (i = 0; i < nparts; i++) { if (!parts[i]) break; memcpy(tmp, parts[i], lparts[i]); tmp += lparts[i]; } if (i < nparts) break; // Sequence had a hole /* If profile is needed right now, for CMYK->RGB */ if (memx && init_cmyk2rgb(settings, icc, icclen, inv)) break; // Transform is ready, so drop the profile settings->icc = icc; settings->icc_size = icclen; icc = NULL; // Leave the profile be break; } free(icc); #undef PARTHDR #endif if (pr) ls_init("JPEG", 0); for (i = 0; i < height; i++) { memp = settings->img[CHN_IMAGE] + width * i * bpp; jpeg_read_scanlines(&cinfo, memx ? &memx : &memp, 1); if (memx) cmyk2rgb(memp, memx, width, inv, settings); ls_progress(settings, i, 20); } done_cmyk2rgb(settings); jpeg_finish_decompress(&cinfo); res = 1; fail: if (pr) progress_end(); jpeg_destroy_decompress(&cinfo); fclose(fp); free(memx); return (res); } static int save_jpeg(char *file_name, ls_settings *settings) { struct jpeg_compress_struct cinfo; JSAMPROW row_pointer; FILE *fp; int i; if (settings->bpp == 1) return WRONG_FORMAT; if ((fp = fopen(file_name, "wb")) == NULL) return -1; cinfo.err = jpeg_std_error(&jerr.pub); jerr.pub.error_exit = my_error_exit; if (setjmp(jerr.setjmp_buffer)) { jpeg_destroy_compress(&cinfo); fclose(fp); return -1; } jpeg_create_compress(&cinfo); jpeg_stdio_dest( &cinfo, fp ); cinfo.image_width = settings->width; cinfo.image_height = settings->height; cinfo.input_components = 3; cinfo.in_color_space = JCS_RGB; jpeg_set_defaults(&cinfo); jpeg_set_quality(&cinfo, settings->jpeg_quality, TRUE ); jpeg_start_compress( &cinfo, TRUE ); row_pointer = settings->img[CHN_IMAGE]; if (!settings->silent) ls_init("JPEG", 1); for (i = 0; i < settings->height; i++ ) { jpeg_write_scanlines(&cinfo, &row_pointer, 1); row_pointer += 3 * settings->width; ls_progress(settings, i, 20); } jpeg_finish_compress( &cinfo ); if (!settings->silent) progress_end(); jpeg_destroy_compress( &cinfo ); fclose(fp); return 0; } #endif #ifdef NEED_FILE2MEM /* Read in the entire file, up to max size if given */ static int file2mem(char *file_name, unsigned char **where, size_t *len, size_t max) { FILE *fp; unsigned char *buf; f_long l; int res = -1; if (!(fp = fopen(file_name, "rb"))) return (-1); fseek(fp, 0, SEEK_END); l = ftell(fp); /* Where a f_long is too short to hold the file's size, address space is * too small to usefully hold the whole file anyway - WJ */ /* And when a hard limit is set, it should be honored */ if ((l > 0) && (!max || (l <= max))) { fseek(fp, 0, SEEK_SET); res = FILE_MEM_ERROR; if ((buf = malloc(l))) { res = -1; if (fread(buf, 1, l, fp) < l) free(buf); else *where = buf , *len = l , res = 0; } } fclose(fp); return (res); } #endif #ifdef U_JP2 /* *** PREFACE *** * OpenJPEG 1.x is wasteful in the extreme, with memory overhead of about * 7 times the unpacked image size. So it can fail to handle even such * resolutions that fit into available memory with lots of room to spare. * Still, JasPer is an even worse memory hog, if a somewhat faster one. * Another thing - Linux builds of OpenJPEG cannot properly encode an opacity * channel (fixed in SVN on 06.11.09, revision 541) * And JP2 images with 4 channels, produced by OpenJPEG, cause JasPer * to die horribly. * Version 2.3.0 (04.10.17) was a sharp improvement, being twice faster than * JasPer when decompressing and less memory hungry (overhead of 5x size). When * compressing however, as of 2.3.1 still was about twice slower than JasPer. * Version 2.4.0 (28.12.20) fixed that, becoming about twice faster than JasPer * when compressing too. * Decompression speedup happened only for 64-bit builds, but on 32-bit with * multiple cores, multithreading still can let it overtake JasPer - WJ */ static int parse_opj(opj_image_t *image, ls_settings *settings) { opj_image_comp_t *comp; unsigned char xtb[256], *dest; int i, j, k, w, h, w0, nc, step, shift; unsigned delta; int *src, cmask = CMASK_IMAGE, res; if (image->numcomps < 3) /* Guess this is paletted */ { set_gray(settings); settings->bpp = 1; } else settings->bpp = 3; if ((nc = settings->bpp) < image->numcomps) nc++ , cmask = CMASK_RGBA; comp = image->comps; settings->width = w = (comp->w + (1 << comp->factor) - 1) >> comp->factor; settings->height = h = (comp->h + (1 << comp->factor) - 1) >> comp->factor; for (i = 1; i < nc; i++) /* Check if all components are the same size */ { comp++; if ((w != (comp->w + (1 << comp->factor) - 1) >> comp->factor) || (h != (comp->h + (1 << comp->factor) - 1) >> comp->factor)) return (-1); } if ((res = allocate_image(settings, cmask))) return (res); /* Unpack data */ for (i = 0 , comp = image->comps; i < nc; i++ , comp++) { if (i < settings->bpp) /* Image */ { dest = settings->img[CHN_IMAGE] + i; step = settings->bpp; } else /* Alpha */ { dest = settings->img[CHN_ALPHA]; if (!dest) break; /* No alpha allocated */ step = 1; } w0 = comp->w; delta = comp->sgnd ? 1U << (comp->prec - 1) : 0; shift = comp->prec > 8 ? comp->prec - 8 : 0; set_xlate(xtb, comp->prec - shift); for (j = 0; j < h; j++) { src = comp->data + j * w0; for (k = 0; k < w; k++) { *dest = xtb[(src[k] + delta) >> shift]; dest += step; } } } #ifdef U_LCMS #if U_JP2 >= 2 /* 2.x */ /* Extract ICC profile if it's of use */ if (!settings->icc_size && image->icc_profile_buf && (image->icc_profile_len < INT_MAX) && (settings->icc = malloc(image->icc_profile_len))) memcpy(settings->icc, image->icc_profile_buf, settings->icc_size = image->icc_profile_len); #endif #endif return (1); } static opj_image_t *prepare_opj(ls_settings *settings) { opj_image_cmptparm_t channels[4]; opj_image_t *image; unsigned char *src; int i, j, k, nc, step; int *dest, w = settings->width, h = settings->height; nc = settings->img[CHN_ALPHA] ? 4 : 3; memset(channels, 0, sizeof(channels)); for (i = 0; i < nc; i++) { channels[i].prec = channels[i].bpp = 8; channels[i].dx = channels[i].dy = 1; channels[i].w = w; channels[i].h = h; } image = opj_image_create(nc, channels, #if U_JP2 < 2 /* 1.x */ CLRSPC_SRGB); #else /* 2.x */ OPJ_CLRSPC_SRGB); #endif if (!image) return (NULL); image->x0 = image->y0 = 0; image->x1 = w; image->y1 = h; /* Fill it */ k = w * h; for (i = 0; i < nc; i++) { if (i < 3) { src = settings->img[CHN_IMAGE] + i; step = 3; } else { src = settings->img[CHN_ALPHA]; step = 1; } dest = image->comps[i].data; for (j = 0; j < k; j++ , src += step) dest[j] = *src; } return (image); } #if U_JP2 < 2 /* 1.x */ static void stupid_callback(const char *msg, void *client_data) { } static int load_jpeg2000(char *file_name, ls_settings *settings) { opj_dparameters_t par; opj_dinfo_t *dinfo; opj_cio_t *cio = NULL; opj_image_t *image = NULL; opj_event_mgr_t useless_events; // !!! Silently made mandatory in v1.2 unsigned char *buf = NULL; size_t l; int pr, res; /* Read in the entire file, provided its size fits into int */ if ((res = file2mem(file_name, &buf, &l, INT_MAX))) return (res); /* Decompress it */ dinfo = opj_create_decompress(settings->ftype == FT_J2K ? CODEC_J2K : CODEC_JP2); if (!dinfo) goto lfail; memset(&useless_events, 0, sizeof(useless_events)); useless_events.error_handler = useless_events.warning_handler = useless_events.info_handler = stupid_callback; opj_set_event_mgr((opj_common_ptr)dinfo, &useless_events, stderr); opj_set_default_decoder_parameters(&par); opj_setup_decoder(dinfo, &par); cio = opj_cio_open((opj_common_ptr)dinfo, buf, l); if (!cio) goto lfail; if ((pr = !settings->silent)) ls_init("JPEG2000", 0); image = opj_decode(dinfo, cio); opj_cio_close(cio); opj_destroy_decompress(dinfo); free(buf); if (!image) goto ifail; /* Analyze what we got */ // !!! OpenJPEG 1.1.1 does *NOT* properly set image->color_space !!! res = parse_opj(image, settings); ifail: if (pr) progress_end(); opj_image_destroy(image); return (res); lfail: opj_destroy_decompress(dinfo); free(buf); return (res); } static int save_jpeg2000(char *file_name, ls_settings *settings) { opj_cparameters_t par; opj_cinfo_t *cinfo; opj_cio_t *cio = NULL; opj_image_t *image; opj_event_mgr_t useless_events; // !!! Silently made mandatory in v1.2 FILE *fp; int k, res = -1; if (settings->bpp == 1) return WRONG_FORMAT; if ((fp = fopen(file_name, "wb")) == NULL) return -1; /* Create intermediate structure */ image = prepare_opj(settings); if (!image) goto ffail; /* Compress it */ if (!settings->silent) ls_init("JPEG2000", 1); cinfo = opj_create_compress(settings->ftype == FT_JP2 ? CODEC_JP2 : CODEC_J2K); if (!cinfo) goto fail; memset(&useless_events, 0, sizeof(useless_events)); useless_events.error_handler = useless_events.warning_handler = useless_events.info_handler = stupid_callback; opj_set_event_mgr((opj_common_ptr)cinfo, &useless_events, stderr); opj_set_default_encoder_parameters(&par); par.tcp_numlayers = 1; par.tcp_rates[0] = settings->jp2_rate; par.cp_disto_alloc = 1; opj_setup_encoder(cinfo, &par, image); cio = opj_cio_open((opj_common_ptr)cinfo, NULL, 0); if (!cio) goto fail; if (!opj_encode(cinfo, cio, image, NULL)) goto fail; /* Write it */ k = cio_tell(cio); if (fwrite(cio->buffer, 1, k, fp) == k) res = 0; fail: if (cio) opj_cio_close(cio); opj_destroy_compress(cinfo); opj_image_destroy(image); if (!settings->silent) progress_end(); ffail: fclose(fp); return (res); } #else /* 2.x */ static int load_jpeg2000(char *file_name, ls_settings *settings) { opj_dparameters_t par; opj_codec_t *dinfo; opj_stream_t *inp = NULL; opj_image_t *image = NULL; int i, pr, res = -1; #if !OPJ_VERSION_MINOR /* 2.0.x */ FILE *fp; #endif #if !OPJ_VERSION_MINOR /* 2.0.x */ if ((fp = fopen(file_name, "rb")) == NULL) return (-1); if (!(inp = opj_stream_create_default_file_stream(fp, TRUE))) goto ffail; #else /* 2.1+ */ if (!(inp = opj_stream_create_default_file_stream(file_name, TRUE))) return (-1); #endif /* Decompress it */ dinfo = opj_create_decompress(settings->ftype == FT_J2K ? OPJ_CODEC_J2K : OPJ_CODEC_JP2); if (!dinfo) goto ffail; opj_set_default_decoder_parameters(&par); if (!opj_setup_decoder(dinfo, &par)) goto dfail; #if defined(U_THREADS) && (OPJ_VERSION_MINOR >= 2) /* 2.2+ */ /* Not much effect on 64 bit as of 2.3.0 - only 10% faster from a 2nd core * But since 2.3.1, 1.3x faster with 2 cores, 1.7x with 4+ */ opj_codec_set_threads(dinfo, helper_threads()); #endif if ((pr = !settings->silent)) ls_init("JPEG2000", 0); i = opj_read_header(inp, dinfo, &image) && opj_decode(dinfo, inp, image) && opj_end_decompress(dinfo, inp); opj_destroy_codec(dinfo); opj_stream_destroy(inp); if (!i) goto ifail; /* Parse what we got */ if (image->color_space >= OPJ_CLRSPC_SYCC) goto ifail; // sYCC and CMYK - unsupported till seen in the wild res = parse_opj(image, settings); ifail: if (pr) progress_end(); opj_image_destroy(image); return (res); dfail: opj_destroy_codec(dinfo); ffail: opj_stream_destroy(inp); #if !OPJ_VERSION_MINOR /* 2.0.x */ fclose(fp); #endif return (res); } static int save_jpeg2000(char *file_name, ls_settings *settings) { opj_cparameters_t par; opj_codec_t *cinfo; opj_stream_t *outp = NULL; opj_image_t *image; int res = -1; #if !OPJ_VERSION_MINOR /* 2.0.x */ FILE *fp; #endif if (settings->bpp == 1) return WRONG_FORMAT; #if !OPJ_VERSION_MINOR /* 2.0.x */ if ((fp = fopen(file_name, "wb")) == NULL) return (-1); if (!(outp = opj_stream_create_default_file_stream(fp, FALSE))) goto ffail; #else /* 2.1+ */ if (!(outp = opj_stream_create_default_file_stream(file_name, FALSE))) return (-1); #endif /* Create intermediate structure */ image = prepare_opj(settings); if (!image) goto ffail; /* Compress it */ if (!settings->silent) ls_init("JPEG2000", 1); cinfo = opj_create_compress(settings->ftype == FT_JP2 ? OPJ_CODEC_JP2 : OPJ_CODEC_J2K); if (!cinfo) goto fail; opj_set_default_encoder_parameters(&par); par.tcp_numlayers = 1; par.tcp_rates[0] = settings->jp2_rate; par.cp_disto_alloc = 1; opj_setup_encoder(cinfo, &par, image); #if defined(U_THREADS) && (OPJ_VERSION_MINOR >= 4) /* 2.4+ */ /* As of 2.4.0, 1.4x faster with 2 cores, 1.7x with 4+ */ opj_codec_set_threads(cinfo, helper_threads()); #endif if (opj_start_compress(cinfo, image, outp) && opj_encode(cinfo, outp) && opj_end_compress(cinfo, outp)) res = 0; fail: opj_destroy_codec(cinfo); opj_image_destroy(image); if (!settings->silent) progress_end(); ffail: opj_stream_destroy(outp); #if !OPJ_VERSION_MINOR /* 2.0.x */ fclose(fp); #endif return (res); } #endif #endif #ifdef U_JASPER /* *** PREFACE *** * JasPer is QUITE a memory waster, with peak memory usage nearly TEN times the * unpacked image size. But what is worse, its API is 99% undocumented. * And to add insult to injury, it reacts to some invalid JP2 files (4-channel * ones written by OpenJPEG) by abort()ing, instead of returning error - WJ */ static int jasper_init; static int load_jpeg2000(char *file_name, ls_settings *settings) { jas_image_t *img; jas_stream_t *inp; jas_matrix_t *mx; jas_seqent_t *src; char *fmt; unsigned char xtb[256], *dest; int nc, cspace, mode, slots[4]; int bits, shift, chan, step; unsigned delta; int i, j, k, n, nx, w, h, bpp, pr = 0, res = -1; /* Init the dumb library */ if (!jasper_init) jas_init(); jasper_init = TRUE; /* Open the file */ inp = jas_stream_fopen(file_name, "rb"); if (!inp) return (-1); /* Validate format */ fmt = jas_image_fmttostr(jas_image_getfmt(inp)); if (!fmt || strcmp(fmt, settings->ftype == FT_JP2 ? "jp2" : "jpc")) goto ffail; /* Decode the file into a halfbaked pile of bytes */ if ((pr = !settings->silent)) ls_init("JPEG2000", 0); img = jas_image_decode(inp, -1, NULL); jas_stream_close(inp); if (!img) goto dfail; /* Analyze the pile's contents */ nc = jas_image_numcmpts(img); mode = jas_clrspc_fam(cspace = jas_image_clrspc(img)); if (mode == JAS_CLRSPC_FAM_GRAY) bpp = 1; else if (mode == JAS_CLRSPC_FAM_RGB) bpp = 3; else goto ifail; if (bpp == 3) { slots[0] = jas_image_getcmptbytype(img, JAS_IMAGE_CT_COLOR(JAS_IMAGE_CT_RGB_R)); slots[1] = jas_image_getcmptbytype(img, JAS_IMAGE_CT_COLOR(JAS_IMAGE_CT_RGB_G)); slots[2] = jas_image_getcmptbytype(img, JAS_IMAGE_CT_COLOR(JAS_IMAGE_CT_RGB_B)); if ((slots[1] < 0) | (slots[2] < 0)) goto ifail; } else { slots[0] = jas_image_getcmptbytype(img, JAS_IMAGE_CT_COLOR(JAS_IMAGE_CT_GRAY_Y)); set_gray(settings); } if (slots[0] < 0) goto ifail; if (nc > bpp) { slots[bpp] = jas_image_getcmptbytype(img, JAS_IMAGE_CT_OPACITY); /* !!! JasPer has a bug - it doesn't write out component definitions if color * channels are in natural order, thus losing the types of any extra components. * (See where variable "needcdef" in src/libjasper/jp2/jp2_enc.c gets unset.) * Then on reading, type will be replaced by component's ordinal number - WJ */ if (slots[bpp] < 0) slots[bpp] = jas_image_getcmptbytype(img, bpp); /* Use an unlabeled extra component for alpha if no labeled one */ if (slots[bpp] < 0) slots[bpp] = jas_image_getcmptbytype(img, JAS_IMAGE_CT_UNKNOWN); nc = bpp + (slots[bpp] >= 0); // Ignore extra channels if no alpha } w = jas_image_cmptwidth(img, slots[0]); h = jas_image_cmptheight(img, slots[0]); for (i = 1; i < nc; i++) /* Check if all components are the same size */ { if ((jas_image_cmptwidth(img, slots[i]) != w) || (jas_image_cmptheight(img, slots[i]) != h)) goto ifail; } /* Allocate "matrix" */ res = FILE_MEM_ERROR; mx = jas_matrix_create(1, w); if (!mx) goto ifail; /* Allocate image */ settings->width = w; settings->height = h; settings->bpp = bpp; if ((res = allocate_image(settings, nc > bpp ? CMASK_RGBA : CMASK_IMAGE))) goto mfail; if (!settings->img[CHN_ALPHA]) nc = bpp; res = 1; #if U_LCMS /* JasPer implements CMS internally, but without lcms, it makes no sense * to provide all the interface stuff for this one rare format - WJ */ while (!settings->icc_size && (bpp == 3) && (cspace != JAS_CLRSPC_SRGB)) { jas_cmprof_t *prof; jas_image_t *timg; res = FILE_LIB_ERROR; prof = jas_cmprof_createfromclrspc(JAS_CLRSPC_SRGB); if (!prof) break; timg = jas_image_chclrspc(img, prof, JAS_CMXFORM_INTENT_PER); jas_cmprof_destroy(prof); if (!timg) break; jas_image_destroy(img); img = timg; res = 1; // Success - further code is fail-proof break; } #endif /* Unravel the ugly thing into proper format */ nx = h * nc; for (i = n = 0; i < nc; i++) { if (i < bpp) /* Image */ { dest = settings->img[CHN_IMAGE] + i; step = settings->bpp; } else /* Alpha */ { dest = settings->img[CHN_ALPHA]; step = 1; } chan = slots[i]; bits = jas_image_cmptprec(img, chan); delta = jas_image_cmptsgnd(img, chan) ? 1U << (bits - 1) : 0; shift = bits > 8 ? bits - 8 : 0; set_xlate(xtb, bits - shift); for (j = 0; j < h; j++ , n++) { jas_image_readcmpt(img, chan, 0, j, w, 1, mx); src = jas_matrix_getref(mx, 0, 0); for (k = 0; k < w; k++) { *dest = xtb[(src[k] + delta) >> shift]; dest += step; } if (pr && ((n * 10) % nx >= nx - 10)) progress_update((float)n / nx); } } mfail: jas_matrix_destroy(mx); ifail: jas_image_destroy(img); dfail: if (pr) progress_end(); return (res); ffail: jas_stream_close(inp); return (-1); } static int save_jpeg2000(char *file_name, ls_settings *settings) { static const jas_image_cmpttype_t chans[4] = { JAS_IMAGE_CT_COLOR(JAS_IMAGE_CT_RGB_R), JAS_IMAGE_CT_COLOR(JAS_IMAGE_CT_RGB_G), JAS_IMAGE_CT_COLOR(JAS_IMAGE_CT_RGB_B), JAS_IMAGE_CT_OPACITY }; jas_image_cmptparm_t cp[4]; jas_image_t *img; jas_stream_t *outp; jas_matrix_t *mx; jas_seqent_t *dest; char buf[256], *opts = NULL; unsigned char *src; int w = settings->width, h = settings->height, res = -1; int i, j, k, n, nx, nc, step, pr; if (settings->bpp == 1) return WRONG_FORMAT; /* Init the dumb library */ if (!jasper_init) jas_init(); jasper_init = TRUE; /* Open the file */ outp = jas_stream_fopen(file_name, "wb"); if (!outp) return (-1); /* Setup component parameters */ memset(cp, 0, sizeof(cp)); // Zero out all that needs zeroing cp[0].hstep = cp[0].vstep = 1; cp[0].width = w; cp[0].height = h; cp[0].prec = 8; cp[3] = cp[2] = cp[1] = cp[0]; /* Create image structure */ nc = 3 + !!settings->img[CHN_ALPHA]; img = jas_image_create(nc, cp, JAS_CLRSPC_SRGB); if (!img) goto fail; /* Allocate "matrix" */ mx = jas_matrix_create(1, w); if (!mx) goto fail2; if ((pr = !settings->silent)) ls_init("JPEG2000", 1); /* Fill image structure */ nx = h * nc; nx += nx / 10 + 1; // Show "90% done" while compressing for (i = n = 0; i < nc; i++) { /* !!! The only workaround for JasPer losing extra components' types on * write is to reorder the RGB components - but then, dumb readers, such * as ones in Mozilla and GTK+, would read them in wrong order - WJ */ jas_image_setcmpttype(img, i, chans[i]); if (i < 3) /* Image */ { src = settings->img[CHN_IMAGE] + i; step = settings->bpp; } else /* Alpha */ { src = settings->img[CHN_ALPHA]; step = 1; } for (j = 0; j < h; j++ , n++) { dest = jas_matrix_getref(mx, 0, 0); for (k = 0; k < w; k++) { dest[k] = *src; src += step; } jas_image_writecmpt(img, i, 0, j, w, 1, mx); if (pr && ((n * 10) % nx >= nx - 10)) if (progress_update((float)n / nx)) goto fail3; } } /* Compress it */ if (pr) progress_update(0.9); if (settings->jp2_rate) // Lossless if NO "rate" option passed sprintf(opts = buf, "rate=%g", 1.0 / settings->jp2_rate); if (!jas_image_encode(img, outp, jas_image_strtofmt( settings->ftype == FT_JP2 ? "jp2" : "jpc"), opts)) res = 0; jas_stream_flush(outp); if (pr) progress_update(1.0); fail3: if (pr) progress_end(); jas_matrix_destroy(mx); fail2: jas_image_destroy(img); fail: jas_stream_close(outp); return (res); } #endif /* Slow-but-sure universal bitstream parsers; may read extra byte at the end */ static void stream_MSB(unsigned char *src, unsigned char *dest, int cnt, int bits, int bit0, int bitstep, int step) { int i, j, v, mask = (1 << bits) - 1; for (i = 0; i < cnt; i++) { j = bit0 >> 3; v = (src[j] << 8) | src[j + 1]; v >>= 16 - bits - (bit0 & 7); *dest = (unsigned char)(v & mask); bit0 += bitstep; dest += step; } } static void stream_LSB(unsigned char *src, unsigned char *dest, int cnt, int bits, int bit0, int bitstep, int step) { int i, j, v, mask = (1 << bits) - 1; for (i = 0; i < cnt; i++) { j = bit0 >> 3; v = (src[j + 1] << 8) | src[j]; v >>= bit0 & 7; *dest = (unsigned char)(v & mask); bit0 += bitstep; dest += step; } } static void pack_MSB(unsigned char *dest, unsigned char *src, int len, int bw) { int i; memset(dest, 0, (len + 7) >> 3); for (i = 0; i < len; i++) dest[i >> 3] |= (*src++ == bw) << (~i & 7); } static void copy_bytes(unsigned char *dest, unsigned char *src, int len, int bpp, int step); #ifdef U_TIFF /* *** PREFACE *** * TIFF is a bitch, and libtiff is a joke. An unstable and buggy joke, at that. * It's a fact of life - and when some TIFFs don't load or are mangled, that * also is a fact of life. Installing latest libtiff may help - or not; sending * a bugreport with the offending file attached may help too - but again, it's * not guaranteed. But the common varieties of TIFF format should load OK. */ tiff_format tiff_formats[TIFF_MAX_TYPES] = { { _("None"), COMPRESSION_NONE, TIFFLAGS, XF_COMPT }, { "Group 3", COMPRESSION_CCITTFAX3, FF_BW | TIFF0FLAGS, XF_COMPT }, { "Group 4", COMPRESSION_CCITTFAX4, FF_BW | TIFF0FLAGS, XF_COMPT }, { "PackBits", COMPRESSION_PACKBITS, TIFFLAGS, XF_COMPT }, { "LZW", COMPRESSION_LZW, TIFFLAGS, XF_COMPT, 1 }, { "ZIP", COMPRESSION_ADOBE_DEFLATE, TIFFLAGS, XF_COMPT | XF_COMPZT, 1 }, #ifdef COMPRESSION_LZMA { "LZMA2", COMPRESSION_LZMA, TIFFLAGS, XF_COMPT | XF_COMPLZ, 1 }, #endif #ifdef COMPRESSION_ZSTD { "ZSTD", COMPRESSION_ZSTD, TIFFLAGS, XF_COMPT | XF_COMPZS, 1 }, #endif { "JPEG", COMPRESSION_JPEG, FF_RGB | TIFF0FLAGS, XF_COMPT | XF_COMPJ }, #ifdef COMPRESSION_WEBP { "WebP", COMPRESSION_WEBP, FF_RGB | FF_ALPHAR | TIFF0FLAGS, XF_COMPT | XF_COMPWT }, #endif { NULL } }; int tiff_lzma, tiff_zstd; /* FALSE by default */ void init_tiff_formats() // Check what libtiff can handle { tiff_format *src, *dest; /* Try all compiled-in formats */ src = dest = tiff_formats + 1; // COMPRESSION_NONE is always there while (src->name) { if (TIFFIsCODECConfigured(src->id)) *dest++ = *src; src++; } /* Zero out extra slots */ while (dest != src) *dest++ = *src; /* Set flag variables */ #ifdef COMPRESSION_LZMA tiff_lzma = TIFFIsCODECConfigured(COMPRESSION_LZMA); #endif #ifdef COMPRESSION_ZSTD tiff_zstd = TIFFIsCODECConfigured(COMPRESSION_ZSTD); #endif } static int load_tiff_frame(TIFF *tif, ls_settings *settings) { char cbuf[1024]; uint16 bpsamp, sampp, xsamp, pmetric, planar, orient, sform; uint16 *sampinfo, *red16, *green16, *blue16; uint32 width, height, tw = 0, th = 0, rps = 0; uint32 *tr, *raster = NULL; unsigned char *tmp, *buf = NULL; int bpp = 3, cmask = CMASK_IMAGE, argb = FALSE, pr = FALSE; int i, j, mirror, res; /* Let's learn what we've got */ TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLESPERPIXEL, &sampp); TIFFGetFieldDefaulted(tif, TIFFTAG_EXTRASAMPLES, &xsamp, &sampinfo); if (!TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &pmetric)) { /* Defaults like in libtiff */ if (sampp - xsamp == 1) pmetric = PHOTOMETRIC_MINISBLACK; else if (sampp - xsamp == 3) pmetric = PHOTOMETRIC_RGB; else return (-1); } TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLEFORMAT, &sform); TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width); TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height); TIFFGetFieldDefaulted(tif, TIFFTAG_BITSPERSAMPLE, &bpsamp); TIFFGetFieldDefaulted(tif, TIFFTAG_PLANARCONFIG, &planar); planar = planar != PLANARCONFIG_CONTIG; TIFFGetFieldDefaulted(tif, TIFFTAG_ORIENTATION, &orient); switch (orient) { case ORIENTATION_TOPLEFT: case ORIENTATION_LEFTTOP: mirror = 0; break; case ORIENTATION_TOPRIGHT: case ORIENTATION_RIGHTTOP: mirror = 1; break; default: case ORIENTATION_BOTLEFT: case ORIENTATION_LEFTBOT: mirror = 2; break; case ORIENTATION_BOTRIGHT: case ORIENTATION_RIGHTBOT: mirror = 3; break; } if (TIFFIsTiled(tif)) { TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tw); TIFFGetField(tif, TIFFTAG_TILELENGTH, &th); } else { TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rps); } /* Extract position from it */ settings->x = settings->y = 0; while (TRUE) { float xres, yres, dxu = 0, dyu = 0; if (!TIFFGetField(tif, TIFFTAG_XPOSITION, &dxu) && !TIFFGetField(tif, TIFFTAG_YPOSITION, &dyu)) break; // Have position, now need resolution if (!TIFFGetField(tif, TIFFTAG_XRESOLUTION, &xres)) break; // X resolution we have, what about Y? yres = xres; // Default TIFFGetField(tif, TIFFTAG_YRESOLUTION, &yres); // Convert ResolutionUnits (whatever they are) to pixels settings->x = rint(dxu * xres); settings->y = rint(dyu * yres); break; } /* Let's decide how to store it */ if ((width > MAX_WIDTH) || (height > MAX_HEIGHT)) return (TOO_BIG); settings->width = width; settings->height = height; if ((sform != SAMPLEFORMAT_UINT) && (sform != SAMPLEFORMAT_INT) && (sform != SAMPLEFORMAT_VOID)) argb = TRUE; else switch (pmetric) { case PHOTOMETRIC_PALETTE: { png_color *cp = settings->pal; int i, j, k, na = 0, nd = 1; /* Old palette format */ if (bpsamp > 8) { argb = TRUE; break; } if (!TIFFGetField(tif, TIFFTAG_COLORMAP, &red16, &green16, &blue16)) return (-1); settings->colors = j = 1 << bpsamp; /* Analyze palette */ for (k = i = 0; i < j; i++) { k |= red16[i] | green16[i] | blue16[i]; } if (k > 255) na = 128 , nd = 257; /* New palette format */ for (i = 0; i < j; i++ , cp++) { cp->red = (red16[i] + na) / nd; cp->green = (green16[i] + na) / nd; cp->blue = (blue16[i] + na) / nd; } /* If palette is all we need */ if ((settings->mode == FS_PALETTE_LOAD) || (settings->mode == FS_PALETTE_DEF)) return (EXPLODE_FAILED); /* Fallthrough */ } case PHOTOMETRIC_MINISWHITE: case PHOTOMETRIC_MINISBLACK: bpp = 1; break; case PHOTOMETRIC_RGB: break; case PHOTOMETRIC_SEPARATED: /* Leave non-CMYK separations to libtiff */ if (sampp - xsamp == 4) break; default: argb = TRUE; } /* libtiff can't handle this and neither can we */ if (argb && !TIFFRGBAImageOK(tif, cbuf)) return (-1); settings->bpp = bpp; /* Photoshop writes alpha as EXTRASAMPLE_UNSPECIFIED anyway */ if (xsamp) cmask = CMASK_RGBA; /* !!! No alpha support for RGB mode yet */ if (argb) cmask = CMASK_IMAGE; if ((res = allocate_image(settings, cmask))) return (res); res = -1; #ifdef U_LCMS #ifdef TIFFTAG_ICCPROFILE /* Extract ICC profile if it's of use */ if (!settings->icc_size) { uint32 size; unsigned char *data; /* TIFFTAG_ICCPROFILE was broken beyond hope in libtiff 3.8.0 * (see libtiff 3.8.1+ changelog entry for 2006-01-04) */ if (!strstr(TIFFGetVersion(), " 3.8.0") && TIFFGetField(tif, TIFFTAG_ICCPROFILE, &size, &data) && (size < INT_MAX) && /* If profile is needed right now, for CMYK->RGB */ !((pmetric == PHOTOMETRIC_SEPARATED) && !argb && init_cmyk2rgb(settings, data, size, FALSE)) && (settings->icc = malloc(size))) { settings->icc_size = size; memcpy(settings->icc, data, size); } } #endif #endif if ((pr = !settings->silent)) ls_init("TIFF", 0); /* Read it as ARGB if can't understand it ourselves */ if (argb) { /* libtiff is too much of a moving target if finer control is * needed, so let's trade memory for stability */ raster = (uint32 *)_TIFFmalloc(width * height * sizeof(uint32)); res = FILE_MEM_ERROR; if (!raster) goto fail2; res = FILE_LIB_ERROR; if (!TIFFReadRGBAImage(tif, width, height, raster, 0)) goto fail2; res = -1; /* Parse the RGB part only - alpha might be eaten by bugs */ tr = raster; for (i = height - 1; i >= 0; i--) { tmp = settings->img[CHN_IMAGE] + width * i * bpp; j = width; while (j--) { tmp[0] = TIFFGetR(*tr); tmp[1] = TIFFGetG(*tr); tmp[2] = TIFFGetB(*tr); tmp += 3; tr++; } ls_progress(settings, height - i, 10); } _TIFFfree(raster); raster = NULL; /* !!! Now it would be good to read in alpha ourselves - but not yet... */ res = 1; } /* Read & interpret it ourselves */ else { unsigned char xtable[256], *src, *tbuf = NULL; uint32 x0, y0, xstep = tw ? tw : width, ystep = th ? th : rps; int aalpha, tsz = 0, wbpp = bpp; int bpr, bits1, bit0, db, n, nx; int j, k, bsz, plane, nplanes; if (pmetric == PHOTOMETRIC_SEPARATED) // Needs temp buffer tsz = xstep * ystep * (wbpp = 4); nplanes = planar ? wbpp + !!settings->img[CHN_ALPHA] : 1; bsz = (tw ? TIFFTileSize(tif) : TIFFStripSize(tif)) + 1; bpr = tw ? TIFFTileRowSize(tif) : TIFFScanlineSize(tif); buf = _TIFFmalloc(bsz + tsz); res = FILE_MEM_ERROR; if (!buf) goto fail2; res = FILE_LIB_ERROR; if (tsz) tbuf = buf + bsz; // Temp buffer for CMYK->RGB /* Flag associated alpha */ aalpha = settings->img[CHN_ALPHA] && (pmetric != PHOTOMETRIC_PALETTE) && (sampinfo[0] == EXTRASAMPLE_ASSOCALPHA); bits1 = bpsamp > 8 ? 8 : bpsamp; /* Setup greyscale palette */ if ((bpp == 1) && (pmetric != PHOTOMETRIC_PALETTE)) { /* Demultiplied values are 0..255 */ j = aalpha ? 256 : 1 << bits1; settings->colors = j--; k = pmetric == PHOTOMETRIC_MINISBLACK ? 0 : j; mem_bw_pal(settings->pal, k, j ^ k); } /* !!! Assume 16-, 32- and 64-bit data follow machine's * endianness, and everything else is packed big-endian way - * like TIFF 6.0 spec says; but TIFF 5.0 and before specs said * differently, so let's wait for examples to see if I'm right * or not; as for 24- and 128-bit, even different libtiff * versions handle them differently, so I leave them alone * for now - WJ */ bit0 = (G_BYTE_ORDER == G_LITTLE_ENDIAN) && ((bpsamp == 16) || (bpsamp == 32) || (bpsamp == 64)) ? bpsamp - 8 : 0; db = (planar ? 1 : sampp) * bpsamp; /* Prepare to rescale what we've got */ memset(xtable, 0, 256); set_xlate(xtable, bits1); /* Progress steps */ nx = ((width + xstep - 1) / xstep) * nplanes * height; /* Read image tile by tile - considering strip a wide tile */ for (n = y0 = 0; y0 < height; y0 += ystep) for (x0 = 0; x0 < width; x0 += xstep) for (plane = 0; plane < nplanes; plane++) { unsigned char *tmp, *tmpa; uint32 x, y, w, h, l; int i, k, dx, dxa, dy, dys; /* Read one piece */ if (tw) { if (TIFFReadTile(tif, buf, x0, y0, 0, plane) < 0) goto fail2; } else { if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, y0, plane), buf, bsz) < 0) goto fail2; } /* Prepare decoding loops */ if (mirror & 1) /* X mirror */ { x = width - x0; w = x < xstep ? x : xstep; x -= w; } else { x = x0; w = x + xstep > width ? width - x : xstep; } if (mirror & 2) /* Y mirror */ { y = height - y0; h = y < ystep ? y : ystep; y -= h; } else { y = y0; h = y + ystep > height ? height - y : ystep; } /* Prepare pointers */ dx = dxa = 1; dy = width; i = y * width + x; tmp = tmpa = settings->img[CHN_ALPHA] + i; if (plane >= wbpp); // Alpha else if (tbuf) // CMYK { dx = 4; dy = w; tmp = tbuf + plane; } else // RGB/indexed { dx = bpp; tmp = settings->img[CHN_IMAGE] + plane + i * bpp; } dy *= dx; dys = bpr; src = buf; /* Account for horizontal mirroring */ if (mirror & 1) { // Write bytes backward tmp += (w - 1) * dx; tmpa += w - 1; dx = -dx; dxa = -1; } /* Account for vertical mirroring */ if (mirror & 2) { // Read rows backward src += (h - 1) * dys; dys = -dys; } /* Decode it */ for (l = 0; l < h; l++ , n++ , src += dys , tmp += dy) { if (pr && ((n * 10) % nx >= nx - 10)) progress_update((float)n / nx); stream_MSB(src, tmp, w, bits1, bit0, db, dx); if (planar) continue; for (k = 1; k < wbpp; k++) { stream_MSB(src, tmp + k, w, bits1, bit0 + bpsamp * k, db, dx); } if (settings->img[CHN_ALPHA]) { stream_MSB(src, tmpa, w, bits1, bit0 + bpsamp * wbpp, db, dxa); tmpa += width; } } /* Convert CMYK to RGB if needed */ if (!tbuf || (planar && (plane != 3))) continue; if (bits1 < 8) // Rescale to 8-bit do_xlate(xtable, tbuf, w * h * 4); cmyk2rgb(tbuf, tbuf, w * h, FALSE, settings); src = tbuf; tmp = settings->img[CHN_IMAGE] + (y * width + x) * 3; w *= 3; for (l = 0; l < h; l++ , tmp += width * 3 , src += w) memcpy(tmp, src, w); } done_cmyk2rgb(settings); j = width * height; tmp = settings->img[CHN_IMAGE]; src = settings->img[CHN_ALPHA]; /* Unassociate alpha */ if (aalpha) { if (wbpp > 3) // Converted from CMYK { unsigned char *img = tmp; int i, k, a; if (bits1 < 8) do_xlate(xtable, src, j); bits1 = 8; // No further rescaling needed /* Remove white background */ for (i = 0; i < j; i++ , img += 3) { a = src[i] - 255; k = a + img[0]; img[0] = k < 0 ? 0 : k; k = a + img[1]; img[1] = k < 0 ? 0 : k; k = a + img[2]; img[2] = k < 0 ? 0 : k; } } mem_demultiply(tmp, src, j, bpp); tmp = NULL; // Image is done } if (bits1 < 8) { /* Rescale alpha */ if (src) do_xlate(xtable, src, j); /* Rescale RGB */ if (tmp && (wbpp == 3)) do_xlate(xtable, tmp, j * 3); } res = 1; } fail2: if (pr) progress_end(); if (raster) _TIFFfree(raster); if (buf) _TIFFfree(buf); return (res); } static int load_tiff_frames(char *file_name, ani_settings *ani) { TIFF *tif; ls_settings w_set; int res; /* We don't want any echoing to the output */ TIFFSetErrorHandler(NULL); TIFFSetWarningHandler(NULL); if (!(tif = TIFFOpen(file_name, "r"))) return (-1); while (TRUE) { res = FILE_TOO_LONG; if (!check_next_frame(&ani->fset, ani->settings.mode, FALSE)) goto fail; w_set = ani->settings; w_set.gif_delay = -1; // Multipage res = load_tiff_frame(tif, &w_set); if (res != 1) goto fail; res = process_page_frame(file_name, ani, &w_set); if (res) goto fail; /* Try to get next frame */ if (!TIFFReadDirectory(tif)) break; } res = 1; fail: TIFFClose(tif); return (res); } #ifndef TIFF_VERSION_BIG /* The ONLY useful way to detect libtiff 4.x vs 3.x */ #define tmsize_t tsize_t #endif static tmsize_t mTIFFread(thandle_t fd, void* buf, tmsize_t size) { return mfread(buf, 1, size, (memFILE *)fd); } static tmsize_t mTIFFwrite(thandle_t fd, void* buf, tmsize_t size) { return mfwrite(buf, 1, size, (memFILE *)fd); } static toff_t mTIFFlseek(thandle_t fd, toff_t off, int whence) { return mfseek((memFILE *)fd, (f_long)off, whence) ? -1 : ((memFILE *)fd)->m.here; } static int mTIFFclose(thandle_t fd) { return 0; } static toff_t mTIFFsize(thandle_t fd) { return ((memFILE *)fd)->top; } static int mTIFFmap(thandle_t fd, void** base, toff_t* size) { *base = ((memFILE *)fd)->m.buf; *size = ((memFILE *)fd)->top; return 1; } static void mTIFFunmap(thandle_t fd, void* base, toff_t size) { } static int load_tiff(char *file_name, ls_settings *settings, memFILE *mf) { TIFF *tif; int res; /* We don't want any echoing to the output */ TIFFSetErrorHandler(NULL); TIFFSetWarningHandler(NULL); if (!mf) tif = TIFFOpen(file_name, "r"); else tif = TIFFClientOpen("", "r", (void *)mf, mTIFFread, mTIFFwrite, mTIFFlseek, mTIFFclose, mTIFFsize, mTIFFmap, mTIFFunmap); if (!tif) return (-1); res = load_tiff_frame(tif, settings); if ((res == 1) && TIFFReadDirectory(tif)) res = FILE_HAS_FRAMES; TIFFClose(tif); return (res); } static int save_tiff(char *file_name, ls_settings *settings, memFILE *mf) { unsigned char buf[MAX_WIDTH / 8], *src, *row = NULL; uint16 rgb[256 * 3]; unsigned int tflags, sflags, xflags; int i, l, type, bw, af, pf, res = 0, pmetric = -1; int w = settings->width, h = settings->height, bpp = settings->bpp; TIFF *tif; /* Select output mode */ sflags = FF_SAVE_MASK_FOR(*settings); type = settings->tiff_type; if (type < 0) type = bpp == 3 ? tiff_rtype : // RGB settings->colors <= 2 ? tiff_btype : // BW tiff_itype; // Indexed if (settings->mode == FS_CLIPBOARD) { type = 0; // Uncompressed /* RGB for clipboard mask */ if (settings->img[CHN_ALPHA]) sflags = FF_RGB , bpp = 3; } tflags = tiff_formats[type].flags; sflags &= tflags; bw = !(sflags & (FF_256 | FF_RGB)); if (!sflags) return WRONG_FORMAT; // Paranoia af = settings->img[CHN_ALPHA] && (tflags & FF_ALPHA); /* Use 1-bit mode where possible */ if (!bw && !af && (sflags & FF_BW)) { /* No need of palette if the colors are full white and black */ i = PNG_2_INT(settings->pal[0]); bw = (!i ? 0xFFFFFF : i == 0xFFFFFF ? 0 : -1) == PNG_2_INT(settings->pal[1]) ? 1 : -1; } /* !!! When using predictor, libtiff 3.8 modifies row buffer in-place */ pf = tiff_predictor && !bw && tiff_formats[type].pflag; if (af || pf || (bpp > settings->bpp)) { row = malloc(w * (bpp + af)); if (!row) return -1; } TIFFSetErrorHandler(NULL); // We don't want any echoing to the output TIFFSetWarningHandler(NULL); if (!mf) tif = TIFFOpen(file_name, "w"); else tif = TIFFClientOpen("", "w", (void *)mf, mTIFFread, mTIFFwrite, mTIFFlseek, mTIFFclose, mTIFFsize, mTIFFmap, mTIFFunmap); if (!tif) { free(row); return -1; } /* Write regular tags */ TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, w); TIFFSetField(tif, TIFFTAG_IMAGELENGTH, h); TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, bpp + af); TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, bw ? 1 : 8); TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); /* Write compression-specific tags */ TIFFSetField(tif, TIFFTAG_COMPRESSION, tiff_formats[type].id); xflags = tiff_formats[type].xflags; if (xflags & XF_COMPZT) TIFFSetField(tif, TIFFTAG_ZIPQUALITY, settings->png_compression); #ifdef COMPRESSION_LZMA if (xflags & XF_COMPLZ) TIFFSetField(tif, TIFFTAG_LZMAPRESET, settings->lzma_preset); #endif #ifdef COMPRESSION_ZSTD if (xflags & XF_COMPZS) TIFFSetField(tif, TIFFTAG_ZSTD_LEVEL, settings->zstd_level); #endif #ifdef COMPRESSION_WEBP if (xflags & XF_COMPWT) { TIFFSetField(tif, TIFFTAG_WEBP_LEVEL, settings->webp_quality); // !!! libtiff 4.0.10 *FAILS* to do it losslessly despite trying if (settings->webp_quality == 100) TIFFSetField(tif, TIFFTAG_WEBP_LOSSLESS, 1); } #endif if (xflags & XF_COMPJ) { TIFFSetField(tif, TIFFTAG_JPEGQUALITY, settings->jpeg_quality); TIFFSetField(tif, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB); pmetric = PHOTOMETRIC_YCBCR; } if (pf) TIFFSetField(tif, TIFFTAG_PREDICTOR, PREDICTOR_HORIZONTAL); if (bw > 0) pmetric = get_bw(settings) ? PHOTOMETRIC_MINISWHITE : PHOTOMETRIC_MINISBLACK; else if (bpp == 1) { pmetric = PHOTOMETRIC_PALETTE; memset(rgb, 0, sizeof(rgb)); l = bw ? 2 : 256; for (i = 0; i < settings->colors; i++) { rgb[i] = settings->pal[i].red * 257; rgb[i + l] = settings->pal[i].green * 257; rgb[i + l * 2] = settings->pal[i].blue * 257; } TIFFSetField(tif, TIFFTAG_COLORMAP, rgb, rgb + l, rgb + l * 2); } else if (pmetric < 0) pmetric = PHOTOMETRIC_RGB; TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, pmetric); if (af) { rgb[0] = EXTRASAMPLE_UNASSALPHA; TIFFSetField(tif, TIFFTAG_EXTRASAMPLES, 1, rgb); } /* Actually write the image */ if (!settings->silent) ls_init("TIFF", 1); for (i = 0; i < h; i++) { src = settings->img[CHN_IMAGE] + w * i * settings->bpp; if (bw) /* Pack the bits */ { pack_MSB(buf, src, w, 1); src = buf; } else if (row) /* Fill the buffer */ src = prepare_row(row, settings, bpp + af, i); if (TIFFWriteScanline(tif, src, i, 0) == -1) { res = -1; break; } ls_progress(settings, i, 20); } TIFFClose(tif); if (!settings->silent) progress_end(); free(row); return (res); } #endif #ifdef U_WEBP /* *** PREFACE *** * WebP Demux API is exceedingly cumbersome in case you don't feed the entire * file to it in one single memory block. Stepping through the RIFF container to * pick individual chunks is more manageable. */ /* Macro for little-endian tags (RIFF) */ #define TAG4(A,B,C,D) ((A) + ((B) << 8) + ((C) << 16) + ((D) << 24)) #define GET24(buf) (((buf)[2] << 16) + ((buf)[1] << 8) + (buf)[0]) #define PUT24(buf, v) (buf)[0] = (v) & 0xFF; (buf)[1] = ((v) >> 8) & 0xFF; \ (buf)[2] = ((v) >> 16) & 0xFF; /* !!! In documentation, bit fields are written in reverse; actual flag values * used by libwebp are as if bits are numbered right to left instead - WJ */ /* Macros for WEBP tags */ #define TAG4_RIFF TAG4('R', 'I', 'F', 'F') #define TAG4_WEBP TAG4('W', 'E', 'B', 'P') #define TAG4_VP8X TAG4('V', 'P', '8', 'X') #define TAG4_ANIM TAG4('A', 'N', 'I', 'M') #define TAG4_ANMF TAG4('A', 'N', 'M', 'F') #define TAG4_VP8 TAG4('V', 'P', '8', ' ') #define TAG4_VP8L TAG4('V', 'P', '8', 'L') #define TAG4_ALPH TAG4('A', 'L', 'P', 'H') #define TAG4_ICCP TAG4('I', 'C', 'C', 'P') #define TAG4_EXIF TAG4('E', 'X', 'I', 'F') #define TAG4_XMP TAG4('X', 'M', 'P', ' ') #define RIFF_TAGSIZE 4 /* RIFF block header */ #define RIFF_TAG 0 /* 32b */ #define RIFF_SIZE 4 /* 32b */ #define RIFF_HSIZE 8 /* WEBP header block (VP8X tag) */ #define VP8X_FLAGS 0 /* 8b */ #define VP8X_W1 4 /* 24b */ #define VP8X_H1 7 /* 24b */ #define VP8X_SIZE 10 /* VP8X flags (ignore on read) */ #define VP8XF_ANIM 2 #define VP8XF_ALPHA 16 #define VP8XF_ICC 32 /* ANIM block */ /* !!! Background color & alpha are ignored by vwebp */ #define ANIM_BKG_B 0 /* 8b */ #define ANIM_BKG_G 1 /* 8b */ #define ANIM_BKG_R 2 /* 8b */ #define ANIM_BKG_A 3 /* 8b */ #define ANIM_LOOP 4 /* 16b */ #define ANIM_SIZE 6 /* ANMF block header */ #define ANMF_X2 0 /* 24b */ #define ANMF_Y2 3 /* 24b */ #define ANMF_W1 6 /* 24b */ #define ANMF_H1 9 /* 24b */ #define ANMF_DELAY 12 /* 24b */ #define ANMF_FLAGS 15 /* 8b */ #define ANMF_HSIZE 16 /* ANMF flags */ #define ANMF_F_NOBLEND 2 #define ANMF_F_BKG 1 /* Dispose to background */ #define HAVE_IMG 0x01 #define HAVE_VP8X 0x02 #define HAVE_ANIM 0x04 #define HAVE_XTRA 0x08 #define HAVE_ALPH 0x10 #define HAVE_ANMF 0x20 typedef struct { FILE *f; unsigned len; // File data left unparsed unsigned size; // How much to read for this frame int blocks; unsigned char hdr[VP8X_SIZE], bkg[4]; unsigned char anmf[ANMF_HSIZE + RIFF_TAGSIZE]; } webphead; static int load_webp_frame(webphead *wp, ls_settings *settings) { WebPDecoderConfig dconf; unsigned char *buf; int wh, bpp, wbpp = 3, cmask = CMASK_IMAGE, res = -1; if (!WebPInitDecoderConfig(&dconf)) return (-1); // Wrong lib version if (!(buf = malloc(wp->size))) return (FILE_MEM_ERROR); if (fread(buf, 1, wp->size, wp->f) != wp->size) goto fail; if (WebPGetFeatures((void *)buf, wp->size, &dconf.input) != VP8_STATUS_OK) goto fail; if (dconf.input.has_alpha) wbpp = 4 , cmask = CMASK_RGBA; wh = dconf.input.width * dconf.input.height; settings->width = dconf.input.width; settings->height = dconf.input.height; settings->bpp = wbpp; /* Get the extras from frame header */ if (wp->blocks & HAVE_ANMF) { settings->x = GET24(wp->anmf + ANMF_X2) * 2; settings->y = GET24(wp->anmf + ANMF_Y2) * 2; /* Within mtPaint delays are 1/100s granular */ settings->gif_delay = (GET24(wp->anmf + ANMF_DELAY) + 9) / 10; // Round up } if ((res = allocate_image(settings, cmask))) goto fail; bpp = settings->img[CHN_ALPHA] ? 4 : 3; dconf.output.colorspace = bpp > 3 ? MODE_RGBA : MODE_RGB; dconf.output.u.RGBA.rgba = settings->img[CHN_IMAGE]; dconf.output.u.RGBA.stride = settings->width * bpp; dconf.output.u.RGBA.size = wh * bpp; dconf.output.is_external_memory = 1; if (!settings->silent) ls_init("WebP", 0); res = FILE_LIB_ERROR; if (WebPDecode(buf, wp->size, &dconf) == VP8_STATUS_OK) { if (bpp == 4) /* Separate out alpha from RGBA */ { copy_bytes(settings->img[CHN_ALPHA], settings->img[CHN_IMAGE] + 3, wh, 1, 4); copy_bytes(settings->img[CHN_IMAGE], settings->img[CHN_IMAGE], wh, 3, 4); } if (wbpp > 3) /* Downsize image channel */ { unsigned char *w = realloc(settings->img[CHN_IMAGE], wh * 3); if (w) settings->img[CHN_IMAGE] = w; } res = 1; } if (!settings->silent) progress_end(); WebPFreeDecBuffer(&dconf.output); fail: free(buf); return (res); } static int webp_scan(webphead *wp, ls_settings *settings) { unsigned char buf[256]; FILE *fp = wp->f; unsigned tag, tl; f_long alph = -1; if (!settings) // Next-frame mode { /* If a regular image was first, believe there are no other frames */ if (!(wp->blocks & HAVE_ANMF)) return (FALSE); wp->blocks &= ~(HAVE_ALPH | HAVE_IMG); // Prepare for new frame } /* Read block headers & see what we get */ while ((wp->len >= RIFF_HSIZE) && (fread(buf, 1, RIFF_HSIZE, fp) == RIFF_HSIZE)) { tag = GET32(buf); tl = GET32(buf + RIFF_SIZE); if (tl > 0xFFFFFFFFU - 1 - RIFF_HSIZE) break; // MAX_CHUNK_PAYLOAD if (tl >= F_LONG_MAX) break; // Limit for what can be handled tl += tl & 1; // Pad if (wp->len < tl + RIFF_HSIZE) break; // Does not fit in RIFF wp->len -= tl + RIFF_HSIZE; if (tag == TAG4_ANMF) { if (tl < ANMF_HSIZE + RIFF_HSIZE) break; if (fread(wp->anmf, 1, ANMF_HSIZE + RIFF_TAGSIZE, fp) != ANMF_HSIZE + RIFF_TAGSIZE) break; fseek(fp, -RIFF_TAGSIZE, SEEK_CUR); wp->blocks |= HAVE_ANMF; tag = GET32(wp->anmf + ANMF_HSIZE); if (tag == TAG4_ALPH) wp->blocks |= HAVE_ALPH; else if ((tag != TAG4_VP8) && (tag != TAG4_VP8L)) break; // Damaged? wp->size = tl - ANMF_HSIZE; wp->blocks |= HAVE_IMG; break; // Done } /* Be extra accepting - skip duplicates of header chunks w/o failing */ else if (!settings && ((tag == TAG4_VP8X) || (tag == TAG4_ANIM) || (tag == TAG4_ICCP))); /* Fail on encountering image chunk where a frame should be */ else if (!settings && ((tag == TAG4_VP8) || (tag == TAG4_VP8L) || (tag == TAG4_ALPH))) break; else if (tag == TAG4_VP8X) { if (tl != VP8X_SIZE) break; if (fread(wp->hdr, 1, VP8X_SIZE, fp) != VP8X_SIZE) break; wp->blocks |= HAVE_VP8X; continue; } else if (tag == TAG4_ANIM) { if (tl != ANIM_SIZE) break; if (fread(buf, 1, ANIM_SIZE, fp) != ANIM_SIZE) break; /* Rearrange the bytes the sane way */ wp->bkg[0] = buf[ANIM_BKG_R]; wp->bkg[1] = buf[ANIM_BKG_G]; wp->bkg[2] = buf[ANIM_BKG_B]; wp->bkg[3] = buf[ANIM_BKG_A]; wp->blocks |= HAVE_ANIM; continue; } #ifdef U_LCMS else if (tag == TAG4_ICCP) { unsigned char *tmp = NULL; wp->blocks |= HAVE_XTRA; if (!settings->icc_size && (tl < INT_MAX) && // For sanity (and icc_size size) (tmp = malloc(tl)) && (fread(tmp, 1, tl, fp) == tl)) { settings->icc = tmp; settings->icc_size = tl; continue; } if (tmp) /* Failed to read */ { free(tmp); break; } } #endif else if (tag == TAG4_ALPH) { wp->blocks |= HAVE_ALPH; alph = ftell(fp); if (alph < 0) break; } else if ((tag == TAG4_VP8) || (tag == TAG4_VP8L)) { fseek(fp, -RIFF_HSIZE, SEEK_CUR); wp->size = tl + RIFF_HSIZE; if (alph > 0) // Need to start with alpha { f_long here = ftell(fp); if (here < 0) break; // Too long for us /* From ALPH header to this block's end */ wp->size += here - alph + RIFF_HSIZE; fseek(fp, alph - RIFF_HSIZE, SEEK_SET); } wp->blocks |= HAVE_IMG; break; } else wp->blocks |= HAVE_XTRA; /* Default: skip (the rest of) tag data */ if (tl && fseek(fp, tl, SEEK_CUR)) break; } return (wp->blocks & HAVE_IMG); } static int webp_behead(FILE *fp, webphead *wp, ls_settings *settings) { unsigned char buf[RIFF_HSIZE + RIFF_TAGSIZE]; unsigned tl; memset(wp, 0, sizeof(webphead)); wp->f = fp; /* Read the RIFF header & check signature */ if (fread(buf, 1, RIFF_HSIZE + RIFF_TAGSIZE, fp) < RIFF_HSIZE + RIFF_TAGSIZE) return (FALSE); if ((GET32(buf) != TAG4_RIFF) || (GET32(buf + RIFF_HSIZE) != TAG4_WEBP)) return (FALSE); tl = GET32(buf + RIFF_SIZE); if (tl < RIFF_TAGSIZE + RIFF_HSIZE) return (FALSE); tl -= RIFF_TAGSIZE; tl += tl & 1; // Pad wp->len = tl; webp_scan(wp, settings); return (wp->blocks & HAVE_IMG); } static int load_webp_frames(char *file_name, ani_settings *ani) { webphead wp; ani_status stat; ls_settings w_set, init_set; FILE *fp; int bpp, disposal, res = -1; if (!(fp = fopen(file_name, "rb"))) return (-1); memset(w_set.img, 0, sizeof(chanlist)); /* Init temp container */ init_set = ani->settings; if (!webp_behead(fp, &wp, &init_set)) goto fail; /* Need to have them to read them */ if ((wp.blocks & (HAVE_VP8X | HAVE_ANMF)) != (HAVE_VP8X | HAVE_ANMF)) goto fail; /* Init state structure */ memset(&stat, 0, sizeof(stat)); stat.mode = ani->mode; stat.defw = GET24(wp.hdr + VP8X_W1) + 1; stat.defh = GET24(wp.hdr + VP8X_H1) + 1; /* WebP has no palette of its own, use the default one */ mem_pal_copy(stat.newpal, ani->settings.pal); stat.newcols = ani->settings.colors; stat.newtrans = -1; // No color-key transparency /* !!! vwebp ignores the value by default, and one example animation * expects transparency despite background set to opaque white - WJ */ // memcpy(stat.bkg, wp.bkg, 4); // RGBA background /* Go through images */ while (TRUE) { res = FILE_TOO_LONG; if (!check_next_frame(&ani->fset, ani->settings.mode, TRUE)) goto fail; w_set = init_set; res = load_webp_frame(&wp, &w_set); if (res != 1) goto fail; disposal = wp.anmf[ANMF_FLAGS] & ANMF_F_BKG ? FM_DISP_REMOVE : FM_DISP_LEAVE; delete_alpha(&w_set, 255); stat.blend = !(wp.anmf[ANMF_FLAGS] & ANMF_F_NOBLEND) && w_set.img[CHN_ALPHA]; /* Analyze how we can merge the frames */ res = TOO_BIG; bpp = analyze_rgba_frame(&stat, &w_set); if (bpp < 0) goto fail; /* Allocate a new frame */ res = add_frame(ani, &stat, &w_set, bpp, disposal); if (res) goto fail; /* Do actual compositing, remember disposal method */ composite_frame(&ani->fset, &stat, &w_set); mem_free_chanlist(w_set.img); memset(w_set.img, 0, sizeof(chanlist)); /* Write out those frames worthy to be stored */ res = done_frame(file_name, ani, FALSE); if (res != 1) goto fail; /* Step to the next frame, if any */ if (!webp_scan(&wp, NULL)) break; } /* Write out the final frame if not written before */ res = done_frame(file_name, ani, TRUE); fail: mem_free_chanlist(w_set.img); fclose(fp); return (res); } static int load_webp(char *file_name, ls_settings *settings) { webphead wp; FILE *fp; int res = -1; if (!(fp = fopen(file_name, "rb"))) return (-1); if (webp_behead(fp, &wp, settings)) { res = load_webp_frame(&wp, settings); if ((res == 1) && webp_scan(&wp, NULL)) res = FILE_HAS_FRAMES; } fclose(fp); return (res); } static int webp_fwrite(const uint8_t *data, size_t data_size, const WebPPicture *picture) { return (fwrite(data, sizeof(uint8_t), data_size, picture->custom_ptr) == data_size); } static int webp_progress(int percent, const WebPPicture *picture) { return (!progress_update((float)percent / 100)); } char *webp_presets[] = { _("Lossless"), _("Default"), _("Picture"), _("Photo"), _("Drawing"), _("Icon"), _("Text"), NULL }; // !!! Min version 0.5.0 static int save_webp(char *file_name, ls_settings *settings) { static const signed char presets[] = { WEBP_PRESET_DEFAULT, /* Lossless */ WEBP_PRESET_DEFAULT, WEBP_PRESET_PICTURE, WEBP_PRESET_PHOTO, WEBP_PRESET_DRAWING, WEBP_PRESET_ICON, WEBP_PRESET_TEXT }; WebPConfig conf; WebPPicture pic; FILE *fp; unsigned char *rgba; int wh, st, res = -1; if (settings->bpp == 1) return WRONG_FORMAT; if ((fp = fopen(file_name, "wb")) == NULL) return (-1); if (!WebPConfigPreset(&conf, presets[settings->webp_preset], settings->webp_quality)) goto ffail; // Lib failure if (!settings->webp_preset) WebPConfigLosslessPreset(&conf, settings->webp_compression); conf.exact = TRUE; // Preserve invisible parts /* Prepare intermediate container */ if (!WebPPictureInit(&pic)) goto ffail; // Lib failure pic.use_argb = TRUE; pic.width = settings->width; pic.height = settings->height; wh = pic.width * pic.height; pic.writer = webp_fwrite; pic.custom_ptr = (void *)fp; if (!settings->silent) pic.progress_hook = webp_progress; if (settings->img[CHN_ALPHA]) /* Need RGBA */ { rgba = malloc(wh * 4); if (!rgba) goto ffail; copy_bytes(rgba, settings->img[CHN_IMAGE], wh, 4, 3); copy_bytes(rgba + 3, settings->img[CHN_ALPHA], wh, 4, 1); st = WebPPictureImportRGBA(&pic, rgba, pic.width * 4); free(rgba); } /* RGB is enough */ else st = WebPPictureImportRGB(&pic, settings->img[CHN_IMAGE], pic.width * 3); /* Do encode */ if (st) { if (!settings->silent) ls_init("WebP", 1); if (WebPEncode(&conf, &pic)) res = 0; WebPPictureFree(&pic); if (!settings->silent) progress_end(); } ffail: fclose(fp); return (res); } #endif /* Version 2 fields */ #define BMP_FILESIZE 2 /* 32b */ #define BMP_XHOT 6 /* 16b */ #define BMP_YHOT 8 /* 16b */ #define BMP_DATAOFS 10 /* 32b */ #define BMP_HDR2SIZE 14 /* 32b */ #define BMP_WIDTH 18 /* s32b */ #define BMP_HEIGHT 22 /* s32b */ #define BMP_PLANES 26 /* 16b */ #define BMP_BPP 28 /* 16b */ #define BMP2_HSIZE 30 /* Version 3 fields */ #define BMP_COMPRESS 30 /* 32b */ #define BMP_DATASIZE 34 /* 32b */ #define BMP_XDPI 38 /* s32b */ #define BMP_YDPI 42 /* s32b */ #define BMP_COLORS 46 /* 32b */ #define BMP_ICOLORS 50 /* 32b */ #define BMP3_HSIZE 54 /* Version 4 fields */ #define BMP_RMASK 54 /* 32b */ #define BMP_GMASK 58 /* 32b */ #define BMP_BMASK 62 /* 32b */ #define BMP_AMASK 66 /* 32b */ #define BMP_CSPACE 70 /* 32b */ #define BMP4_HSIZE 122 /* Version 5 fields */ #define BMP_INTENT 122 /* 32b */ #define BMP_ICCOFS 126 /* 32b */ #define BMP_ICCSIZE 130 /* 32b */ #define BMP5_HSIZE 138 #define BMP_MAXHSIZE (BMP5_HSIZE + 256 * 4) /* OS/2 1.x alternative fields */ #define OS2BMP_WIDTH 18 /* 16b */ #define OS2BMP_HEIGHT 20 /* 16b */ #define OS2BMP_PLANES 22 /* 16b */ #define OS2BMP_BPP 24 /* 16b */ #define OS2BMP_HSIZE 26 /* OS/2 2.x bitmap header is version 3 fields plus some extra */ #define OS2BMP2_HSIZE 78 /* Shortened header variant encountered in the wild */ #define OS2BMP2_HSIZE_S 38 /* OS/2 bitmap array fields */ #define OS2BA_HDRSIZE 2 /* 32b */ #define OS2BA_NEXT 6 /* 32b */ #define OS2BA_HSIZE 14 /* In OS/2 files, BMP_FILESIZE may instead contain header size */ /* Colorspace tags */ #define BMPCS_WIN TAG4B('W', 'i', 'n', ' ') #define BMPCS_SRGB TAG4B('s', 'R', 'G', 'B') #define BMPCS_LINK TAG4B('L', 'I', 'N', 'K') #define BMPCS_EMBED TAG4B('M', 'B', 'E', 'D') static int load_bmp(char *file_name, ls_settings *settings, memFILE *mf) { guint32 masks[4]; unsigned char hdr[BMP5_HSIZE], xlat[256], *dest, *tmp, *buf = NULL; memFILE fake_mf; FILE *fp = NULL; unsigned l, ofs; int shifts[4], bpps[4]; int def_alpha = FALSE, cmask = CMASK_IMAGE, comp = 0, ba = 0, rle = 0, res = -1; int i, j, k, n, ii, w, h, bpp, wbpp; int bl, rl, step, skip, dx, dy; if (!mf) { if (!(fp = fopen(file_name, "rb"))) return (-1); memset(mf = &fake_mf, 0, sizeof(fake_mf)); fake_mf.file = fp; } /* Read the largest header */ k = mfread(hdr, 1, BMP5_HSIZE, mf); /* Bitmap array? */ if ((k > OS2BA_HSIZE) && (hdr[0] == 'B') && (hdr[1] == 'A')) { /* Just skip the header to go for 1st bitmap: no example files * with more than one bitmap anyway */ ba = OS2BA_HSIZE; memmove(hdr, hdr + ba, k -= ba); } /* Check general validity */ if (k < OS2BMP_HSIZE) goto fail; /* Least supported header size */ if ((hdr[0] != 'B') || (hdr[1] != 'M')) goto fail; /* Signature */ l = GET32(hdr + BMP_HDR2SIZE); if (k - BMP_HDR2SIZE < l) goto fail; l += BMP_HDR2SIZE; if (ba && (l > OS2BMP2_HSIZE)) goto fail; /* Should not exist */ ofs = GET32(hdr + BMP_DATAOFS); if (l + ba > ofs) goto fail; // Overlap if (ofs > F_LONG_MAX) goto fail; // Cannot handle this length /* Check format type: OS/2 or Windows */ if (l == OS2BMP_HSIZE) { w = GET16(hdr + OS2BMP_WIDTH); h = GET16(hdr + OS2BMP_HEIGHT); bpp = GET16(hdr + OS2BMP_BPP); } else if (l >= BMP2_HSIZE) { w = GET32s(hdr + BMP_WIDTH); h = GET32s(hdr + BMP_HEIGHT); bpp = GET16(hdr + BMP_BPP); } else goto fail; /* Check format */ if (l >= BMP3_HSIZE) comp = GET32(hdr + BMP_COMPRESS); /* !!! Some 8bpp OS/2 BMPs in the wild have compression not marked */ if (!comp && (bpp == 8) && (h > 0) && (l == OS2BMP2_HSIZE_S)) { unsigned fsize = GET32(hdr + BMP_DATASIZE); if (fsize && (fsize != w * h)) comp = 1; } /* Only 1, 4, 8, 16, 24 and 32 bpp allowed */ rle = comp; switch (bpp) { case 1: if (comp) goto fail; /* No compression */ break; case 4: if (comp && (comp != 2)) goto fail; /* RLE4 */ break; case 8: if (comp && (comp != 1)) goto fail; /* RLE8 */ break; case 24: if (comp == 4) /* RLE24 or JPEG */ { /* If not definitely OS/2 header, consider it JPEG */ if ((l != OS2BMP2_HSIZE) && (l != OS2BMP2_HSIZE_S)) goto fail; break; } // Fallthrough case 16: case 32: rle = 0; if (comp && (comp != 3)) goto fail; /* Bitfields */ shifts[3] = bpps[3] = masks[3] = 0; /* No alpha by default */ if (comp == 3) { /* V3-style bitfields? */ if ((l == BMP3_HSIZE) && (ofs >= BMP_AMASK)) l = BMP_AMASK; if (l < BMP_AMASK) goto fail; masks[0] = GET32(hdr + BMP_RMASK); masks[1] = GET32(hdr + BMP_GMASK); masks[2] = GET32(hdr + BMP_BMASK); if (l >= BMP_AMASK + 4) masks[3] = GET32(hdr + BMP_AMASK); if (masks[3]) cmask = CMASK_RGBA; /* Convert masks into bit lengths and offsets */ for (i = 0; i < 4; i++) { /* Bit length - just count bits */ j = bitcount(masks[i]); /* Bit offset - add in bits _before_ mask */ k = bitcount(masks[i] - 1) + 1; if (j > 8) j = 8; shifts[i] = k - j; bpps[i] = j; } } else if (bpp == 16) { shifts[0] = 10; shifts[1] = 5; shifts[2] = 0; bpps[0] = bpps[1] = bpps[2] = 5; } else { shifts[0] = 16; shifts[1] = 8; shifts[2] = 0; bpps[0] = bpps[1] = bpps[2] = 8; if (bpp == 32) /* Consider alpha present by default */ { shifts[3] = 24; bpps[3] = 8; cmask = CMASK_RGBA; def_alpha = TRUE; /* Uncertain if alpha */ } } break; default: goto fail; } if (rle && (h < 0)) goto fail; // Forbidden /* Load palette if needed */ if (bpp < 16) { unsigned char tbuf[1024]; unsigned n, j = 0; if (l >= BMP_COLORS + 4) j = GET32(hdr + BMP_COLORS); if (!j) j = 1 << bpp; n = ofs - l - ba; k = l < BMP2_HSIZE ? 3 : 4; /* !!! Some OS/2 2.x BMPs have 3-bpc palettes too */ if ((l == OS2BMP2_HSIZE) && (n < j * 4) && (n >= j * 3)) k = 3; n /= k; if (n < j) j = n; if (!j) goto fail; /* Wrong palette size */ if (j > 256) j = 256; /* Let overlarge palette be */ settings->colors = j; mfseek(mf, l + ba, SEEK_SET); i = mfread(tbuf, 1, j * k, mf); if (i < j * k) goto fail; /* Cannot read palette */ tmp = tbuf; for (i = 0; i < j; i++) { settings->pal[i].red = tmp[2]; settings->pal[i].green = tmp[1]; settings->pal[i].blue = tmp[0]; tmp += k; } /* If palette is all we need */ res = 1; if ((settings->mode == FS_PALETTE_LOAD) || (settings->mode == FS_PALETTE_DEF)) goto fail; } res = -1; /* Allocate buffer and image */ settings->width = w; settings->height = abs(h); settings->bpp = wbpp = bpp < 16 ? 1 : 3; rl = ((w * bpp + 31) >> 3) & ~3; /* Row data length */ bl = rl; /* By default, only one row at a time */ /* For RLE, load all compressed data at once */ if (rle) { unsigned fsize = GET32(hdr + BMP_DATASIZE); if (fsize > INT_MAX - 1) goto fail; bl = fsize; } /* Sanity check */ if (bl <= 0) goto fail; /* To accommodate bitparser's extra step */ buf = malloc(bl + 1); res = FILE_MEM_ERROR; if (!buf) goto fail; if ((res = allocate_image(settings, cmask))) goto fail2; #ifdef U_LCMS /* V5 can have embedded ICC profile */ while (!settings->icc_size && (l == BMP5_HSIZE) && (GET32(hdr + BMP_CSPACE) == BMPCS_EMBED)) { unsigned char *icc = NULL; unsigned n, size = GET32(hdr + BMP_ICCSIZE), ofs = GET32(hdr + BMP_ICCOFS); if (!size || (size > INT_MAX)) break; // Avoid the totally crazy if (ofs > F_LONG_MAX - BMP_HDR2SIZE) break; // Too far if (mfseek(mf, ofs + BMP_HDR2SIZE, SEEK_SET)) break; // Cannot go there icc = malloc(size); if (!icc) break; n = mfread(icc, 1, size, mf); if (n != size) free(icc); // Failed else settings->icc_size = size , settings->icc = icc; // Got it break; } #endif if (!settings->silent) ls_init("BMP", 0); mfseek(mf, ofs, SEEK_SET); /* Seek to data */ if (h < 0) /* Prepare row loop */ { step = 1; i = 0; h = -h; } else { step = -1; i = h - 1; } res = FILE_LIB_ERROR; if (!rle) /* No RLE */ { for (n = 0; (i < h) && (i >= 0); n++ , i += step) { j = mfread(buf, 1, rl, mf); if (j < rl) goto fail3; dest = settings->img[CHN_IMAGE] + w * i * wbpp; if (bpp < 16) /* Indexed */ stream_MSB(buf, dest, w, bpp, 0, bpp, 1); else /* RGB */ { stream_LSB(buf, dest + 0, w, bpps[0], shifts[0], bpp, 3); stream_LSB(buf, dest + 1, w, bpps[1], shifts[1], bpp, 3); stream_LSB(buf, dest + 2, w, bpps[2], shifts[2], bpp, 3); if (settings->img[CHN_ALPHA]) stream_LSB(buf, settings->img[CHN_ALPHA] + w * i, w, bpps[3], shifts[3], bpp, 1); } ls_progress(settings, n, 10); } /* Rescale shorter-than-byte RGBA components */ if (bpp > 8) for (i = 0; i < 4; i++) { if (bpps[i] >= 8) continue; k = 3; if (i == 3) { tmp = settings->img[CHN_ALPHA]; if (!tmp) continue; k = 1; } else tmp = settings->img[CHN_IMAGE] + i; set_xlate(xlat, bpps[i] + !bpps[i]); // Let 0-wide fields be n = w * h; for (j = 0; j < n; j++ , tmp += k) *tmp = xlat[*tmp]; } res = 1; } else /* RLE - always bottom-up */ { k = mfread(buf, 1, bl, mf); if (k < bl) goto fail3; memset(settings->img[CHN_IMAGE], 0, w * h * wbpp); skip = j = 0; dest = settings->img[CHN_IMAGE] + w * i * wbpp; for (tmp = buf; tmp - buf + 1 < k; ) { /* Don't fail on out-of-bounds writes */ if (*tmp) /* Fill block */ { dx = n = *tmp; if (j + n > w) dx = j > w ? 0 : w - j; if (bpp == 24) /* 24-bit */ { copy_run(dest + j * 3, tmp + 1, dx, 3, 0, TRUE); j += n; tmp += 4; continue; } if (bpp == 8) /* 8-bit */ { memset(dest + j, tmp[1], dx); j += n; tmp += 2; continue; } for (ii = 0; ii < dx; ii++) /* 4-bit */ { dest[j++] = tmp[1] >> 4; if (++ii >= dx) break; dest[j++] = tmp[1] & 0xF; } j += n - dx; tmp += 2; continue; } if (tmp[1] > 2) /* Copy block */ { dx = n = tmp[1]; if (j + n > w) dx = j > w ? 0 : w - j; tmp += 2; if (bpp == 24) { copy_run(dest + j * 3, tmp, dx, 3, 3, TRUE); j += n; tmp += (n * 3 + 1) & ~1; continue; } if (bpp == 8) /* 8-bit */ { memcpy(dest + j, tmp, dx); j += n; tmp += (n + 1) & ~1; continue; } for (ii = 0; ii < dx; ii++) /* 4-bit */ { dest[j++] = *tmp >> 4; if (++ii >= dx) break; dest[j++] = *tmp++ & 0xF; } j += n - dx; tmp += (((n + 3) & ~3) - (dx & ~1)) >> 1; continue; } if (tmp[1] == 2) /* Skip block */ { dx = tmp[2] + j; dy = tmp[3]; if (dx > w) goto fail3; if (dy > i) dx = 0 , dy = i + 1; // To the end } else /* End-of-something block */ { dx = 0; dy = tmp[1] ? i + 1 : 1; } /* Transparency detected first time? */ if (!skip && ((dy != 1) || dx || (j < w))) { if ((res = allocate_image(settings, CMASK_ALPHA))) goto fail3; res = FILE_LIB_ERROR; skip = 1; if (settings->img[CHN_ALPHA]) /* Got alpha */ { memset(settings->img[CHN_ALPHA], 255, w * h); skip = 2; } } /* Row skip */ for (ii = 0; ii < dy; ii++ , i--) { if ((skip > 1) && (j < w)) memset(settings->img[CHN_ALPHA] + w * i + j, 0, w - j); j = 0; ls_progress(settings, h - i - 1, 10); } /* Column skip */ if (skip > 1) memset(settings->img[CHN_ALPHA] + w * i + j, 0, dx - j); j = dx; /* No more rows left */ if (i < 0) { res = 1; break; } dest = settings->img[CHN_IMAGE] + w * i * wbpp; tmp += 2 + tmp[1]; } } /* Delete all-zero "alpha" */ if (def_alpha) delete_alpha(settings, 0); fail3: if (!settings->silent) progress_end(); fail2: free(buf); fail: if (fp) fclose(fp); return (res); } /* Use BMP4 instead of BMP3 for images with alpha */ /* #define USE_BMP4 */ /* Most programs just use 32-bit RGB BMP3 for RGBA */ static int save_bmp(char *file_name, ls_settings *settings, memFILE *mf) { unsigned char *buf, *tmp; memFILE fake_mf; FILE *fp = NULL; int i, j, ll, hsz0, hsz, dsz, fsz; int w = settings->width, h = settings->height, bpp = settings->bpp; i = w > BMP_MAXHSIZE / 4 ? w * 4 : BMP_MAXHSIZE; buf = malloc(i); if (!buf) return (-1); memset(buf, 0, i); if (!mf) { if (!(fp = fopen(file_name, "wb"))) { free(buf); return (-1); } memset(mf = &fake_mf, 0, sizeof(fake_mf)); fake_mf.file = fp; } /* Sizes of BMP parts */ if (((settings->mode == FS_CLIPBOARD) || (bpp == 3)) && settings->img[CHN_ALPHA]) bpp = 4; ll = (bpp * w + 3) & ~3; j = bpp == 1 ? settings->colors : 0; #ifdef USE_BMP4 hsz0 = bpp == 4 ? BMP4_HSIZE : BMP3_HSIZE; #else hsz0 = BMP3_HSIZE; #endif hsz = hsz0 + j * 4; dsz = ll * h; fsz = hsz + dsz; /* Prepare header */ buf[0] = 'B'; buf[1] = 'M'; PUT32(buf + BMP_FILESIZE, fsz); PUT32(buf + BMP_DATAOFS, hsz); i = hsz0 - BMP_HDR2SIZE; PUT32(buf + BMP_HDR2SIZE, i); PUT32(buf + BMP_WIDTH, w); PUT32(buf + BMP_HEIGHT, h); PUT16(buf + BMP_PLANES, 1); PUT16(buf + BMP_BPP, bpp * 8); #ifdef USE_BMP4 i = bpp == 4 ? 3 : 0; /* Bitfield "compression" / no compression */ PUT32(buf + BMP_COMPRESS, i); #else PUT32(buf + BMP_COMPRESS, 0); /* No compression */ #endif PUT32(buf + BMP_DATASIZE, dsz); PUT32(buf + BMP_COLORS, j); PUT32(buf + BMP_ICOLORS, j); #ifdef USE_BMP4 if (bpp == 4) { memset(buf + BMP_RMASK, 0, BMP4_HSIZE - BMP_RMASK); buf[BMP_RMASK + 2] = buf[BMP_GMASK + 1] = buf[BMP_BMASK + 0] = buf[BMP_AMASK + 3] = 0xFF; /* Masks for 8-bit BGRA */ buf[BMP_CSPACE] = 1; /* Device-dependent RGB */ } #endif tmp = buf + hsz0; for (i = 0; i < j; i++ , tmp += 4) { tmp[0] = settings->pal[i].blue; tmp[1] = settings->pal[i].green; tmp[2] = settings->pal[i].red; } mfwrite(buf, 1, tmp - buf, mf); /* Write rows */ if (!settings->silent) ls_init("BMP", 1); memset(buf + ll - 4, 0, 4); for (i = h - 1; i >= 0; i--) { prepare_row(buf, settings, bpp, i); mfwrite(buf, 1, ll, mf); ls_progress(settings, h - i, 20); } if (fp) fclose(fp); if (!settings->silent) progress_end(); free(buf); return 0; } /* Partial ctype implementation for C locale; * space 1, digit 2, alpha 4, punctuation 8 */ static unsigned char ctypes[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 8, 8, 8, 8, 8, 8, 8, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 4, 8, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; #define ISSPACE(x) (ctypes[(unsigned char)(x)] & 1) #define ISALPHA(x) (ctypes[(unsigned char)(x)] & 4) #define ISALNUM(x) (ctypes[(unsigned char)(x)] & 6) #define ISCNTRL(x) (!ctypes[(unsigned char)(x)]) #define WHITESPACE "\t\n\v\f\r " typedef struct { FILE *fp; char *buf, *ptr; int size, str, nl; } cctx; static void fsetC(cctx *ctx, FILE *fp, char *buf, int len) { if (fp) /* Full init */ { ctx->fp = fp; ctx->buf = ctx->ptr = buf; ctx->buf[0] = '\0'; ctx->size = len; ctx->str = 0; ctx->nl = 1; // Not middle of line } else /* Switch buffers to a LARGER one */ { int l = strlen(ctx->ptr); memmove(buf, ctx->ptr, l); buf[l] = '\0'; ctx->buf = ctx->ptr = buf; ctx->size = len; } } /* Reads text and cuts out C-style comments */ static char *fgetsC(cctx *ctx) { char *buf = ctx->buf; int i, l = 0, has_chars = 0, in_comment = 0, in_string = ctx->str; /* Keep unparsed tail if the line isn't yet terminated */ if (!ctx->nl && ((l = strlen(ctx->ptr)))) { memmove(buf, ctx->ptr, l); for (i = 0; i < l; i++) if (!ISSPACE(buf[i])) has_chars++; } ctx->ptr = buf; buf[l] = '\0'; while (TRUE) { /* Read a line */ if (!fgets(buf + l, ctx->size - l, ctx->fp)) return (NULL); /* Scan it for comments */ i = l; l += strlen(buf + l); ctx->nl = l && (buf[l - 1] == '\n'); // Remember line termination for (; i < l; i++) { if (in_string) { /* Ignore backslash before quote, as libXpm does */ if (buf[i] == '"') in_string = 0; /* Close a string */ continue; } if (in_comment) { if ((buf[i] == '/') && i && (buf[i - 1] == '*')) { /* Replace comment by a single space */ buf[in_comment - 1] = ' '; memcpy(buf + in_comment, buf + i + 1, l - i); l = in_comment + l - i - 1; i = in_comment - 1; in_comment = 0; } continue; } if (!ISSPACE(buf[i])) has_chars++; if (buf[i] == '"') in_string = 1; /* Open a string */ else if ((buf[i] == '*') && i && (buf[i - 1] == '/')) { /* Open a comment */ in_comment = i; has_chars -= 2; } } /* Fail unterminated strings, forbid continuations for simplicity */ if (in_string && ctx->nl) return (NULL); /* Whitespace ending in unclosed comment - reduce it */ if ((in_comment > 1) && !has_chars) { buf[0] = '/'; buf[1] = '*'; in_comment = 1; } /* Fail overlong lines ending in unclosed comment */ if (in_comment >= ctx->size - 3) return (NULL); /* Continue reading till the comment closes */ if (in_comment) { l = in_comment + 1; continue; } /* All line is whitespace - continue reading */ if (!has_chars) { l = !l || ctx->nl ? 0 : 1; // Remember 1 leading space continue; } /* Remember if last string hasn't ended */ ctx->str = in_string; return (buf); } } /* Gets next C string out of buffer */ static char *fstrC(cctx *ctx) { char *s, *t, *w = ctx->ptr; /* String has to begin somewhere */ while (!(s = strchr(w, '"'))) { *(ctx->ptr = ctx->buf) = '\0'; if (!(w = fgetsC(ctx))) return (NULL); } /* And to end on the same line */ t = strchr(s + 1, '"'); if (!t) { ctx->ptr = s; if (!(s = fgetsC(ctx))) return (NULL); t = strchr(s + 1, '"'); } if (!t) return (NULL); // Overlong string /* Cut off the remainder */ if (*++t) { *t++ = '\0'; // Ignoring whatever it was while (ISSPACE(*t)) t++; } /* Remember the tail */ ctx->ptr = t; return (s); } /* Gets next C line out of buffer */ static char *flineC(cctx *ctx) { /* Skip to end of this line */ while (!ctx->nl) { *(ctx->ptr = ctx->buf) = '\0'; if (!fgetsC(ctx)) return (NULL); } /* And read the next */ return (fgetsC(ctx)); } /* "One at a time" hash function */ static guint32 hashf(guint32 seed, char *key, int len) { int i; for (i = 0; i < len; i++) { seed += key[i]; seed += seed << 10; seed ^= seed >> 6; } seed += seed << 3; seed ^= seed >> 11; seed += seed << 15; return (seed); } #define HASHSEED 0x811C9DC5 #define HASH_RND(X) ((X) * 0x10450405 + 1) #define HSIZE 16384 #define HMASK 0x1FFF /* For cuckoo hashing of 4096 items into 16384 slots */ #define MAXLOOP 39 /* This is the limit from libXPM */ #define XPM_MAXCOL 4096 /* Cuckoo hash of IDs for load or RGB triples for save */ typedef struct { short hash[HSIZE]; char *keys; int step, cpp, cnt; guint32 seed; } str_hash; static int ch_find(str_hash *cuckoo, char *str) { guint32 key; int k, idx, step = cuckoo->step, cpp = cuckoo->cpp; key = hashf(cuckoo->seed, str, cpp); k = (key & HMASK) * 2; while (TRUE) { idx = cuckoo->hash[k]; if (idx && !memcmp(cuckoo->keys + (idx - 1) * step, str, cpp)) return (idx); if (k & 1) return (0); /* Not found */ k = ((key >> 16) & HMASK) * 2 + 1; } } static int ch_insert(str_hash *cuckoo, char *str) { char *p, *keys; guint32 key; int i, j, k, n, idx, step, cpp; n = ch_find(cuckoo, str); if (n) return (n - 1); keys = cuckoo->keys; step = cuckoo->step; cpp = cuckoo->cpp; if (cuckoo->cnt >= XPM_MAXCOL) return (-1); p = keys + cuckoo->cnt++ * step; memcpy(p, str, cpp); p[cpp] = 0; for (n = cuckoo->cnt; n <= cuckoo->cnt; n++) { idx = n; /* Normal cuckoo process */ for (i = 0; i < MAXLOOP; i++) { key = hashf(cuckoo->seed, keys + (idx - 1) * step, cpp); key >>= (i & 1) << 4; j = (key & HMASK) * 2 + (i & 1); k = cuckoo->hash[j]; cuckoo->hash[j] = idx; idx = k; if (!idx) break; } if (!idx) continue; /* Failed insertion - mutate seed */ cuckoo->seed = HASH_RND(cuckoo->seed); memset(cuckoo->hash, 0, sizeof(short) * HSIZE); n = 1; /* Rehash everything */ } return (cuckoo->cnt - 1); } #define XPM_COL_DEFS 5 #define BUCKET_SIZE 8 /* Comments are allowed where valid */ static int load_xpm(char *file_name, ls_settings *settings) { static const char *cmodes[XPM_COL_DEFS] = { "c", "g", "g4", "m", "s" }; unsigned char *cbuf, *src, *dest, pal[XPM_MAXCOL * 3], *dst0 = pal; guint32 *slots; char lbuf[4096], *buf = lbuf, *bh = NULL; char ckeys[XPM_MAXCOL * 32], *cdefs[XPM_COL_DEFS], *r, *r2, *t; str_hash cuckoo; cctx ctx; FILE *fp; int uninit_(n), uninit_(nx), uninit_(nslots); int w, h, cols, cpp, hx, hy, res = -1, bpp = 1, trans = -1; int i, j, k, l, lsz = sizeof(lbuf), step = 3, pr = FALSE; if (!(fp = fopen(file_name, "r"))) return (-1); /* Read the header - accept XPM3 and nothing else */ j = 0; fscanf(fp, " /* XPM */%n", &j); if (!j) goto fail; fsetC(&ctx, fp, lbuf, sizeof(lbuf)); /* Init reader */ /* Skip right to the first string like libXpm does */ if (!(r = fstrC(&ctx))) goto fail; /* Read the values section */ i = sscanf(r + 1, "%d%d%d%d%d%d", &w, &h, &cols, &cpp, &hx, &hy); if (i == 4) hx = hy = -1; else if (i != 6) goto fail; /* Extension marker is ignored, as are extensions themselves */ /* More than 16M colors or no colors at all aren't accepted */ if ((cols < 1) || (cols > 0x1000000)) goto fail; /* Stupid chars per pixel values aren't either */ if ((cpp < 1) || (cpp > 31)) goto fail; /* More than 4096 colors accepted only if 4 cpp or less */ if ((cols > XPM_MAXCOL) && (cpp > 4)) goto fail; /* RGB image if more than 256 colors */ if (cols > 256) bpp = 3; /* Store values */ settings->width = w; settings->height = h; settings->bpp = bpp; if (bpp == 1) settings->colors = cols; settings->hot_x = hx; settings->hot_y = hy; settings->xpm_trans = -1; /* Allocate things early, to avoid reading huge color table and THEN * failing for bad dimensions of / lack of memory for the image itself */ if ((settings->mode != FS_PALETTE_LOAD) && (settings->mode != FS_PALETTE_DEF)) { if ((res = allocate_image(settings, CMASK_IMAGE))) goto fail; /* Allocate row buffer */ i = w * cpp + 4 + 1024; if (i > lsz) buf = malloc(lsz = i); res = FILE_MEM_ERROR; if (!buf) goto fail; fsetC(&ctx, NULL, buf, lsz); /* Switch buffers */ /* Init bucketed hash */ if (cols > XPM_MAXCOL) { nslots = (cols + BUCKET_SIZE - 1) / BUCKET_SIZE; bh = multialloc(MA_ALIGN_DEFAULT, &slots, (nslots + 1) * sizeof(*slots), &cbuf, cols * (4 + 3), NULL); if (!bh) goto fail2; dst0 = cbuf + 4; step = 4 + 3; } if ((pr = !settings->silent)) { ls_init("XPM", 0); progress_update(0.0); /* A color seems to cost like about 2 pixels to load */ n = (cols * 2) / w; nx = n + h; } } /* Too many colors do not a palette make */ else if (bpp > 1) goto fail; /* Init cuckoo hash */ if (!bh) { memset(&cuckoo, 0, sizeof(cuckoo)); cuckoo.keys = ckeys; cuckoo.step = 32; cuckoo.cpp = cpp; cuckoo.seed = HASHSEED; } /* Read colormap */ res = -1; for (i = 0 , dest = dst0; i < cols; i++ , dest += step) { if (!(r = fstrC(&ctx))) goto fail3; l = strlen(r); if (l < cpp + 4) goto fail3; r[l - 1] = '\0'; // Cut off closing quote /* Insert color into hash */ if (bh) strncpy(dest - 4, r + 1, 4); else ch_insert(&cuckoo, r + 1); /* Parse color definitions */ memset(cdefs, 0, sizeof(cdefs)); r += cpp + 2; k = -1; r2 = NULL; while (TRUE) { while (ISSPACE(*r)) r++; if (!*r) break; t = r++; while (*r && !ISSPACE(*r)) r++; if (*r) *r++ = '\0'; if (k < 0) /* Mode */ { for (j = 0; j < XPM_COL_DEFS; j++) { if (!strcmp(t, cmodes[j])) break; } if (j < XPM_COL_DEFS) /* Key */ { k = j; r2 = NULL; continue; } } if (!r2) /* Color name */ { if (k < 0) goto fail3; cdefs[k] = r2 = t; k = -1; } else /* Add next part of name */ { l = strlen(r2); r2[l] = ' '; memmove(r2 + l + 1, t, strlen(t) + 1); } } if (!r2) goto fail3; /* Key w/o name */ /* Translate the best one */ for (j = 0; j < XPM_COL_DEFS; j++) { int c; if (!cdefs[j]) continue; if (!strcasecmp(cdefs[j], "none")) /* Transparent */ { trans = i; break; } c = parse_color(cdefs[j]); if (c < 0) continue; dest[0] = INT_2_R(c); dest[1] = INT_2_G(c); dest[2] = INT_2_B(c); break; } /* Not one understandable color */ if (j >= XPM_COL_DEFS) goto fail3; } /* With bucketed hashing, half the work per color is not done yet */ if (pr) progress_update((float)(bh ? n / 2 : n) / nx); /* Create palette */ if (bpp == 1) { dest = dst0; for (i = 0; i < cols; i++ , dest += step) { settings->pal[i].red = dest[0]; settings->pal[i].green = dest[1]; settings->pal[i].blue = dest[2]; } if (trans >= 0) { settings->xpm_trans = trans; settings->pal[trans].red = settings->pal[trans].green = 115; settings->pal[trans].blue = 0; } /* If palette is all we need */ res = 1; if ((settings->mode == FS_PALETTE_LOAD) || (settings->mode == FS_PALETTE_DEF)) goto fail3; } /* Find an unused color for transparency */ else if (trans >= 0) { unsigned char cmap[XPM_MAXCOL / 8], *cc = cmap; int l = XPM_MAXCOL; if (bh) // Allocate color cube { l = 0x1000000; cc = malloc(l / 8); res = FILE_MEM_ERROR; if (!cc) goto fail3; } memset(cc, 0, l / 8); for (i = 0 , dest = dst0; i < cols; i++ , dest += step) { if (i == trans) continue; j = MEM_2_INT(dest, 0); if (j < l) cc[j >> 3] |= 1 << (j & 7); } /* Unused color IS there, as buffer has bits per total colors; * if one is transparent, then a bit stays unset in there */ dest = cc; while (*dest == 0xFF) dest++; j = (dest - cc) * 8; i = *dest; while (i & 1) j++ , i >>= 1; if (bh) free(cc); /* Store the result */ settings->rgb_trans = j; dest = dst0 + trans * step; dest[0] = INT_2_R(j); dest[1] = INT_2_G(j); dest[2] = INT_2_B(j); } if (bh) /* Sort the colors by their buckets */ { unsigned char *w, *ww, tbuf[4 + 3]; int ds, ins; /* First, count how many goes where */ for (i = 0 , dest = cbuf; i < cols; i++ , dest += 4 + 3) (slots + 1)[hashf(HASHSEED, dest, cpp) % nslots]++; /* Then, prepare buckets' offsets */ for (i = 0; i < nslots; i++) slots[i + 1] += slots[i]; /* Now, starting from first, move colors where they belong */ for (i = 0; i < cols; ) { /* Color */ w = cbuf + i * (4 + 3); /* Its home */ ds = hashf(HASHSEED, w, cpp) % nslots; /* Its insertion point */ ins = --slots[ds + 1]; /* Already in place */ if (ins <= i) { slots[ds + 1] = ++i; // Adjust continue; } /* Move it */ ww = cbuf + ins * (4 + 3); memcpy(tbuf, ww, 4 + 3); memcpy(ww, w, 4 + 3); memcpy(w, tbuf, 4 + 3); } if (pr) progress_update((float)n / nx); } /* Now, read the image */ res = FILE_LIB_ERROR; dest = settings->img[CHN_IMAGE]; for (i = 0; i < h; i++) { if (!(r = fstrC(&ctx))) goto fail3; /* libXpm allows overlong strings */ if (strlen(++r) < w * cpp + 1) goto fail3; for (j = 0; j < w; j++ , dest += bpp) { if (bh) { unsigned char *w; int ds, n; ds = hashf(HASHSEED, r, cpp) % nslots; k = slots[ds]; w = cbuf + k * (4 + 3); n = slots[ds + 1]; for (; k < n; k++ , w += 4 + 3) /* Trying to avoid function call */ if ((*w == *r) && !memcmp(w, r, cpp)) break; k = k >= n ? 0 : k + 1; } else k = ch_find(&cuckoo, r); if (!k) goto fail3; r += cpp; if (bpp == 1) *dest = k - 1; else { src = dst0 + (k - 1) * step; dest[0] = src[0]; dest[1] = src[1]; dest[2] = src[2]; } } if (pr && ((n++ * 10) % nx >= nx - 10)) progress_update((float)n / nx); } res = 1; fail3: if (pr) progress_end(); free(bh); fail2: if (buf != lbuf) free(buf); fail: fclose(fp); return (res); } static const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" "!#$%&'()*,-.:;<=>?@[]^_`{|}~", hex[] = "0123456789ABCDEF"; /* Extract valid C identifier from filename */ static char *extract_ident(char *fname, int *len) { char *tmp; int l; tmp = strrchr(fname, DIR_SEP); tmp = tmp ? tmp + 1 : fname; for (; *tmp && !ISALPHA(*tmp); tmp++); for (l = 0; (l < 256) && ISALNUM(tmp[l]); l++); *len = l; return (tmp); } #define CTABLE_SIZE (0x1000000 / 32) #define CINDEX_SIZE (0x1000000 / 256) /* Find color index using bitmap with sparse counters */ static int ct_index(int rgb, guint32 *ctable) { guint32 bit = 1U << (rgb & 31), *cindex = ctable + CTABLE_SIZE; int n, d = rgb >> 5, m = d & 7; if (!(ctable[d] & bit)) return (-1); // Not found n = cindex[d >> 3]; while (m > 0) n += bitcount(ctable[d - m--]); return (n + bitcount(ctable[d] & (bit - 1))); } static int save_xpm(char *file_name, ls_settings *settings) { unsigned char rgbmem[XPM_MAXCOL * 4], *src; guint32 *cindex, *ctable = NULL; const char *ctb; char ws[5], tc[5] = " "; char *buf, *tmp; str_hash cuckoo; FILE *fp; int bpp = settings->bpp, w = settings->width, h = settings->height; int uninit_(ccmask); int i, j, k, l, c, cpp, cols, trans = -1; tmp = extract_ident(file_name, &l); if (!l) return -1; /* Collect RGB colors */ if (bpp == 3) { trans = settings->rgb_trans; /* Init hash */ memset(&cuckoo, 0, sizeof(cuckoo)); cuckoo.keys = rgbmem; cuckoo.step = 4; cuckoo.cpp = 3; cuckoo.seed = HASHSEED; j = w * h; src = settings->img[CHN_IMAGE]; for (i = 0; i < j; i++ , src += 3) { if (ch_insert(&cuckoo, src) < 0) break; /* Too many colors for this mode */ } if (i < j) /* Too many colors, collect & count 'em */ { ctable = calloc(CTABLE_SIZE + CINDEX_SIZE, sizeof(*ctable)); if (!ctable) return (-1); // No memory src = settings->img[CHN_IMAGE]; for (i = 0; i < j; i++ , src += 3) { int n = MEM_2_INT(src, 0); ctable[n >> 5] |= 1U << (n & 31); } cindex = ctable + CTABLE_SIZE; for (i = cols = 0; i < CTABLE_SIZE; i++) { if (!(i & 7)) cindex[i >> 3] = cols; cols += bitcount(ctable[i]); } /* RGB to index */ if (trans > -1) trans = ct_index(trans, ctable); } else /* Sensible number of colors, cuckoo hashing works */ { cols = cuckoo.cnt; /* RGB to index */ if (trans > -1) { char trgb[3]; trgb[0] = INT_2_R(trans); trgb[1] = INT_2_G(trans); trgb[2] = INT_2_B(trans); trans = ch_find(&cuckoo, trgb) - 1; } } } /* Process indexed colors */ else { cols = settings->colors; src = rgbmem; for (i = 0; i < cols; i++ , src += 4) { src[0] = settings->pal[i].red; src[1] = settings->pal[i].green; src[2] = settings->pal[i].blue; } trans = settings->xpm_trans; } cpp = cols > 92 * 92 * 92 ? 4 : cols > 92 * 92 ? 3 : cols > 92 ? 2 : 1; buf = malloc(w * cpp + 16); // Prepare row buffer if (!buf || !(fp = fopen(file_name, "w"))) { free(buf); free(ctable); return -1; } if (!settings->silent) ls_init("XPM", 1); fprintf(fp, "/* XPM */\n" ); fprintf(fp, "static char *%.*s_xpm[] = {\n", l, tmp); if ((settings->hot_x >= 0) && (settings->hot_y >= 0)) fprintf(fp, "\"%d %d %d %d %d %d\",\n", w, h, cols, cpp, settings->hot_x, settings->hot_y); else fprintf(fp, "\"%d %d %d %d\",\n", w, h, cols, cpp); /* Create colortable */ ctb = cols > 16 ? base64 : hex; tc[cpp] = '\0'; if (ctable) // From bitmap { for (i = c = 0; i < CTABLE_SIZE; i++) { guint32 n = ctable[i]; for (k = 0; n; k++ , n >>= 1) { if (!(n & 1)) continue; l = i * 32 + k; // Color /* Color ID */ ws[0] = ctb[c % 92]; ws[1] = ctb[(c / 92) % 92]; ws[2] = ctb[(c / (92 * 92)) % 92]; ws[3] = ctb[c / (92 * 92 * 92)]; ws[cpp] = '\0'; if (c == trans) // Transparency fprintf(fp, "\"%s\tc None\",\n", tc); else fprintf(fp, "\"%s\tc #%02X%02X%02X\",\n", ws, INT_2_R(l), INT_2_G(l), INT_2_B(l)); c++; } } } else // From cuckoo's keys { ccmask = 255 >> cpp; // 63 for 2 cpp, 127 for 1 for (i = 0; i < cols; i++) { if (i == trans) { fprintf(fp, "\"%s\tc None\",\n", tc); continue; } ws[0] = ctb[i & ccmask]; ws[1] = ctb[i >> 6]; ws[cpp] = '\0'; src = rgbmem + i * 4; fprintf(fp, "\"%s\tc #%02X%02X%02X\",\n", ws, src[0], src[1], src[2]); } } w *= bpp; for (i = 0; i < h; i++) { src = settings->img[CHN_IMAGE] + i * w; tmp = buf; *tmp++ = '"'; for (j = 0; j < w; j += bpp, tmp += cpp) { if (bpp == 1) k = src[j]; else if (!ctable) k = ch_find(&cuckoo, src + j) - 1; else k = ct_index(MEM_2_INT(src, j), ctable); if (k == trans) tmp[0] = tmp[1] = tmp[2] = tmp[3] = ' '; else if (ctable) { tmp[0] = ctb[k % 92]; tmp[1] = ctb[(k / 92) % 92]; tmp[2] = ctb[(k / (92 * 92)) % 92]; tmp[3] = ctb[k / (92 * 92 * 92)]; } else // Backward compatible mapping { tmp[0] = ctb[k & ccmask]; tmp[1] = ctb[k >> 6]; } } strcpy(tmp, i < h - 1 ? "\",\n" : "\"\n};\n"); fputs(buf, fp); ls_progress(settings, i, 10); } fclose(fp); if (!settings->silent) progress_end(); free(buf); free(ctable); return 0; } static int load_xbm(char *file_name, ls_settings *settings) { static const char XPMtext[] = "0123456789ABCDEFabcdef,} \t\n", XPMval[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 10, 11, 12, 13, 14, 15, 16, 16, 16, 16, 16 }; unsigned char ctb[256], *dest; char lbuf[4096], *r; cctx ctx; FILE *fp; int w , h, hx = -1, hy = -1, bpn = 16, res = -1; int i, j, k, c, v = 0; if (!(fp = fopen(file_name, "r"))) return (-1); /* Read & parse what serves as header to XBM */ fsetC(&ctx, fp, lbuf, sizeof(lbuf)); /* Init reader */ /* Width and height - required part in fixed order */ if (!(r = flineC(&ctx))) goto fail; if (!sscanf(r, "#define %*s%n %d", &i, &w)) goto fail; if (strncmp(r + i - 5, "width", 5)) goto fail; if (!(r = flineC(&ctx))) goto fail; if (!sscanf(r, "#define %*s%n %d", &i, &h)) goto fail; if (strncmp(r + i - 6, "height", 6)) goto fail; /* Hotspot X and Y - optional part in fixed order */ if (!(r = flineC(&ctx))) goto fail; if (sscanf(r, "#define %*s%n %d", &i, &hx)) { if (strncmp(r + i - 5, "x_hot", 5)) goto fail; if (!(r = flineC(&ctx))) goto fail; if (!sscanf(r, "#define %*s%n %d", &i, &hy)) goto fail; if (strncmp(r + i - 5, "y_hot", 5)) goto fail; if (!(r = flineC(&ctx))) goto fail; } /* "Intro" string */ j = 0; sscanf(r, " static short %*[^[]%n[] = {%n", &i, &j); if (!j) { bpn = 8; /* X11 format - 8-bit data */ j = 0; sscanf(r, " static unsigned char %*[^[]%n[] = {%n", &i, &j); if (!j) sscanf(r, " static char %*[^[]%n[] = {%n", &i, &j); if (!j) goto fail; } if (strncmp(r + i - 4, "bits", 4)) goto fail; // !!! For now, newline is required between "intro" and data /* Store values */ settings->width = w; settings->height = h; settings->bpp = 1; settings->hot_x = hx; settings->hot_y = hy; /* Palette is white and black */ set_bw(settings); /* Allocate image */ if ((res = allocate_image(settings, CMASK_IMAGE))) goto fail; /* Prepare to read data */ memset(ctb, 17, sizeof(ctb)); for (i = 0; XPMtext[i]; i++) { ctb[(unsigned char)XPMtext[i]] = XPMval[i]; } /* Now, read the image */ if (!settings->silent) ls_init("XBM", 0); res = FILE_LIB_ERROR; dest = settings->img[CHN_IMAGE]; for (i = 0; i < h; i++) { for (j = k = 0; j < w; j++ , k--) { if (!k) /* Get next value, the way X itself does */ { v = 0; while (TRUE) { if ((c = getc(fp)) == EOF) goto fail2; c = ctb[c & 255]; if (c < 16) /* Accept hex digits */ { v = (v << 4) + c; k++; } /* Silently ignore out-of-place chars */ else if (c > 16) continue; /* Stop on delimiters after digits */ else if (k) break; } k = bpn; } *dest++ = v & 1; v >>= 1; } ls_progress(settings, i, 10); } res = 1; fail2: if (!settings->silent) progress_end(); fail: fclose(fp); return (res); } #define BPL 12 /* Bytes per line */ #define CPB 6 /* Chars per byte */ static int save_xbm(char *file_name, ls_settings *settings) { unsigned char bw, *src; unsigned char row[MAX_WIDTH / 8]; char buf[CPB * BPL + 16], *tmp; FILE *fp; int i, j, k, l, w = settings->width, h = settings->height; if ((settings->bpp != 1) || (settings->colors > 2)) return WRONG_FORMAT; /* Extract valid C identifier from name */ tmp = extract_ident(file_name, &i); if (!i) return -1; if (!(fp = fopen(file_name, "w"))) return -1; fprintf(fp, "#define %.*s_width %i\n", i, tmp, w); fprintf(fp, "#define %.*s_height %i\n", i, tmp, h); if ((settings->hot_x >= 0) && (settings->hot_y >= 0)) { fprintf(fp, "#define %.*s_x_hot %i\n", i, tmp, settings->hot_x); fprintf(fp, "#define %.*s_y_hot %i\n", i, tmp, settings->hot_y); } fprintf(fp, "static unsigned char %.*s_bits[] = {\n", i, tmp); if (!settings->silent) ls_init("XBM", 1); bw = get_bw(settings); j = k = (w + 7) >> 3; i = l = 0; while (TRUE) { if (j >= k) { if (i >= h) break; src = settings->img[CHN_IMAGE] + i * w; memset(row, 0, k); for (j = 0; j < w; j++) { if (src[j] == bw) row[j >> 3] |= 1 << (j & 7); } j = 0; ls_progress(settings, i, 10); i++; } for (; (l < BPL) && (j < k); l++ , j++) { tmp = buf + l * CPB; tmp[0] = ' '; tmp[1] = '0'; tmp[2] = 'x'; tmp[3] = hex[row[j] >> 4]; tmp[4] = hex[row[j] & 0xF]; tmp[5] = ','; } if ((l == BPL) && (j < k)) { buf[BPL * CPB] = '\n'; buf[BPL * CPB + 1] = '\0'; fputs(buf, fp); l = 0; } } strcpy(buf + l * CPB - 1, " };\n"); fputs(buf, fp); fclose(fp); if (!settings->silent) progress_end(); return 0; } /* * Those who don't understand PCX are condemned to reinvent it, poorly. :-) */ #define LSS_WIDTH 4 /* 16b */ #define LSS_HEIGHT 6 /* 16b */ #define LSS_PALETTE 8 /* 16 * 3 * 8b */ #define LSS_HSIZE 56 static int load_lss(char *file_name, ls_settings *settings) { unsigned char hdr[LSS_HSIZE], *dest, *tmp, *buf = NULL; FILE *fp; f_long l; int i, j, k, w, h, bl, idx, last, cnt, res = -1; if (!(fp = fopen(file_name, "rb"))) return (-1); /* Read the header */ k = fread(hdr, 1, LSS_HSIZE, fp); /* Check general validity */ if (k < LSS_HSIZE) goto fail; /* Least supported header size */ if (strncmp(hdr, "\x3D\xF3\x13\x14", 4)) goto fail; /* Signature */ w = GET16(hdr + LSS_WIDTH); h = GET16(hdr + LSS_HEIGHT); settings->width = w; settings->height = h; settings->bpp = 1; settings->colors = 16; /* Read palette */ tmp = hdr + LSS_PALETTE; for (i = 0; i < 16; i++) { settings->pal[i].red = tmp[0] << 2 | tmp[0] >> 4; settings->pal[i].green = tmp[1] << 2 | tmp[1] >> 4; settings->pal[i].blue = tmp[2] << 2 | tmp[2] >> 4; tmp += 3; } /* If palette is all we need */ res = 1; if ((settings->mode == FS_PALETTE_LOAD) || (settings->mode == FS_PALETTE_DEF)) goto fail; /* Load all image at once */ fseek(fp, 0, SEEK_END); l = ftell(fp); if (l <= LSS_HSIZE) goto fail; /* Too large or too small */ l -= LSS_HSIZE; fseek(fp, LSS_HSIZE, SEEK_SET); bl = (w * h * 3) >> 1; /* Cannot possibly be longer */ if (bl > l) bl = l; buf = malloc(bl); res = FILE_MEM_ERROR; if (!buf) goto fail2; if ((res = allocate_image(settings, CMASK_IMAGE))) goto fail2; if (!settings->silent) ls_init("LSS16", 0); res = FILE_LIB_ERROR; j = fread(buf, 1, bl, fp); if (j < bl) goto fail3; dest = settings->img[CHN_IMAGE]; idx = 0; bl += bl; for (i = 0; i < h; i++) { last = 0; idx = (idx + 1) & ~1; for (j = 0; j < w; ) { if (idx >= bl) goto fail3; k = (buf[idx >> 1] >> ((idx & 1) << 2)) & 0xF; ++idx; if (k != last) { dest[j++] = last = k; continue; } if (idx >= bl) goto fail3; cnt = (buf[idx >> 1] >> ((idx & 1) << 2)) & 0xF; ++idx; if (!cnt) { if (idx >= bl) goto fail3; cnt = (buf[idx >> 1] >> ((idx & 1) << 2)) & 0xF; ++idx; if (idx >= bl) goto fail3; k = (buf[idx >> 1] >> ((idx & 1) << 2)) & 0xF; ++idx; cnt = (k << 4) + cnt + 16; } if (cnt > w - j) cnt = w - j; memset(dest + j, last, cnt); j += cnt; } dest += w; } res = 1; fail3: if (!settings->silent) progress_end(); fail2: free(buf); fail: fclose(fp); return (res); } static int save_lss(char *file_name, ls_settings *settings) { unsigned char *buf, *tmp, *src; FILE *fp; int i, j, uninit_(k), last, cnt, idx; int w = settings->width, h = settings->height; if ((settings->bpp != 1) || (settings->colors > 16)) return WRONG_FORMAT; i = w > LSS_HSIZE ? w : LSS_HSIZE; buf = malloc(i); if (!buf) return -1; memset(buf, 0, i); if (!(fp = fopen(file_name, "wb"))) { free(buf); return -1; } /* Prepare header */ buf[0] = 0x3D; buf[1] = 0xF3; buf[2] = 0x13; buf[3] = 0x14; PUT16(buf + LSS_WIDTH, w); PUT16(buf + LSS_HEIGHT, h); j = settings->colors > 16 ? 16 : settings->colors; tmp = buf + LSS_PALETTE; for (i = 0; i < j; i++) { tmp[0] = settings->pal[i].red >> 2; tmp[1] = settings->pal[i].green >> 2; tmp[2] = settings->pal[i].blue >> 2; tmp += 3; } fwrite(buf, 1, LSS_HSIZE, fp); /* Write rows */ if (!settings->silent) ls_init("LSS16", 1); src = settings->img[CHN_IMAGE]; for (i = 0; i < h; i++) { memset(buf, 0, w); last = cnt = idx = 0; for (j = 0; j < w; ) { for (; j < w; j++) { k = *src++ & 0xF; if ((k != last) || (++cnt >= 255 + 16)) break; } if (cnt) { buf[idx >> 1] |= last << ((idx & 1) << 2); ++idx; if (cnt >= 16) { ++idx; /* Insert zero */ cnt -= 16; buf[idx >> 1] |= (cnt & 0xF) << ((idx & 1) << 2); ++idx; cnt >>= 4; } buf[idx >> 1] |= cnt << ((idx & 1) << 2); ++idx; } if (j++ >= w) break; /* Final repeat */ cnt = 0; if (k == last) continue; /* Chain of repeats */ buf[idx >> 1] |= k << ((idx & 1) << 2); ++idx; last = k; } idx = (idx + 1) & ~1; fwrite(buf, 1, idx >> 1, fp); ls_progress(settings, i, 10); } fclose(fp); if (!settings->silent) progress_end(); free(buf); return 0; } /* *** PREFACE *** * No other format has suffered so much at the hands of inept coders. With TGA, * exceptions are the rule, and files perfectly following the specification are * impossible to find. While I did my best to handle the format's perversions * that I'm aware of, there surely exist other kinds of weird TGAs that will * load wrong, or not at all. If you encounter one such, send a bugreport with * the file attached to it. */ /* TGA header */ #define TGA_IDLEN 0 /* 8b */ #define TGA_PALTYPE 1 /* 8b */ #define TGA_IMGTYPE 2 /* 8b */ #define TGA_PALSTART 3 /* 16b */ #define TGA_PALCOUNT 5 /* 16b */ #define TGA_PALBITS 7 /* 8b */ #define TGA_X0 8 /* 16b */ #define TGA_Y0 10 /* 16b */ #define TGA_WIDTH 12 /* 16b */ #define TGA_HEIGHT 14 /* 16b */ #define TGA_BPP 16 /* 8b */ #define TGA_DESC 17 /* 8b */ #define TGA_HSIZE 18 /* Image descriptor bits */ #define TGA_ALPHA 0x0F #define TGA_R2L 0x10 #define TGA_T2B 0x20 #define TGA_IL 0xC0 /* Interleave mode - obsoleted in TGA 2.0 */ /* TGA footer */ #define TGA_EXTOFS 0 /* 32b */ #define TGA_DEVOFS 4 /* 32b */ #define TGA_SIGN 8 #define TGA_FSIZE 26 /* TGA extension area */ #define TGA_EXTLEN 0 /* 16b */ #define TGA_SOFTID 426 /* 41 bytes */ #define TGA_SOFTV 467 /* 16b */ #define TGA_ATYPE 494 /* 8b */ #define TGA_EXTSIZE 495 static void extend_bytes(unsigned char *dest, int len, int maxval) { unsigned char tb[256]; memset(tb, 255, 256); set_xlate_n(tb, maxval); do_xlate(tb, dest, len); } static int load_tga(char *file_name, ls_settings *settings) { unsigned char hdr[TGA_HSIZE], ftr[TGA_FSIZE], ext[TGA_EXTSIZE]; unsigned char pal[256 * 4], xlat5[32], xlat6[64], trans[256]; unsigned char *buf = NULL, *dest, *dsta, *src = NULL, *srca = NULL; unsigned char *bstart, *bstop; FILE *fp; f_long fl; unsigned fofs; int i, k, w, h, bpp, ftype, ptype, ibpp, rbits, abits, itrans = FALSE; int rle, real_alpha = FALSE, assoc_alpha = FALSE, wmode = 0, res = -1; int iofs, buflen; int ix, ishift, imask, ax, ashift, amask; int start, xstep, xstepb, ystep, ccnt, rcnt, strl, y; if (!(fp = fopen(file_name, "rb"))) return (-1); /* Read the header */ k = fread(hdr, 1, TGA_HSIZE, fp); if (k < TGA_HSIZE) goto fail; /* TGA has no signature as such - so check fields one by one */ ftype = hdr[TGA_IMGTYPE]; if (!(ftype & 3) || (ftype & 0xF4)) goto fail; /* Invalid type */ /* Fail on interleave, because of lack of example files */ if (hdr[TGA_DESC] & TGA_IL) goto fail; rle = ftype & 8; iofs = TGA_HSIZE + hdr[TGA_IDLEN]; rbits = hdr[TGA_BPP]; if (!rbits) goto fail; /* Zero bpp */ abits = hdr[TGA_DESC] & TGA_ALPHA; if (abits > rbits) goto fail; /* Weird alpha */ /* Workaround for a rather frequent bug */ if (abits == rbits) abits = 0; ibpp = (rbits + 7) >> 3; rbits -= abits; set_xlate(xlat5, 5); ptype = hdr[TGA_PALTYPE]; switch (ftype & 3) { case 1: /* Paletted */ { int pbpp, i, j, k, l; png_color *pptr; if (ptype != 1) goto fail; /* Invalid palette */ /* Don't want to bother with overlong palette without even * having one example where such a thing exists - WJ */ if (rbits > 8) goto fail; k = GET16(hdr + TGA_PALSTART); if (k >= 1 << rbits) goto fail; /* Weird palette start */ j = GET16(hdr + TGA_PALCOUNT); if (!j || (k + j > 1 << rbits)) goto fail; /* Weird size */ ptype = hdr[TGA_PALBITS]; /* The options are quite limited here in practice */ if (!ptype || (ptype > 32) || ((ptype & 7) && (ptype != 15))) goto fail; pbpp = (ptype + 7) >> 3; l = j * pbpp; /* Read the palette */ fseek(fp, iofs, SEEK_SET); if (fread(pal + k * pbpp, 1, l, fp) != l) goto fail; iofs += l; /* Store the palette */ settings->colors = j + k; memset(settings->pal, 0, 256 * 3); pptr = settings->pal + k; for (i = 0; i < l; i += pbpp , pptr++) { switch (pbpp) { case 1: /* 8-bit greyscale */ pptr->red = pptr->green = pptr->blue = pal[i]; break; case 2: /* 5:5:5 BGR */ pptr->blue = xlat5[pal[i] & 0x1F]; pptr->green = xlat5[(((pal[i + 1] << 8) + pal[i]) >> 5) & 0x1F]; pptr->red = xlat5[(pal[i + 1] >> 2) & 0x1F]; break; case 3: case 4: /* 8:8:8 BGR */ pptr->blue = pal[i + 0]; pptr->green = pal[i + 1]; pptr->red = pal[i + 2]; break; } } /* If palette is all we need */ res = 1; if ((settings->mode == FS_PALETTE_LOAD) || (settings->mode == FS_PALETTE_DEF)) goto fail; /* Assemble transparency table */ memset(trans, 255, 256); if (ptype == 15) { int i, n, tr; for (i = n = 0; i < j; i++) n += pal[i + i + 1] & 0x80; /* Assume the less frequent value is transparent */ tr = n >> 6 < j ? 0x80 : 0; for (i = 0; i < j; i++) { if ((pal[i + i + 1] & 0x80) == tr) trans[i + k] = 0; } } else if (ptype == 32) { for (i = 0; i < j; i++) trans[i + k] = pal[i * 4 + 3]; } else break; /* Cannot have transparent color at all */ /* If all alphas are identical, ignore them */ itrans = !is_filled(trans + k, trans[k], j); break; } case 2: /* RGB */ /* Options are very limited - and bugs abound. Presence or * absence of attribute bits can't be relied upon. */ switch (rbits) { case 16: /* 5:5:5 BGR or 5:6:5 BGR or 5:5:5:1 BGRA */ if (abits) goto fail; if (tga_565) { set_xlate(xlat6, 6); wmode = 4; break; } rbits = 15; /* Fallthrough */ case 15: /* 5:5:5 BGR or 5:5:5:1 BGRA */ if (abits > 1) goto fail; abits = 1; /* Here it's unreliable to uselessness */ wmode = 2; break; case 32: /* 8:8:8 BGR or 8:8:8:8 BGRA */ if (abits) goto fail; rbits = 24; abits = 8; wmode = 6; break; case 24: /* 8:8:8 BGR or 8:8:8:8 BGRA */ if (abits && (abits != 8)) goto fail; wmode = 6; break; default: goto fail; } break; case 3: /* Greyscale */ /* Not enough examples - easier to handle all possibilities */ /* Create palette */ settings->colors = rbits > 8 ? 256 : 1 << rbits; mem_bw_pal(settings->pal, 0, settings->colors - 1); break; } /* Prepare for reading bitfields */ i = abits > 8 ? abits - 8 : 0; abits -= i; i += rbits; ax = i >> 3; ashift = i & 7; amask = (1 << abits) - 1; i = rbits > 8 ? rbits - 8 : 0; rbits -= i; ix = i >> 3; ishift = i & 7; imask = (1 << rbits) - 1; /* Now read the footer if one is available */ fseek(fp, 0, SEEK_END); fl = ftell(fp); while (fl >= iofs + TGA_FSIZE) { fseek(fp, fl - TGA_FSIZE, SEEK_SET); k = fread(ftr, 1, TGA_FSIZE, fp); if (k < TGA_FSIZE) break; if (strcmp(ftr + TGA_SIGN, "TRUEVISION-XFILE.")) break; fofs = GET32(ftr + TGA_EXTOFS); if ((fofs > F_LONG_MAX - TGA_EXTSIZE - TGA_FSIZE) || (fofs < iofs) || (fofs + TGA_EXTSIZE + TGA_FSIZE > fl)) break; /* Invalid location */ fseek(fp, fofs, SEEK_SET); k = fread(ext, 1, TGA_EXTSIZE, fp); if ((k < TGA_EXTSIZE) || /* !!! 3D Studio writes 494 into this field */ (GET16(ext + TGA_EXTLEN) < TGA_EXTSIZE - 1)) break; /* Invalid size */ if ((ftype & 3) != 1) /* Premultiplied alpha? */ assoc_alpha = ext[TGA_ATYPE] == 4; /* Can believe alpha bits contain alpha if this field says so */ real_alpha |= assoc_alpha | (ext[TGA_ATYPE] == 3); break; } /* Allocate buffer and image */ settings->width = w = GET16(hdr + TGA_WIDTH); settings->height = h = GET16(hdr + TGA_HEIGHT); settings->bpp = bpp = (ftype & 3) == 2 ? 3 : 1; buflen = ibpp * w; if (rle && (w < 129)) buflen = ibpp * 129; buf = malloc(buflen + 1); /* One extra byte for bitparser */ res = FILE_MEM_ERROR; if (!buf) goto fail; if ((res = allocate_image(settings, abits ? CMASK_RGBA : CMASK_IMAGE))) goto fail2; /* Don't even try reading alpha if nowhere to store it */ if (abits && settings->img[CHN_ALPHA]) wmode |= 1; res = -1; if (!settings->silent) ls_init("TGA", 0); fseek(fp, iofs, SEEK_SET); /* Seek to data */ /* Prepare loops */ start = 0; xstep = 1; ystep = 0; if (hdr[TGA_DESC] & TGA_R2L) { /* Right-to-left */ start = w - 1; xstep = -1; ystep = 2 * w; } if (!(hdr[TGA_DESC] & TGA_T2B)) { /* Bottom-to-top */ start += (h - 1) * w; ystep -= 2 * w; } xstepb = xstep * bpp; res = FILE_LIB_ERROR; dest = settings->img[CHN_IMAGE] + start * bpp; dsta = settings->img[CHN_ALPHA] + start; y = ccnt = rcnt = 0; bstart = bstop = buf + buflen; strl = w; while (TRUE) { int j; j = bstop - bstart; if (j < ibpp) { if (bstop - buf < buflen) goto fail3; /* Truncated file */ memcpy(buf, bstart, j); j += fread(buf + j, 1, buflen - j, fp); bstop = (bstart = buf) + j; if (!rle) /* Uncompressed */ { if (j < buflen) goto fail3; /* Truncated file */ rcnt = w; /* "Copy block" a row long */ } } while (TRUE) { /* Read pixels */ if (rcnt) { int l, n; l = rcnt < strl ? rcnt : strl; if (j < ibpp * l) l = j / ibpp; rcnt -= l; strl -= l; while (l--) { switch (wmode) { case 1: /* Generic alpha */ *dsta = (((bstart[ax + 1] << 8) + bstart[ax]) >> ashift) & amask; case 0: /* Generic single channel */ *dest = (((bstart[ix + 1] << 8) + bstart[ix]) >> ishift) & imask; break; case 3: /* One-bit alpha for 16 bpp */ *dsta = bstart[1] >> 7; case 2: /* 5:5:5 BGR */ n = (bstart[1] << 8) + bstart[0]; dest[0] = xlat5[(n >> 10) & 0x1F]; dest[1] = xlat5[(n >> 5) & 0x1F]; dest[2] = xlat5[n & 0x1F]; break; case 5: /* Cannot happen */ case 4: /* 5:6:5 BGR */ n = (bstart[1] << 8) + bstart[0]; dest[0] = xlat5[n >> 11]; dest[1] = xlat6[(n >> 5) & 0x3F]; dest[2] = xlat5[n & 0x1F]; break; case 7: /* One-byte alpha for 32 bpp */ *dsta = bstart[3]; case 6: /* 8:8:8 BGR */ dest[0] = bstart[2]; dest[1] = bstart[1]; dest[2] = bstart[0]; break; } dest += xstepb; dsta += xstep; bstart += ibpp; } if (!strl || rcnt) break; /* Row end or buffer end */ } /* Copy pixels */ if (ccnt) { int i, l; l = ccnt < strl ? ccnt : strl; ccnt -= l; strl -= l; for (i = 0; i < l; i++ , dest += xstepb) { dest[0] = src[0]; if (bpp == 1) continue; dest[1] = src[1]; dest[2] = src[2]; } if (wmode & 1) memset(xstep < 0 ? dsta - l + 1 : dsta, *srca, l); dsta += xstep * l; if (!strl || ccnt) break; /* Row end or buffer end */ } /* Read block header */ j = bstop - bstart - 1; if (j < 0) break; /* Nothing in buffer */ rcnt = *bstart++; if (rcnt > 0x7F) /* Repeat block - one read + some copies */ { ccnt = rcnt & 0x7F; rcnt = 1; src = dest; srca = dsta; } else ++rcnt; /* Copy block - several reads */ } if (strl) continue; /* It was buffer end */ ls_progress(settings, y, 10); if (++y >= h) break; /* All done */ dest += ystep * bpp; if (dsta) dsta += ystep; strl = w; } /* Check if alpha channel is valid */ if (!real_alpha && settings->img[CHN_ALPHA]) delete_alpha(settings, settings->img[CHN_ALPHA][0]); /* Check if alpha in 16-bpp BGRA is inverse */ if (settings->img[CHN_ALPHA] && (wmode == 3) && !assoc_alpha) { unsigned char *timg, *talpha; int i, j = w * h, k = 0, l; timg = settings->img[CHN_IMAGE]; talpha = settings->img[CHN_ALPHA]; for (i = 0; i < j; i++) { l = 5; if (!(timg[0] | timg[1] | timg[2])) l = 1; else if ((timg[0] & timg[1] & timg[2]) == 255) l = 4; k |= l << talpha[i]; if (k == 0xF) break; /* Colors independent of alpha */ timg += 3; } /* If 0-covered parts more colorful than 1-covered, invert alpha */ if ((k & 5) > ((k >> 1) & 5)) { for (i = 0; i < j; i++) talpha[i] ^= 1; } } /* Rescale alpha */ if (settings->img[CHN_ALPHA] && (abits < 8)) extend_bytes(settings->img[CHN_ALPHA], w * h, (1 << abits) - 1); /* Unassociate alpha */ if (settings->img[CHN_ALPHA] && assoc_alpha && (abits > 1)) { mem_demultiply(settings->img[CHN_IMAGE], settings->img[CHN_ALPHA], w * h, bpp); } res = 0; /* Apply palette transparency */ if (itrans) res = palette_trans(settings, trans); if (!res) res = 1; fail3: if (!settings->silent) progress_end(); fail2: free(buf); fail: fclose(fp); return (res); } static int save_tga(char *file_name, ls_settings *settings) { unsigned char hdr[TGA_HSIZE], ftr[TGA_FSIZE], pal[256 * 4]; unsigned char *buf, *src, *srca, *dest; FILE *fp; int i, j, y0, y1, vstep, pcn, pbpp = 3; int w = settings->width, h = settings->height, bpp = settings->bpp; int rle = settings->tga_RLE; /* Indexed images not supposed to have alpha in TGA standard */ if ((bpp == 3) && settings->img[CHN_ALPHA]) bpp = 4; i = w * bpp; if (rle) i += i + (w >> 7) + 3; buf = malloc(i); if (!buf) return -1; if (!(fp = fopen(file_name, "wb"))) { free(buf); return -1; } /* Prepare header */ memset(hdr, 0, TGA_HSIZE); switch (bpp) { case 1: /* Indexed */ hdr[TGA_PALTYPE] = 1; hdr[TGA_IMGTYPE] = 1; PUT16(hdr + TGA_PALCOUNT, settings->colors); if ((settings->xpm_trans >= 0) && (settings->xpm_trans < settings->colors)) pbpp = 4; hdr[TGA_PALBITS] = pbpp * 8; break; case 4: /* RGBA */ hdr[TGA_DESC] = 8; case 3: /* RGB */ hdr[TGA_IMGTYPE] = 2; break; } hdr[TGA_BPP] = bpp * 8; PUT16(hdr + TGA_WIDTH, w); PUT16(hdr + TGA_HEIGHT, h); if (rle) hdr[TGA_IMGTYPE] |= 8; if (!tga_defdir) hdr[TGA_DESC] |= TGA_T2B; fwrite(hdr, 1, TGA_HSIZE, fp); /* Write palette */ if (bpp == 1) { dest = pal; for (i = 0; i < settings->colors; i++ , dest += pbpp) { dest[0] = settings->pal[i].blue; dest[1] = settings->pal[i].green; dest[2] = settings->pal[i].red; if (pbpp > 3) dest[3] = 255; } /* Mark transparent color */ if (pbpp > 3) pal[settings->xpm_trans * 4 + 3] = 0; fwrite(pal, 1, dest - pal, fp); } /* Write rows */ if (!settings->silent) ls_init("TGA", 1); if (tga_defdir) { y0 = h - 1; y1 = -1; vstep = -1; } else { y0 = 0; y1 = h; vstep = 1; } for (i = y0 , pcn = 0; i != y1; i += vstep , pcn++) { prepare_row(buf, settings, bpp, i); /* Fill uncompressed row */ src = buf; dest = buf + w * bpp; if (rle) /* Compress */ { unsigned char *tmp; int k, l; for (j = 1; j <= w; j++) { tmp = srca = src; src += bpp; /* Scan row for repeats */ for (; j < w; j++ , src += bpp) { switch (bpp) { case 4: if (src[3] != srca[3]) break; case 3: if (src[2] != srca[2]) break; case 2: if (src[1] != srca[1]) break; case 1: if (src[0] != srca[0]) break; default: continue; } /* Useful repeat? */ if (src - srca > bpp + 2) break; srca = src; } /* Avoid too-short repeats at row ends */ if (src - srca <= bpp + 2) srca = src; /* Create copy blocks */ for (k = (srca - tmp) / bpp; k > 0; k -= 128) { l = k > 128 ? 128 : k; *dest++ = l - 1; memcpy(dest, tmp, l *= bpp); dest += l; tmp += l; } /* Create repeat blocks */ for (k = (src - srca) / bpp; k > 0; k -= 128) { l = k > 128 ? 128 : k; *dest++ = l + 127; memcpy(dest, srca, bpp); dest += bpp; } } } fwrite(src, 1, dest - src, fp); ls_progress(settings, pcn, 20); } /* Write footer */ memcpy(ftr + TGA_SIGN, "TRUEVISION-XFILE.", TGA_FSIZE - TGA_SIGN); memset(ftr, 0, TGA_SIGN); fwrite(ftr, 1, TGA_FSIZE, fp); fclose(fp); if (!settings->silent) progress_end(); free(buf); return 0; } /* PCX header */ #define PCX_ID 0 /* 8b */ #define PCX_VER 1 /* 8b */ #define PCX_ENC 2 /* 8b */ #define PCX_BPP 3 /* 8b */ #define PCX_X0 4 /* 16b */ #define PCX_Y0 6 /* 16b */ #define PCX_X1 8 /* 16b */ #define PCX_Y1 10 /* 16b */ #define PCX_HDPI 12 /* 16b */ #define PCX_VDPI 14 /* 16b */ #define PCX_PAL 16 /* 8b*3*16 */ #define PCX_NPLANES 65 /* 8b */ #define PCX_LINELEN 66 /* 16b */ #define PCX_PALTYPE 68 /* 16b */ #define PCX_HRES 70 /* 16b */ #define PCX_VRES 72 /* 16b */ #define PCX_HSIZE 128 #define PCX_BUFSIZE 16384 /* Bytes read at a time */ /* Default EGA/VGA palette */ static const png_color def_pal[16] = { {0x00, 0x00, 0x00}, {0x00, 0x00, 0xAA}, {0x00, 0xAA, 0x00}, {0x00, 0xAA, 0xAA}, {0xAA, 0x00, 0x00}, {0xAA, 0x00, 0xAA}, {0xAA, 0x55, 0x00}, {0xAA, 0xAA, 0xAA}, {0x55, 0x55, 0x55}, {0x55, 0x55, 0xFF}, {0x55, 0xFF, 0x55}, {0x55, 0xFF, 0xFF}, {0xFF, 0x55, 0x55}, {0xFF, 0x55, 0xFF}, {0xFF, 0xFF, 0x55}, {0xFF, 0xFF, 0xFF}, }; static int load_pcx(char *file_name, ls_settings *settings) { static const unsigned char planarconfig[9] = { 0x11, /* BW */ 0x12, /* 4c */ 0x21, /* 4c */ 0x31, /* 8c */ 0x41, /* 16c */ 0x14, /* 16c */ 0x18, /* 256c */ 0x38, /* RGB */ 0x48 /* RGBA */ }; unsigned char hdr[PCX_HSIZE], pbuf[769]; unsigned char *buf, *row, *dest, *tmp; FILE *fp; int ver, bits, planes, ftype; int y, ccnt, bstart, bstop, strl, plane, cf; int w, h, cols, buflen, bpp = 3, res = -1; if (!(fp = fopen(file_name, "rb"))) return (-1); /* Read the header */ if (fread(hdr, 1, PCX_HSIZE, fp) < PCX_HSIZE) goto fail; /* PCX has no real signature - so check fields one by one */ if ((hdr[PCX_ID] != 10) || (hdr[PCX_ENC] > 1)) goto fail; ver = hdr[PCX_VER]; if (ver > 5) goto fail; bits = hdr[PCX_BPP]; planes = hdr[PCX_NPLANES]; if ((bits == 24) && (planes == 1)) ftype = 7; /* Single-plane RGB */ else if ((bits | planes) > 15) goto fail; else if ((tmp = memchr(planarconfig, (planes << 4) | bits, 9))) ftype = tmp - planarconfig; else goto fail; /* Prepare palette */ if (ftype < 7) { bpp = 1; settings->colors = cols = 1 << (bits * planes); /* BW (0 is black) */ if (cols == 2) { settings->pal[0] = def_pal[0]; settings->pal[1] = def_pal[15]; } /* Default 256-color palette - assumed greyscale */ else if ((ver == 3) && (cols == 256)) set_gray(settings); /* Default 16-color palette */ else if ((ver == 3) && (cols == 16)) memcpy(settings->pal, def_pal, sizeof(def_pal)); /* !!! CGA palette is evil: what the PCX spec describes is the way it * was handled by PC Paintbrush 3.0, while 4.0 was using an entirely * different, undocumented encoding for palette selection. * The only seemingly sane way to differentiate the two is to look at * paletteinfo field: zeroed in 3.0, set in 4.0+ - WJ */ else if (cols == 4) { /* Bits 2:1:0 in index: color burst:palette:intensity */ static const unsigned char cga_pals[8 * 3] = { 2, 4, 6, 10, 12, 14, 3, 5, 7, 11, 13, 15, 3, 4, 7, 11, 12, 15, 3, 4, 7, 11, 12, 15 }; int i, idx = hdr[PCX_PAL + 3] >> 5; // PB 3.0 if (GET16(hdr + PCX_PALTYPE)) // PB 4.0 { /* Pick green palette if G>B in slot 1 */ i = hdr[PCX_PAL + 5] >= hdr[PCX_PAL + 4]; /* Pick bright palette if max(G,B) > 200 */ idx = i * 2 + (hdr[PCX_PAL + 4 + i] > 200); } settings->pal[0] = def_pal[hdr[PCX_PAL] >> 4]; for (i = 1 , idx *= 3; i < 4; i++) settings->pal[i] = def_pal[cga_pals[idx++]]; } /* VGA palette - read from file */ else if (cols == 256) { if ((fseek(fp, -769, SEEK_END) < 0) || (fread(pbuf, 1, 769, fp) < 769) || (pbuf[0] != 0x0C)) goto fail; rgb2pal(settings->pal, pbuf + 1, 256); } /* 8 or 16 colors - read from header */ else rgb2pal(settings->pal, hdr + PCX_PAL, cols); /* If palette is all we need */ res = 1; if ((settings->mode == FS_PALETTE_LOAD) || (settings->mode == FS_PALETTE_DEF)) goto fail; } /* Allocate buffer and image */ settings->width = w = GET16(hdr + PCX_X1) - GET16(hdr + PCX_X0) + 1; settings->height = h = GET16(hdr + PCX_Y1) - GET16(hdr + PCX_Y0) + 1; settings->bpp = bpp; buflen = GET16(hdr + PCX_LINELEN); res = -1; if (buflen < ((w * bits + 7) >> 3)) goto fail; /* To accommodate bitparser's extra step */ buf = malloc(PCX_BUFSIZE + buflen + 1); res = FILE_MEM_ERROR; if (!buf) goto fail; row = buf + PCX_BUFSIZE; if ((res = allocate_image(settings, ftype > 7 ? CMASK_RGBA : CMASK_IMAGE))) goto fail2; /* Read and decode the file */ if (!settings->silent) ls_init("PCX", 0); res = FILE_LIB_ERROR; fseek(fp, PCX_HSIZE, SEEK_SET); dest = settings->img[CHN_IMAGE]; if (bits == 1) memset(dest, 0, w * h); // Write will be by OR y = plane = ccnt = 0; bstart = bstop = PCX_BUFSIZE; strl = buflen; cf = hdr[PCX_ENC] ? 0xC0 : 0x100; // Compressed, or not while (TRUE) { unsigned char v; /* Keep the buffer filled */ if (bstart >= bstop) { bstart -= bstop; bstop = fread(buf, 1, PCX_BUFSIZE, fp); if (bstop <= bstart) goto fail3; /* Truncated file */ } /* Decode data */ v = buf[bstart]; if (ccnt) /* Middle of a run */ { int l = strl < ccnt ? strl : ccnt; memset(row + buflen - strl, v, l); strl -= l; ccnt -= l; } else if (v >= cf) /* Start of a run */ { ccnt = v & 0x3F; bstart++; } else row[buflen - strl--] = v; bstart += !ccnt; if (strl) continue; /* Store a line */ if (bits == 1) // N planes of 1-bit data (MSB first) { unsigned char uninit_(v), *tmp = row; int i, n = 7 - plane; for (i = 0; i < w; i++ , v += v) { if (!(i & 7)) v = *tmp++; dest[i] |= (v & 0x80) >> n; } } else if (bits == 24) // 1 plane of RGB memcpy(dest, row, w * 3); else if (plane < 3) // BPP planes of 2/4/8-bit data (MSB first) stream_MSB(row, dest + plane, w, bits, 0, bits, bpp); else if (settings->img[CHN_ALPHA]) // 8-bit alpha plane memcpy(settings->img[CHN_ALPHA] + y * w, row, w); if (++plane >= planes) { ls_progress(settings, y, 10); if (++y >= h) break; dest += w * bpp; plane = 0; } strl = buflen; } res = 1; fail3: if (!settings->silent) progress_end(); fail2: free(buf); fail: fclose(fp); return (res); } static int save_pcx(char *file_name, ls_settings *settings) { unsigned char *buf, *src, *dest; FILE *fp; int w = settings->width, h = settings->height, bpp = settings->bpp; int i, l, plane, cnt; /* Allocate buffer */ i = w * 2; // Buffer one plane, with worst-case RLE expansion factor 2 if (i < PCX_HSIZE) i = PCX_HSIZE; if (i < 769) i = 769; // For palette buf = calloc(1, i); // Zeroing out is for header if (!buf) return (-1); if (!(fp = fopen(file_name, "wb"))) { free(buf); return (-1); } /* Prepare header */ memcpy(buf, "\x0A\x05\x01\x08", 4); // Version 5 PCX, 8 bits/plane PUT16(buf + PCX_X1, w - 1); PUT16(buf + PCX_Y1, h - 1); PUT16(buf + PCX_HDPI, 300); // GIMP sets DPI to this value PUT16(buf + PCX_VDPI, 300); buf[PCX_NPLANES] = bpp; PUT16(buf + PCX_LINELEN, w); buf[PCX_PALTYPE] = 1; fwrite(buf, 1, PCX_HSIZE, fp); /* Compress & write pixel rows */ if (!settings->silent) ls_init("PCX", 1); src = settings->img[CHN_IMAGE]; for (i = 0; i < h; i++ , src += w * bpp) { for (plane = 0; plane < bpp; plane++) { unsigned char v, *tmp = src + plane; dest = buf; cnt = 0; l = w; while (l > 0) { v = *tmp; tmp += bpp; cnt++; if ((--l <= 0) || (cnt == 0x3F) || (v != *tmp)) { if ((cnt > 1) || (v >= 0xC0)) *dest++ = cnt | 0xC0; *dest++ = v; cnt = 0; } } fwrite(buf, 1, dest - buf, fp); } ls_progress(settings, i, 20); } /* Write palette */ if (bpp == 1) { buf[0] = 0x0C; pal2rgb(buf + 1, settings->pal, settings->colors, 256); fwrite(buf, 1, 769, fp); } fclose(fp); if (!settings->silent) progress_end(); free(buf); return (0); } /* *** PREFACE *** * LBM format has no one definitive documentation source, nor a good testsuite, * and while I found enough examples of some types, other ones I never observed * in the wild remain unsupported. If you encounter some such curiosity failing * to load or loading wrong, send a bugreport with the file attached to it. */ /* Macros for IFF tags; big-endian too */ #define TAG4B_FORM TAG4B('F', 'O', 'R', 'M') #define TAG4B_ILBM TAG4B('I', 'L', 'B', 'M') #define TAG4B_PBM TAG4B('P', 'B', 'M', ' ') #define TAG4B_BMHD TAG4B('B', 'M', 'H', 'D') #define TAG4B_CMAP TAG4B('C', 'M', 'A', 'P') #define TAG4B_GRAB TAG4B('G', 'R', 'A', 'B') #define TAG4B_DEST TAG4B('D', 'E', 'S', 'T') #define TAG4B_CAMG TAG4B('C', 'A', 'M', 'G') #define TAG4B_BODY TAG4B('B', 'O', 'D', 'Y') /* Multipalette tags */ #define TAG4B_SHAM TAG4B('S', 'H', 'A', 'M') #define TAG4B_CTBL TAG4B('C', 'T', 'B', 'L') #define TAG4B_PCHG TAG4B('P', 'C', 'H', 'G') /* LBM header block (BMHD tag) */ #define BMHD_W 0 /* 16b */ #define BMHD_H 2 /* 16b */ #define BMHD_X0 4 /* 16b */ #define BMHD_Y0 6 /* 16b */ #define BMHD_BPP 8 /* 8b */ #define BMHD_MASK 9 /* 8b */ #define BMHD_COMP 10 /* 8b */ #define BMHD_PAD 11 /* 8b */ #define BMHD_TRAN 12 /* 16b */ #define BMHD_ASPX 14 /* 8b */ #define BMHD_ASPY 15 /* 8b */ #define BMHD_SCW 16 /* 16b */ #define BMHD_SCH 18 /* 16b */ #define BMHD_SIZE 20 /* LBM DEST block */ #define DEST_DEPTH 0 /* 8b */ #define DEST_PAD 1 /* 8b */ #define DEST_PICK 2 /* 16b */ #define DEST_ONOFF 4 /* 16b */ #define DEST_MASK 6 /* 16b */ #define DEST_SIZE 8 /* PCHG block header */ #define PCHG_COMPR 0 /* 16b */ #define PCHG_FLAGS 2 /* 16b */ #define PCHG_START 4 /* 16b */ #define PCHG_COUNT 6 /* 16b */ #define PCHG_CHLIN 8 /* 16b */ #define PCHG_MINR 10 /* 16b */ #define PCHG_MAXR 12 /* 16b */ #define PCHG_MAXCH 14 /* 16b */ #define PCHG_TOTCH 16 /* 32b */ #define PCHG_HSIZE 20 #define HAVE_BMHD 1 #define HAVE_CMAP 2 #define HAVE_GRAB 4 #define HAVE_DEST 8 static int load_lbm(char *file_name, ls_settings *settings) { static const unsigned char bitdepths[] = { 1, 2, 3, 4, 5, 6, 7, 8, 21, 24, 32 }; unsigned char hdr[BMHD_SIZE], dbuf[DEST_SIZE], pchdr[PCHG_HSIZE]; unsigned char pbuf[768], wbuf[256]; unsigned char *buf, *row, *dest, *mpp, *pr = NULL; FILE *fp; int y, ccnt, bstart, bstop, strl, np, ap, mp; f_long ctbl = 0, pchg = 0; unsigned tag, tl; int pstart = 0, ctbll = 0, pchgl = 0, pcnt = 0, sh2 = 0; int w, h, bpp, bits, mask, tbits, buflen, plen, half = 0, ham = 0; int pbm, palsize = 0, blocks = 0, hx = 0, hy = 0, res = -1; int i, j, l, p, pad, want_pal; if (!(fp = fopen(file_name, "rb"))) return (-1); /* Read the IFF header & check signature */ if (fread(wbuf, 1, 12, fp) < 12) goto fail; if (GET32B(wbuf) != TAG4B_FORM) goto fail; tag = GET32B(wbuf + 8); if (!(pbm = tag == TAG4B_PBM) && !(tag == TAG4B_ILBM)) goto fail; /* Read block headers & see what we get */ want_pal = (settings->mode == FS_PALETTE_LOAD) || (settings->mode == FS_PALETTE_DEF); while (fread(wbuf, 1, 8, fp) == 8) { tag = GET32B(wbuf); tl = GET32B(wbuf + 4); if (tl >= INT_MAX) break; // Sanity check pad = tl & 1; if (tag == TAG4B_BMHD) { if (tl != BMHD_SIZE) break; if (fread(hdr, 1, BMHD_SIZE, fp) != BMHD_SIZE) break; blocks |= HAVE_BMHD; continue; } else if (tag == TAG4B_CMAP) { /* Allow palette being too long */ palsize = tl > 768 ? 768 : tl; if (fread(pbuf, 1, palsize, fp) != palsize) break; blocks |= HAVE_CMAP; tl -= palsize; /* If palette is all we need; hope there's only one */ if (want_pal) { res = 1; break; } // Fallthrough } else if (tag == TAG4B_GRAB) { if ((tl != 4) || (fread(wbuf, 1, 4, fp) != 4)) break; blocks |= HAVE_GRAB; hx = GET16B(wbuf); hy = GET16B(wbuf + 2); continue; } else if (tag == TAG4B_DEST) { if (tl != DEST_SIZE) break; if (fread(dbuf, 1, DEST_SIZE, fp) != DEST_SIZE) break; blocks |= HAVE_DEST; continue; } else if (tag == TAG4B_CAMG) { if ((tl != 4) || (fread(wbuf, 1, 4, fp) != 4)) break; tag = GET32B(wbuf); half = tag & 0x80; ham = tag & 0x800; continue; } else if ((tag == TAG4B_SHAM) || (tag == TAG4B_CTBL)) { ctbl = ftell(fp); ctbll = tl; // SHAM has "version" word at the beginning if (tag == TAG4B_SHAM) { if (tl < 2) break; ctbl += 2 , ctbll -= 2; } } else if (tag == TAG4B_PCHG) { if ((tl < PCHG_HSIZE) || (fread(pchdr, 1, PCHG_HSIZE, fp) != PCHG_HSIZE)) break; pchg = ftell(fp); pchgl = tl -= PCHG_HSIZE; } else if (tag == TAG4B_BODY) { /* Palette & header must be before body */ if (!want_pal && (blocks & HAVE_BMHD)) res = 0; break; } /* Default: skip (the rest of) tag data */ tl += pad; if (tl && fseek(fp, tl, SEEK_CUR)) break; } if (res < 0) goto fail; /* Parse bitplanes */ tbits = !(blocks & HAVE_BMHD) ? 0 : // Palette may happen before header blocks & HAVE_DEST ? dbuf[DEST_DEPTH] : hdr[BMHD_BPP]; /* Prepare palette */ if (blocks & HAVE_CMAP) { /* Corrective multipliers to counteract dumb shift */ static const unsigned char mult[8] = { 128, 128, 130, 132, 136, 146, 170, 255 }; /* Limit palette to actual bitplanes */ l = palsize / 3; if (tbits && (tbits < 9)) { i = tbits; if (ham) i = i > 6 ? 6 : 4; else if (half && (i > 5)) i = 5; i = 1 << i; if (l > i) l = i; } /* Detect and correct palettes where 6..1-bit color was shifted * left by 2..7 without replicating high bits into low */ l *= 3; for (i = 0 , j = 0x80; i < l; i++) j |= pbuf[i]; for (i = 0; !(j & 1); i++) j >>= 1; for (j = mult[i] , i = 0; i < l; i++) pbuf[i] = (pbuf[i] * j) >> 7; /* Apply half-brite mode */ if (half && (l <= 32 * 3)) { memset(pbuf + l, 0, 32 * 3 - l); for (i = 0; i < l; i++) pbuf[i + 32 * 3] = pbuf[i] >> 1; l += 32 * 3; } /* Store the result */ rgb2pal(settings->pal, pbuf, settings->colors = l / 3); } if (want_pal) goto fail; /* Check sanity */ res = -1; if (hdr[BMHD_COMP] > 1) goto fail; // Unknown compression type bits = hdr[BMHD_BPP]; if (!memchr(bitdepths, bits, sizeof(bitdepths))) goto fail; if (ham) { if ((bits < 5) || (bits > 8)) goto fail; // No reason for grayscale HAM to exist if (!(blocks & HAVE_CMAP)) goto fail; ham = bits > 6 ? 6 : 4; // Shift value } if (ctbl) { h = GET16B(hdr + BMHD_H); sh2 = ctbll == (h >> 1) * 32; if (!sh2 && (ctbll != h * 32)) goto fail; // Size must match pchg = pchgl = 0; // If both present, simpler is better if (bits > (ham ? 6 : 4)) goto fail; } if (pchg) { /* No examples of anything but uncompressed 12-bit PCHG blocks, * so no reason to waste code supporting anything else */ if (GET16B(pchdr + PCHG_COMPR)) goto fail; if (GET16B(pchdr + PCHG_FLAGS) != 1) goto fail; if (bits > (half || ham ? 6 : 5)) goto fail; pstart = GET16B(pchdr + PCHG_START); pcnt = GET16B(pchdr + PCHG_COUNT); } mask = hdr[BMHD_MASK] == 1; if (pbm && (mask || ham || ctbl || pchg || (bits != 8))) goto fail; // Not compatible /* DEST block if any */ if (blocks & HAVE_DEST) { unsigned skip, setv, v; /* For simplicity, as no one ever saw files w/DEST anyway */ if ((tbits < bits) || (tbits > 8) || ham) goto fail; /* Make a lookup table for remapping bits after the fact; * ignore planeMask in hope it masks only planeOnOff */ skip = ((1 << tbits) - 1) & ~GET16B(dbuf + DEST_PICK); // Skipmask setv = skip & GET16B(dbuf + DEST_ONOFF); // Setmask for (v = i = 0; !(i >> bits); i++) { wbuf[i] = v | setv; v = (v + skip + 1) & ~skip; // Increment across gaps } } /* 21-bit RGB */ else if (bits == 21) { set_xlate(wbuf, 7); blocks |= HAVE_DEST; // !!! Let same xlate do either thing } /* Make greyscale palette if needed */ if ((tbits <= 8) && !(blocks & HAVE_CMAP)) mem_bw_pal(settings->pal, 0, (settings->colors = 1 << tbits) - 1); /* Transparent color - nearly always a glitch, rarely a real thing */ if (!lbm_untrans && (hdr[BMHD_MASK] > 1)) { j = GET16B(hdr + BMHD_TRAN); if (j < settings->colors) settings->xpm_trans = j; } if (blocks & HAVE_GRAB) settings->hot_x = hx , settings->hot_y = hy; /* Allocate buffer and image */ settings->width = w = GET16B(hdr + BMHD_W); settings->height = h = GET16B(hdr + BMHD_H); plen = ctbll + pchgl; settings->bpp = bpp = ham || plen || (bits > 8) ? 3 : 1; buflen = pbm ? w + (w & 1) : ((w + 15) >> 4) * 2 * (bits + mask); buf = multialloc(MA_ALIGN_DEFAULT, &buf, PCX_BUFSIZE, &row, buflen, &mpp, plen, NULL); res = FILE_MEM_ERROR; if (!buf) goto fail; i = bits == 32 ? CMASK_RGBA : CMASK_IMAGE; if (mask) i |= CMASK_FOR(lbm_mask); if ((res = allocate_image(settings, i))) goto fail2; if (!pbm) // Prepare for writes by OR { memset(settings->img[CHN_IMAGE], 0, w * h * bpp); if (settings->img[CHN_ALPHA]) memset(settings->img[CHN_ALPHA], 0, w * h); if ((i & ~CMASK_RGBA) && settings->img[lbm_mask]) memset(settings->img[lbm_mask], 0, w * h); } /* Load color change table if any */ if (plen) { f_long b = ftell(fp); if (fseek(fp, ctbl + pchg, SEEK_SET) || (fread(mpp, 1, plen, fp) != plen)) goto fail2; fseek(fp, b, SEEK_SET); if (!ham) ham = 8; // Use same decoding loop in mode 0 pr = mpp + ((pcnt + 31) >> 5) * 4; } /* Read and decode the file */ if (!settings->silent) ls_init("LBM", 0); res = FILE_LIB_ERROR; ap = bits > 24 ? 24 : -1; // First alpha plane if (!settings->img[CHN_ALPHA]) ap = -1; // No alpha mp = bits; // Mask plane if (!mask || !lbm_mask || !settings->img[lbm_mask] || ((lbm_mask == CHN_ALPHA) && (ap > 0))) mp = -1; np = mp > 0 ? bits + 1 : (ap > 0) || (bits < 24) ? bits : 24; // Planes to read y = ccnt = 0; if (!hdr[BMHD_COMP]) ccnt = buflen * h; // Uncompressed is file-sized copy run bstart = bstop = PCX_BUFSIZE; strl = buflen; while (TRUE) { /* Keep the buffer filled */ if (bstart >= bstop) { bstart -= bstop; bstop = fread(buf, 1, PCX_BUFSIZE, fp); if (bstop <= bstart) goto fail3; /* Truncated file */ } /* Decode data */ if (ccnt < 0) /* Middle of a repeat run */ { int l = strl + ccnt < 0 ? strl : -ccnt; memset(row + buflen - strl, buf[bstart], l); strl -= l; bstart += !(ccnt += l); } else if (ccnt > 0) /* Middle of a copy run */ { int l = strl < ccnt ? strl : ccnt; if (l > bstop - bstart) l = bstop - bstart; memcpy(row + buflen - strl, buf + bstart, l); strl -= l; ccnt -= l; bstart += l; } else /* Start of a run */ { ccnt = buf[bstart]; ccnt += ccnt < 128 ? 1 : -257; bstart++; } if (strl) continue; /* Store a line */ p = y * w; dest = settings->img[CHN_IMAGE] + p * bpp; if (pbm) memcpy(dest, row, w); while (!pbm) { unsigned char *dsta = NULL, *dstm = NULL; unsigned char uninit_(v), *tmp, *dp; int i, n, plane, step = bpp; if (ap > 0) dsta = settings->img[CHN_ALPHA] + p; if (mp > 0) dstm = settings->img[lbm_mask] + p; for (plane = 0; plane < np; plane++) { tmp = row + ((w + 15) >> 4) * 2 * plane; if (bits == 21) dp = dest + plane % 3 , n = 1 + plane / 3; else dp = dest + (plane >> 3) , n = 7 - (plane & 7); if (plane == mp) dp = dstm , step = 1; // Mask else if (plane >= 24) dp = dsta , step = 1; // Alpha if (!dp) continue; // Skipping alpha till mask for (i = 0; i < w; i++ , v += v , dp += step) { if (!(i & 7)) v = *tmp++; *dp |= (v & 0x80) >> n; } } if (!ham) break; /* Multipalette, simpler kind */ if (ctbl && !(y & sh2)) { unsigned char *dest = pbuf; for (i = 0; i < 16; i++ , pr += 2 , dest += 3) { int v = GET16B(pr); dest[0] = ((v >> 8) & 0xF) * 0x11; dest[1] = ((v >> 4) & 0xF) * 0x11; dest[2] = (v & 0xF) * 0x11; } } /* Multipalette, complex kind */ while (pchg && (y >= pstart) && (y < pstart + pcnt)) { unsigned char *dest; int n, n16, v, i, j; i = y - pstart; j = (i >> 5) * 4; if (!((GET32B(mpp + j) >> (~i & 0x1F)) & 1)) break; // Nothing to do for this line n16 = pr[1]; // Colors 16-31 for this many n = pr[0] + n16; // Total indices pr += 2; while (n-- > 0) { v = GET16B(pr); pr += 2; dest = pbuf + (n < n16) * 16 * 3 + (v >> 12) * 3; dest[0] = ((v >> 8) & 0xF) * 0x11; dest[1] = ((v >> 4) & 0xF) * 0x11; dest[2] = (v & 0xF) * 0x11; } if (half) for (i = 0; i < 32 * 3; i++) pbuf[i + 32 * 3] = pbuf[i] >> 1; break; } /* Recode the row */ /* !!! Start with palette color 0 as amigaos.net says and * GrafX2 does, not RGB 0 as ilbmtopnm does */ tmp = pbuf; dp = dest; for (i = 0; i < w; i++ , dp += 3) { n = (v = *dp) >> ham; if (!n) tmp = pbuf + v * 3; // Palette color dp[0] = tmp[0]; dp[1] = tmp[1]; dp[2] = tmp[2]; tmp = dp; if (!n) continue; v ^= n << ham; n ^= (n >> 1) ^ 3; // 0BRG -> RGB /* !!! In HAM8, preserve low 2 bits as Amiga docs * say and ilbmtopnm does; but in HAM6, put value * into lower & upper bits like GrafX2 and unlike * ilbmtopnm: those old Amigas did not HAVE any * color bits beyond the 4 */ dp[n] = ham == 4 ? v + (v << 4) : (v << 2) + (dp[n] & 3); } break; } ls_progress(settings, y, 10); if (++y >= h) break; strl = buflen; } res = 1; /* Finalize DEST or 21-bit */ if (blocks & HAVE_DEST) do_xlate(wbuf, settings->img[CHN_IMAGE], w * h * bpp); /* Finalize mask */ if (mp < 0); // No mask else if (is_filled(settings->img[lbm_mask], settings->img[lbm_mask][0], w * h)) deallocate_image(settings, CMASK_FOR(lbm_mask)); // Useless mask else { memset(wbuf + 1, 255, 255); // Nonzero means fully opaque wbuf[0] = 0; do_xlate(wbuf, settings->img[lbm_mask], w * h); } fail3: if (!settings->silent) progress_end(); fail2: free(buf); fail: fclose(fp); return (res); } static int save_lbm(char *file_name, ls_settings *settings) { unsigned char *buf, *wb, *src, *dest; FILE *fp; f_long bstart, fend; unsigned l; int w = settings->width, h = settings->height, bpp = settings->bpp; int pbm = settings->lbm_pbm && (bpp == 1), comp = !!settings->lbm_pack; int i, j, np1, rl, plane, st, cnt, np = 0, mask = 0; /* Count bitplanes */ if (!pbm) { mask = settings->img[lbm_mask] ? lbm_mask : 0; if (bpp == 1) // Planes to hold indexed color { i = settings->colors - 1; if (i > 15) np = 4 , i >>= 4; if (i > 3) np += 2 , i >>= 2; if (i > 1) np++ , i >>= 1; np += i; } else np = settings->img[CHN_ALPHA] ? 32 : 24; // RGBA/RGB if ((np == 32) && (mask == CHN_ALPHA)) mask = 0; // No need } /* Allocate buffer */ rl = pbm ? w + (w & 1) : ((w + 15) >> 4) * 2; // One plane i = rl + (rl + 127) / 128; // Worst-case RLE expansion if (!pbm) i *= np + !!mask; // Buffer all planes i += comp * rl; // Uncompressed source if (i < 8 + 768) i = 8 + 768; // For CMAP & header buf = calloc(1, i); // Zeroing out is for header if (!buf) return (-1); wb = buf + comp * rl; // Compressed data go here if (!(fp = fopen(file_name, "wb"))) { free(buf); return (-1); } /* Prepare header */ memcpy(buf, "FORM\0\0\0\0", 8); memcpy(buf + 8, pbm ? "PBM " : "ILBM", 4); memcpy(buf + 12, "BMHD", 4); PUT32B(buf + 16, BMHD_SIZE); PUT16B(buf + 20 + BMHD_W, w); PUT16B(buf + 20 + BMHD_H, h); buf[20 + BMHD_BPP] = pbm ? 8 : np; buf[20 + BMHD_MASK] = mask ? 1 : 0; buf[20 + BMHD_COMP] = comp; if (!mask && (settings->xpm_trans >= 0)) { buf[20 + BMHD_MASK] = 2; PUT16B(buf + 20 + BMHD_TRAN, settings->xpm_trans); } buf[20 + BMHD_ASPX] = buf[20 + BMHD_ASPY] = 1; /* Leave page size unset */ // PUT16B(buf + 20 + BMHD_W, w); // PUT16B(buf + 20 + BMHD_H, h); fwrite(buf, 1, 20 + BMHD_SIZE, fp); /* Palette (none for RGB/RGBA, to avoid confusing readers) */ if (bpp == 1) { memcpy(buf, "CMAP", 4); i = settings->colors * 3; i += i & 1; // Align the size itself, as in every example observed PUT32B(buf + 4, i); pal2rgb(buf + 8, settings->pal, settings->colors, 256); fwrite(buf, 1, 8 + i, fp); } /* Anchor point */ if ((settings->hot_x >= 0) && (settings->hot_y >= 0)) { memcpy(buf, "GRAB", 4); PUT32B(buf + 4, 4); PUT16B(buf + 8, settings->hot_x); PUT16B(buf + 10, settings->hot_y); fwrite(buf, 1, 8 + 4, fp); } /* Compress & write pixel rows */ if (!settings->silent) ls_init("LBM", 1); fwrite("BODY\0\0\0\0", 1, 8, fp); bstart = ftell(fp); np1 = np + (pbm || mask); // Total planes for (i = 0; i < h; i++) { src = settings->img[CHN_IMAGE] + w * bpp * i; dest = wb; for (plane = 0; plane < np1; plane++) { unsigned char v, *d, *s = src + (plane >> 3); int n = plane & 7, step = bpp; d = comp ? buf : dest; if (pbm) { /* Copy indexed row */ memcpy(d, src, w); d += w; } else { /* Extract a bitplane */ if (plane >= 24) // Alpha s = settings->img[CHN_ALPHA] + w * i , step = 1; if (plane == np) // Mask - threshold at 128 s = settings->img[mask] + w * i , step = 1 , n = 7; for (j = v = 0; j < w; j++ , s += step) { v |= ((*s >> n) & 1) << (~j & 7); if (~j & 7) continue; *d++ = v; v = 0; } if (w & 7) *d++ = v; } if ((d - buf) & 1) *d++ = 0; // Align if (!comp) { dest = d; continue; } /* Compress a bitplane */ #define FILL 1 #define EMIT 2 #define STOP 4 #define NFIL 8 s = buf; st = cnt = 0; while (TRUE) { if (d - s <= 0) st |= EMIT + STOP; else if (cnt == 128) st |= EMIT; else if (st & FILL) { if (s[0] != *(s - 1)) st = EMIT + FILL; } else if ((d - s > 1) && (s[0] == s[1])) { /* Code pairs as repeats only when NOT following * a copy block; code triples as repeats always */ if (!cnt || ((d - s > 2) && (s[0] == s[2]))) st = EMIT + NFIL; } if (!(st & EMIT)) { s++ , cnt++; continue; } if (st & FILL) { *dest++ = 257 - cnt; *dest++ = *(s - 1); } else if (cnt) { *dest++ = cnt - 1; memcpy(dest, s - cnt, cnt); dest += cnt; } if (st & STOP) break; if (st & NFIL) { s += cnt = 2; st = FILL; } else st = cnt = 0; } #undef FILL #undef EMIT #undef STOP #undef NFIL } fwrite(wb, 1, dest - wb, fp); ls_progress(settings, i, 20); } /* Align last block & write sizes */ fend = ftell(fp); l = fend - bstart; if (l & 1) fwrite("", 1, 1, fp); // Padding PUT32B(buf, l); fseek(fp, bstart - 4, SEEK_SET); fwrite(buf, 1, 4, fp); l = fend - 8; l += l & 1; // Aligned PUT32B(buf, l); fseek(fp, 4, SEEK_SET); fwrite(buf, 1, 4, fp); fclose(fp); if (!settings->silent) progress_end(); free(buf); return (0); } typedef void (*cvt_func)(unsigned char *dest, unsigned char *src, int len, int bpp, int step, int maxval); static void convert_16b(unsigned char *dest, unsigned char *src, int len, int bpp, int step, int maxval) { int i, v, m = maxval * 2; if (!(step -= bpp)) bpp *= len , len = 1; step *= 2; while (len-- > 0) { i = bpp; while (i--) { v = (src[0] << 8) + src[1]; src += 2; *dest++ = (v * (255 * 2) + maxval) / m; } src += step; } } static void copy_bytes(unsigned char *dest, unsigned char *src, int len, int bpp, int step) { int i, dd = 0; if (!(step -= bpp)) bpp *= len , len = 1; else if (step < 0) bpp -= dd = -step , step = 0; while (len-- > 0) { i = bpp; while (i--) *dest++ = *src++; src += step; dest += dd; } } static int check_next_pnm(FILE *fp, char id) { char buf[2]; if (fread(buf, 2, 1, fp)) { fseek(fp, -2, SEEK_CUR); if ((buf[0] == 'P') && (buf[1] == id)) return (FILE_HAS_FRAMES); } return (1); } /* Parse PAM header */ static char *pam_behead(memFILE *mf, int whdm[4]) { char wbuf[2048]; char *t1, *t2, *tail, *res = NULL; int i, n, l, flag = 0; /* Read header, check for basic PAM */ if (!mfgets(wbuf, sizeof(wbuf), mf) || strncmp(wbuf, "P7", 2)) return (NULL); while (TRUE) { if (!mfgets(wbuf, sizeof(wbuf), mf)) break; if (!wbuf[0] || (wbuf[0] == '#')) continue; // Empty line or comment t1 = wbuf + strspn(wbuf, WHITESPACE); l = strcspn(t1, WHITESPACE); t2 = t1 + l + strspn(t1 + l, WHITESPACE); t1[l] = '\0'; if (!strcmp(t1, "ENDHDR")) { if (flag < 0x0F) break; // Incomplete header return (res ? res : strdup("")); // TUPLTYPE is optional } if (!*t2) break; // There must be something but whitespace tail = t2 + strcspn(t2, WHITESPACE); if (!strcmp(t1, "TUPLTYPE")) { if (res) continue; // Only first value matters while (TRUE) { t1 = tail + strspn(tail, WHITESPACE); if (!*t1) break; tail = t1 + strcspn(t1, WHITESPACE); } // Preserve value for caller *tail = '\0'; res = strdup(t2); continue; } // Other fields are numeric *tail = '\0'; i = strtol(t2, &tail, 10); if (*tail) break; if (i < 1) break; // Must be at least 1 if (!strcmp(t1, "WIDTH")) n = 0; else if (!strcmp(t1, "HEIGHT")) n = 1; else if (!strcmp(t1, "DEPTH")) n = 2; else if (!strcmp(t1, "MAXVAL")) n = 3; else break; // Unknown IDs not allowed whdm[n] = i; n = 1 << n; if (flag & n) break; // No duplicate entries flag |= n; } free(res); return (NULL); } /* PAM loader does not support nonstandard types "GRAYSCALEFP" and "RGBFP", * because handling format variations which aren't found in the wild * is a waste of code - WJ */ static int load_pam_frame(FILE *fp, ls_settings *settings) { static const char *typenames[] = { "BLACKANDWHITE", "BLACKANDWHITE_ALPHA", "GRAYSCALE", "GRAYSCALE_ALPHA", "RGB", "RGB_ALPHA", "CMYK", "CMYK_ALPHA", NULL }; static const char depths[] = { 1, 2, 1, 2, 3, 4, 4, 5 }; memFILE fake_mf; cvt_func cvt_stream; char *t1; unsigned char *dest, *buf = NULL; int maxval, w, h, depth, ftype = -1; int i, j, ll, bpp, trans, vl, res, whdm[4]; /* Read header */ memset(&fake_mf, 0, sizeof(fake_mf)); fake_mf.file = fp; if (!(t1 = pam_behead(&fake_mf, whdm))) return (-1); /* Compare TUPLTYPE to list of known ones */ if (*t1) for (i = 0; typenames[i]; i++) { if (strcmp(t1, typenames[i])) continue; ftype = i; break; } free(t1); // No use anymore w = whdm[0]; h = whdm[1]; depth = whdm[2]; maxval = whdm[3]; /* Interpret unknown content as RGB or grayscale */ if (ftype < 0) ftype = depth >= 3 ? 4 : 2; /* Validate */ if ((depth < depths[ftype]) || (depth > 16) || (maxval > 65535)) return (-1); bpp = ftype < 4 ? 1 : 3; trans = ftype & 1; vl = maxval < 256 ? 1 : 2; ll = w * depth * vl; /* !!! ImageMagick writes BLACKANDWHITE as GRAYSCALE */ if ((ftype < 2) && (maxval > 1)) ftype += 2; if (ftype < 2) set_bw(settings); // BW else if (bpp == 1) set_gray(settings); // Grayscale /* Allocate row buffer if cannot read directly into image */ if (trans || (vl > 1) || (bpp != depth)) { buf = malloc(ll); if (!buf) return (FILE_MEM_ERROR); } /* Allocate image */ settings->width = w; settings->height = h; settings->bpp = bpp; res = allocate_image(settings, trans ? CMASK_RGBA : CMASK_IMAGE); if (res) goto fail; /* Read the image */ if (!settings->silent) ls_init("PAM", 0); res = FILE_LIB_ERROR; cvt_stream = vl > 1 ? convert_16b : (cvt_func)copy_bytes; for (i = 0; i < h; i++) { dest = buf ? buf : settings->img[CHN_IMAGE] + ll * i; j = fread(dest, 1, ll, fp); if (j < ll) goto fail2; ls_progress(settings, i, 10); if (!buf) continue; // Nothing else to do here if (settings->img[CHN_ALPHA]) // Have alpha - parse it { cvt_stream(settings->img[CHN_ALPHA] + w * i, buf + depths[ftype] * vl - vl, w, 1, depth, maxval); } dest = settings->img[CHN_IMAGE] + w * bpp * i; if (ftype >= 6) // CMYK { cvt_stream(buf, buf, w, 4, depth, maxval); if (maxval < 255) extend_bytes(buf, w * 4, maxval); cmyk2rgb(dest, buf, w, FALSE, settings); } else cvt_stream(dest, buf, w, bpp, depth, maxval); } /* Check for next frame */ res = check_next_pnm(fp, '7'); fail2: if (maxval < 255) // Extend what we've read { j = w * h; if (settings->img[CHN_ALPHA]) extend_bytes(settings->img[CHN_ALPHA], j, maxval); j *= bpp; dest = settings->img[CHN_IMAGE]; if (ftype >= 6); // CMYK is done already else if (ftype > 1) extend_bytes(dest, j, maxval); else // Convert BW from 1-is-white to 1-is-black { for (i = 0; i < j; i++ , dest++) *dest = !*dest; } } if (!settings->silent) progress_end(); fail: free(buf); return (res); } #define PNM_BUFSIZE 4096 typedef struct { FILE *f; int ptr, end, eof, comment; char buf[PNM_BUFSIZE + 2]; } pnmbuf; /* What PBM documentation says is NOT what Netpbm actually does; skipping a * comment in file header, it does not consume the newline after it - WJ */ static void pnm_skip_comment(pnmbuf *pnm) { pnm->comment = !pnm->buf[pnm->ptr += strcspn(pnm->buf + pnm->ptr, "\r\n")]; } static char *pnm_gets(pnmbuf *pnm, int data) { int k, l; while (TRUE) { while (pnm->ptr < pnm->end) { l = pnm->ptr + strspn(pnm->buf + pnm->ptr, WHITESPACE); if (pnm->buf[l] == '#') { if (data) return (NULL); pnm->ptr = l; pnm_skip_comment(pnm); continue; } k = l + strcspn(pnm->buf + l, WHITESPACE "#"); if (pnm->buf[k] || pnm->eof) { pnm->ptr = k + 1; if (pnm->buf[k] == '#') { if (data) return (NULL); pnm_skip_comment(pnm); } pnm->buf[k] = '\0'; return (pnm->buf + l); } memmove(pnm->buf, pnm->buf + l, pnm->end -= l); pnm->ptr = 0; break; } if (pnm->eof) return (NULL); if (pnm->ptr >= pnm->end) pnm->ptr = pnm->end = 0; l = PNM_BUFSIZE - pnm->end; if (l <= 0) return (NULL); // A "token" of 4096 chars means failure pnm->end += k = fread(pnm->buf + pnm->end, 1, l, pnm->f); pnm->eof = k < l; if (pnm->comment) pnm_skip_comment(pnm); } } static int pnm_endhdr(pnmbuf *pnm, int plain) { while (pnm->comment) { pnm_skip_comment(pnm); if (!pnm->comment) break; if (pnm->eof) return (FALSE); pnm->end = fread(pnm->buf, 1, PNM_BUFSIZE, pnm->f); pnm->eof = pnm->end < PNM_BUFSIZE; } /* Last whitespace in header already got consumed while parsing */ /* Buffer will remain in use in plain mode */ if (!plain && (pnm->ptr < pnm->end)) fseek(pnm->f, pnm->ptr - pnm->end, SEEK_CUR); return (TRUE); } static int load_pnm_frame(FILE *fp, ls_settings *settings) { pnmbuf pnm; char *s, *tail; unsigned char *dest; int i, l, m, w, h, bpp, maxval, plain, mode, fid, res; /* Identify*/ memset(&pnm, 0, sizeof(pnm)); pnm.f = fp; fid = settings->ftype == FT_PBM ? 0 : settings->ftype == FT_PGM ? 1 : 2; if (!(s = pnm_gets(&pnm, FALSE))) return (-1); if ((s[0] != 'P') || ((s[1] != fid + '1') && (s[1] != fid + '4'))) return (-1); plain = s[1] < '4'; /* Read header */ if (!(s = pnm_gets(&pnm, FALSE))) return (-1); w = strtol(s, &tail, 10); if (*tail) return (-1); if (!(s = pnm_gets(&pnm, FALSE))) return (-1); h = strtol(s, &tail, 10); if (*tail) return (-1); bpp = maxval = 1; if (settings->ftype == FT_PBM) set_bw(settings); else { if (!(s = pnm_gets(&pnm, FALSE))) return (-1); maxval = strtol(s, &tail, 10); if (*tail) return (-1); if ((maxval <= 0) || (maxval > 65535)) return (-1); if (settings->ftype == FT_PGM) set_gray(settings); else bpp = 3; } if (!pnm_endhdr(&pnm, plain)) return (-1); /* Store values */ settings->width = w; settings->height = h; settings->bpp = bpp; /* Allocate image */ if ((res = allocate_image(settings, CMASK_IMAGE))) return (res); /* Now, read the image */ mode = settings->ftype == FT_PBM ? plain /* 0 and 1 */ : plain ? 2 : maxval < 255 ? 3 : maxval > 255 ? 4 : 5; s = ""; if (!settings->silent) ls_init("PNM", 0); res = FILE_LIB_ERROR; l = w * bpp; m = maxval * 2; for (i = 0; i < h; i++) { dest = settings->img[CHN_IMAGE] + l * i; switch (mode) { case 0: /* Raw packed bits */ { #if PNM_BUFSIZE * 8 < MAX_WIDTH #error "Buffer too small to read PBM row all at once" #endif int i, j, k; unsigned char *tp = pnm.buf; k = (w + 7) >> 3; j = fread(tp, 1, k, fp); for (i = 0; i < w; i++) *dest++ = (tp[i >> 3] >> (~i & 7)) & 1; if (j < k) goto fail2; break; } case 3: /* Raw byte values - extend later */ case 5: /* Raw 0..255 values - trivial */ if (fread(dest, 1, l, fp) < l) goto fail2; break; case 1: /* Chars "0" and "1" */ { int i; unsigned char ch; for (i = 0; i < l; i++) { if (!s[0] && !(s = pnm_gets(&pnm, TRUE))) goto fail2; ch = *s++ - '0'; if (ch > 1) goto fail2; *dest++ = ch; } break; } case 2: /* Integers in ASCII */ { int i, n; for (i = 0; i < l; i++) { if (!(s = pnm_gets(&pnm, TRUE))) goto fail2; n = strtol(s, &tail, 10); if (*tail) goto fail2; if ((n < 0) || (n > maxval)) goto fail2; n = (n * (255 * 2) + maxval) / m; *dest++ = n; } break; } case 4: /* Raw ushorts in MSB order */ { int i, j, k, ll; for (ll = l * 2; ll > 0; ll -= k) { k = PNM_BUFSIZE < ll ? PNM_BUFSIZE : ll; j = fread(pnm.buf, 1, k, fp); i = j >> 1; convert_16b(dest, pnm.buf, i, 1, 1, maxval); dest += i; if (j < k) goto fail2; } break; } } ls_progress(settings, i, 10); } res = 1; /* Check for next frame */ if (!plain) res = check_next_pnm(fp, fid + '4'); fail2: if (mode == 3) // Extend what we've read extend_bytes(settings->img[CHN_IMAGE], l * h, maxval); if (!settings->silent) progress_end(); return (res); } static int load_pnm_frames(char *file_name, ani_settings *ani) { FILE *fp; ls_settings w_set; int res, is_pam = ani->settings.ftype == FT_PAM, next = TRUE; if (!(fp = fopen(file_name, "rb"))) return (-1); while (next) { res = FILE_TOO_LONG; if (!check_next_frame(&ani->fset, ani->settings.mode, FALSE)) goto fail; w_set = ani->settings; w_set.gif_delay = -1; // Multipage res = (is_pam ? load_pam_frame : load_pnm_frame)(fp, &w_set); next = res == FILE_HAS_FRAMES; if ((res != 1) && !next) goto fail; res = process_page_frame(file_name, ani, &w_set); if (res) goto fail; } res = 1; fail: fclose(fp); return (res); } static int load_pnm(char *file_name, ls_settings *settings) { FILE *fp; int res; if (!(fp = fopen(file_name, "rb"))) return (-1); res = (settings->ftype == FT_PAM ? load_pam_frame : load_pnm_frame)(fp, settings); fclose(fp); return (res); } static int save_pbm(char *file_name, ls_settings *settings) { unsigned char buf[MAX_WIDTH / 8], bw, *src; FILE *fp; int i, l, w = settings->width, h = settings->height; if ((settings->bpp != 1) || (settings->colors > 2)) return WRONG_FORMAT; if (!(fp = fopen(file_name, "wb"))) return (-1); if (!settings->silent) ls_init("PBM", 1); fprintf(fp, "P4\n%d %d\n", w, h); bw = get_bw(settings); /* Write rows */ src = settings->img[CHN_IMAGE]; l = (w + 7) >> 3; for (i = 0; i < h; i++) { pack_MSB(buf, src, w, bw); src += w; fwrite(buf, l, 1, fp); ls_progress(settings, i, 20); } fclose(fp); if (!settings->silent) progress_end(); return (0); } static int save_ppm(char *file_name, ls_settings *settings) { FILE *fp; int i, l, m, w = settings->width, h = settings->height; if (settings->bpp != 3) return WRONG_FORMAT; if (!(fp = fopen(file_name, "wb"))) return (-1); if (!settings->silent) ls_init("PPM", 1); fprintf(fp, "P6\n%d %d\n255\n", w, h); /* Write rows */ m = (l = w * 3) * h; // Write entire file at once if no progressbar if (settings->silent) l = m; for (i = 0; m > 0; m -= l , i++) { fwrite(settings->img[CHN_IMAGE] + l * i, l, 1, fp); ls_progress(settings, i, 20); } fclose(fp); if (!settings->silent) progress_end(); return (0); } static int save_pam(char *file_name, ls_settings *settings) { unsigned char xv, xa, *dest, *src, *srca, *buf = NULL; FILE *fp; int ibpp = settings->bpp, w = settings->width, h = settings->height; int i, j, bpp; if ((ibpp != 3) && (settings->colors > 2)) return WRONG_FORMAT; bpp = ibpp + !!settings->img[CHN_ALPHA]; /* For BW: image XOR 1 if white is 0, alpha AND 1 */ xv = 0; xa = 255; if (ibpp == 1) xv = get_bw(settings) , xa = 1; if (bpp != 3) // BW needs inversion, and alpha, interlacing { buf = malloc(w * bpp); if (!buf) return (-1); } if (!(fp = fopen(file_name, "wb"))) { free(buf); return (-1); } if (!settings->silent) ls_init("PAM", 1); fprintf(fp, "P7\nWIDTH %d\nHEIGHT %d\nDEPTH %d\nMAXVAL %d\n" "TUPLTYPE %s%s\nENDHDR\n", w, h, bpp, ibpp == 1 ? 1 : 255, ibpp == 1 ? "BLACKANDWHITE" : "RGB", bpp > ibpp ? "_ALPHA" : ""); for (i = 0; i < h; i++) { src = settings->img[CHN_IMAGE] + i * w * ibpp; if ((dest = buf)) { srca = NULL; if (settings->img[CHN_ALPHA]) srca = settings->img[CHN_ALPHA] + i * w; for (j = 0; j < w; j++) { *dest++ = *src++ ^ xv; if (ibpp > 1) { *dest++ = *src++; *dest++ = *src++; } if (srca) *dest++ = *srca++ & xa; } src = buf; } fwrite(src, 1, w * bpp, fp); ls_progress(settings, i, 20); } fclose(fp); if (!settings->silent) progress_end(); free(buf); return (0); } /* *** PREFACE *** * PMM is mtPaint's own format, extending the PAM format in a compatible way; * PAM tools from Netpbm can easily split a PMM file into regular PAM files, or * build it back from these. Some extra values are stored inside the "TUPLTYPE" * fields, because Netpbm tools do NOT preserve comments but don't much care * about TUPLTYPE. Other things, like palette, are stored as separate * pseudo-images preceding the bitmap, with their own TUPLTYPE and extra values. * When building a PMM file out of PAMs by hand, just write out the PMM_ID1 * string, below, before the first PAM file - WJ */ # define PMM_ID1 "P7\n#MTPAINT#" typedef struct { char *next; // the rest of string char *tag; // last found tag int val; // its value if any } tagline; /* Parse a tag out of string */ static int nexttag(tagline *iter, int split_under) { char *s, *tail, *str = iter->next; int l, n, res = 1; iter->tag = str; if (!str || !*str) return (0); // Empty l = strcspn(str, "_=" WHITESPACE + !split_under); if (!l) return (0); // No tag here - format violation s = str + l; if (*s == '=') /* NAME=VALUE */ { n = strtol(++s, &tail, 10); if ((tail == s) || (*tail && !strchr(WHITESPACE, *tail))) return (0); // Unparsable or no value - format violation iter->val = n; s = tail; res = 2; // Have value } else s += (*s == '_'); /* NAME_ */ iter->next = s + strspn(s, WHITESPACE); str[l] = '\0'; return (res); // Parsed another tag } /* Interpret known value tags, ignore unknown ones */ static void readtags(tagline *tl, ls_settings *settings, int bpp) { static const char *tags[] = { "TRANS", "DELAY", "X", "Y", NULL }; int j, i = 2; // Skip channel tags if no extra channels if (!bpp) while ((i = nexttag(tl, FALSE)) == 1); while (i == 2) { for (j = 0; tags[j] && strcmp(tl->tag, tags[j]); j++); i = tl->val; switch (j) { case 0: // Transparent color /* Invalid value - ignore */ if (i < -1) break; /* No transparency - disable */ if (i == -1) settings->xpm_trans = settings->rgb_trans = -1; /* Indexed transparency */ else if (bpp < 3) { if (i < settings->colors) settings->xpm_trans = i; } /* RGB transparency */ else if (i <= 0xFFFFFF) { int j = settings->xpm_trans; png_color *p = settings->pal + j; // Only if differs from indexed if ((j < 0) || (PNG_2_INT(*p) != i)) settings->rgb_trans = i; } break; case 1: // Anim delay, in 0.01 sec if (i >= 0) settings->gif_delay = i; break; case 2: // X offset settings->x = i; break; case 3: // Y offset settings->y = i; break; // !!! No other parameters yet } i = nexttag(tl, FALSE); } } static int load_pmm_frame(memFILE *mf, ls_settings *settings) { /* !!! INDEXED is at index 1, RGB at index 3 to use index as BPP */ static const char *blocks[] = { "TAGS", "INDEXED", "PALETTE", "RGB", NULL }; tagline tl; unsigned char *dest, *buf = NULL; char *ttype = NULL; int w, h, depth, rgbpp, cmask = CMASK_IMAGE; int i, j, l, res, whdm[4], slots[NUM_CHANNELS]; while (TRUE) { res = -1; free(ttype); if (!(tl.next = ttype = pam_behead(mf, whdm))) break; if (whdm[3] > 255) break; // 16-bit values not allowed depth = whdm[2]; if (depth > 16) break; // Depth limited to sane values w = whdm[0]; h = whdm[1]; /* Parse out type tag */ j = -1; if (nexttag(&tl, TRUE) == 1) { for (j = 0; blocks[j] && strcmp(blocks[j], tl.tag); j++); if (!blocks[j]) j = -1; } if (!j) readtags(&tl, settings, 0); /* TAGS */ if (j <= 0) /* !!! IGNORE anything unrecognized & skip "TAGS" */ { mfseek(mf, w * h * depth, SEEK_CUR); continue; } if (j == 2) /* PALETTE */ { unsigned char pbuf[256 * 16], *tp = pbuf; /* Validate */ if ((depth < 3) || (w < 2) || (w > 256) || (h != 1)) break; settings->colors = w; settings->xpm_trans = settings->rgb_trans = -1; // Default /* Skip channel tags, interpret value tags */ readtags(&tl, settings, 0); if (mfread(pbuf, depth, w, mf) != w) break; // Failed /* Store palette */ extend_bytes(tp, w * depth, whdm[3]); for (i = 0; i < w; i++) { settings->pal[i].red = tp[0]; settings->pal[i].green = tp[1]; settings->pal[i].blue = tp[2]; tp += depth; } /* If palette is all we need */ res = EXPLODE_FAILED; if ((settings->mode == FS_PALETTE_LOAD) || (settings->mode == FS_PALETTE_DEF)) break; continue; } /* Got an image bitmap */ // !!! Only slots 1 & 3 fall through to here rgbpp = j; /* Add up extra channels */ memset(slots, 0, sizeof(slots)); while ((i = nexttag(&tl, FALSE)) == 1) { if (!strcmp(tl.tag, "ALPHA")) i = CHN_ALPHA; else if (!strcmp(tl.tag, "SELECTION")) i = CHN_SEL; else if (!strcmp(tl.tag, "MASK")) i = CHN_MASK; else // Unknown channel - skip { j++; continue; } slots[i] = j++; cmask |= CMASK_FOR(i); } if (j > depth) break; // Cannot be /* Interpret value tags */ if (i == 2) readtags(&tl, settings, rgbpp); l = w * depth; /* Allocate row buffer if cannot read directly into image */ if (rgbpp != depth) { res = FILE_MEM_ERROR; if (!(buf = malloc(l))) break; } /* Allocate image */ settings->width = w; settings->height = h; settings->bpp = rgbpp; if ((res = allocate_image(settings, cmask))) break; /* Read the image */ if (!settings->silent) ls_init("* PMM *", 0); res = FILE_LIB_ERROR; for (i = 0; i < h; i++) { dest = settings->img[CHN_IMAGE] + w * rgbpp * i; if (!mfread(buf ? buf : dest, l, 1, mf)) goto fail; ls_progress(settings, i, 10); if (!buf) continue; // Nothing else to do here copy_bytes(dest, buf, w, rgbpp, depth); for (j = CHN_ALPHA; j < NUM_CHANNELS; j++) if (settings->img[j]) copy_bytes( settings->img[j] + w * i, buf + slots[j], w, 1, depth); } /* Extend what we've read */ if (whdm[3] < 255) { i = w * h * rgbpp; for (j = CHN_IMAGE; j < NUM_CHANNELS; j++) { if (settings->img[j]) extend_bytes( settings->img[j], i, whdm[3]); i = w * h; } } /* Check for next frame */ res = 1; if (mfread(ttype, 2, 1, mf)) // it was no shorter than "RGB" { mfseek(mf, -2, SEEK_CUR); if (!strncmp(ttype, "P7", 2)) res = FILE_HAS_FRAMES; } fail: if (!settings->silent) progress_end(); break; } free(buf); free(ttype); return (res); } static int load_pmm_frames(char *file_name, ani_settings *ani, memFILE *mf) { memFILE fake_mf; FILE *fp = NULL; ls_settings w_set, init_set; int res, next; if (!mf) { if (!(fp = fopen(file_name, "rb"))) return (-1); memset(mf = &fake_mf, 0, sizeof(fake_mf)); fake_mf.file = fp; } init_set = ani->settings; init_set.gif_delay = -1; // Multipage by default while (TRUE) { w_set = init_set; res = load_pmm_frame(mf, &w_set); next = res == FILE_HAS_FRAMES; if ((res != 1) && !next) break; /* !!! RGB transparency may modify the palette */ map_rgb_trans(&w_set); if ((res = process_page_frame(file_name, ani, &w_set))) break; res = 1; if (!next) break; res = FILE_TOO_LONG; if (!check_next_frame(&ani->fset, ani->settings.mode, w_set.gif_delay >= 0)) break; /* Update initial values */ init_set.colors = w_set.colors; // Palettes are inheritable init_set.xpm_trans = w_set.xpm_trans; init_set.rgb_trans = w_set.rgb_trans; init_set.gif_delay = w_set.gif_delay; } fclose(fp); return (res); } static int load_pmm(char *file_name, ls_settings *settings, memFILE *mf) { memFILE fake_mf; FILE *fp = NULL; int res; if (!mf) { if (!(fp = fopen(file_name, "rb"))) return (-1); memset(mf = &fake_mf, 0, sizeof(fake_mf)); fake_mf.file = fp; } res = load_pmm_frame(mf, settings); if (fp) fclose(fp); return (res); } static int save_pmm(char *file_name, ls_settings *settings, memFILE *mf) { unsigned char *dest, *src, *buf = NULL; unsigned char sbuf[768]; memFILE fake_mf; FILE *fp = NULL; int rgbpp = settings->bpp, w = settings->width, h = settings->height; int i, k, bpp; for (i = bpp = 0; i < NUM_CHANNELS; i++) bpp += !!settings->img[i]; bpp += rgbpp - 1; /* Allocate row buffer if needed */ if ((bpp != rgbpp) && (settings->mode != FS_PALETTE_SAVE)) { buf = malloc(w * bpp); if (!buf) return (-1); } if (!mf) { if (!(fp = fopen(file_name, "wb"))) { free(buf); return (-1); } memset(mf = &fake_mf, 0, sizeof(fake_mf)); fake_mf.file = fp; } if (!settings->silent) ls_init("* PMM *", 1); /* First, write palette */ if (settings->pal) { mfputs(PMM_ID1 "\n", mf); snprintf(sbuf, sizeof(sbuf), "WIDTH %d\n", settings->colors); mfputs(sbuf, mf); // Extra data for palette: transparent index if any sbuf[0] = '\0'; if (settings->xpm_trans >= 0) snprintf(sbuf, sizeof(sbuf), " TRANS=%d", settings->xpm_trans); mfputss(mf, "HEIGHT 1\nDEPTH 3\nMAXVAL 255\nTUPLTYPE PALETTE", sbuf, "\nENDHDR\n", NULL); pal2rgb(sbuf, settings->pal, settings->colors, 0); mfwrite(sbuf, 1, settings->colors * 3, mf); } /* All done if only writing palette */ if (settings->mode == FS_PALETTE_SAVE) goto done; /* Now, write image bitmap */ mfputs(PMM_ID1 "\n", mf); snprintf(sbuf, sizeof(sbuf), "WIDTH %d\nHEIGHT %d\nDEPTH %d\n", w, h, bpp); mfputss(mf, sbuf, "MAXVAL 255\nTUPLTYPE ", rgbpp > 1 ? "RGB" : "INDEXED", settings->img[CHN_ALPHA] ? "_ALPHA" : "", settings->img[CHN_SEL] ? " SELECTION" : "", settings->img[CHN_MASK] ? " MASK" : "", "\nENDHDR\n", NULL); for (i = 0; i < h; i++) { src = settings->img[CHN_IMAGE] + i * w * rgbpp; if ((dest = buf)) { copy_bytes(dest, src, w, bpp, rgbpp); dest += rgbpp; for (k = CHN_ALPHA; k < NUM_CHANNELS; k++) if (settings->img[k]) copy_bytes(dest++, settings->img[k] + i * w, w, bpp, 1); src = buf; } mfwrite(src, 1, w * bpp, mf); ls_progress(settings, i, 20); } done: if (fp) fclose(fp); if (!settings->silent) progress_end(); free(buf); return 0; } /* Put screenshots and X pixmaps on an equal footing with regular files */ #ifdef HAVE_PIXMAPS static int save_pixmap(ls_settings *settings, memFILE *mf) { pixmap_info p; unsigned char *src, *dest, *sel, *buf = NULL; int i, j, l, w = settings->width, h = settings->height; /* !!! Pixmap export used only for FS_CLIPBOARD, where the case of * selection without alpha is already prevented */ if ((settings->bpp == 1) || settings->img[CHN_ALPHA]) { buf = malloc(w * 3); if (!buf) return (-1); } if (!export_pixmap(&p, w, h)) { free(buf); return (-1); } /* Plain RGB - copy it whole */ if (!buf) pixmap_put_rows(&p, settings->img[CHN_IMAGE], 0, h); /* Something else - render & copy row by row */ else { l = w * settings->bpp; for (i = 0; i < h; i++) { src = settings->img[CHN_IMAGE] + l * i; if (settings->bpp == 3) memcpy(buf, src, l); else do_convert_rgb(0, 1, w, buf, src, settings->pal); /* There is no way to send alpha to XPaint, so I use * alpha (and selection if any) to blend image with * white and send the result - WJ */ if (settings->img[CHN_ALPHA]) { src = settings->img[CHN_ALPHA] + w * i; sel = settings->img[CHN_SEL] ? settings->img[CHN_SEL] + w * i : NULL; dest = buf; for (j = 0; j < w; j++) { int ii, jj, k = *src++; if (sel) { k *= *sel++; k = (k + (k >> 8) + 1) >> 8; } for (ii = 0; ii < 3; ii++) { jj = 255 * 255 + (*dest - 255) * k; *dest++ = (jj + (jj >> 8) + 1) >> 8; } } } pixmap_put_rows(&p, buf, i, 1); } free(buf); } *(XID_type *)mf->m.buf = p.xid; mf->top = sizeof(XID_type); return (0); } #else /* Pixmap export fails by definition in absence of X */ #define save_pixmap(A,B) (-1) #endif static int load_pixmap(ls_settings *settings, memFILE *mf) { pixmap_info p; int res = -1; if (import_pixmap(&p, mf ? (void *)mf->m.buf : NULL)) // !mf == screenshot { settings->width = p.w; settings->height = p.h; settings->bpp = 3; res = allocate_image(settings, CMASK_IMAGE); if (!res) res = pixmap_get_rows(&p, settings->img[CHN_IMAGE], 0, p.h) ? 1 : -1; drop_pixmap(&p); } return (res); } /* Handle SVG import using gdk-pixbuf */ #if (GDK_PIXBUF_MAJOR > 2) || ((GDK_PIXBUF_MAJOR == 2) && (GDK_PIXBUF_MINOR >= 4)) #define MAY_HANDLE_SVG static int svg_check = -1; static int svg_supported() { GSList *tmp, *ff; int i, res = FALSE; ff = gdk_pixbuf_get_formats(); for (tmp = ff; tmp; tmp = tmp->next) { gchar **mime = gdk_pixbuf_format_get_mime_types(tmp->data); for (i = 0; mime[i]; i++) { res |= strstr(mime[i], "image/svg") == mime[i]; } g_strfreev(mime); if (res) break; } g_slist_free(ff); return (res); } static int load_svg(char *file_name, ls_settings *settings) { GdkPixbuf *pbuf; GError *err = NULL; guchar *src; unsigned char *dest, *dsta; int i, j, w, h, bpp, cmask, skip, res = -1; #if (GDK_PIXBUF_MAJOR == 2) && (GDK_PIXBUF_MINOR < 8) /* 2.4 can constrain size only while preserving aspect ratio; * 2.6 can constrain size fully, but not partially */ if (settings->req_w && settings->req_h) pbuf = gdk_pixbuf_new_from_file_at_scale(file_name, settings->req_w, settings->req_h, FALSE, &err); else pbuf = gdk_pixbuf_new_from_file(file_name, &err); #else /* 2.8+ is full-featured */ pbuf = gdk_pixbuf_new_from_file_at_scale(file_name, settings->req_w ? settings->req_w : -1, settings->req_h ? settings->req_h : -1, !(settings->req_w && settings->req_h), &err); #endif if (!pbuf) { if ((err->domain == GDK_PIXBUF_ERROR) && (err->code == GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY)) res = FILE_MEM_ERROR; g_error_free(err); return (res); } /* Prevent images loading wrong in case gdk-pixbuf ever starts using * something other than 8-bit RGB/RGBA without me noticing - WJ */ if (gdk_pixbuf_get_bits_per_sample(pbuf) != 8) goto fail; bpp = gdk_pixbuf_get_n_channels(pbuf); if (bpp == 4) cmask = CMASK_RGBA; else if (bpp == 3) cmask = CMASK_IMAGE; else goto fail; settings->width = w = gdk_pixbuf_get_width(pbuf); settings->height = h = gdk_pixbuf_get_height(pbuf); settings->bpp = 3; if ((res = allocate_image(settings, cmask))) goto fail; skip = gdk_pixbuf_get_rowstride(pbuf) - w * bpp; src = gdk_pixbuf_get_pixels(pbuf); dest = settings->img[CHN_IMAGE]; dsta = settings->img[CHN_ALPHA]; for (i = 0; i < h; i++ , src += skip) for (j = 0; j < w; j++ , src += bpp , dest += 3) { dest[0] = src[0]; dest[1] = src[1]; dest[2] = src[2]; if (dsta) *dsta++ = src[3]; } res = 1; /* Delete all-set "alpha" */ delete_alpha(settings, 255); fail: g_object_unref(pbuf); return (res); } #endif /* Handle SVG import using rsvg-convert */ static int import_svg(char *file_name, ls_settings *settings) { da_settings ds; char buf[PATHBUF]; int res = -1; if (!get_tempname(buf, file_name, FT_PNG)) return (-1); memset(&ds, 0, sizeof(ds)); ds.sname = file_name; ds.dname = buf; ds.width = settings->req_w; ds.height = settings->req_h; if (!run_def_action_x(DA_SVG_CONVERT, &ds)) res = load_png(buf, settings, NULL, FALSE); unlink(buf); /* Delete all-set "alpha" */ if (res == 1) delete_alpha(settings, 255); return (res); } /* Handle textual palette file formats - GIMP's GPL and mtPaint's own TXT */ static void to_pal(png_color *c, int *rgb) { c->red = rgb[0] < 0 ? 0 : rgb[0] > 255 ? 255 : rgb[0]; c->green = rgb[1] < 0 ? 0 : rgb[1] > 255 ? 255 : rgb[1]; c->blue = rgb[2] < 0 ? 0 : rgb[2] > 255 ? 255 : rgb[2]; } static int load_txtpal(char *file_name, ls_settings *settings) { char lbuf[4096]; FILE *fp; png_color *c = settings->pal; int i, rgb[3], n = 0, res = -1; if (!(fp = fopen(file_name, "r"))) return (-1); if (!fgets(lbuf, 4096, fp)) goto fail; if (settings->ftype == FT_GPL) { if (strstr(lbuf, "GIMP Palette") != lbuf) goto fail; while (fgets(lbuf, 4096, fp) && (n < 256)) { /* Just ignore invalid/unknown lines */ if (sscanf(lbuf, "%d %d %d", rgb + 0, rgb + 1, rgb + 2) != 3) continue; to_pal(c++, rgb); n++; } } else { if (sscanf(lbuf, "%i", &n) != 1) goto fail; /* No further validation of anything at all */ n = n < 2 ? 2 : n > 256 ? 256 : n; for (i = 0; i < n; i++) { fscanf(fp, "%i,%i,%i\n", rgb + 0, rgb + 1, rgb + 2); to_pal(c++, rgb); } } settings->colors = n; if (n > 0) res = 1; fail: fclose(fp); return (res); } static int save_txtpal(char *file_name, ls_settings *settings) { FILE *fp; char *tpl; png_color *cp; int i, l, n = settings->colors; if ((fp = fopen(file_name, "w")) == NULL) return (-1); if (settings->ftype == FT_GPL) // .gpl file { tpl = extract_ident(file_name, &l); if (!l) tpl = "mtPaint" , l = strlen("mtPaint"); fprintf(fp, "GIMP Palette\nName: %.*s\nColumns: 16\n#\n", l, tpl); tpl = "%3i %3i %3i\tUntitled\n"; } else // .txt file { fprintf(fp, "%i\n", n); tpl = "%i,%i,%i\n"; } cp = settings->pal; for (i = 0; i < n; i++ , cp++) fprintf(fp, tpl, cp->red, cp->green, cp->blue); fclose(fp); return (0); } /* Handle raw palette file formats - 6-bit PAL and 8-bit ACT */ static int load_rawpal(char *file_name, ls_settings *settings) { unsigned char buf[769], xlat[256], *tp; FILE *fp; char *stop; int i, l, ftype; memset(buf, 0, sizeof(buf)); if (!(fp = fopen(file_name, "rb"))) return (-1); l = fread(buf, 1, 769, fp); fclose(fp); if (!l || (l > 768) || (l % 3)) return (-1); // Wrong size l /= 3; /* !!! Filetype in ls_settings is ignored */ ftype = FT_NONE; if ((stop = strrchr(file_name, '.'))) { if (!strcasecmp(stop + 1, "act")) { if (l != 256) return (-1); ftype = FT_ACT; } else if (!strcasecmp(stop + 1, "pal")) ftype = FT_PAL; } if (l < 256) ftype = FT_PAL; if (ftype != FT_ACT) // Default to 6-bit { set_xlate(xlat, 6); for (i = 64; i < 255; i++) xlat[i] = xlat[i - 64]; } else set_xlate(xlat, 8); // 1:1 for (i = 0 , tp = buf; i < l; i++) { settings->pal[i].red = xlat[tp[0]]; settings->pal[i].green = xlat[tp[1]]; settings->pal[i].blue = xlat[tp[2]]; tp += 3; } settings->colors = l; return (1); } static int save_rawpal(char *file_name, ls_settings *settings) { FILE *fp; unsigned char buf[768], xlat[256], *tp; png_color *cp; int i, n = settings->colors; if (!(fp = fopen(file_name, "wb"))) return (-1); memset(buf, 0, 768); if (settings->ftype == FT_PAL) // 6-bit for (i = 0; i < 256; i++) xlat[i] = (63 * 2 * i + 255) / (255 * 2); else for (i = 0; i < 256; i++) xlat[i] = i; // 8-bit ACT cp = settings->pal; for (i = 0 , tp = buf; i < n; i++ , cp++) { tp[0] = xlat[cp->red]; tp[1] = xlat[cp->green]; tp[2] = xlat[cp->blue]; tp += 3; } if (settings->ftype != FT_PAL) n = 256; i = fwrite(buf, n * 3, 1, fp); fclose(fp); return (i ? 0 : -1); } static int save_image_x(char *file_name, ls_settings *settings, memFILE *mf) { ls_settings setw = *settings; // Make a copy to safely modify png_color greypal[256]; int res; /* Prepare to handle clipboard export */ if (setw.mode != FS_CLIPBOARD); // not export else if (setw.ftype & FTM_EXTEND) setw.mode = FS_CLIP_FILE; // to mtPaint else if (setw.img[CHN_SEL] && !setw.img[CHN_ALPHA]) { /* Pass clipboard mask as alpha if there is no alpha already */ setw.img[CHN_ALPHA] = setw.img[CHN_SEL]; setw.img[CHN_SEL] = NULL; } setw.ftype &= FTM_FTYPE; /* Be silent if only writing palette */ if (setw.mode == FS_PALETTE_SAVE) setw.silent = TRUE; /* Provide a grayscale palette if needed */ if ((setw.bpp == 1) && !setw.pal) mem_bw_pal(setw.pal = greypal, 0, 255); /* Validate transparent color (for now, forbid out-of-palette RGB * transparency altogether) */ if (setw.colors && (setw.xpm_trans >= setw.colors)) setw.xpm_trans = setw.rgb_trans = -1; switch (setw.ftype) { default: case FT_PNG: res = save_png(file_name, &setw, mf); break; case FT_GIF: res = save_gif(file_name, &setw); break; #ifdef U_JPEG case FT_JPEG: res = save_jpeg(file_name, &setw); break; #endif #ifdef HANDLE_JP2 case FT_JP2: case FT_J2K: res = save_jpeg2000(file_name, &setw); break; #endif #ifdef U_TIFF case FT_TIFF: res = save_tiff(file_name, &setw, mf); break; #endif #ifdef U_WEBP case FT_WEBP: res = save_webp(file_name, &setw); break; #endif case FT_BMP: res = save_bmp(file_name, &setw, mf); break; case FT_XPM: res = save_xpm(file_name, &setw); break; case FT_XBM: res = save_xbm(file_name, &setw); break; case FT_LSS: res = save_lss(file_name, &setw); break; case FT_TGA: res = save_tga(file_name, &setw); break; case FT_PCX: res = save_pcx(file_name, &setw); break; case FT_LBM: res = save_lbm(file_name, &setw); break; case FT_PBM: res = save_pbm(file_name, &setw); break; case FT_PPM: res = save_ppm(file_name, &setw); break; case FT_PAM: res = save_pam(file_name, &setw); break; case FT_PMM: res = save_pmm(file_name, &setw, mf); break; case FT_PIXMAP: res = save_pixmap(&setw, mf); break; /* Palette files */ case FT_GPL: case FT_TXT: res = save_txtpal(file_name, &setw); break; case FT_PAL: case FT_ACT: res = save_rawpal(file_name, &setw); break; } return (res); } int save_image(char *file_name, ls_settings *settings) { return (save_image_x(file_name, settings, NULL)); } int save_mem_image(unsigned char **buf, int *len, ls_settings *settings) { memFILE mf; int res; memset(&mf, 0, sizeof(mf)); if ((settings->ftype & FTM_FTYPE) == FT_PIXMAP) mf.m.buf = malloc(sizeof(XID_type)); // Expect to know type here else if (!(file_formats[settings->ftype & FTM_FTYPE].flags & FF_WMEM)) return (-1); else mf.m.buf = malloc(mf.m.size = 0x4000 - 64); /* Be silent when saving to memory */ settings->silent = TRUE; res = save_image_x(NULL, settings, &mf); if (res) free(mf.m.buf); else *buf = mf.m.buf , *len = mf.top; return (res); } static void store_image_extras(image_info *image, image_state *state, ls_settings *settings) { #if U_LCMS /* Apply ICC profile */ while (settings->icc_size > 0) { cmsHPROFILE from, to; cmsHTRANSFORM how = NULL; int l = settings->icc_size - sizeof(icHeader); unsigned char *iccdata = settings->icc + sizeof(icHeader); /* Do nothing if the profile seems to be the default sRGB one */ if ((l == 3016) && (hashf(HASHSEED, iccdata, l) == 0xBA0A8E52UL) && (hashf(HASH_RND(HASHSEED), iccdata, l) == 0x94C42C77UL)) break; from = cmsOpenProfileFromMem((void *)settings->icc, settings->icc_size); to = cmsCreate_sRGBProfile(); if (from && (cmsGetColorSpace(from) == icSigRgbData)) how = cmsCreateTransform(from, TYPE_RGB_8, to, TYPE_RGB_8, INTENT_PERCEPTUAL, 0); if (how && (settings->bpp == 1)) /* For GIF: apply to palette */ { unsigned char tm[256 * 3]; int l = settings->colors; pal2rgb(tm, settings->pal, l, 0); cmsDoTransform(how, tm, tm, l); rgb2pal(settings->pal, tm, l); cmsDeleteTransform(how); } else if (how) { unsigned char *img = settings->img[CHN_IMAGE]; size_t l = settings->width, sz = l * settings->height; int i, j; if (!settings->silent) progress_init(_("Applying colour profile"), 1); else if (sz < UINT_MAX) l = sz; j = sz / l; for (i = 0; i < j; i++ , img += l * 3) { if (!settings->silent && ((i * 20) % j >= j - 20)) if (progress_update((float)i / j)) break; cmsDoTransform(how, img, img, l); } progress_end(); cmsDeleteTransform(how); } if (from) cmsCloseProfile(from); cmsCloseProfile(to); break; } #endif // !!! Changing any values is frequently harmful in this mode, so don't do it if (settings->mode == FS_CHANNEL_LOAD) return; /* Stuff RGB transparency into color 255 */ map_rgb_trans(settings); /* Accept vars which make sense */ state->xbm_hot_x = settings->hot_x; state->xbm_hot_y = settings->hot_y; if (settings->gif_delay > 0) preserved_gif_delay = settings->gif_delay; /* Accept palette */ image->trans = settings->xpm_trans; mem_pal_copy(image->pal, settings->pal); image->cols = settings->colors; } static int load_image_x(char *file_name, memFILE *mf, int mode, int ftype, int rw, int rh) { layer_image *lim = NULL; png_color pal[256]; ls_settings settings; int i, tr, res, res0, undo = ftype & FTM_UNDO; /* Clipboard import - from mtPaint, or from something other? */ if ((mode == FS_CLIPBOARD) && (ftype & FTM_EXTEND)) mode = FS_CLIP_FILE; ftype &= FTM_FTYPE; /* Prepare layer slot */ if (mode == FS_LAYER_LOAD) { lim = layer_table[layers_total].image; if (!lim) lim = layer_table[layers_total].image = alloc_layer(0, 0, 1, 0, NULL); else if (layers_total) mem_free_image(&lim->image_, FREE_IMAGE); if (!lim) return (FILE_MEM_ERROR); } /* Fit scalable image into channel */ if (mode == FS_CHANNEL_LOAD) rw = mem_width , rh = mem_height; init_ls_settings(&settings, NULL); settings.req_w = rw; settings.req_h = rh; /* Preset delay to -1, to detect animations by its changing */ settings.gif_delay = -1; #ifdef U_LCMS /* Set size to -1 when we don't want color profile */ if (!apply_icc || ((mode == FS_CHANNEL_LOAD) ? (MEM_BPP != 3) : (mode != FS_PNG_LOAD) && (mode != FS_LAYER_LOAD))) settings.icc_size = -1; #endif /* 0th layer load is just an image load */ if ((mode == FS_LAYER_LOAD) && !layers_total) mode = FS_PNG_LOAD; settings.mode = mode; settings.ftype = ftype; settings.pal = pal; /* Clear hotspot & transparency */ settings.hot_x = settings.hot_y = -1; settings.xpm_trans = settings.rgb_trans = -1; /* Be silent if working from memory */ if (mf) settings.silent = TRUE; /* !!! Use default palette - for now */ mem_pal_copy(pal, mem_pal_def); settings.colors = mem_pal_def_i; switch (ftype) { default: case FT_PNG: res0 = load_png(file_name, &settings, mf, FALSE); break; case FT_GIF: res0 = load_gif(file_name, &settings); break; #ifdef U_JPEG case FT_JPEG: res0 = load_jpeg(file_name, &settings); break; #endif #ifdef HANDLE_JP2 case FT_JP2: case FT_J2K: res0 = load_jpeg2000(file_name, &settings); break; #endif #ifdef U_TIFF case FT_TIFF: res0 = load_tiff(file_name, &settings, mf); break; #endif #ifdef U_WEBP case FT_WEBP: res0 = load_webp(file_name, &settings); break; #endif case FT_BMP: res0 = load_bmp(file_name, &settings, mf); break; case FT_XPM: res0 = load_xpm(file_name, &settings); break; case FT_XBM: res0 = load_xbm(file_name, &settings); break; case FT_LSS: res0 = load_lss(file_name, &settings); break; case FT_TGA: res0 = load_tga(file_name, &settings); break; case FT_PCX: res0 = load_pcx(file_name, &settings); break; case FT_LBM: res0 = load_lbm(file_name, &settings); break; case FT_PBM: case FT_PGM: case FT_PPM: case FT_PAM: res0 = load_pnm(file_name, &settings); break; case FT_PMM: res0 = load_pmm(file_name, &settings, mf); break; case FT_PIXMAP: res0 = load_pixmap(&settings, mf); break; case FT_SVG: #ifdef MAY_HANDLE_SVG if (svg_check < 0) svg_check = svg_supported(); if (svg_check) res0 = load_svg(file_name, &settings); else #endif res0 = import_svg(file_name, &settings); break; /* Palette files */ case FT_GPL: case FT_TXT: res0 = load_txtpal(file_name, &settings); break; case FT_PAL: case FT_ACT: res0 = load_rawpal(file_name, &settings); break; } /* Consider animated GIF a success */ res = res0 == FILE_HAS_FRAMES ? 1 : res0; /* Ignore frames beyond first if in-memory (imported clipboard) */ if (mf) res0 = res; switch (mode) { case FS_PNG_LOAD: /* Image */ /* Success, or lib failure with single image - commit load */ if ((res == 1) || (!lim && (res == FILE_LIB_ERROR))) { if (!mem_img[CHN_IMAGE] || !undo) mem_new(settings.width, settings.height, settings.bpp, 0); else undo_next_core(UC_DELETE, settings.width, settings.height, settings.bpp, CMASK_ALL); memcpy(mem_img, settings.img, sizeof(chanlist)); store_image_extras(&mem_image, &mem_state, &settings); update_undo(&mem_image); mem_undo_prepare(); if (lim) layer_copy_from_main(0); /* Report whether the file is animated or multipage */ res = res0; if ((res == FILE_HAS_FRAMES) && /* If file contains frame delay value... */ ((settings.gif_delay >= 0) || /* ...or it cannot be multipage at all... */ !(file_formats[ftype].flags & FF_LAYER))) res = FILE_HAS_ANIM; /* ...then it's animated */ } /* Failure */ else { mem_free_chanlist(settings.img); /* If loader managed to delete image before failing */ if (!mem_img[CHN_IMAGE]) create_default_image(); } break; case FS_CLIPBOARD: /* Imported clipboard */ if ((res == 1) && mem_clip_alpha && !mem_clip_mask) { /* "Alpha" likely means clipboard mask here */ mem_clip_mask = mem_clip_alpha; mem_clip_alpha = NULL; memcpy(settings.img, mem_clip.img, sizeof(chanlist)); } /* Fallthrough */ case FS_CLIP_FILE: /* Clipboard */ /* Convert color transparency to alpha */ tr = settings.bpp == 3 ? settings.rgb_trans : settings.xpm_trans; if ((res == 1) && (tr >= 0)) { /* Add alpha channel if no alpha yet */ if (!settings.img[CHN_ALPHA]) { i = settings.width * settings.height; /* !!! Create committed */ mem_clip_alpha = malloc(i); if (mem_clip_alpha) { settings.img[CHN_ALPHA] = mem_clip_alpha; memset(mem_clip_alpha, 255, i); } } if (!settings.img[CHN_ALPHA]) res = FILE_MEM_ERROR; else mem_mask_colors(settings.img[CHN_ALPHA], settings.img[CHN_IMAGE], 0, settings.width, settings.height, settings.bpp, tr, tr); } /* Success - accept data */ if (res == 1); /* !!! Clipboard data committed already */ /* Failure needing rollback */ else if (settings.img[CHN_IMAGE]) { /* !!! Too late to restore previous clipboard */ mem_free_image(&mem_clip, FREE_ALL); } break; case FS_CHANNEL_LOAD: /* Success - commit load */ if (res == 1) { /* Add frame & stuff data into it */ undo_next_core(UC_DELETE, mem_width, mem_height, mem_img_bpp, CMASK_CURR); mem_img[mem_channel] = settings.img[CHN_IMAGE]; update_undo(&mem_image); if (mem_channel == CHN_IMAGE) store_image_extras(&mem_image, &mem_state, &settings); mem_undo_prepare(); } /* Failure */ else free(settings.img[CHN_IMAGE]); break; case FS_LAYER_LOAD: /* Layer */ /* Success - commit load */ if (res == 1) { mem_alloc_image(0, &lim->image_, settings.width, settings.height, settings.bpp, 0, NULL); memcpy(lim->image_.img, settings.img, sizeof(chanlist)); store_image_extras(&lim->image_, &lim->state_, &settings); update_undo(&lim->image_); } /* Failure */ else mem_free_chanlist(settings.img); break; case FS_PATTERN_LOAD: /* Success - rebuild patterns */ if (res == 1) set_patterns(&settings); free(settings.img[CHN_IMAGE]); break; case FS_PALETTE_LOAD: case FS_PALETTE_DEF: /* Drop image channels if any */ mem_free_chanlist(settings.img); /* This "failure" in this context serves as shortcut */ if (res == EXPLODE_FAILED) res = 1; /* In case of image format, retry as raw palette */ if ((res != 1) && (file_formats[ftype].flags & FF_IMAGE)) res = load_rawpal(file_name, &settings); /* Utter failure - do nothing */ if ((res != 1) || (settings.colors <= 0)); /* Replace default palette */ else if (mode == FS_PALETTE_DEF) { mem_pal_copy(mem_pal_def, pal); mem_pal_def_i = settings.colors; } /* Change current palette */ else { mem_undo_next(UNDO_PAL); mem_pal_copy(mem_pal, pal); mem_cols = settings.colors; } break; } free(settings.icc); return (res); } int load_image(char *file_name, int mode, int ftype) { return (load_image_x(file_name, NULL, mode, ftype, 0, 0)); } int load_mem_image(unsigned char *buf, int len, int mode, int ftype) { memFILE mf; if (((ftype & FTM_FTYPE) != FT_PIXMAP) /* Special case */ && !(file_formats[ftype & FTM_FTYPE].flags & FF_RMEM)) return (-1); memset(&mf, 0, sizeof(mf)); mf.m.buf = buf; mf.top = mf.m.size = len; return (load_image_x(NULL, &mf, mode, ftype, 0, 0)); } int load_image_scale(char *file_name, int mode, int ftype, int w, int h) { return (load_image_x(file_name, NULL, mode, ftype, w, h)); } // !!! The only allowed modes for now are FS_LAYER_LOAD and FS_EXPLODE_FRAMES // !!! Load from memblock is not supported yet static int load_frames_x(ani_settings *ani, int ani_mode, char *file_name, int mode, int ftype) { png_color pal[256]; ftype &= FTM_FTYPE; ani->mode = ani_mode; init_ls_settings(&ani->settings, NULL); #ifdef U_LCMS /* Set size to -1 when we don't want color profile */ /* if (!apply_icc) */ ani->settings.icc_size = -1; // !!! Disable for now #endif ani->settings.mode = mode; ani->settings.ftype = ftype; ani->settings.pal = pal; /* Clear hotspot & transparency */ ani->settings.hot_x = ani->settings.hot_y = -1; ani->settings.xpm_trans = ani->settings.rgb_trans = -1; /* No load progressbar when exploding frames */ if (mode == FS_EXPLODE_FRAMES) ani->settings.silent = TRUE; /* !!! Use default palette - for now */ mem_pal_copy(pal, mem_pal_def); ani->settings.colors = mem_pal_def_i; switch (ftype) { case FT_PNG: return (load_apng_frames(file_name, ani)); case FT_GIF: return (load_gif_frames(file_name, ani)); #ifdef U_TIFF case FT_TIFF: return (load_tiff_frames(file_name, ani)); #endif #ifdef U_WEBP case FT_WEBP: return (load_webp_frames(file_name, ani)); #endif case FT_PBM: case FT_PGM: case FT_PPM: case FT_PAM: return (load_pnm_frames(file_name, ani)); case FT_PMM: return (load_pmm_frames(file_name, ani, NULL)); } return (-1); } int load_frameset(frameset *frames, int ani_mode, char *file_name, int mode, int ftype) { ani_settings ani; int res; memset(&ani, 0, sizeof(ani_settings)); res = load_frames_x(&ani, ani_mode, file_name, mode, ftype); /* Treat out-of-memory error as fatal, to avoid worse things later */ if ((res == FILE_MEM_ERROR) || !ani.fset.cnt) mem_free_frames(&ani.fset); /* Pass too-many-frames error along */ else if (res == FILE_TOO_LONG); /* Consider all other errors partial failures */ else if (res != 1) res = FILE_LIB_ERROR; /* Just pass the frameset to the outside, for now */ *frames = ani.fset; return (res); } /* Write out the last frame to indexed sequence, and delete it */ static int write_out_frame(char *file_name, ani_settings *ani, ls_settings *f_set) { ls_settings w_set; image_frame *frame = ani->fset.frames + ani->fset.cnt - 1; char new_name[PATHBUF + 32], *tmp; int n, deftype = ani->desttype, res; /* Show progress, for unknown final count */ n = nextpow2(ani->cnt); if (n < 16) n = 16; progress_update((float)ani->cnt / n); tmp = strrchr(file_name, DIR_SEP); if (!tmp) tmp = file_name; else tmp++; file_in_dir(new_name, ani->destdir, tmp, PATHBUF); tmp = new_name + strlen(new_name); sprintf(tmp, ".%03d", ani->cnt); if (f_set) w_set = *f_set; else { init_ls_settings(&w_set, NULL); memcpy(w_set.img, frame->img, sizeof(chanlist)); w_set.width = frame->width; w_set.height = frame->height; w_set.pal = frame->pal ? frame->pal : ani->fset.pal; w_set.bpp = frame->bpp; w_set.colors = frame->cols; w_set.xpm_trans = frame->trans; } w_set.ftype = deftype; w_set.silent = TRUE; if (!(file_formats[deftype].flags & FF_SAVE_MASK_FOR(w_set))) { w_set.ftype = FT_PNG; ani->miss++; } w_set.mode = ani->mode; // Only FS_EXPLODE_FRAMES for now res = ani->error = save_image(new_name, &w_set); if (!res) ani->cnt++; if (f_set) // Delete { mem_free_chanlist(f_set->img); memset(f_set->img, 0, sizeof(chanlist)); } // Set for deletion else frame->flags |= FM_NUKE; return (res); } static void warn_miss(int miss, int total, int ftype) { char *txt = g_strdup_printf( __("%d out of %d frames could not be saved as %s - saved as PNG instead"), miss, total, file_formats[ftype].name); alert_box(_("Warning"), txt, "", NULL); // Not an error g_free(txt); } int explode_frames(char *dest_path, int ani_mode, char *file_name, int ftype, int desttype) { ani_settings ani; int res; memset(&ani, 0, sizeof(ani_settings)); ani.desttype = desttype; ani.destdir = dest_path; progress_init(_("Explode frames"), 0); progress_update(0.0); res = load_frames_x(&ani, ani_mode, file_name, FS_EXPLODE_FRAMES, ftype); progress_update(1.0); if (res == 1); // Everything went OK else if (res == FILE_MEM_ERROR); // Report memory problem else if (ani.error) // Sequence write failure - soft or hard? res = ani.cnt ? FILE_EXP_BREAK : EXPLODE_FAILED; else if (ani.cnt) // Failed to read some middle frame res = FILE_LIB_ERROR; mem_free_frames(&ani.fset); progress_end(); if (ani.miss && (res == 1)) warn_miss(ani.miss, ani.cnt, ani.desttype & FTM_FTYPE); return (res); } int export_undo(char *file_name, ls_settings *settings) { char new_name[PATHBUF + 32]; int start = mem_undo_done, res = 0, lenny, i, j; int deftype = settings->ftype, miss = 0; strncpy(new_name, file_name, PATHBUF); lenny = strlen( file_name ); ls_init("UNDO", 1); settings->silent = TRUE; for (j = 0; j < 2; j++) { for (i = 1; i <= start + 1; i++) { if (!res && (!j ^ (settings->mode == FS_EXPORT_UNDO))) { progress_update((float)i / (start + 1)); settings->ftype = deftype; if (!(file_formats[deftype].flags & FF_SAVE_MASK)) { settings->ftype = FT_PNG; miss++; } sprintf(new_name + lenny, "%03i.%s", i, file_formats[settings->ftype].ext); memcpy(settings->img, mem_img, sizeof(chanlist)); settings->pal = mem_pal; settings->width = mem_width; settings->height = mem_height; settings->bpp = mem_img_bpp; settings->colors = mem_cols; res = save_image(new_name, settings); } if (!j) /* Goto first image */ { if (mem_undo_done > 0) mem_do_undo(FALSE); } else if (mem_undo_done < start) mem_do_undo(TRUE); } } progress_end(); if (miss && !res) warn_miss(miss, mem_undo_done, deftype); return (res); } int export_ascii ( char *file_name ) { char ch[16] = " .,:;+=itIYVXRBM"; int i, j; unsigned char pix; FILE *fp; if ((fp = fopen(file_name, "w")) == NULL) return -1; for ( j=0; j= '1') && (buf[1] <= '6')) { static const unsigned char pnms[3] = { FT_PBM, FT_PGM, FT_PPM }; return (pnms[(buf[1] - '1') % 3]); } if (!memcmp(buf, "GIMP Palette", strlen("GIMP Palette"))) return (FT_GPL); /* Check layers signature and version */ if (!memcmp(buf, LAYERS_HEADER, strlen(LAYERS_HEADER))) { stop = strchr(buf, '\n'); if (!stop || (stop - buf > 32)) return (FT_NONE); i = atoi(++stop); if (i == 1) return (FT_LAYERS1); /* !!! Not implemented yet */ // if (i == 2) return (FT_LAYERS2); return (FT_NONE); } /* Assume generic GZIP is SVGZ */ if (!memcmp(buf, "\x1F\x8B", 2)) return (FT_SVG); /* Assume generic XML is SVG */ i = 0; sscanf(buf, " 5) break; if (buf[1] > 1) return (FT_PCX); if (buf[2] != 1) break; // Uncompressed PCX is nonstandard /* Ambiguity - look at name as a last resort * Bias to PCX - TGAs usually have 0th byte = 0 */ stop = strrchr(name, '.'); if (!stop) return (FT_PCX); if (!strcasecmp(stop + 1, "tga")) break; return (FT_PCX); } /* Check if this is TGA */ if ((buf[1] < 2) && (buf[2] < 12) && ((1 << buf[2]) & 0x0E0F)) return (FT_TGA); /* Simple check for "txt" palette format */ if ((sscanf(buf, "%i", &i) == 1) && (i > 0) && (i <= 256)) return (FT_TXT); /* Simple check for XPM */ stop = strstr(buf, "XPM"); if (stop) { i = stop - buf; stop = strchr(buf, '\n'); if (!stop || (stop - buf > i)) return (FT_XPM); } /* Check possibility of XBM by absence of control chars */ for (i = 0; buf[i] && (buf[i] != '\n'); i++) { if (ISCNTRL(buf[i])) return (FT_NONE); } return (FT_XBM); } int detect_file_format(char *name, int need_palette) { FILE *fp; int i, f; if (!(fp = fopen(name, "rb"))) return (-1); i = do_detect_format(name, fp); f = file_formats[i].flags; if (need_palette) { /* Check for PAL/ACT raw format */ if (!(f & (FF_16 | FF_256 | FF_PALETTE))) { f_long l; fseek(fp, 0, SEEK_END); l = ftell(fp); i = (l > 0) && (l <= 768) && !(l % 3) ? FT_PAL : FT_NONE; } } else if (!(f & (FF_IMAGE | FF_LAYER))) i = FT_NONE; fclose(fp); return (i); } // Can this file be opened for reading? /* 0 = readable, -1 = not exists, 1 = error, 2 = a directory */ int valid_file(char *filename) { FILE *fp = fopen(filename, "r"); if (!fp) return (errno == ENOENT ? -1 : 1); else { struct stat buf; int d = fstat(fileno(fp), &buf) ? 1 : S_ISDIR(buf.st_mode) ? 2 : 0; fclose(fp); return (d); } } mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/png.h000066400000000000000000000143211471325446300217000ustar00rootroot00000000000000/* png.h Copyright (C) 2004-2019 Mark Tyler and Dmitry Groshev This file is part of mtPaint. mtPaint 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. mtPaint 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 mtPaint in the file COPYING. */ // Loading/Saving errors #define WRONG_FORMAT -10 #define TOO_BIG -11 #define EXPLODE_FAILED -12 #define FILE_LIB_ERROR 0xBAD01 #define FILE_MEM_ERROR 0xBAD02 #define FILE_HAS_FRAMES 0xBAD03 #define FILE_HAS_ANIM 0xBAD04 #define FILE_TOO_LONG 0xBAD05 #define FILE_EXP_BREAK 0xBAD06 /* File types */ enum { FT_NONE = 0, FT_PNG, FT_JPEG, FT_JP2, FT_J2K, FT_TIFF, FT_GIF, FT_BMP, FT_XPM, FT_XBM, FT_LSS, FT_TGA, FT_PCX, FT_PBM, FT_PGM, FT_PPM, FT_PAM, FT_GPL, FT_TXT, FT_PAL, FT_ACT, FT_LAYERS1, FT_LAYERS2, FT_PIXMAP, FT_SVG, FT_PMM, FT_WEBP, FT_LBM, NUM_FTYPES }; #define FTM_FTYPE 0x00FF /* File type mask */ #define FTM_EXTEND 0x0100 /* Allow extended format */ #define FTM_UNDO 0x0200 /* Allow undoing */ #define FTM_FRAMES 0x0400 /* Allow frameset use */ /* Primary features supported by file formats */ #define FF_BW 0x0001 /* Black and white */ #define FF_16 0x0002 /* 16 colors */ #define FF_256 0x0004 /* 256 colors */ #define FF_IDX 0x0007 /* Indexed image */ #define FF_RGB 0x0008 /* Truecolor */ #define FF_IMAGE 0x000F /* Image of any kind */ #define FF_ANIM 0x0010 /* Animation */ #define FF_ALPHAI 0x0020 /* Alpha channel for indexed images */ #define FF_ALPHAR 0x0040 /* Alpha channel for RGB images */ #define FF_ALPHA 0x0060 /* Alpha channel for all images */ #define FF_MULTI 0x0080 /* Multiple channels */ #define FF_LAYER 0x0100 /* Layered images */ #define FF_PALETTE 0x0200 /* Palette file (not image) */ #define FF_RMEM 0x0400 /* Can be read from memory */ #define FF_WMEM 0x0800 /* Can be written to memory */ #define FF_MEM 0x0C00 /* Both of the above */ #define FF_NOSAVE 0x1000 /* Can be read but not written */ #define FF_SCALE 0x2000 /* Freely scalable (vector format) */ /* Configurable features of file formats */ #define XF_TRANS 0x0001 /* Indexed transparency */ #define XF_SPOT 0x0002 /* "Hot spot" */ #define XF_COMPJ 0x0004 /* JPEG compression */ #define XF_COMPZ 0x0008 /* PNG zlib compression */ #define XF_COMPR 0x0010 /* RLE compression */ #define XF_COMPJ2 0x0020 /* JPEG2000 compression */ #define XF_COMPZT 0x0040 /* TIFF deflate compression */ #define XF_COMPLZ 0x0080 /* TIFF LZMA2 compression */ #define XF_COMPWT 0x0100 /* TIFF WebP compression */ #define XF_COMPZS 0x0200 /* TIFF ZSTD compression */ #define XF_COMPT 0x0400 /* TIFF selectable compression */ #define XF_COMPV8 0x0800 /* WebP V8 compression */ #define XF_COMPV8L 0x1000 /* WebP V8L compression */ #define XF_COMPW 0x2000 /* WebP selectable compression */ #define XF_COMPRL 0x4000 /* LBM RLE compression */ #define XF_PBM 0x8000 /* "Planar" LBM, aka PBM */ #define FF_SAVE_MASK (mem_img_bpp == 3 ? FF_RGB : mem_cols > 16 ? FF_256 : \ mem_cols > 2 ? FF_16 | FF_256 : FF_IDX) #define FF_SAVE_MASK_FOR(X) ((X).bpp == 3 ? FF_RGB : (X).colors > 16 ? FF_256 : \ (X).colors > 2 ? FF_16 | FF_256 : FF_IDX) /* Animation loading modes */ #define ANM_PAGE 0 /* No animation (pages as written) */ #define ANM_RAW 1 /* Raw frames (as written) */ #define ANM_COMP 2 /* Composited frames (as displayed) */ #define ANM_NOZERO 3 /* Composited frames with nonzero delays (as seen) */ #define LONGEST_EXT 5 typedef struct { char *name, *ext, *ext2; unsigned int flags, xflags; } fformat; extern fformat file_formats[]; #define TIFF_MAX_TYPES 11 /* Enough for NULL-terminated list of them all */ typedef struct { char *name; int id; unsigned int flags, xflags; int pflag; } tiff_format; extern tiff_format tiff_formats[]; int tiff_lzma, tiff_zstd; /* LZMA2 & ZSTD compression supported */ extern char *webp_presets[]; /* All-in-one transport container for save/load */ typedef struct { /* Configuration data */ int mode, ftype; int xpm_trans; int hot_x, hot_y; int req_w, req_h; // Size request for scalable formats int jpeg_quality; int png_compression; int lzma_preset; int zstd_level; int tiff_type; int tga_RLE; int jp2_rate; int webp_preset, webp_quality, webp_compression; int lbm_pack, lbm_pbm; int gif_delay; int rgb_trans; int silent; /* Image data */ chanlist img; png_color *pal; int width, height, bpp, colors; int x, y; /* Extra data */ int icc_size; char *icc; } ls_settings; int silence_limit, jpeg_quality, png_compression; int tga_RLE, tga_565, tga_defdir, jp2_rate; int lzma_preset, zstd_level, tiff_predictor, tiff_rtype, tiff_itype, tiff_btype; int webp_preset, webp_quality, webp_compression; int lbm_mask, lbm_untrans, lbm_pack, lbm_pbm; int apply_icc; int file_type_by_ext(char *name, guint32 mask); int save_image(char *file_name, ls_settings *settings); int save_mem_image(unsigned char **buf, int *len, ls_settings *settings); int load_image(char *file_name, int mode, int ftype); int load_mem_image(unsigned char *buf, int len, int mode, int ftype); int load_image_scale(char *file_name, int mode, int ftype, int w, int h); // !!! The only allowed mode for now is FS_LAYER_LOAD int load_frameset(frameset *frames, int ani_mode, char *file_name, int mode, int ftype); int explode_frames(char *dest_path, int ani_mode, char *file_name, int ftype, int desttype); int export_undo(char *file_name, ls_settings *settings); int export_ascii ( char *file_name ); int detect_file_format(char *name, int need_palette); #define detect_image_format(X) detect_file_format(X, FALSE) #define detect_palette_format(X) detect_file_format(X, TRUE) int valid_file(char *filename); // Can this file be opened for reading? /* Compression levels range for ZSTD */ #define ZSTD_MIN 1 #define ZSTD_MAX 22 #ifdef U_TIFF void init_tiff_formats(); // Check what libtiff can handle #endif mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/polygon.c000066400000000000000000000207121471325446300225770ustar00rootroot00000000000000/* polygon.c Copyright (C) 2005-2015 Mark Tyler and Dmitry Groshev This file is part of mtPaint. mtPaint 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. mtPaint 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 mtPaint in the file COPYING. */ #include "polygon.h" #include "mygtk.h" #include "memory.h" int poly_points; int poly_mem[MAX_POLY][2]; // Coords in poly_mem are raw coords as plotted over image int poly_xy[4]; static int cmp_spans(const void *span1, const void *span2) { return (((int *)span1)[2] - ((int *)span2)[2]); } /* !!! This code clips polygon to image boundaries, and when using buffer * assumes it covers the intersection area - WJ */ void poly_draw(int filled, unsigned char *buf, int wbuf) { #define SPAN_STEP 5 /* x0, x1, y0, y1, next */ linedata line; unsigned char borders[MAX_WIDTH]; int spans[(MAX_POLY + 1) * SPAN_STEP], *span, *span2; int i, j, k, nspans, y, rxy[4]; int oldmode = mem_undo_opacity; /* Intersect image & polygon rectangles */ clip(rxy, 0, 0, mem_width - 1, mem_height - 1, poly_xy); // !!! clip() can intersect inclusive rectangles, but not check result if ((rxy[0] > rxy[2]) || (rxy[1] > rxy[3])) return; /* Adjust buffer pointer */ if (buf) buf -= rxy[1] * wbuf + rxy[0]; mem_undo_opacity = TRUE; j = poly_points - 1; for (i = 0; i < poly_points; j = i++) { int x0 = poly_mem[j][0], y0 = poly_mem[j][1]; int x1 = poly_mem[i][0], y1 = poly_mem[i][1]; if (!filled) { f_circle(x0, y0, tool_size); tline(x0, y0, x1, y1, tool_size); } else if (!buf) sline(x0, y0, x1, y1); else { int tk; line_init(line, x0, y0, x1, y1); if (line_clip(line, rxy, &tk) < 0) continue; for (; line[2] >= 0; line_step(line)) { buf[line[0] + line[1] * wbuf] = 255; } } // Outline is needed to properly edge the polygon } if (!filled) goto done; // If drawing outline only, finish now /* Build array of vertical spans */ span = spans + SPAN_STEP; j = poly_points - 1; for (i = 0; i < poly_points; j = i++) { int x0 = poly_mem[j][0], y0 = poly_mem[j][1]; int x1 = poly_mem[i][0], y1 = poly_mem[i][1]; // No use for horizontal spans if (y0 == y1) continue; // Order points by increasing Y k = y0 > y1; span[k] = x0; span[k + 2] = y0; k ^= 1; span[k] = x1; span[k + 2] = y1; // Check vertical boundaries if ((span[3] <= 0) || (span[2] >= mem_height - 1)) continue; // Accept the span span += SPAN_STEP; } nspans = (span - spans) / SPAN_STEP - 1; if (!nspans) goto done; // No interior to fill /* Sort and link spans */ qsort(spans + SPAN_STEP, nspans, SPAN_STEP * sizeof(int), cmp_spans); for (i = 0; i < nspans; i++) spans[i * SPAN_STEP + 4] = i + 1; spans[nspans * SPAN_STEP + 4] = 0; // Chain terminator spans[2] = spans[3] = MAX_HEIGHT; // Loops breaker /* Let's scan! */ memset(borders, 0, mem_width); y = spans[SPAN_STEP + 2] + 1; if (y < 0) y = 0; for (; y < mem_height; y++) { unsigned char tv = 0; int i, x, x0 = mem_width, x1 = 0; /* Label the intersections */ if (!spans[4]) break; // List is empty span = spans; while (TRUE) { int dx, dy; // Unchain used-up spans while ((span2 = spans + span[4] * SPAN_STEP)[3] < y) span[4] = span2[4]; if (y <= span2[2]) break; // Y too small yet span = span2; dx = span[1] - span[0]; dy = span[3] - span[2]; x = (dx * 2 * (y - span[2]) + dy) / (dy * 2) + span[0]; if (x >= mem_width) x1 = mem_width; // Fill to end else { if (x < 0) x = 0; if (x0 > x) x0 = x; if (x1 <= x) x1 = x + 1; borders[x] ^= 1; } } /* Draw the runs */ if (x0 >= mem_width) continue; // No pixels for (i = x0; i < x1; i++) { tv ^= borders[i]; // !!! "&" is for larger-than-byte char type; normally, GCC will optimize it out borders[i] = (~tv + 1) & 255; } x1 -= x0; if (!buf) put_pixel_row(x0, y, x1, borders + x0); else { unsigned char *dest = buf + y * wbuf + x0; unsigned char *src = borders + x0; for (i = 0; i < x1; i++) dest[i] |= src[i]; } memset(borders + x0, 0, x1); } done: mem_undo_opacity = oldmode; #undef SPAN_STEP } void poly_mask() // Paint polygon onto clipboard mask { mem_clip_mask_init(0); /* Clear mask */ if (!mem_clip_mask) return; /* Failed to get memory */ poly_draw(TRUE, mem_clip_mask, mem_clip_w); } void poly_paint() // Paint polygon onto image { poly_draw(TRUE, NULL, 0); } void poly_outline() // Paint polygon outline onto image { poly_draw(FALSE, NULL, 0); } void poly_add(int x, int y) // Add point to list { if (poly_points >= MAX_POLY) return; poly_mem[poly_points][0] = x; poly_mem[poly_points][1] = y; poly_points++; } void poly_bounds() { int i, x, y; poly_min_x = poly_max_x = poly_mem[0][0]; poly_min_y = poly_max_y = poly_mem[0][1]; for (i = 1; i < poly_points; i++) { x = poly_mem[i][0]; if (poly_min_x > x) poly_min_x = x; if (poly_max_x < x) poly_max_x = x; y = poly_mem[i][1]; if (poly_min_y > y) poly_min_y = y; if (poly_max_y < y) poly_max_y = y; } } void flood_fill_poly( int x, int y, unsigned int target ) { int minx = x, maxx = x, ended = 0, newx = 0; mem_clip_mask[ x + y*mem_clip_w ] = 1; while ( ended == 0 ) // Search left for target pixels { minx--; if ( minx < 0 ) ended = 1; else { if ( mem_clipboard[ minx + y*mem_clip_w ] == target ) mem_clip_mask[ minx + y*mem_clip_w ] = 1; else ended = 1; } } minx++; ended = 0; while ( ended == 0 ) // Search right for target pixels { maxx++; if ( maxx >= mem_clip_w ) ended = 1; else { if ( mem_clipboard[ maxx + y*mem_clip_w ] == target ) mem_clip_mask[ maxx + y*mem_clip_w ] = 1; else ended = 1; } } maxx--; if ( (y-1) >= 0 ) // Recurse upwards for ( newx = minx; newx <= maxx; newx++ ) if ( mem_clipboard[ newx + (y-1)*mem_clip_w ] == target && mem_clip_mask[newx + mem_clip_w*(y-1)] != 1 ) flood_fill_poly( newx, y-1, target ); if ( (y+1) < mem_clip_h ) // Recurse downwards for ( newx = minx; newx <= maxx; newx++ ) if ( mem_clipboard[ newx + (y+1)*mem_clip_w ] == target && mem_clip_mask[newx + mem_clip_w*(y+1)] != 1 ) flood_fill_poly( newx, y+1, target ); } void flood_fill24_poly( int x, int y, int target ) { int minx = x, maxx = x, ended = 0, newx = 0; mem_clip_mask[ x + y*mem_clip_w ] = 1; while ( ended == 0 ) // Search left for target pixels { minx--; if ( minx < 0 ) ended = 1; else { if ( MEM_2_INT(mem_clipboard, 3*(minx + mem_clip_w*y) ) == target ) mem_clip_mask[ minx + y*mem_clip_w ] = 1; else ended = 1; } } minx++; ended = 0; while ( ended == 0 ) // Search right for target pixels { maxx++; if ( maxx >= mem_clip_w ) ended = 1; else { if ( MEM_2_INT(mem_clipboard, 3*(maxx + mem_clip_w*y) ) == target ) mem_clip_mask[ maxx + y*mem_clip_w ] = 1; else ended = 1; } } maxx--; if ( (y-1) >= 0 ) // Recurse upwards for ( newx = minx; newx <= maxx; newx++ ) if ( MEM_2_INT(mem_clipboard, 3*(newx + mem_clip_w*(y-1)) ) == target && mem_clip_mask[newx + mem_clip_w*(y-1)] != 1 ) flood_fill24_poly( newx, y-1, target ); if ( (y+1) < mem_clip_h ) // Recurse downwards for ( newx = minx; newx <= maxx; newx++ ) if ( MEM_2_INT(mem_clipboard, 3*(newx + mem_clip_w*(y+1)) ) == target && mem_clip_mask[newx + mem_clip_w*(y+1)] != 1 ) flood_fill24_poly( newx, y+1, target ); } void poly_lasso(int poly) // Lasso around current clipboard { int i, j, x = 0, y = 0; if (!mem_clip_mask) return; /* Nothing to do */ /* Fill seed is either the first point of polygon, * or top left corner of the clipboard */ if (poly) { x = poly_mem[0][0] - poly_min_x; y = poly_mem[0][1] - poly_min_y; if ((x < 0) || (x >= mem_clip_w) || (y < 0) || (y >= mem_clip_h)) x = y = 0; // Point is outside clipboard } if ( mem_clip_bpp == 1 ) { j = mem_clipboard[x + y*mem_clip_w]; flood_fill_poly( x, y, j ); } if ( mem_clip_bpp == 3 ) { i = 3*(x + y*mem_clip_w); j = MEM_2_INT(mem_clipboard, i); flood_fill24_poly( x, y, j ); } j = mem_clip_w*mem_clip_h; for ( i=0; ilabel_tablet_device, nm, LABEL_VALUE); g_free(nm); } static void prefs_evt(pref_dd *dt, void **wdata, int what) { char *p, oldpal[PATHBUF], oldpat[PATHBUF]; if (what == op_EVT_DESTROY) // Finalize { cmd_sensitive(menu_slots[MENU_PREFS], TRUE); return; } if (what != op_EVT_CANCEL) // OK/Apply { // Preserve old values strncpy0(oldpal, inifile_get(DEFAULT_PAL_INI, ""), PATHBUF); strncpy0(oldpat, inifile_get(DEFAULT_PAT_INI, ""), PATHBUF); /* Read back from V-code slots */ run_query(wdata); mem_undo_depth = dt->undo_depth[0]; mem_xbm_hot_x = dt->hot_x[0]; mem_xbm_hot_y = dt->hot_y[0]; #ifdef U_NLS inifile_set("languageSETTING", pref_lang_ini_code[dt->lang]); setup_language(); string_init(); // Translate static strings #endif set_master_pattern(dt->pattern); inifile_set("clipFilename", mem_clip_file); if (strcmp(oldpal, p = inifile_get(DEFAULT_PAL_INI, ""))) load_def_palette(p); if (strcmp(oldpat, p = inifile_get(DEFAULT_PAT_INI, ""))) load_def_patterns(p); update_stuff(UPD_PREFS); /* Apply this undoable setting after everything else */ mem_set_trans(dt->trans[0]); } if (what != op_EVT_CLICK) run_destroy(wdata); // OK/Cancel } static int tablet_preview(pref_dd *dt, void **wdata, int what, void **where, mouse_ext *mouse) { if (mouse->button == 1) { char txt[64]; snprintf(txt, sizeof(txt), "%s = %.2f", __("Pressure"), mouse->pressure * (1.0 / MAX_PRESSURE)); cmd_setv(dt->label_tablet_pressure, txt, LABEL_VALUE); } return (TRUE); } static char *xchans[NUM_CHANNELS]; /// V-CODE #define WBbase pref_dd static void *pref_code[] = { WINDOW(_("Preferences")), // nonmodal EVENT(DESTROY, prefs_evt), MKSHRINK, // shrinkable BORDER(SCROLL, 0), WANTMAX, // max size XSCROLL(1, 1), // auto/auto BORDER(NBOOK, 0), NBOOKl, BORDER(TABLE, 10), BORDER(LABEL, 4), BORDER(SPIN, 4), BORDER(ENTRY, 0), /// ---- TAB1 - GENERAL PAGE(_("General")), GROUPN, #ifdef U_THREADS TABLE2(6), TSPINv(_("Max threads (0 to autodetect)"), maxthreads, 0, 256), TSPINv(_("Min kpixels per render thread"), kpix_threads, 16, (MAX_WIDTH * MAX_HEIGHT + 1023) / 1024), #define XROWS 2 #else TABLE2(4), #define XROWS 0 #endif TSPINv(_("Max memory used for undo (MB)"), mem_undo_limit, 1, 2048), TSPINa(_("Max undo levels"), undo_depth), TSPINv(_("Communal layer undo space (%)"), mem_undo_common, 0, 100), TLHBOXpl(4, 0, 3 + XROWS, 2), MLABEL(_("Bayer master pattern")), XLENTRY(pattern, 48), WDONE, WDONE, CHECKv(_("Use gamma correction by default"), use_gamma), CHECKv(_("Use gamma correction when painting"), paint_gamma), CHECKv(_("Separate patterns for A & B"), pattern_B), /* !!! Only processing is scriptable, interface is not */ UNLESSx(script, 1), CHECKv(_("Optimize alpha chequers"), chequers_optimize), CHECKv(_("Disable view window transparencies"), opaque_view), CHECKv(_("Enable overlays by layer"), layer_overlay), WDONE, #ifdef U_NLS /// ---- TAB2 - LANGUAGE PAGE(_("Language")), VBOXBS, MLABELc(_("Select preferred language translation\n\n" "You will need to restart mtPaint\nfor this to take full effect")), OPT(pref_langs, PREF_LANGS, lang), WDONE, WDONE, #endif /// ---- TAB3 - INTERFACE PAGE(_("Interface")), TABLE2(3), TSPINv(_("Greyscale backdrop"), mem_background, 0, 255), TSPINv(_("Selection nudge pixels"), mem_nudge, 2, MAX_WIDTH), TSPINv(_("Max Pan Window Size"), max_pan, 64, 256), WDONE, CHECKv(_("Display clipboard while pasting"), show_paste), CHECKv(_("Mouse cursor = Tool"), cursor_tool), CHECKb(_("Confirm Exit"), confx, "exitToggle"), CHECKv(_("Q key quits mtPaint"), q_quit), CHECKv(_("Arrow keys scroll canvas"), arrow_scroll), CHECKv(_("Changing tool commits paste"), paste_commit), CHECKb(_("Centre tool settings dialogs"), centre, "centerSettings"), CHECKb(_("New image sets zoom to 100%"), zoom, "zoomToggle"), CHECKv(_("Zoom on cursor position"), cursor_zoom), #if GTK_MAJOR_VERSION >= 2 CHECKv(_("Mouse Scroll Wheel = Zoom"), scroll_zoom), CHECKv(_("Use menu icons"), show_menu_icons), #endif ENDIF(1), // !script WDONE, /// ---- TAB4 - FILES PAGE(_("Files")), GROUPN, TABLE2(8), TSPINa(_("Transparency index"), trans), TSPINa(_("XBM X hotspot"), hot_x), TSPINa(_("XBM Y hotspot"), hot_y), TSPINv(_("JPEG Save Quality (100=High)"), jpeg_quality, 0, 100), TSPINv(_("JPEG2000 Compression (0=Lossless)"), jp2_rate, 0, 100), TSPINv(_("PNG Compression (0=None)"), png_compression, 0, 9), TSPINv(_("Recently Used Files"), recent_files, 0, MAX_RECENT), TSPINv(_("Progress bar silence limit"), silence_limit, 0, 28), WDONE, CHECKv(_("TGA RLE Compression"), tga_RLE), CHECKv(_("Read 16-bit TGAs as 5:6:5 BGR"), tga_565), CHECKv(_("Write TGAs in bottom-up row order"), tga_defdir), CHECKv(_("Undoable image loading"), undo_load), #ifdef U_LCMS CHECKv(_("Apply colour profile"), apply_icc), #endif WDONE, BORDER(OPT, 2), #ifdef U_TIFF /// ---- TAB5 - TIFF PAGE("TIFF"), GROUPN, TABLE2(5), // !!! Here also DPI (default) TOPTDv(_("Compression (RGB)"), tiffrs, tiff_rtype), TOPTDv(_("Compression (indexed)"), tiffis, tiff_itype), TOPTDv(_("Compression (monochrome)"), tiffbs, tiff_btype), IFvx(tiff_lzma, 1), TSPINv(_("LZMA2 Compression (0=None)"), lzma_preset, 0, 9), ENDIF(1), IFvx(tiff_zstd, 1), TSPINv(_("ZSTD Compression Level"), zstd_level, ZSTD_MIN, ZSTD_MAX), ENDIF(1), WDONE, CHECKv(_("Enable predictor"), tiff_predictor), WDONE, #endif #ifdef U_WEBP /// ---- TAB6 - WebP PAGE("WebP"), GROUPN, TABLE2(3), TOPTv(_("Compression mode"), webp_presets, 0, webp_preset), TSPINv(_("V8 Save Quality (100=High)"), webp_quality, 0, 100), TSPINv(_("V8L Compression (0=None)"), webp_compression, 0, 9), WDONE, WDONE, #endif /// ---- TAB7 - LBM PAGE("LBM"), GROUPN, TABLE2(1), TOPTv(_("Channel for Mask Plane"), xchans, NUM_CHANNELS, lbm_mask), WDONE, CHECKv(_("Ignore Transparent Colour"), lbm_untrans), CHECKv(_("PackBits Compression"), lbm_pack), CHECKv(_("Write Indexed as Planar Bitmap (PBM)"), lbm_pbm), WDONE, /* !!! Interface is not scriptable */ UNLESSx(script, 1), /// ---- TAB8 - PATHS PAGE(_("Paths")), PATHv(_("Clipboard Files"), _("Select Clipboard File"), FS_CLIP_FILE, mem_clip_file), PATHs(_("HTML Browser Program"), _("Select Browser Program"), FS_SELECT_FILE, HANDBOOK_BROWSER_INI), PATHs(_("Location of Handbook index"), _("Select Handbook Index File"), FS_SELECT_FILE, HANDBOOK_LOCATION_INI), PATHs(_("Default Palette"), _("Select Default Palette"), FS_SELECT_FILE, DEFAULT_PAL_INI), PATHs(_("Default Patterns"), _("Select Default Patterns File"), FS_SELECT_FILE, DEFAULT_PAT_INI), #if GTK_MAJOR_VERSION == 3 PATHs(_("Default CSS"), _("Select Default CSS File"), FS_SELECT_FILE, DEFAULT_CSS_INI), #elif GTK_MAJOR_VERSION == 2 PATHs(_("Default Theme"), _("Select Default Theme File"), FS_SELECT_FILE, DEFAULT_THEME_INI), #endif WDONE, /// ---- TAB9 - STATUS BAR PAGE(_("Status Bar")), CHECKv(_("Canvas Geometry"), status_on[0]), CHECKv(_("Cursor X,Y"), status_on[1]), CHECKv(_("Pixel [I] {RGB}"), status_on[2]), CHECKv(_("Selection Geometry"), status_on[3]), CHECKv(_("Undo / Redo"), status_on[4]), WDONE, /// ---- TAB10 - TABLET PAGE(_("Tablet")), FVBOXB(_("Device Settings")), BORDER(LABEL, 0), REF(label_tablet_device), MLABELxr("", 5, 5, 0), BORDER(BUTTON, 0), TABLETBTN(_("Configure Device")), EVENT(CHANGE, tablet_update_device), TRIGGER, DEFBORDER(BUTTON), BORDER(TABLE, 0), XTABLE(2, 4), BORDER(CHECK, 0), TLABELx(_("Tool Variable"), 5, 5, 5), TLLABELpx(factor_str, 1, 0, 5, 5, 4), TLCHECKv(_("Size"), tablet_tool_use[0], 0, 1), TLCHECKv(_("Flow"), tablet_tool_use[1], 0, 2), TLCHECKv(_("Opacity"), tablet_tool_use[2], 0, 3), // Size/Flow/Opacity sliders BORDER(SPINSLIDE, 0), TLSPINSLIDEvs(tablet_tool_factor[0], -MAX_TF, MAX_TF, 1, 1), TLSPINSLIDEvs(tablet_tool_factor[1], -MAX_TF, MAX_TF, 1, 2), TLSPINSLIDEvs(tablet_tool_factor[2], -MAX_TF, MAX_TF, 1, 3), WDONE, WDONE, FVBOXB(_("Test Area")), COLORPATCHv("\xFF\xFF\xFF", 128, 64), // white EVENT(XMOUSE, tablet_preview), EVENT(MXMOUSE, tablet_preview), REF(label_tablet_pressure), MLABELr(""), WDONE, WDONE, ENDIF(1), // !script WDONE, // notebook /// Bottom of Prefs window OKBOX3(_("OK"), prefs_evt, _("Cancel"), prefs_evt, _("Apply"), prefs_evt), WSHOW }; #undef WBbase void pressed_preferences() { #ifdef U_TIFF char *tiffts[3][TIFF_MAX_TYPES]; #endif char txt[128]; pref_dd tdata = { { mem_undo_depth & ~1, MIN_UNDO & ~1, MAX_UNDO & ~1 }, { mem_xpm_trans, -1, mem_cols - 1 }, { mem_xbm_hot_x, -1, mem_width - 1 }, { mem_xbm_hot_y, -1, mem_height - 1 }, FALSE, TRUE, FALSE, 0, !!script_cmds, txt, inifile_get("masterPattern", ""), NULL, NULL, NULL, NULL }; // Make sure the user can only open 1 prefs window cmd_sensitive(menu_slots[MENU_PREFS], FALSE); #ifdef U_TIFF tiff_rtype = tiff_type_selector(FF_RGB, tiff_rtype, tdata.tiffrs = tiffts[0]); tiff_itype = tiff_type_selector(FF_256, tiff_itype, tdata.tiffis = tiffts[1]); tiff_btype = tiff_type_selector(FF_BW, tiff_btype, tdata.tiffbs = tiffts[2]); #endif #ifdef U_NLS { char *cur = inifile_get("languageSETTING", "system"); int i; for (i = 0; i < PREF_LANGS; i++) if (!strcmp(pref_lang_ini_code[i], cur)) tdata.lang = i; } #endif snprintf(txt, sizeof(txt), "%s (%%)", __("Factor")); if (!xchans[0]) { memcpy(xchans, channames_, sizeof(xchans)); xchans[CHN_IMAGE] = _("None"); } run_create_(pref_code, &tdata, sizeof(tdata), script_cmds); } /// KEYMAPPER WINDOW typedef struct { keymap_dd *km; char **slots, **keys, **ext; char **keylist; char *newkey; void **sel, **keyb, **keysel, **add, **remove; int slot, nslots, csize; int key, nkeys, lsize; } keysel_dd; static void refresh_keys(keysel_dd *dt) { key_dd *kd; int i = dt->km->nkeys, j = 0, n = dt->slot, l = dt->km->nkeys; for (kd = dt->km->keys , i = l; i-- > 0; kd++) if (kd->slot - 1 == n) dt->keylist[j++] = kd->name; dt->nkeys = j; cmd_reset(dt->keysel, dt); cmd_sensitive(dt->add, l < dt->km->maxkeys); cmd_sensitive(dt->remove, j); } static void slot_select(keysel_dd *dt, void **wdata, int what, void **where) { key_dd *kd; int i, j, l = dt->km->nkeys; cmd_read(where, dt); /* Init */ if (dt->nslots < dt->km->nslots) { dt->nslots = dt->km->nslots; for (kd = dt->km->keys , i = l; i-- > 0; kd++) { if ((j = kd->slot - 1) < 0) continue; if (dt->keys[j]) dt->ext[j] = ">>>"; else dt->keys[j] = kd->name; } cmd_reset(origin_slot(where), dt); } /* Collect keys for this row */ dt->key = 0; refresh_keys(dt); } static void addrem_evt(keysel_dd *dt, void **wdata, int what, void **where) { key_dd *kd; char *name, *msg; int i, j, l, m, old, add = origin_slot(where) == dt->add; /* Get */ name = dt->keylist[dt->key]; // Default is remove if (add) { cmd_read(dt->keyb, dt); name = dt->newkey; if (!name) return; // No key yet } /* Find */ l = dt->km->nkeys; kd = dt->km->keys; for (i = 0; i < l; i++) if (kd[i].name == name) break; /* Check */ m = old = dt->slot + 1; if ((i < l) && add && (old = kd[i].slot)) { if (old < 0) { alert_box(_("Error"), _("This key is builtin"), NULL); return; } msg = g_strdup_printf(__("This key is mapped to:\n\"%s\""), dt->slots[old - 1]); j = alert_box(_("Warning"), msg, _("Cancel"), old != m ? _("Remap") : NULL, NULL); g_free(msg); if (j != 2) return; } /* Delete */ if (i < l) memmove(kd + i, kd + i + 1, sizeof(*kd) * (--l - i)); /* Insert */ if (add) { kd += l++; kd->name = name; kd->slot = m; } /* Update */ dt->km->nkeys = l; /* Refresh */ old--; m--; dt->ext[old] = dt->keys[old] = dt->ext[m] = dt->keys[m] = NULL; for (kd = dt->km->keys , i = l; i-- > 0; kd++) { j = kd->slot - 1; if ((j != old) && (j != m)) continue; if (dt->keys[j]) dt->ext[j] = ">>>"; else dt->keys[j] = kd->name; } cmd_setv(dt->sel, (void *)m, LISTC_RESET_ROW); if (old != m) cmd_setv(dt->sel, (void *)old, LISTC_RESET_ROW); refresh_keys(dt); } static void done_evt(keysel_dd *dt, void **wdata, int what) { if (what != op_EVT_CANCEL) // OK/Apply cmd_setv(main_keys, dt->km, KEYMAP_MAP); if (what != op_EVT_CLICK) // OK/Cancel run_destroy(wdata); } #define WBbase keysel_dd static void *keysel_code[] = { WINDOWm(_("Keyboard Shortcuts")), MKSHRINK, // WXYWH("keysel_window", 600, 400), TALLOC(keys, csize), TALLOC(ext, csize), TALLOC(keylist, lsize), BORDER(SCROLL, 0), BORDER(BUTTON, 0), XHBOXBS, WANTMAXW, // max width XSCROLL(1, 2), // auto/always WLIST, PTXTCOLUMNp(slots, sizeof(char *), 0, 0), PTXTCOLUMNp(keys, sizeof(char *), 0, 0), PTXTCOLUMNp(ext, sizeof(char *), 0, 0), REF(sel), LISTCu(slot, nslots, slot_select), TRIGGER, VBOXS, REF(keyb), KEYBUTTON(newkey), MINWIDTH(150), XSCROLL(1, 1), // auto/auto WLIST, PTXTCOLUMNp(keylist, sizeof(char *), 0, 0), REF(keysel), LISTCu(key, nkeys, NULL), REF(add), UBUTTON(_("Add"), addrem_evt), REF(remove), UBUTTON(_("Remove"), addrem_evt), WDONE, // XVBOX WDONE, // XHBOX DEFBORDER(BUTTON), OKBOX3(_("OK"), done_evt, _("Cancel"), done_evt, _("Apply"), done_evt), CLEANUP(km), WSHOW }; #undef WBbase void keys_selector() { keysel_dd tdata; memset(&tdata, 0, sizeof(tdata)); cmd_peekv(main_keys, &tdata.km, sizeof(tdata.km), KEYMAP_MAP); tdata.slots = tdata.km->slotnames + 1; tdata.csize = tdata.km->nslots * sizeof(char *); tdata.lsize = tdata.km->maxkeys * sizeof(char *); run_create(keysel_code, &tdata, sizeof(tdata)); } mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/prefs.h000066400000000000000000000021641471325446300222350ustar00rootroot00000000000000/* prefs.h Copyright (C) 2005-2020 Mark Tyler and Dmitry Groshev This file is part of mtPaint. mtPaint 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. mtPaint 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 mtPaint in the file COPYING. */ #define HANDBOOK_BROWSER_INI "docsBrowser" #define HANDBOOK_LOCATION_INI "docsLocation" #define DEFAULT_PAL_INI "defaultPalette" #define DEFAULT_PAT_INI "defaultPatterns" #define DEFAULT_THEME_INI "defaultTheme" #define DEFAULT_CSS_INI "defaultCSS" #define MAX_TF 100 /* Tablet tool factor scale */ int tablet_tool_use[3]; // Size, flow, opacity int tablet_tool_factor[3]; // Size, flow, opacity void pressed_preferences(); void keys_selector(); mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/shifter.c000066400000000000000000000157611471325446300225640ustar00rootroot00000000000000/* shifter.c Copyright (C) 2006-2016 Mark Tyler and Dmitry Groshev This file is part of mtPaint. mtPaint 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. mtPaint 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 mtPaint in the file COPYING. */ #include "global.h" #include "mygtk.h" #include "memory.h" #include "vcode.h" #include "png.h" #include "mainwindow.h" #include "canvas.h" #include "shifter.h" #define NSHIFT 8 typedef struct { int frame[3]; int row, sfd[3]; png_color old_pal[256]; void **spinpack, **label, **slider; void **clear, **fix, **create; } shifter_dd; static int shift_play_state, shift_timer_state, spins[NSHIFT][3][3]; /* Shift palette between a & b shift times */ static void pal_shift(png_color *old_pal, int a, int b, int shift) { int i, j, d, dir = 1; if (a == b) return; // a=b => so nothing to do if (a > b) dir = a , a = b , b = dir , dir = -1; d = b - a + 1; shift %= d; j = a + dir * shift; if (j < a) j += d; for (i = a; i <= b; i++) { mem_pal[i] = old_pal[j]; if (++j > b) j = a; } } /* Set current palette to a given position in cycle */ static void shifter_set_palette(shifter_dd *dt, int pos) { int i, pos2; mem_pal_copy(mem_pal, dt->old_pal); if (!pos) return; // pos=0 => original state for (i = 0; i < NSHIFT; i++) // Implement each of the shifts { // Normalize the position shift for delay pos2 = pos / (spins[i][2][0] + 1); pal_shift(dt->old_pal, spins[i][0][0], spins[i][1][0], pos2); } } static gboolean shift_play_timer_call(gpointer data) { if (!shift_play_state) { shift_timer_state = 0; return FALSE; // Stop animating } else { shifter_dd *dt = data; int i; cmd_read(dt->slider, dt); i = dt->frame[0] + 1; if (i > dt->frame[2]) i = dt->frame[1]; cmd_set(dt->slider, i); return TRUE; } } static void shifter_slider_moved(shifter_dd *dt, void **wdata, int what, void **where) { cmd_read(where, dt); shifter_set_palette(dt, dt->frame[0]); update_stuff(UPD_PAL); } static int gcd(int a, int b) { int c; while (b > 0) { c = b; b = a % b; a = c; } return (a); } static void reset_frames(shifter_dd *dt) { char txt[130]; int i, j, l, lcm; for (lcm = 1 , i = 0; i < NSHIFT; i++) { l = spins[i][0][0] - spins[i][1][0]; if (!l) continue; // Total frames needed for shifts, including delays l = (1 + abs(l)) * (spins[i][2][0] + 1); // Calculate the lowest common multiple for all of the numbers j = gcd(lcm, l); lcm = (lcm / j) * l; } dt->frame[2] = lcm - 1; // Re-centre the slider if its out of range on the new scale if (dt->frame[0] >= lcm) dt->frame[0] = 0; cmd_setv(dt->slider, dt->frame, SPIN_ALL); // Set min/max value of slider snprintf(txt, 128, "%s = %i", _("Frames"), lcm); cmd_setv(dt->label, txt, LABEL_VALUE); } /* An input widget has changed in the dialog */ static void shifter_moved(shifter_dd *dt, void **wdata, int what, void **where) { int i, j, *v = cmd_read(where, dt); /* Scriptable parts */ if (v == &dt->row) return; if (v && (v != spins[0][0])) { j = v - dt->sfd; i = spins[dt->row][j][2]; spins[dt->row][j][0] = *v < i ? *v : i; } reset_frames(dt); } static int shift_all(shifter_dd *dt, void **wdata, int what, void **where, multi_ext *mx) { int i, j, rows = mx->nrows; /* Sanity check */ if ((rows > NSHIFT) || (mx->ncols > 3) || (mx->mincols < 3) || (mx->fractcol >= 0)) return (0); // Error for (i = 0; i < rows; i++) { int *row = mx->rows[i] + 1; for (j = 0; j < 3; j++) spins[i][j][0] = bounded(row[j], 0, spins[i][j][2]); } for (; i < NSHIFT; i++) spins[i][0][0] = spins[i][1][0] = spins[i][2][0] = 0; reset_frames(dt); return (1); } static void shift_btn(shifter_dd *dt, void **wdata, int what, void **where) { int i; if ((what == op_EVT_OK) || (what == op_EVT_CANCEL)) { shift_play_state = FALSE; // Stop mem_pal_copy(mem_pal, dt->old_pal); update_stuff(UPD_PAL); run_destroy(wdata); return; } if (what == op_EVT_CHANGE) // Play toggle { cmd_read(where, dt); if (shift_play_state && !shift_timer_state) // Start timer shift_timer_state = threads_timeout_add(100, shift_play_timer_call, dt); return; } where = origin_slot(where); if (where == dt->fix) // Button to fix palette pressed { i = dt->frame[0]; if (!i || (i > dt->frame[2])) return; // Nothing to do mem_pal_copy(mem_pal, dt->old_pal); spot_undo(UNDO_PAL); shifter_set_palette(dt, i); mem_pal_copy(dt->old_pal, mem_pal); cmd_set(dt->slider, 0); update_stuff(UPD_PAL); } else if (where == dt->clear) // Button to clear all of the values { for (i = 0; i < NSHIFT; i++) spins[i][0][0] = spins[i][1][0] = spins[i][2][0] = 0; cmd_reset(dt->spinpack, dt); shifter_moved(dt, wdata, op_EVT_CHANGE, dt->spinpack); } else if (where == dt->create) // Button to create a sequence of undo images { if (!dt->frame[2]) return; // Nothing to do for (i = 0; i <= dt->frame[2]; i++) { shifter_set_palette(dt, i); spot_undo(UNDO_PAL); } shifter_set_palette(dt, dt->frame[0]); update_stuff(UPD_PAL); } } #undef _ #define _(X) X #define WBbase shifter_dd static void *shifter_code[] = { WINDOWm(_("Palette Shifter")), XVBOXB, // !!! Originally the main vbox was that way TABLE(4, 9), BORDER(LABEL, 0), uSPIN(row, 0, 7), EVENT(CHANGE, shifter_moved), EVENT(MULTI, shift_all), TLLABELx(_("Start"), 1, 0, 0, 0, 5), uSPIN(sfd[0], 0, 255), EVENT(CHANGE, shifter_moved), TLLABELx(_("Finish"), 2, 0, 0, 0, 5), uSPIN(sfd[1], 0, 255), EVENT(CHANGE, shifter_moved), TLLABELx(_("Delay"), 3, 0, 0, 0, 5), uSPIN(sfd[2], 0, 255), EVENT(CHANGE, shifter_moved), DEFBORDER(LABEL), TLTEXT("0\n1\n2\n3\n4\n5\n6\n7", 0, 1), REF(spinpack), TLSPINPACKv(spins, 3 * NSHIFT, shifter_moved, 3, 1, 1), TRIGGER, WDONE, HBOX, UTOGGLEv(_("Play"), shift_play_state, shift_btn), UNNAME, BORDER(LABEL, 0), REF(label), XLABELcr(""), WDONE, REF(slider), SPINSLIDEa(frame), OPNAME("Play"), EVENT(CHANGE, shifter_slider_moved), HSEP, HBOX, REF(clear), BUTTONs(_("Clear"), shift_btn), REF(fix), BUTTONs(_("Fix Palette"), shift_btn), REF(create), BUTTONs(_("Create Frames"), shift_btn), CANCELBTN(_("Close"), shift_btn), uOKBTN(shift_btn), WDONE, // !!! Transient windows cannot be minimized; don't know if that's desirable here ONTOP0, WSHOW }; #undef WBbase #undef _ #define _(X) __(X) void pressed_shifter() { shifter_dd tdata; int i; memset(&tdata, 0, sizeof(tdata)); mem_pal_copy(tdata.old_pal, mem_pal); for (i = 0; i < NSHIFT; i++) { spins[i][0][2] = spins[i][1][2] = mem_cols - 1; spins[i][2][2] = 255; } shift_play_state = FALSE; // Stopped run_create_(shifter_code, &tdata, sizeof(tdata), script_cmds); } mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/shifter.h000066400000000000000000000012651471325446300225630ustar00rootroot00000000000000/* shifter.h Copyright (C) 2006-2007 Mark Tyler This file is part of mtPaint. mtPaint 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. mtPaint 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 mtPaint in the file COPYING. */ void pressed_shifter(); mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/spawn.c000066400000000000000000000634361471325446300222520ustar00rootroot00000000000000/* spawn.c Copyright (C) 2007-2021 Mark Tyler and Dmitry Groshev This file is part of mtPaint. mtPaint 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. mtPaint 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 mtPaint in the file COPYING. */ #include #include "global.h" #undef _ #define _(X) X #include "mygtk.h" #include "inifile.h" #include "memory.h" #include "vcode.h" #include "png.h" #include "canvas.h" #include "mainwindow.h" #include "spawn.h" static char *mt_temp_dir; static char *get_tempdir() { char *env; env = getenv("TMPDIR"); if (!env || !*env) env = getenv("TMP"); if (!env || !*env) env = getenv("TEMP"); #ifdef P_tmpdir if (!env || !*env) env = P_tmpdir; #endif if (!env || !*env || (strlen(env) >= PATHBUF)) // Bad if too long #ifdef WIN32 env = "\\"; #else env = "/tmp"; #endif return (env); } static char *new_temp_dir() { char *buf, *base = get_tempdir(); #ifdef HAVE_MKDTEMP buf = file_in_dir(NULL, base, "mtpaintXXXXXX", PATHBUF); if (!buf) return (NULL); if (mkdtemp(buf)) { chmod(buf, 0755); return (buf); } #else buf = tempnam(base, "mttmp"); if (!buf) return (NULL); #ifdef WIN32 /* No mkdtemp() in MinGW */ /* tempnam() may use Unix path separator */ reseparate(buf); if (!mkdir(buf)) return (buf); #else if (!mkdir(buf, 0755)) return (buf); #endif #endif free(buf); return (NULL); } /* Store index for name, or fetch it (when idx < 0) */ static int last_temp_index(char *name, int idx) { // !!! For now, use simplest model - same index regardless of name static int index; if (idx >= 0) index = idx; return (index); } typedef struct { void *next, *id; int type, rgb; char name[1]; } tempfile; static void *tempchain; static char *remember_temp_file(char *name, int type, int rgb) { static wjmem *tempstore; tempfile *tmp, *tm0; if ((tempstore || (tempstore = wjmemnew(0, 0))) && (tmp = wjmalloc(tempstore, offsetof(tempfile, name) + strlen(name) + 1, ALIGNOF(tempfile)))) { tmp->type = type; tmp->rgb = rgb; strcpy(tmp->name, name); if (mem_tempfiles) /* Have anchor - insert after it */ { tm0 = tmp->id = mem_tempfiles; tmp->next = tm0->next; tm0->next = (void *)tmp; } else /* No anchor - insert before all */ { tmp->next = tempchain; mem_tempfiles = tempchain = tmp->id = (void *)tmp; } return (tmp->name); } return (NULL); // Failed to allocate } void spawn_quit() { tempfile *tmp; for (tmp = tempchain; tmp; tmp = tmp->next) unlink(tmp->name); if (mt_temp_dir) rmdir(mt_temp_dir); } int get_tempname(char *buf, char *f, int type) { char nstub[NAMEBUF], ids[32], *c; int fd, cnt, idx; /* Prepare temp directory */ if (!mt_temp_dir) mt_temp_dir = new_temp_dir(); if (!mt_temp_dir) return (FALSE); /* Temp dir creation failed */ /* Stubify filename */ strcpy(nstub, "tmp"); if (f) /* Have original filename */ { c = strrchr(f, DIR_SEP); if (c) f = c + 1; c = strrchr(f, '.'); if (c != f) /* Extension should not be alone */ wjstrcat(nstub, NAMEBUF, f, c ? c - f : strlen(f), NULL); } f = nstub; /* Create temp file */ while (TRUE) { idx = last_temp_index(f, -1); ids[0] = 0; for (cnt = 0; cnt < 256; cnt++ , idx++) { if (idx) sprintf(ids, "%d", idx); snprintf(buf, PATHBUF, "%s" DIR_SEP_STR "%s%s.%s", mt_temp_dir, f, ids, file_formats[type].ext); fd = open(buf, O_WRONLY | O_CREAT | O_EXCL, 0644); if (fd >= 0) break; } last_temp_index(f, idx); if (fd >= 0) break; if (!strcmp(f, "tmp")) return (FALSE); /* Utter failure */ f = "tmp"; /* Try again with "tmp" */ } close(fd); return (TRUE); } static char *get_temp_file(int type, int rgb) { ls_settings settings; tempfile *tmp; unsigned char *img = NULL; char buf[PATHBUF], *f = "tmp.png"; int res; /* Use the original file if possible */ if (!mem_changed && mem_filename && (!rgb ^ (mem_img_bpp == 3)) && ((type == FT_NONE) || (detect_file_format(mem_filename, FALSE) == type))) return (mem_filename); /* Analyze name */ if ((type == FT_NONE) && mem_filename) type = file_type_by_ext(f = mem_filename, FF_SAVE_MASK); if (type == FT_NONE) type = FT_PNG; /* Use existing file if possible */ for (tmp = mem_tempfiles; tmp; tmp = tmp->next) { if (tmp->id != mem_tempfiles) break; if ((tmp->type == type) && (tmp->rgb == rgb)) return (tmp->name); } /* Create temp file */ if (!get_tempname(buf, f, type)) return (NULL); /* Fail */ /* Save image */ init_ls_settings(&settings, NULL); memcpy(settings.img, mem_img, sizeof(chanlist)); settings.pal = mem_pal; settings.width = mem_width; settings.height = mem_height; settings.bpp = mem_img_bpp; settings.colors = mem_cols; settings.ftype = type; if (rgb && (mem_img_bpp == 1)) /* Save indexed as RGB */ { settings.img[CHN_IMAGE] = img = malloc(mem_width * mem_height * 3); if (!img) return (NULL); /* Failed to allocate RGB buffer */ settings.bpp = 3; do_convert_rgb(0, 1, mem_width * mem_height, img, mem_img[CHN_IMAGE], mem_pal); } res = save_image(buf, &settings); free(img); if (res) return (NULL); /* Failed to save */ return (remember_temp_file(buf, type, rgb)); } static int escape_filename(char *buf, char *name, int tail) { #define QF 1 /* Quote it */ #define WF 2 /* Wildcard: quote or unquote */ #define UF 4 /* Unquote it */ #define EF 8 /* Escape it */ static char *spec = " !\"#$%&'()*+,:;<=>?@[]^`{|}~"; static char what[256]; char *p; int i, l, v, q = QF, d = 0; /* Initialize char types table */ if (!what[0]) { /* Let's be extra safe and quote most anything at all non-alphanumeric */ for (i = 0; i < ' '; i++) what[i] = QF; for (p = spec; *p; p++) what[(unsigned char)*p] = QF; /* Wildcards may need outquoting instead */ what['?'] = what['*'] = WF; #ifdef WIN32 /* !!! With delayed expansion '^' and '!' need extra '^' quoting * them, but I don't know how to detect if it's enabled globally, * so if it is, user is out of luck - WJ */ what['%'] |= EF; // Escape '%' #define QUOTE '"' #define ESCAPE '%' #else /* Backslashes need quoting or escaping too outside Windows */ what['\\'] = QF; /* And single quotes need outquoting and escaping */ what['\''] = UF | EF; #define QUOTE '\'' #define ESCAPE '\\' #endif } l = strlen(name); if (tail < 0) tail = l; // No outquoting wildcards at all /* See if we need to quote it, or not, or what */ for (i = 0; i < l; i++) if ((v = what[(unsigned char)name[i]] & (QF | WF | UF))) break; if (v & WF) v |= i >= tail ? UF : QF; /* If we need quoting first, start from beginning for nicer look */ if (v & QF) { if (buf) buf[d] = QUOTE; d++ , q = UF; } /* Minus sign as a first character is a special problem */ if (name[0] == '-') { if (buf) buf[d] = '.' , buf[d + 1] = DIR_SEP; d += 2; } for (i = 0; i < l; i++) { v = what[(unsigned char)name[i]]; if (v & WF) // Wildcard v |= i >= tail ? UF : QF; if (v & q) // Quote/outquote { if (buf) buf[d] = QUOTE; q ^= QF | UF; d++; } if (v & EF) // Escape { if (buf) buf[d] = ESCAPE; d++; } if (buf) buf[d] = name[i]; d++; } if (q & UF) // Add end quote { if (buf) buf[d] = QUOTE; d++; } if (buf) buf[d] = 0; // Terminate the string return (d); #undef QUOTE #undef ESCAPE #undef QF #undef WF #undef UF #undef EF } static char *pat_chars = "%fNxywhXYWHCTBASM"; enum { PAT_percent = 0, PAT_f, PAT_N, PAT_x, PAT_y, PAT_w, PAT_h, PAT_X, PAT_Y, PAT_W, PAT_H, PAT_C, PAT_T, PAT_B, PAT_A, PAT_S, PAT_M, PAT_NONE }; char *interpolate_line(char *pattern, int cmd) { char buf[64], *fname = NULL, *line = NULL, *pat = pattern; int rgb = mem_img_bpp == 3, fform = FT_NONE, extend = !cmd; int i, j, l, rect[4]; while (cmd) { /* Skip initial whitespace if any */ pat += strspn(pat, " \t"); /* Finish if not a transform request */ if (*pat != '>') break; l = strcspn(++pat, "> \t"); if (!strncasecmp("RGB", pat, l)) rgb = TRUE; else if (!strncmp("%", pat, l)) extend = TRUE; else { for (i = FT_NONE + 1; i < NUM_FTYPES; i++) { fformat *ff = file_formats + i; if ((ff->flags & FF_IMAGE) && !(ff->flags & FF_NOSAVE) && (!strncasecmp(ff->name, pat, l) || !strncasecmp(ff->ext, pat, l) || (ff->ext2[0] && !strncasecmp(ff->ext2, pat, l)))) fform = i; } } pat += l; } if (!extend && !strstr(pattern, "%f")) return (pattern); // Leave alone if (fform != FT_NONE) { unsigned int flags = file_formats[fform].flags; if (rgb && !(flags & FF_RGB)) fform = FT_NONE; // No way else if (flags & FF_SAVE_MASK); // Is OK else if (flags & FF_RGB) rgb = TRUE; // Fallback else fform = FT_NONE; // Give up } /* Current selection */ memset(rect, 0, sizeof(rect)); if (marq_status > MARQUEE_NONE) marquee_at(rect); while (TRUE) { char c, *res, *p = pat; l = 0; while ((c = *p++)) { i = PAT_NONE; if ((c == '%') && *p && ((res = strchr(pat_chars, *p))) && (extend || (res == pat_chars + PAT_f))) i = res - pat_chars; switch (i) { /* Current file, quoted, for processing */ case PAT_f: p++; if (!cmd) continue; // No temp files in info mode if (!fname) { fname = get_temp_file(fform, rgb); /* Temp save failed */ if (!fname) return (NULL); } /* Add whatever quotes the filename needs */ j = escape_filename(line ? line + l : NULL, fname, -1); l += j; continue; /* Original filename, unquoted, for displaying &c. */ case PAT_N: p++; if (!mem_filename) continue; j = strlen(mem_filename); if (line) memcpy(line + l, mem_filename, j); l += j; continue; /* Selected area */ case PAT_x: case PAT_y: case PAT_w: case PAT_h: j = rect[i - PAT_x]; break; /* Cursor position */ case PAT_X: j = perim_wx; break; case PAT_Y: j = perim_wy; break; /* Image geometry */ case PAT_W: j = mem_width; break; case PAT_H: j = mem_height; break; /* Colors in palette */ case PAT_C: j = mem_cols; break; /* Transparent index */ case PAT_T: j = mem_xpm_trans; break; /* Bytes per pixel */ case PAT_B: j = mem_img_bpp; break; /* Extra channels */ case PAT_A: case PAT_S: case PAT_M: j = !!mem_img[CHN_ALPHA + i - PAT_A]; break; /* Doubled percent sign */ case PAT_percent: p++; // Fallthrough /* Everything else */ default: if (line) line[l] = c; l++; continue; } /* Anything expanding to a number */ j = sprintf(buf, "%d", j); if (line) memcpy(line + l, buf, j); l += j; p++; } if (line) return (line); line = calloc(l + 1, 1); if (!line) return (NULL); // No memory to expand this pattern } } int spawn_expansion(char *cline, char *directory) // Replace %f with "current filename", then run via shell { int res = -1; char *s1; #ifdef WIN32 char *argv[4] = { getenv("COMSPEC"), "/C", cline, NULL }; #else char *argv[4] = { "sh", "-c", cline, NULL }; #endif s1 = interpolate_line(cline, TRUE); if (!s1) return (-1); else if (s1 != cline) { argv[2] = s1; res = spawn_process(argv, directory); free(s1); } else { res = spawn_process(argv, directory); } // Note that on Linux systems, returning 0 means that the shell was // launched OK, but gives no info on the success of the program being run by the shell. // To find out what happened you will need to use the output window. // MT 18-1-2007 return res; } // Front End stuff static char *faction_ini[3] = { "fact%dName", "fact%dCommand", "fact%dDir" }; #define MAXNAMELEN 2048 typedef struct { char name[MAXNAMELEN]; char cmd[PATHTXT]; // UTF-8 char dir[PATHBUF]; // system encoding } spawn_row; typedef struct { spawn_row *strs; char *name, *cmd; void **list, **group; int idx, nidx, cnt; int lock; char dir[PATHBUF]; } spawn_dd; void pressed_file_action(int item) { char *comm, *dir, txt[64]; sprintf(txt, faction_ini[1], item); comm = inifile_get(txt,""); sprintf(txt, faction_ini[2], item); dir = inifile_get(txt,""); spawn_expansion(comm, dir); } static void faction_changed(spawn_dd *dt, void **wdata, int what, void **where) { void *cause; spawn_row *rp; if (dt->lock) return; cause = cmd_read(where, dt); rp = dt->strs + dt->idx; if (cause == dt->dir) strncpy(rp->dir, dt->dir, sizeof(rp->dir)); else { strncpy0(rp->name, dt->name, sizeof(rp->name)); strncpy0(rp->cmd, dt->cmd, sizeof(rp->cmd)); cmd_setv(dt->list, (void *)dt->idx, LISTC_RESET_ROW); } } static void faction_select_row(spawn_dd *dt, void **wdata, int what, void **where) { spawn_row *rp; cmd_read(where, dt); if (dt->nidx == dt->idx) return; // no change dt->lock = TRUE; /* Get strings from array, and reset entries */ rp = dt->strs + (dt->idx = dt->nidx); dt->name = rp->name; dt->cmd = rp->cmd; strncpy(dt->dir, rp->dir, PATHBUF); cmd_reset(dt->group, dt); dt->lock = FALSE; } static void update_faction_menu() // Populate menu { int i, v, items = 0; char txt[64], *nm, *cm; void **slot; /* Show valid slots in menu */ for (i = 1; i <= FACTION_PRESETS_TOTAL; i++) { sprintf(txt, faction_ini[0], i); nm = inifile_get(txt, ""); sprintf(txt, faction_ini[1], i); cm = inifile_get(txt, ""); slot = menu_slots[MENU_FACTION1 - 1 + i]; if ((v = nm && nm[0] && (nm[0] != '#') && cm && cm[0] && (cm[0] != '#'))) cmd_setv(slot, nm, LABEL_VALUE); cmd_showhide(slot, v); // Hide by default cmd_sensitive(slot, v); // Make insensitive for shortcuts items += v; } /* Hide separator if no valid slots */ cmd_showhide(menu_slots[MENU_FACTION_S], items); } void init_factions() { #ifndef WIN32 int i, j; static char *row_def[][3] = { {"View EXIF data (leafpad)", "exif %f | leafpad"}, {"View filesystem data (xterm)", "xterm -hold -e ls -l %f"}, {"Edit in Gimp", "gimp %f"}, {"View in GQview", "gqview %f"}, {"Print image", "kprinter %f"}, {"Email image", "seamonkey -compose attachment=file://%f"}, {"Send image to Firefox", "firefox %f"}, {"Send image to OpenOffice", "soffice %f"}, {"Edit Clipboards", "mtpaint ~/.clip*"}, {"Time delayed screenshot", "sleep 10; mtpaint -s &"}, {"View image information", "xterm -hold -sb -rightbar -geometry 100x100 -e identify -verbose %f"}, {"#Create temp directory", "mkdir ~/images"}, {"#Remove temp directory", "rm -rf ~/images"}, {"#GIF to PNG conversion (in situ)", "mogrify -format png *.gif"}, {"#ICO to PNG conversion (temp directory)", "ls --file-type *.ico | xargs -I FILE convert FILE ~/images/FILE.png"}, {"Convert image to ICO file", "mogrify -format ico %f"}, {"Create thumbnails in temp directory", "ls --file-type * | xargs -I FILE convert FILE -thumbnail 120x120 -sharpen 1 -quality 95 ~/images/th_FILE.jpg"}, {"Create thumbnails (in situ)", "ls --file-type * | xargs -I FILE convert FILE -thumbnail 120x120 -sharpen 1 -quality 95 th_FILE.jpg"}, {"Peruse temp images", "mtpaint ~/images/*"}, {"Rename *.jpeg to *.jpg", "rename .jpeg .jpg *.jpeg"}, {"Remove spaces from filenames", "for file in *\" \"*; do mv \"$file\" `echo $file | sed -e 's/ /_/g'`; done"}, {"Remove extra .jpg. from filename", "rename .jpg. . *.jpg.jpg"}, // {"", ""}, {NULL, NULL, NULL} }, txt[64]; for (i = 0; row_def[i][0]; i++) // Needed for first time usage - populate inifile list { for (j = 0; j < 3; j++) { sprintf(txt, faction_ini[j], i + 1); inifile_get(txt, row_def[i][j]); } } #endif update_faction_menu(); // Prepare menu } static void faction_btn(spawn_dd *dt, void **wdata, int what, void **where) { spawn_row *rp = dt->strs; char *s, txt[64], buf[PATHBUF]; int i, j, idx[FACTION_ROWS_TOTAL]; if (what == op_EVT_CLICK) /* Execute */ { gtkncpy(buf, dt->cmd, PATHBUF); spawn_expansion(buf, dt->dir); return; } cmd_peekv(dt->list, idx, sizeof(idx), LISTC_ORDER); for (i = 0; i < FACTION_ROWS_TOTAL; i++ , rp++) { for (j = 0; j < 3; j++) { sprintf(txt, faction_ini[j], idx[i] + 1); if (!j) s = rp->name; else if (j == 1) gtkncpy(s = buf, rp->cmd, sizeof(buf)); else s = rp->dir; inifile_set(txt, s); } } update_faction_menu(); run_destroy(wdata); } #define WBbase spawn_dd static void *spawn_code[] = { WINDOWm(_("Configure File Actions")), DEFSIZE(500, 400), XVBOXB, // !!! Originally the main vbox was that way XSCROLL(1, 1), // auto/auto WLIST, NTXTCOLUMND(_("Action"), spawn_row, name, 200, 0), NTXTCOLUMND(_("Command"), spawn_row, cmd, 0 /* 200 */, 0), COLUMNDATA(strs, sizeof(spawn_row)), CLEANUP(strs), REF(list), LISTCd(nidx, cnt, faction_select_row), TRIGGER, REF(group), GROUPR, BORDER(ENTRY, 0), FHBOXB(_("Action")), XENTRY(name), EVENT(CHANGE, faction_changed), WDONE, FHBOXB(_("Command")), XENTRY(cmd), EVENT(CHANGE, faction_changed), WDONE, PATH(_("Directory"), _("Select Directory"), FS_SELECT_DIR, dir), EVENT(CHANGE, faction_changed), OKBOX3(_("OK"), faction_btn, _("Cancel"), NULL, _("Execute"), faction_btn), WSHOW }; #undef WBbase void pressed_file_configure() { spawn_dd tdata; spawn_row *rp; char txt[64], *s; int i, j; rp = tdata.strs = calloc(FACTION_ROWS_TOTAL, sizeof(spawn_row)); if (!rp) return; // Not enough memory for (i = 1; i <= FACTION_ROWS_TOTAL; i++ , rp++) { for (j = 0; j < 3; j++) { sprintf(txt, faction_ini[j], i); s = inifile_get(txt, ""); if (!j) strncpy0(rp->name, s, sizeof(rp->name)); else if (j == 1) gtkuncpy(rp->cmd, s, sizeof(rp->cmd)); else strncpy0(rp->dir, s, sizeof(rp->dir)); } } tdata.name = tdata.cmd = ""; tdata.dir[0] = '\0'; tdata.idx = -1; tdata.nidx = 0; tdata.cnt = FACTION_ROWS_TOTAL; tdata.lock = FALSE; run_create(spawn_code, &tdata, sizeof(tdata)); } // Process spawning code #ifdef WIN32 /* With Glib's g_spawn*() smart-ass tricks making it utterly unusable in * Windows, the only way is to reimplement the functionality - WJ */ #define WIN32_LEAN_AND_MEAN #include int spawn_process(char *argv[], char *directory) { PROCESS_INFORMATION pi; STARTUPINFO st; gchar *cmdline, *c; int res; memset(&pi, 0, sizeof(pi)); memset(&st, 0, sizeof(st)); st.cb = sizeof(st); cmdline = g_strjoinv(" ", argv); if (directory && !directory[0]) directory = NULL; c = g_locale_from_utf8(cmdline, -1, NULL, NULL, NULL); if (c) { g_free(cmdline); cmdline = c; c = NULL; } if (directory) { c = g_locale_from_utf8(directory, -1, NULL, NULL, NULL); if (c) directory = c; } res = CreateProcessA(NULL, cmdline, NULL, NULL, FALSE, /* CREATE_NEW_CONSOLE | */ CREATE_DEFAULT_ERROR_MODE | NORMAL_PRIORITY_CLASS, NULL, directory, &st, &pi); g_free(cmdline); g_free(c); if (!res) return (1); CloseHandle(pi.hProcess); CloseHandle(pi.hThread); return (0); } #else #include #include #include int spawn_process(char *argv[], char *directory) { pid_t child, grandchild; int res = -1, err, fd_flags, fds[2], status; child = fork(); if ( child < 0 ) return 1; if (child == 0) // Child { if (pipe(fds) == -1) _exit(1); // Set up the pipe grandchild = fork(); if (grandchild == 0) // Grandchild { if (directory) chdir(directory); if (close(fds[0]) != -1) // Close the read pipe /* Make the write end close-on-exec */ if ((fd_flags = fcntl(fds[1], F_GETFD)) != -1) if (fcntl(fds[1], F_SETFD, fd_flags | FD_CLOEXEC) != -1) execvp(argv[0], &argv[0]); /* Run program */ /* If we are here, an error occurred */ /* Send the error code to the parent */ err = errno; write(fds[1], &err, sizeof(err)); _exit(1); } /* Close the write pipe - has to be done BEFORE read */ close(fds[1]); /* Get the error code from the grandchild */ if (grandchild > 0) res = read(fds[0], &err, sizeof(err)); close(fds[0]); // Close the read pipe _exit(res); } waitpid(child, &status, 0); // Wait for child to die res = WEXITSTATUS(status); // Find out the childs exit value return (res); } #endif // Wrapper for animated GIF handling, or other builtin actions #ifdef U_ANIM_IMAGICK /* Use Image Magick for animated GIF processing; not really recommended, * because it is many times slower than Gifsicle, and less efficient */ /* !!! Image Magick version prior to 6.2.6-3 won't work properly */ #define CMD_GIF_CREATE \ "convert ((srcmask)) -layers optimize -set delay ((delay)) -loop 0 ((dest))" #define CMD_GIF_PLAY "animate ((src)) &" #else /* Use Gifsicle; the default choice for animated GIFs */ /* global colourmaps, suppress warning, high optimizations, background * removal method, infinite loops, ensure result works with Java & MS IE */ #define CMD_GIF_CREATE \ "gifsicle --colors 256 -w -O2 -D 2 -l0 --careful -d ((delay)) ((srcmask)) -o ((dest))" #define CMD_GIF_PLAY "gifview -a ((src)) &" #endif /* 'gifviev' and 'animate' both are X-only */ #if (GTK_MAJOR_VERSION > 1) && !defined(GDK_WINDOWING_X11) #undef CMD_GIF_PLAY #define CMD_GIF_PLAY NULL #endif /* Windows shell does not know "&", nor needs it to run mtPaint detached */ #ifndef WIN32 #define CMD_DETACH " &" #else /* WIN32 */ #define CMD_DETACH #ifndef WEXITSTATUS #define WEXITSTATUS(A) ((A) & 0xFF) #endif #endif static char *def_actions[DA_NCODES] = { CMD_GIF_CREATE, CMD_GIF_PLAY, "mtpaint -g ((delay)) -w ((src)).\"???\" -w ((src)).\"????\"", "rsvg-convert ((w)) ((h)) -o ((dest)) ((src))", "vwebp ((src))" CMD_DETACH, "ffplay -loop 0 ((src))" CMD_DETACH, }; static char *interpolate_action(char *pattern, da_settings *ds) { char buf[64], *line = NULL; int j, l, n; while (TRUE) { char c, *res, *p = pattern; l = 0; while ((c = *p++)) { /* Substitutions are ((var)) , copy everything else */ if ((c != '(') || (*p != '(') || (p[1] == '(') || !((res = strstr(p + 1, "))")))) { if (line) line[l] = c; l++; continue; } n = res - ++p; // Position & length of var name j = 0; if (!n); // Paranoia: skip if no name /* Source file */ else if (!strncmp(p, "src", n)) j = escape_filename(line ? line + l : NULL, ds->sname, -1); /* Source mask */ else if (!strncmp(p, "srcmask", n)) { char *w = strrchr(ds->sname, DIR_SEP); j = escape_filename(line ? line + l : NULL, ds->sname, w ? w - ds->sname : 0); } /* Destination file */ else if (!strncmp(p, "dest", n)) j = escape_filename(line ? line + l : NULL, ds->dname, -1); /* Delay in 1/100s */ else if (!strncmp(p, "delay", n)) j = sprintf(line ? line + l : buf, "%d", ds->delay); /* Width */ else if (!strncmp(p, "w", n)) { if (ds->width) j = sprintf(line ? line + l : buf, "-w %d", ds->width); } /* Height */ else if (!strncmp(p, "h", n)) { if (ds->height) j = sprintf(line ? line + l : buf, "-h %d", ds->height); } /* Unknown vars are skipped */ l += j; // Add new part to output p += n + 2; } if (line) return (line); line = calloc(l + 1, 1); if (!line) return (NULL); // No memory to expand this pattern } } int run_def_action(int action, char *sname, char *dname, int delay) { da_settings ds; memset(&ds, 0, sizeof(ds)); ds.sname = sname; ds.dname = dname; ds.delay = delay; return (run_def_action_x(action, &ds)); } int run_def_action_x(int action, da_settings *settings) { char *msg, *c8, *command = NULL; int res, code; if ((action >= 0) && (action < DA_NCODES)) // Paranoia command = def_actions[action]; if (command) command = interpolate_action(command, settings); if (!command) return (-1); res = system(command); if (res) { if (res > 0) code = WEXITSTATUS(res); else code = res; c8 = gtkuncpy(NULL, command, 0); msg = g_strdup_printf(__("Error %i reported when trying to run %s"), code, c8); alert_box(_("Error"), msg, NULL); g_free(msg); g_free(c8); } free(command); return (res); } #ifdef WIN32 #include #define HANDBOOK_LOCATION_WIN "..\\docs\\index.html" #else /* Linux */ #define HANDBOOK_BROWSER "seamonkey" #define HANDBOOK_LOCATION "/usr/doc/mtpaint/index.html" #define HANDBOOK_LOCATION2 "/usr/share/doc/mtpaint/index.html" #endif int show_html(char *browser, char *docs) { char buf[PATHBUF + 2], buf2[PATHBUF]; int i=-1; #ifdef WIN32 char *r; if (!docs || !docs[0]) { /* Use default path relative to installdir */ docs = buf + 1; i = GetModuleFileNameA(NULL, docs, PATHBUF); if (!i) return (-1); r = strrchr(docs, '\\'); if (!r) return (-1); r[1] = 0; strnncat(docs, HANDBOOK_LOCATION_WIN, PATHBUF); } #else /* Linux */ char *argv[5]; if (!docs || !docs[0]) { docs = HANDBOOK_LOCATION; if (valid_file(docs) < 0) docs = HANDBOOK_LOCATION2; } #endif else docs = gtkncpy(buf + 1, docs, PATHBUF); if ((valid_file(docs) < 0)) { alert_box( _("Error"), _("I am unable to find the documentation. Either you need to download the mtPaint Handbook from the web site and install it, or you need to set the correct location in the Preferences window."), NULL); return (-1); } #ifdef WIN32 if (browser && !browser[0]) browser = NULL; if (browser) { /* Quote the filename */ i = strlen(docs); buf[0] = docs[i] = '"'; docs[i + 1] = '\0'; /* Rearrange parameters */ docs = gtkncpy(buf2, browser, PATHBUF); browser = buf; } if ((unsigned int)ShellExecuteA(NULL, "open", docs, browser, NULL, SW_SHOW) <= 32) i = -1; else i = 0; #else argv[1] = docs; argv[2] = NULL; /* Try to use default browser */ if (!browser || !browser[0]) { argv[0] = "xdg-open"; i = spawn_process(argv, NULL); if (!i) return (0); // System has xdg-utils installed // No xdg-utils - try "BROWSER" variable then browser = getenv("BROWSER"); } else browser = gtkncpy(buf2, browser, PATHBUF); if (!browser) browser = HANDBOOK_BROWSER; argv[0] = browser; i = spawn_process(argv, NULL); #endif if (i) alert_box( _("Error"), _("There was a problem running the HTML browser. You need to set the correct program name in the Preferences window."), NULL); return (i); } mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/spawn.h000066400000000000000000000035371471325446300222530ustar00rootroot00000000000000/* spawn.h Copyright (C) 2007-2021 Mark Tyler and Dmitry Groshev This file is part of mtPaint. mtPaint 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. mtPaint 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 mtPaint in the file COPYING. */ #define FACTION_ROWS_TOTAL 25 #define FACTION_PRESETS_TOTAL 15 // This number must exactly match the number of menu items declared char *interpolate_line(char *pattern, int cmd); // Percent variable interpolation int spawn_process(char *argv[], char *directory); // argv must be NULL terminated! int spawn_expansion(char *cline, char *directory); // Replace %f with "current filename", then run via shell void pressed_file_configure(); void pressed_file_action(int item); void init_factions(); // Initialize file action menu int get_tempname(char *buf, char *f, int type); // Create tempfile for name void spawn_quit(); // Delete temp files // Default action codes enum { DA_GIF_CREATE = 0, DA_GIF_PLAY, DA_GIF_EDIT, DA_SVG_CONVERT, DA_WEBP_PLAY, DA_APNG_PLAY, DA_NCODES }; // Run a regular default action int run_def_action(int action, char *sname, char *dname, int delay); /* All-in-one transport container for default actions */ typedef struct { char *sname; char *dname; int delay; // in 1/100s of a second int width, height; } da_settings; // Run any default action int run_def_action_x(int action, da_settings *settings); int show_html(char *browser, char *docs); mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/thread.c000066400000000000000000000273361471325446300223700ustar00rootroot00000000000000/* thread.c Copyright (C) 2009-2017 Dmitry Groshev This file is part of mtPaint. mtPaint 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. mtPaint 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 mtPaint in the file COPYING. */ #include "global.h" #undef _ #define _(X) X #include "mygtk.h" #include "memory.h" #include "thread.h" int maxthreads; #ifdef U_THREADS #include #if GTK_MAJOR_VERSION == 1 #ifdef G_THREADS_IMPL_POSIX #include #include #else #error "Non-POSIX threads not supported with GTK+1" #endif #endif /* Pointless churn is pointless */ G_GNUC_BEGIN_IGNORE_DEPRECATIONS /* Determine number of CPUs/cores */ static int ncores; #ifdef WIN32 #define WIN32_LEAN_AND_MEAN #include static int numcpus() { SYSTEM_INFO info; GetSystemInfo(&info); return (info.dwNumberOfProcessors); } #else static int numcpus() { #ifdef _SC_NPROCESSORS_ONLN return (sysconf(_SC_NPROCESSORS_ONLN)); #elif defined _SC_NPROC_ONLN return (sysconf(_SC_NPROC_ONLN)); #elif defined _SC_CRAY_NCPU return (sysconf(_SC_CRAY_NCPU)); #else return (1); #endif } #endif int helper_threads() { int nt = maxthreads; if (!nt) /* Use as many threads as there are cores */ { if (!ncores) /* Autodetect number of cores */ { ncores = numcpus(); if (ncores < 1) ncores = 1; } nt = ncores; } return (nt); } #define THREAD_ALIGN 128 #define THREAD_DEALIGN 4096 int image_threads(int w, int h) { int n = h / 3; // This can overflow, but mtPaint is unlikely to handle a 8+ Tb image anyway :-) int m = ((size_t)w * h) / (THREAD_DEALIGN + THREAD_ALIGN); return (n < m ? n : m); } /* This function takes *two* variable-length NULL-terminated sequences of * pointer/size pairs; the first sequence describes shared buffers, the * second, thread-local ones. * The memory block it allocates is set up the following way: * - threaddata structure with array of tcb pointers; * - shared buffers (aligned); * - tcb (thread-aligned) for main thread; * - data block (thread-aligned) for main thread; * - private buffers (aligned) for main thread; * - the same for each aux thread in order. */ threaddata *talloc(int flags, int tmax, void *data, int dsize, ...) { va_list args; threaddata *res; char *tmp, *tm2, *tcb0, *tdata; tcb *thread; size_t align = 0, talign = THREAD_ALIGN; size_t sz, tdsz, sharesz, threadsz; int i, nt; if (tmax < 1) tmax = 1; // No less than 1 thread nt = helper_threads(); if (tmax > nt) tmax = nt; if ((flags & MA_ALIGN_MASK) == MA_ALIGN_DOUBLE) align = sizeof(double) - 1; /* Uncomment if data alignment ever exceeds cache line size */ /* if (align >= talign) talign = align + 1; */ /* Calculate space */ va_start(args, dsize); sharesz = 0; while (va_arg(args, void *)) { sharesz = (sharesz + align) & ~align; sharesz += va_arg(args, int); } threadsz = 0; while (va_arg(args, void *)) { threadsz = (threadsz + align) & ~align; threadsz += va_arg(args, int); } va_end(args); if ((tmax == 1) && !(sharesz + threadsz) && (flags & MA_FLAG_NONE)) return (MEM_NONE); sz = (sizeof(tcb) + talign - 1) & ~(talign - 1); sz = (sz + dsize + align) & ~align; threadsz = (sz + threadsz + talign - 1) & ~(talign - 1); if (!(threadsz & (THREAD_DEALIGN - 1))) threadsz += talign; /* Allocate space */ while (TRUE) { tdsz = sizeof(threaddata) + sizeof(tcb *) * (tmax - 1); sz = align ? align + 1 : 0; sz += tdsz + sharesz + talign * 2 + threadsz * tmax; tmp = calloc(1, sz); if (tmp) break; if (!(tmax >>= 1)) return (NULL); } /* Decide what goes where */ res = (void *)tmp; tmp += tdsz; tmp = ALIGNED(tmp, align + 1); // Now points to shared space tcb0 = tmp + sharesz; tcb0 = ALIGNED(tcb0, talign); tm2 = ALIGNED(tcb0, THREAD_DEALIGN); if (tcb0 == tm2) tcb0 += talign; // Now points to tcb0 /* Set up tcbs */ sz = (sizeof(tcb) + talign - 1) & ~(talign - 1); res->count = tmax; res->chunks = -1; // Disabled by default for (i = 0; i < tmax; i++) { res->threads[i] = thread = (void *)(tcb0 + threadsz * i); thread->index = i; thread->count = tmax; thread->tdata = res; thread->data = (void *)((char *)thread + sz); } /* Set up shared data pointers */ va_start(args, dsize); memcpy(tdata = res->threads[0]->data, data, dsize); sz = 0; while ((tm2 = va_arg(args, void *))) { tdsz = va_arg(args, int); if (!tdsz && (flags & MA_SKIP_ZEROSIZE)) continue; tm2 += tdata - (char *)data; *(void **)tm2 = (void *)(tmp + sz); sz = (sz + tdsz + align) & ~align; } for (i = 1; i < tmax; i++) memcpy(res->threads[i]->data, tdata, dsize); /* Set up private data pointers */ sz = dsize; while ((tmp = va_arg(args, void *))) { tdsz = va_arg(args, int); if (!tdsz && (flags & MA_SKIP_ZEROSIZE)) continue; sz = (sz + align) & ~align; for (i = 0; i < tmax; i++) { tdata = res->threads[i]->data; tm2 = tmp + (tdata - (char *)data); *(void **)tm2 = (void *)(tdata + sz); } sz += tdsz; } va_end(args); /* Copy the data block of thread 0 back, for convenience */ memcpy(data, res->threads[0]->data, dsize); /* Return the prepared block */ return (res); } int thread_progress(tcb *thread) { tcb **tp = thread->tdata->threads; int i, j, n = thread->count; for (i = j = 0; i < n; i++) j += tp[i]->progress; if (!progress_update((float)j / thread->tsteps)) return (FALSE); for (i = 0; i < n; i++) tp[i]->stop = TRUE; return (TRUE); } static void thread_chunk(tcb *thread) { threaddata *tdata = thread->tdata; thread_func tf = tdata->what; int nx, step = thread->nsteps; while (TRUE) { tf(thread); if (thread->stop || thread->stopped) break; nx = thread_xadd(&tdata->done, step); if (nx >= tdata->total) break; thread->step0 = nx; thread->nsteps = step > tdata->total - nx ? tdata->total - nx : step; } thread_done(thread); } int threads_running; int launch_threads(thread_func thread, threaddata *tdata, char *title, int total) { tcb *tp; clock_t uninit_(before), now; int i, j, n0, n1, flag = FALSE; #if GTK_MAJOR_VERSION == 1 pthread_t tid; pthread_attr_t attr; int attr_failed; attr_failed = pthread_attr_init(&attr) || #ifdef PTHREAD_SCOPE_SYSTEM pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM) || #endif pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); #endif /* Prepare chunking */ tdata->threads[0]->tsteps = tdata->total = total; i = tdata->count; j = tdata->chunks; if ((i > 1) && (j > 1)) j *= i , total = ((total + j - 1) / j) * i; tdata->done = n1 = total; /* Launch aux threads */ tdata->what = thread; if (tdata->chunks >= 0) thread = thread_chunk; threads_running = TRUE; for (i -= 1; i > 0; i--) { tp = tdata->threads[i]; /* Reinit thread state */ tp->stop = FALSE; tp->stopped = FALSE; tp->progress = 0; /* Allocate work to thread */ tp->step0 = n0 = (n1 * i) / (i + 1); tp->nsteps = n1 - n0; #if GTK_MAJOR_VERSION == 1 if (attr_failed || pthread_create(&tid, &attr, (void *(*)(void *))thread, tp)) #else if (!g_thread_create((GThreadFunc)thread, tp, FALSE, NULL)) #endif tp->stop = TRUE , tp->stopped = TRUE; // Failed to launch else n1 = n0 , flag = TRUE; // Success - work is now being done } threads_running = flag; #if GTK_MAJOR_VERSION == 1 pthread_attr_destroy(&attr); #endif /* Put main thread to work */ tp = tdata->threads[0]; tp->stop = FALSE; tp->stopped = FALSE; tp->progress = 0; tp->step0 = 0; tp->nsteps = n1; if (title) progress_init(title, 1); /* Let init/end be done outside */ thread(tp); /* Wait for aux threads to finish, or user to cancel the job */ flag = 0; while (TRUE) { for (i = j = 1; i < tdata->count; i++) j += tdata->threads[i]->stopped; if (j >= tdata->count) break; // All threads finished if (tdata->threads[0]->stop) // Cancellation requested { if (!flag) before = clock(); else { now = clock(); if (now - before >= 5 * CLOCKS_PER_SEC) { /* Major catastrophe - hung thread(s) */ flag = 2; break; } } flag |= 1; } if (!tdata->silent) thread_progress(tdata->threads[0]); /* Let 'em run */ #if GTK_MAJOR_VERSION == 1 sched_yield(); #else g_thread_yield(); #endif } threads_running = FALSE; if (title) progress_end(); /* !!! Even with OS threading, killing a thread is not supported on some systems, * and if a thread needs killing, it likely has corrupted some data already - WJ */ if (flag <= 1) return (0); // All OK if (!tdata->silent) alert_box(_("Error"), _("Helper thread is not responding. Save your work and exit the program."), NULL); return (-1); } #if !defined(__G_ATOMIC_H__) && !defined(HAVE__SFA) int thread_xadd(volatile int *var, int n) { DEF_MUTEX(xadd_lock); int v; LOCK_MUTEX(xadd_lock); v = *var; *var += n; UNLOCK_MUTEX(xadd_lock); return (v); } #endif #else /* Multithreading disabled - functions manage one thread only */ threaddata *talloc(int flags, int tmax, void *data, int dsize, ...) { va_list args; threaddata *res; char *tmp, *tm2, *tcb0, *tdata; tcb *thread; size_t align = 0, talign = sizeof(double); size_t sz, tdsz, sharesz, threadsz; if ((flags & MA_ALIGN_MASK) == MA_ALIGN_DOUBLE) align = sizeof(double) - 1; /* Uncomment if data alignment here exceeds sizeof(double) */ /* if (align >= talign) talign = align + 1; */ /* Calculate space */ va_start(args, dsize); sharesz = 0; while (va_arg(args, void *)) { sharesz = (sharesz + align) & ~align; sharesz += va_arg(args, int); } threadsz = 0; while (va_arg(args, void *)) { threadsz = (threadsz + align) & ~align; threadsz += va_arg(args, int); } va_end(args); if (!(sharesz + threadsz) && (flags & MA_FLAG_NONE)) return (MEM_NONE); sz = (sizeof(tcb) + talign - 1) & ~(talign - 1); sz = (sz + dsize + align) & ~align; threadsz = (sz + threadsz + talign - 1) & ~(talign - 1); /* Allocate space */ sz = align ? align + 1 : 0; sz += sizeof(threaddata) + sharesz + talign + threadsz; tmp = calloc(1, sz); if (!tmp) return (NULL); /* Decide what goes where */ res = (void *)tmp; tmp += sizeof(threaddata); tmp = ALIGNED(tmp, align + 1); // Now points to shared space tcb0 = tmp + sharesz; tcb0 = ALIGNED(tcb0, talign); /* Set up one tcb */ sz = (sizeof(tcb) + talign - 1) & ~(talign - 1); res->count = 1; res->threads[0] = thread = (void *)tcb0; thread->index = 0; thread->count = 1; thread->tdata = res; thread->data = (void *)((char *)thread + sz); /* Set up shared data pointers */ va_start(args, dsize); memcpy(tdata = res->threads[0]->data, data, dsize); sz = 0; while ((tm2 = va_arg(args, void *))) { tdsz = va_arg(args, int); if (!tdsz && (flags & MA_SKIP_ZEROSIZE)) continue; tm2 += tdata - (char *)data; *(void **)tm2 = (void *)(tmp + sz); sz = (sz + tdsz + align) & ~align; } /* Set up private data pointers */ sz = dsize; while ((tm2 = va_arg(args, void *))) { tdsz = va_arg(args, int); if (!tdsz && (flags & MA_SKIP_ZEROSIZE)) continue; sz = (sz + align) & ~align; tm2 += tdata - (char *)data; *(void **)tm2 = (void *)(tdata + sz); sz += tdsz; } va_end(args); /* Copy the data block back, for convenience */ memcpy(data, res->threads[0]->data, dsize); /* Return the prepared block */ return (res); } int launch_threads(thread_func thread, threaddata *tdata, char *title, int total) { tcb *tp = tdata->threads[0]; tdata->what = thread; tp->step0 = 0; tp->nsteps = total; if (title) progress_init(title, 1); /* Let init/end be done outside */ thread(tp); if (title) progress_end(); return (0); } #endif mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/thread.h000066400000000000000000000067001471325446300223650ustar00rootroot00000000000000/* thread.h Copyright (C) 2009-2017 Dmitry Groshev This file is part of mtPaint. mtPaint 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. mtPaint 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 mtPaint in the file COPYING. */ typedef struct tcb tcb; typedef struct threaddata threaddata; // Thread function type typedef void (*thread_func)(tcb *thread); // Thread control block struct tcb { volatile int stop; // Signal to stop volatile int progress; // Progress counter volatile int stopped; // Stopped state int index; // Thread index int count; // Number of threads int step0, nsteps; // Work allocated to this thread int tsteps; // Total amount of work - set only for thread 0 threaddata *tdata; // Pointer to array header void *data; // Parameters & buffers structure for function }; // Thread array header struct threaddata { volatile int done; // Allocated amount of work int total; // Total amount of work int count; // Number of threads int chunks; // Number of chunks per thread int silent; // No progressbar & error window thread_func what; // Function to run tcb *threads[1]; // Threads' TCBs }; // Configure max number of threads to launch int maxthreads; // Prepare memory structures for threads' use threaddata *talloc(int flags, int tmax, void *data, int dsize, ...); // Launch threads and wait for their exiting int launch_threads(thread_func thread, threaddata *tdata, char *title, int total); #ifdef U_THREADS // Show threading status int threads_running; // Max threads to be used int helper_threads(); // Estimate how many threads is enough for image int image_threads(int w, int h); // Update progressbar from main thread int thread_progress(tcb *thread); // Track a thread's progress static inline int thread_step(tcb *thread, int i, int tlim, int steps) { thread->progress = i; if (thread->index) return (thread->stop); if ((i * steps) % tlim < tlim - steps) return (FALSE); return (thread_progress(thread)); } // Report that thread's work is done static inline void thread_done(tcb *thread) { thread->stopped = TRUE; } // Define a static mutex #define DEF_MUTEX(name) static GStaticMutex name = G_STATIC_MUTEX_INIT // Lock a static mutex #define LOCK_MUTEX(name) \ if (threads_running) g_static_mutex_lock(&name) // Unlock a static mutex #define UNLOCK_MUTEX(name) \ if (threads_running) g_static_mutex_unlock(&name) #ifdef __G_ATOMIC_H__ #define thread_xadd(A,B) g_atomic_int_exchange_and_add((A), (B)) #elif HAVE__SFA #define thread_xadd(A,B) __sync_fetch_and_add((A), (B)) #else int thread_xadd(volatile int *var, int n); #endif #else /* Only one actual thread */ #define helper_threads() 1 #define image_threads(w,h) 1 static inline int thread_step(tcb *thread, int i, int tlim, int steps) { if ((i * steps) % tlim < tlim - steps) return (FALSE); return (progress_update((float)i / tlim)); } #define thread_done(thread) #define DEF_MUTEX(name) #define LOCK_MUTEX(name) #define UNLOCK_MUTEX(name) static inline int thread_xadd(int *var, int n) { int v = *var; *var += n; return (v); } #endif mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/toolbar.c000066400000000000000000000760511471325446300225610ustar00rootroot00000000000000/* toolbar.c Copyright (C) 2006-2021 Mark Tyler and Dmitry Groshev This file is part of mtPaint. mtPaint 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. mtPaint 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 mtPaint in the file COPYING. */ #include "global.h" #undef _ #define _(X) X #include "mygtk.h" #include "memory.h" #include "vcode.h" #include "inifile.h" #include "ani.h" #include "png.h" #include "mainwindow.h" #include "otherwindow.h" #include "canvas.h" #include "toolbar.h" #include "layer.h" #include "viewer.h" #include "channels.h" #include "csel.h" #include "font.h" #include "icons.h" void **icon_buttons[TOTAL_TOOLS]; int toolbar_status[TOOLBAR_MAX]; // True=show void **drawing_col_prev, **drawing_palette; void **toolbar_boxes[TOOLBAR_MAX], // Used for showing/hiding **toolbar_zoom_view; void **m_cursor[TOTAL_CURSORS]; // My mouse cursors void **move_cursor, **busy_cursor, **corner_cursor[4]; // System cursors int patterns_grid_w, patterns_grid_h; static int v_zoom_main = 100, v_zoom_view = 100; static void **toolbar_zoom_main; static void **toolbar_labels[2], // Colour A & B **ts_spinslides[4], // Size, flow, opacity, value **ts_label_channel; // Channel name static unsigned char mem_prev[PREVIEW_WIDTH * PREVIEW_HEIGHT * 3]; // RGB colours, tool, pattern preview static int click_colours(void *dt, void **wdata, int what, void **where, mouse_ext *mouse) { if (mem_img[CHN_IMAGE]) { if (mouse->y > 31) choose_pattern(0); else if (mouse->x < 48) colour_selector(COLSEL_EDIT_AB); else choose_pattern(1); } return (FALSE); } void toolbar_zoom_update() // Update the zoom combos to reflect current zoom { if (!toolbar_zoom_main || !toolbar_zoom_view) return; cmd_set(toolbar_zoom_main, (int)(can_zoom * 100)); cmd_set(toolbar_zoom_view, (int)(vw_zoom * 100)); } static void toolbar_zoom_change(void *dt, void **wdata, int what, void **where) { int *cause = cmd_read(where, dt); float new = *cause < 100 ? 1.0 / (100 / *cause) : *cause / 100.0; if (cause == &v_zoom_main) { int z = cursor_zoom; cursor_zoom = FALSE; // !!! Cursor in dropdown - don't zoom on it align_size(new); cursor_zoom = z; } else vw_align_size(new); } static void **settings_buttons[TOTAL_SETTINGS]; static int v_settings[TOTAL_SETTINGS]; static int *vars_settings[TOTAL_SETTINGS] = { &mem_continuous, &mem_undo_opacity, &tint_mode[0], &tint_mode[1], &mem_cselect, &mem_blend, &mem_unmask, &mem_gradient }; void mode_change(int setting, int state) { if (!*(int *)cmd_read(settings_buttons[setting], NULL) != !state) cmd_set(settings_buttons[setting], state); // Toggle the button if (!state == !*vars_settings[setting]) return; // No change, or changed already *(vars_settings[setting]) = state; if ((setting == SETB_CSEL) && mem_cselect && !csel_data) { csel_init(); mem_cselect = !!csel_data; } update_stuff(setting == SETB_GRAD ? UPD_GMODE : UPD_MODE); } typedef struct { filterwindow_dd fw; int fstep; } flood_dd; static int set_flood(flood_dd *dt, void **wdata) { run_query(wdata); flood_step = dt->fstep / 100.0; return TRUE; } static void *toolwindow_code[] = { UNLESSbt("centerSettings"), WPMOUSE, GOTO(filterwindow_code) }; #define WBbase flood_dd static void *flood_code[] = { VBOXPS, BORDER(SPIN, 0), FSPIN(fstep, 0, 20000), CHECKv(_("RGB Cube"), flood_cube), CHECKv(_("By image channel"), flood_img), CHECKv(_("Gradient-driven"), flood_slide), WDONE, RET }; #undef WBbase void flood_settings() /* Flood fill step */ { flood_dd tdata = { { _("Fill settings"), flood_code, FW_FN(set_flood) }, rint(flood_step * 100) }; run_create_(toolwindow_code, &tdata, sizeof(tdata), script_cmds); } static int set_settings(filterwindow_dd *dt, void **wdata) { run_query(wdata); return TRUE; } #define WBbase filterwindow_dd static void *smudge_code[] = { CHECKv(_("Respect opacity mode"), smudge_mode), RET }; #undef WBbase void smudge_settings() /* Smudge opacity mode */ { static filterwindow_dd tdata = { _("Smudge settings"), smudge_code, FW_FN(set_settings) }; run_create_(toolwindow_code, &tdata, sizeof(tdata), script_cmds); } void init_clone() { if (clone_mode) // Aligned aka relative { clone_status = CLONE_REL; clone_dx = clone_dx0; clone_dy = clone_dy0; if (!(clone_dx0 | clone_dy0)) // Both 0 for default values clone_dx = -tool_size , clone_dy = tool_size; } else // Absolute { clone_status = CLONE_ABS; if (clone_x0 >= 0) clone_x = clone_x0; // -1 for no change if (clone_y0 >= 0) clone_y = clone_y0; } } static int set_clone(filterwindow_dd *dt, void **wdata) { run_query(wdata); if (tool_type == TOOL_CLONE) init_clone(); return (TRUE); } #define WBbase filterwindow_dd static void *clone_code[] = { TABLE(3, 3), BORDER(LABEL, 0), TLABEL(_("Position")), GROUPN, TLXSPINv(clone_x0, -1, MAX_WIDTH - 1, 1, 0), OPNAME("X"), TLXSPINv(clone_y0, -1, MAX_HEIGHT - 1, 2, 0), OPNAME("Y"), TLABEL(_("Offset")), GROUPN, TLXSPINv(clone_dx0, -MAX_WIDTH, MAX_WIDTH, 1, 1), OPNAME("X"), TLXSPINv(clone_dy0, -MAX_HEIGHT, MAX_HEIGHT, 2, 1), OPNAME("Y"), TLCHECKv(_("Aligned"), clone_mode, 0, 2), WDONE, RET }; #undef WBbase void clone_settings() { static filterwindow_dd tdata = { _("Clone settings"), clone_code, FW_FN(set_clone) }; run_create_(toolwindow_code, &tdata, sizeof(tdata), script_cmds); } #define WBbase filterwindow_dd static void *lasso_code[] = { CHECKv(_("By selection channel"), lasso_sel), RET }; #undef WBbase void lasso_settings() /* Lasso selection channel */ { static filterwindow_dd tdata = { _("Lasso settings"), lasso_code, FW_FN(set_settings) }; run_create_(toolwindow_code, &tdata, sizeof(tdata), script_cmds); } #define WBbase filterwindow_dd static void *step_code[] = { VBOXPS, BORDER(SPIN, 0), SPINv(brush_spacing, 0, MAX_WIDTH), // !!! Not implemented yet // CHECKv(_("Flat gradient strokes"), ???), WDONE, RET }; #undef WBbase void step_settings() /* Brush spacing */ { static filterwindow_dd tdata = { _("Brush spacing"), step_code, FW_FN(set_settings) }; run_create_(toolwindow_code, &tdata, sizeof(tdata), script_cmds); } typedef struct { filterwindow_dd fw; int mode, reverse, xform, src; int red, green, blue; char **lnames; void **xb; } blend_dd; static int set_blend(blend_dd *dt, void **wdata) { int i, j; run_query(wdata); i = dt->mode < 0 ? BLEND_NORMAL : dt->mode; // Paranoia j = !dt->red + (!dt->green << 1) + (!dt->blue << 2); /* Don't accept stop-all or do-nothing */ if ((j == 7) || !(i | j | dt->xform | dt->src)) return (FALSE); blend_mode = i | (dt->reverse ? BLEND_REVERSE : 0) | (dt->xform ? BLEND_XFORM : 0) | (j << BLEND_RGBSHIFT); blend_src = dt->src; return (TRUE); } static void blend_xf(blend_dd *dt, void **wdata, int what, void **where) { if (what == op_EVT_CHANGE) /* Toggling transform mode */ { /* OK if initialized */ if (mem_bcsp[1].bcsp[BRCOSA_POSTERIZE]) return; /* OK if toggled off */ cmd_read(where, dt); if (!dt->xform) return; } /* Hide for awhile */ cmd_showhide(GET_WINDOW(wdata), FALSE); /* Send user to do init */ pressed_brcosa(dt->xb); } static char *blends[BLEND_NMODES] = { _("Normal"), _("Hue"), _("Saturation"), _("Value"), _("Colour"), _("Saturate More"), _("Multiply"), _("Divide"), _("Screen"), _("Dodge"), _("Burn"), _("Hard Light"), _("Soft Light"), _("Difference"), _("Darken"), _("Lighten"), _("Grain Extract"), _("Grain Merge"), _("Threshold") }; #define WBbase blend_dd static void *blend_code[] = { COMBO(blends, BLEND_NMODES, mode), CHECK(_("Reverse"), reverse), HBOX, REF(xb), CHECK(_("Transform Colour"), xform), EVENT(CHANGE, blend_xf), EBUTTONs(_("Settings"), blend_xf), WDONE, // HBOX BORDER(OPT, 0), FHBOXB(_("Source")), XOPTD(lnames, src), WDONE, HSEP, EQBOXS, CHECK(_("Red"), red), CHECK(_("Green"), green), CHECK(_("Blue"), blue), WDONE, RET }; #undef WBbase void blend_settings() /* Blend mode */ { char *names[SRC_LAYER + MAX_LAYERS + 2]; char ns[MAX_LAYERS + 1][LAYER_NAMELEN + 5]; blend_dd tdata = { { _("Blend mode"), blend_code, FW_FN(set_blend) }, blend_mode & BLEND_MMASK, blend_mode & BLEND_REVERSE, blend_mode & BLEND_XFORM, blend_src, ~blend_mode & (1 << BLEND_RGBSHIFT), ~blend_mode & (2 << BLEND_RGBSHIFT), ~blend_mode & (4 << BLEND_RGBSHIFT), names }; int i; names[SRC_NORMAL] = _("Normal"); names[SRC_IMAGE] = _("Image"); for (i = 0; i <= layers_total; i++) { snprintf(ns[i], sizeof(ns[i]), "%d %s", i, layer_table[i].name); names[SRC_LAYER + i] = ns[i]; } names[SRC_LAYER + i] = NULL; run_create_(toolwindow_code, &tdata, sizeof(tdata), script_cmds); } #define GP_WIDTH 256 #define GP_HEIGHT 16 static void **grad_view; typedef struct { int size, flow, opac, chan[NUM_CHANNELS]; unsigned char rgb[GP_WIDTH * GP_HEIGHT * 3]; } settings_dd; static void ts_spinslide_moved(settings_dd *dt, void **wdata, int what, void **where) { int n, *cause = cmd_read(where, dt); if (cause == &dt->size) tool_size = dt->size; else if (cause == &dt->flow) tool_flow = dt->flow; else if (cause == &dt->opac) { if (dt->opac != tool_opacity) pressed_opacity(dt->opac); } else /* Somewhere in dt->chan[] */ { n = cause - dt->chan; if (n == CHN_IMAGE) n = mem_channel; if ((n != CHN_IMAGE) && (*cause != channel_col_A[n])) { channel_col_A[n] = *cause; update_stuff(UPD_CAB); } } } void toolbar_settings_exit(void *dt, void **wdata) { if (!wdata) wdata = toolbar_boxes[TOOLBAR_SETTINGS]; if (!wdata) return; toolbar_boxes[TOOLBAR_SETTINGS] = NULL; cmd_set(menu_slots[MENU_TBSET], FALSE); run_destroy(wdata); } static void toolbar_click(void *dt, void **wdata, int what, void **where) { int act_m, res = TRUE; if (what == op_EVT_CHANGE) { void *cause = cmd_read(where, dt); // Good for radiobuttons too, as all action codes are nonzero if (cause) res = *(int *)cause; act_m = TOOL_ID(where); } else act_m = TOOL_IR(where); // op_EVT_CLICK action_dispatch(act_m >> 16, (act_m & 0xFFFF) - 0x8000, res, FALSE); } #define WBbase settings_dd static void *settings_code[] = { TOPVBOXV, // Keep height at max requested, to let dock contents stay put BORDER(TOOLBAR, 0), TOOLBARx(toolbar_click, toolbar_click), SCRIPTED, REFv(settings_buttons[SETB_CONT]), TBTOGGLExv(_("Continuous Mode"), XPM_ICON(mode_cont), ACTMOD(ACT_MODE, SETB_CONT), ACTMOD(DLG_STEP, 0), v_settings[SETB_CONT]), REFv(settings_buttons[SETB_OPAC]), TBTOGGLEv(_("Opacity Mode"), XPM_ICON(mode_opac), ACTMOD(ACT_MODE, SETB_OPAC), v_settings[SETB_OPAC]), REFv(settings_buttons[SETB_TINT]), TBTOGGLEv(_("Tint Mode"), XPM_ICON(mode_tint), ACTMOD(ACT_MODE, SETB_TINT), v_settings[SETB_TINT]), REFv(settings_buttons[SETB_TSUB]), TBTOGGLEv(_("Tint +-"), XPM_ICON(mode_tint2), ACTMOD(ACT_MODE, SETB_TSUB), v_settings[SETB_TSUB]), REFv(settings_buttons[SETB_CSEL]), TBTOGGLExv(_("Colour-Selective Mode"), XPM_ICON(mode_csel), ACTMOD(ACT_MODE, SETB_CSEL), ACTMOD(DLG_COLORS, COLSEL_EDIT_CSEL), v_settings[SETB_CSEL]), REFv(settings_buttons[SETB_FILT]), TBTOGGLExv(_("Blend Mode"), XPM_ICON(mode_blend), ACTMOD(ACT_MODE, SETB_FILT), ACTMOD(DLG_FILT, 0), v_settings[SETB_FILT]), REFv(settings_buttons[SETB_MASK]), TBTOGGLEv(_("Disable All Masks"), XPM_ICON(mode_mask), ACTMOD(ACT_MODE, SETB_MASK), v_settings[SETB_MASK]), REFv(settings_buttons[SETB_GRAD]), TBBOXTOGxv(_("Gradient Mode"), NULL, ACTMOD(ACT_MODE, SETB_GRAD), ACTMOD(DLG_GRAD, 1), v_settings[SETB_GRAD]), REFv(grad_view), RGBIMAGEP(rgb, GP_WIDTH, GP_HEIGHT), // in TBBOXTOG WDONE, /* Colors A & B */ BORDER(LABEL, 0), REFv(toolbar_labels[0]), MLABELxr("", 5, 2, 0), REFv(toolbar_labels[1]), MLABELxr("", 5, 2, 0), ETABLE(2, 4), BORDER(SPINSLIDE, 0), TLABEL(_("Size")), REFv(ts_spinslides[0]), TLSPINSLIDEx(size, 1, 255, 1, 0), EVENT(CHANGE, ts_spinslide_moved), TLABEL(_("Flow")), REFv(ts_spinslides[1]), TLSPINSLIDEx(flow, 1, 255, 1, 1), EVENT(CHANGE, ts_spinslide_moved), TLABEL(_("Opacity")), REFv(ts_spinslides[2]), TLSPINSLIDEx(opac, 0, 255, 1, 2), EVENT(CHANGE, ts_spinslide_moved), uSPIN(chan[CHN_ALPHA], 0, 255), EVENT(SCRIPT, ts_spinslide_moved), OPNAME("Alpha"), uSPIN(chan[CHN_SEL], 0, 255), EVENT(SCRIPT, ts_spinslide_moved), OPNAME("Selection"), uSPIN(chan[CHN_MASK], 0, 255), EVENT(SCRIPT, ts_spinslide_moved), OPNAME("Mask"), REFv(ts_label_channel), TLABELr(""), HIDDEN, REFv(ts_spinslides[3]), TLSPINSLIDEx(chan[CHN_IMAGE], 0, 255, 1, 3), EVENT(CHANGE, ts_spinslide_moved), HIDDEN, ALTNAME("Value"), WEND }; #undef WBbase void **create_settings_box() { static char *noscript; static settings_dd tdata; // zeroed out, get updated later int i; for (i = 0; i < TOTAL_SETTINGS; i++) // Initialize buttons' state v_settings[i] = *vars_settings[i]; return (run_create_(settings_code, &tdata, sizeof(tdata), cmd_mode ? &noscript : NULL)); } static void *sbar_code[] = { WPWHEREVER, WINDOW(_("Settings Toolbar")), EVENT(CANCEL, toolbar_settings_exit), WXYWH("toolbar_settings", 0, 0), REMOUNTv(settings_dock), WSHOW }; static void toolbar_settings_init() { if (cmd_mode) return; if (toolbar_boxes[TOOLBAR_SETTINGS]) // Used when Home key is pressed { cmd_showhide(toolbar_boxes[TOOLBAR_SETTINGS], TRUE); return; } /// SETTINGS TOOLBAR toolbar_boxes[TOOLBAR_SETTINGS] = run_create(sbar_code, sbar_code, 0); } static int zooms[] = { 10, 20, 25, 33, 50, 100, 200, 300, 400, 600, 800, 1000, 1200, 1600, 2000, 4000, 8000, 0 }; /* !!! For later change_to_tool(DEFAULT_TOOL_ICON) to go through, this need be * set to something different initially */ static int tool_id = TTB_PAINT; void *toolbar_code[] = { REFv(m_cursor[TOOL_SQUARE]), XBMCURSOR(square, 0, 0), REFv(m_cursor[TOOL_CIRCLE]), XBMCURSOR(circle, 0, 0), REFv(m_cursor[TOOL_HORIZONTAL]), XBMCURSOR(horizontal, 0, 0), REFv(m_cursor[TOOL_VERTICAL]), XBMCURSOR(vertical, 0, 0), REFv(m_cursor[TOOL_SLASH]), XBMCURSOR(slash, 0, 0), REFv(m_cursor[TOOL_BACKSLASH]), XBMCURSOR(backslash, 0, 0), REFv(m_cursor[TOOL_SPRAY]), XBMCURSOR(spray, 0, 0), REFv(m_cursor[TOOL_SHUFFLE]), XBMCURSOR(shuffle, 0, 0), REFv(m_cursor[TOOL_FLOOD]), XBMCURSOR(flood, 2, 19), REFv(m_cursor[TOOL_SELECT]), XBMCURSOR(select, 10, 10), REFv(m_cursor[TOOL_LINE]), XBMCURSOR(line, 0, 0), REFv(m_cursor[TOOL_SMUDGE]), XBMCURSOR(smudge, 0, 0), REFv(m_cursor[TOOL_POLYGON]), XBMCURSOR(polygon, 10, 10), REFv(m_cursor[TOOL_CLONE]), XBMCURSOR(clone, 0, 0), REFv(m_cursor[TOOL_GRADIENT]), XBMCURSOR(grad, 0, 0), REFv(move_cursor), SYSCURSOR(FLEUR), REFv(busy_cursor), SYSCURSOR(WATCH), REFv(corner_cursor[0]), SYSCURSOR(TOP_LEFT_CORNER), REFv(corner_cursor[1]), SYSCURSOR(TOP_RIGHT_CORNER), REFv(corner_cursor[2]), SYSCURSOR(BOTTOM_LEFT_CORNER), REFv(corner_cursor[3]), SYSCURSOR(BOTTOM_RIGHT_CORNER), TWOBOX, /// MAIN TOOLBAR REFv(toolbar_boxes[TOOLBAR_MAIN]), SMARTTBAR(toolbar_click), UNLESSv(toolbar_status[TOOLBAR_MAIN]), HIDDEN, // Only show if user wants TBBUTTON(_("New Image"), XPM_ICON(new), ACTMOD(DLG_NEW, 0)), TBBUTTON(_("Load Image File"), XPM_ICON(open), ACTMOD(DLG_FSEL, FS_PNG_LOAD)), TBBUTTON(_("Save Image File"), XPM_ICON(save), ACTMOD(ACT_SAVE, 0)), TBSPACE, TBBUTTON(_("Cut"),XPM_ICON(cut), ACTMOD(ACT_COPY, 1)), ACTMAP(NEED_SEL2), TBBUTTON(_("Copy"), XPM_ICON(copy), ACTMOD(ACT_COPY, 0)), ACTMAP(NEED_SEL2), TBBUTTON(_("Paste"), XPM_ICON(paste), ACTMOD(ACT_PASTE, 0)), ACTMAP(NEED_CLIP), TBSPACE, TBBUTTON(_("Undo"), XPM_ICON(undo), ACTMOD(ACT_DO_UNDO, 0)), ACTMAP(NEED_UNDO), TBBUTTON(_("Redo"), XPM_ICON(redo), ACTMOD(ACT_DO_UNDO, 1)), ACTMAP(NEED_REDO), TBSPACE, TBBUTTON(_("Transform Colour"), XPM_ICON(brcosa), ACTMOD(DLG_BRCOSA, 0)), TBBUTTON(_("Pan Window"), XPM_ICON(pan), ACTMOD(ACT_PAN, 0)), SMARTTBMORE(_("More...")), REFv(toolbar_zoom_main), PCTCOMBOv(v_zoom_main, zooms, toolbar_zoom_change), REFv(toolbar_zoom_view), PCTCOMBOv(v_zoom_view, zooms, toolbar_zoom_change), HIDDEN, WDONE, /// TOOLS TOOLBAR REFv(toolbar_boxes[TOOLBAR_TOOLS]), SMARTTBARx(toolbar_click, toolbar_click), UNLESSv(toolbar_status[TOOLBAR_TOOLS]), HIDDEN, // Only show if user wants SCRIPTED, /* !!! scriptbar_code[] adds ALTNAME and event to SMARTTBARx */ CALL(scriptbar_code), REFv(icon_buttons[TTB_PAINT]), TBRBUTTONv(_("Paint"), XPM_ICON(paint), ACTMOD(ACT_TOOL, TTB_PAINT), tool_id), SHORTCUT(F4, 0), /* !!! This, with matching tool_id, would set default tool - which is * exactly the wrong thing to do in here */ // EVENT(CHANGE, toolbar_click), TRIGGER, REFv(icon_buttons[TTB_SHUFFLE]), TBRBUTTONv(_("Shuffle"), XPM_ICON(shuffle), ACTMOD(ACT_TOOL, TTB_SHUFFLE), tool_id), REFv(icon_buttons[TTB_FLOOD]), TBRBUTTONxv(_("Flood Fill"), XPM_ICON(flood), ACTMOD(ACT_TOOL, TTB_FLOOD), ACTMOD(DLG_FLOOD, 0), tool_id), SHORTCUT(f, 0), REFv(icon_buttons[TTB_LINE]), TBRBUTTONv(_("Straight Line"), XPM_ICON(line), ACTMOD(ACT_TOOL, TTB_LINE), tool_id), SHORTCUT(d, 0), REFv(icon_buttons[TTB_SMUDGE]), TBRBUTTONxv(_("Smudge"), XPM_ICON(smudge), ACTMOD(ACT_TOOL, TTB_SMUDGE), ACTMOD(DLG_SMUDGE, 0), tool_id), ACTMAP(NEED_24), REFv(icon_buttons[TTB_CLONE]), TBRBUTTONxv(_("Clone"), XPM_ICON(clone), ACTMOD(ACT_TOOL, TTB_CLONE), ACTMOD(DLG_CLONE, 0), tool_id), REFv(icon_buttons[TTB_SELECT]), TBRBUTTONv(_("Make Selection"), XPM_ICON(select), ACTMOD(ACT_TOOL, TTB_SELECT), tool_id), SHORTCUT(F9, 0), REFv(icon_buttons[TTB_POLY]), TBRBUTTONv(_("Polygon Selection"), XPM_ICON(polygon), ACTMOD(ACT_TOOL, TTB_POLY), tool_id), REFv(icon_buttons[TTB_GRAD]), TBRBUTTONxv(_("Place Gradient"), XPM_ICON(grad_place), ACTMOD(ACT_TOOL, TTB_GRAD), ACTMOD(DLG_GRAD, 0), tool_id), TBSPACE, TBBUTTONx(_("Lasso Selection"), XPM_ICON(lasso), ACTMOD(ACT_LASSO, 0), ACTMOD(DLG_LASSO, 0)), ACTMAP(NEED_LAS2), TBBUTTONx(_("Paste Text"), XPM_ICON(text), ACTMOD(DLG_TEXT, 0), ACTMOD(DLG_TEXT_FT, 0)), UNNAME, /* Not a good access point for scripting the text tools: cannot disable * only one of the two, here. Better to remove the temptation */ TBSPACE, TBBUTTON(_("Ellipse Outline"), XPM_ICON(ellipse2), ACTMOD(ACT_ELLIPSE, 0)), ACTMAP(NEED_SEL), TBBUTTON(_("Filled Ellipse"), XPM_ICON(ellipse), ACTMOD(ACT_ELLIPSE, 1)), ACTMAP(NEED_SEL), TBBUTTON(_("Outline Selection"), XPM_ICON(rect1), ACTMOD(ACT_OUTLINE, 0)), ACTMAP(NEED_SEL2), TBBUTTON(_("Fill Selection"), XPM_ICON(rect2), ACTMOD(ACT_OUTLINE, 1)), ACTMAP(NEED_SEL2), TBSPACE, TBBUTTON(_("Flip Selection Vertically"), XPM_ICON(flip_vs), ACTMOD(ACT_SEL_FLIP_V, 0)), ACTMAP(NEED_PCLIP), TBBUTTON(_("Flip Selection Horizontally"), XPM_ICON(flip_hs), ACTMOD(ACT_SEL_FLIP_H, 0)), ACTMAP(NEED_PCLIP), TBBUTTON(_("Rotate Selection Clockwise"), XPM_ICON(rotate_cs), ACTMOD(ACT_SEL_ROT, 0)), ACTMAP(NEED_PCLIP), TBBUTTON(_("Rotate Selection Anti-Clockwise"), XPM_ICON(rotate_as), ACTMOD(ACT_SEL_ROT, 1)), ACTMAP(NEED_PCLIP), ENDSCRIPT, SMARTTBMORE(_("More...")), WDONE, WDONE, // twobox RET }; void ts_update_gradient() { settings_dd *dt; unsigned char pal[256 * 3], cset[3], *dest, *rgb, *tmp = NULL; int i, j, k, op, op2, frac, slot, idx = 255, wrk[NUM_CHANNELS + 3]; if (!grad_view) return; // Paranoia dt = GET_DDATA(wdata_slot(grad_view)); slot = mem_channel + 1; if (mem_channel != CHN_IMAGE) /* Create pseudo palette */ { for (j = 0; j < 3; j++) for (i = 0; i < 256; i++) { k = mem_background * 255 + (channel_rgb[mem_channel][j] - mem_background) * i + 127; pal[i * 3 + j] = (k + (k >> 8) + 1) >> 8; } } else if (mem_img_bpp == 1) /* Read in current palette */ pal2rgb(pal, mem_pal, 256, 256); else tmp = cset , --slot; /* Use gradient colors */ if (!IS_INDEXED) idx = 0; /* Allow intermediate opacities */ /* Draw the preview, ignoring RGBA coupling */ memset(rgb = dt->rgb, mem_background, GP_WIDTH * GP_HEIGHT * 3); for (i = 0; i < GP_WIDTH; i++) { dest = rgb + i * 3; wrk[CHN_IMAGE + 3] = 0; op = grad_value(wrk, slot, i * (1.0 / (double)(GP_WIDTH - 1))); if (!op) continue; for (j = 0; j < GP_HEIGHT; j++ , dest += GP_WIDTH * 3) { frac = BAYER(i, j); op2 = (op + frac) >> 8; if (!op2) continue; op2 |= idx; if (tmp == cset) { cset[0] = (wrk[0] + frac) >> 8; cset[1] = (wrk[1] + frac) >> 8; cset[2] = (wrk[2] + frac) >> 8; } else { k = (wrk[mem_channel + 3] + frac) >> 8; if (mem_channel == CHN_IMAGE) k = wrk[k]; tmp = pal + 3 * k; } k = dest[0] * 255 + (tmp[0] - dest[0]) * op2; dest[0] = (k + (k >> 8) + 1) >> 8; k = dest[1] * 255 + (tmp[1] - dest[1]) * op2; dest[1] = (k + (k >> 8) + 1) >> 8; k = dest[2] * 255 + (tmp[2] - dest[2]) * op2; dest[2] = (k + (k >> 8) + 1) >> 8; } } /* Show it */ cmd_reset(grad_view, dt); } void toolbar_update_settings() { char txt[64]; int i, j, c, l; for (i = 0; i < 2; i++) { c = "AB"[i]; j = mem_col_[i]; if (mem_img_bpp == 1) l = sprintf(txt, "%c [%d] = {%d,%d,%d}", c, j, mem_pal[j].red, mem_pal[j].green, mem_pal[j].blue); else l = sprintf(txt, "%c = {%i,%i,%i}", c, mem_col_24[i].red, mem_col_24[i].green, mem_col_24[i].blue); if (RGBA_mode && mem_img[CHN_ALPHA]) sprintf(txt + l, " + {%d}", channel_col_[i][CHN_ALPHA]); cmd_setv(toolbar_labels[i], txt, LABEL_VALUE); } i = mem_channel == CHN_IMAGE; cmd_showhide(toolbar_labels[0], i); cmd_showhide(toolbar_labels[1], i); cmd_showhide(ts_spinslides[3], !i); cmd_showhide(ts_label_channel, !i); if (!i) cmd_setv(ts_label_channel, channames[mem_channel], LABEL_VALUE); cmd_sensitive(ts_spinslides[3], !i); // For scripting // Disable opacity for indexed image cmd_sensitive(ts_spinslides[2], !IS_INDEXED); // Update tool settings cmd_set(ts_spinslides[0], tool_size); cmd_set(ts_spinslides[1], tool_flow); cmd_set(ts_spinslides[2], tool_opacity); if (!i) cmd_set(ts_spinslides[3], channel_col_A[mem_channel]); ts_update_gradient(); } static png_color brcosa_palette[256]; static int motion_palette(void *dt, void **wdata, int what, void **where, mouse_ext *mouse) { int pindex; /* If cursor got warped, will have another movement event to handle */ if (drag_index && cmd_checkv(where, MOUSE_BOUND)) return (TRUE); pindex = (mouse->y - PALETTE_SWATCH_Y) / PALETTE_SWATCH_H; pindex = pindex < 0 ? 0 : pindex >= mem_cols ? mem_cols - 1 : pindex; if (drag_index && (drag_index_vals[1] != pindex)) { mem_pal_index_move(drag_index_vals[1], pindex); update_stuff(UPD_MVPAL); drag_index_vals[1] = pindex; } return (TRUE); } static int release_palette(void *dt, void **wdata, int what, void **where, mouse_ext *mouse) { if (drag_index) { drag_index = FALSE; cmd_cursor(drawing_palette, NULL); if ( drag_index_vals[0] != drag_index_vals[1] ) { mem_pal_copy(mem_pal, brcosa_palette); // Get old values back mem_undo_next(UNDO_XPAL); // Do undo stuff mem_pal_index_move( drag_index_vals[0], drag_index_vals[1] ); mem_canvas_index_move( drag_index_vals[0], drag_index_vals[1] ); mem_undo_prepare(); update_stuff(UPD_TPAL | CF_MENU); } } return FALSE; } static int click_palette(void *dt, void **wdata, int what, void **where, mouse_ext *mouse) { int pindex, px = mouse->x, py = mouse->y; /* Filter out multiple clicks */ if (mouse->count > 1) return (TRUE); if (py < PALETTE_SWATCH_Y) return (TRUE); pindex = (py - PALETTE_SWATCH_Y) / PALETTE_SWATCH_H; if (pindex >= mem_cols) return (TRUE); if (px < PALETTE_SWATCH_X) colour_selector(COLSEL_EDIT_ALL + pindex); else if (px < PALETTE_CROSS_X) // Colour A or B changed { if ((mouse->button == 1) && (mouse->state & _Smask)) { mem_pal_copy(brcosa_palette, mem_pal); drag_index = TRUE; drag_index_vals[0] = drag_index_vals[1] = pindex; cmd_cursor(drawing_palette, move_cursor); } else if ((mouse->button == 1) || (mouse->button == 3)) { int ab = (mouse->button == 3) || (mouse->state & _Cmask); mem_col_[ab] = pindex; mem_col_24[ab] = mem_pal[pindex]; update_stuff(UPD_AB); } } else /* if (px >= PALETTE_CROSS_X) */ // Mask changed { mem_mask_setv(NULL, pindex, !mem_prot_mask[pindex]); update_stuff(UPD_CMASK); } return (TRUE); } void *toolbar_palette_code[] = { REFv(toolbar_boxes[TOOLBAR_PALETTE]), VBOXr, UNLESSv(toolbar_status[TOOLBAR_PALETTE]), HIDDEN, HBOXP, REFv(drawing_col_prev), CCANVASIMGv(mem_prev, PREVIEW_WIDTH, PREVIEW_HEIGHT), // centered in box EVENT(RMOUSE, click_colours), WDONE, // HBOXP BORDER(SCROLL, 0), XSCROLL(0, 2), // never/always REFv(drawing_palette), CANVASIMGv(mem_pals, PALETTE_WIDTH, 64), // initial size EVENT(MOUSE, click_palette), EVENT(MMOUSE, motion_palette), EVENT(RMOUSE, release_palette), WDONE, RET }; void toolbar_showhide() // Show/Hide all 4 toolbars { static const unsigned char bar[4] = { TOOLBAR_MAIN, TOOLBAR_TOOLS, TOOLBAR_PALETTE, TOOLBAR_STATUS }; int i; // Don't touch regular toolbars in view mode if (!view_image_only) for (i = 0; i < 4; i++) { int n = bar[i]; if (toolbar_boxes[n]) cmd_showhide(toolbar_boxes[n], toolbar_status[n]); } if (!toolbar_status[TOOLBAR_SETTINGS]) toolbar_settings_exit(NULL, NULL); else { toolbar_settings_init(); cmd_setv(main_window_, (void *)1, WINDOW_RAISE); } } void pressed_toolbar_toggle(int state, int which) { // Menu toggle for toolbars toolbar_status[which] = state; toolbar_showhide(); } /// PATTERNS/TOOL PREVIEW AREA #define EXT_PATTERNS 256 static unsigned char patterns[8 * 8 * (DEF_PATTERNS + EXT_PATTERNS)]; #define pattern0 (patterns + 8 * 8 * DEF_PATTERNS) void mem_set_brush(int val) // Set brush, update size/flow/preview { int offset, j, o, o2; brush_type = mem_brush_list[val][0]; tool_size = mem_brush_list[val][1]; if (mem_brush_list[val][2] > 0) tool_flow = mem_brush_list[val][2]; offset = 3 * (2 + BRUSH_CELL * (val % BRUSH_GRID_W) + 2 * PATCH_WIDTH + BRUSH_CELL * (val / BRUSH_GRID_W) * PATCH_WIDTH); // Offset in brush RGB for (j = 0; j < BRUSH_CELL - 2 * 2; j++) { o = 3 * (PREVIEW_BRUSH_X + PREVIEW_WIDTH * PREVIEW_BRUSH_Y + PREVIEW_WIDTH * j); // Preview offset o2 = offset + 3 * PATCH_WIDTH * j; // Offset in brush RGB memcpy(mem_prev + o, mem_brushes + o2, (BRUSH_CELL - 2 * 2) * 3); } } #if (PREVIEW_BRUSH_X + BRUSH_CELL - 2 * 2 > PREVIEW_WIDTH) || \ (PREVIEW_BRUSH_Y + BRUSH_CELL - 2 * 2 > PREVIEW_HEIGHT) #error "Mismatched preview size" #endif #include "graphics/xbm_patterns.xbm" #if (xbm_patterns_width % 8) || (xbm_patterns_width < 8 * 2) || \ (xbm_patterns_width > 8 * 16) || (xbm_patterns_height % 8) || \ (xbm_patterns_height < 8 * 2) || (xbm_patterns_height > 8 * 16) #error "Unacceptable width/height of patterns bitmap" #endif int set_master_pattern(char *m) { static const unsigned char bayer_map[16] = { 0, 8, 2, 10, 12, 4, 14, 6, 3, 11, 1, 9, 15, 7, 13, 5}; char *tail, buf[16 * 3]; unsigned char map[16], mk[16]; int i, n; buf[0] = '\0'; if (!m) m = inifile_get("masterPattern", ""); if (*m) /* Have string to parse */ { memset(mk, 0, 16); for (i = 0; i < 16; i++) { n = strtol(m, &tail, 10); if ((tail == m) || (n < 0) || (n > 15) || mk[n]++) break; map[i] = n; m = tail + ((i < 15) && (*tail == ',')); } /* Canonicalize string if good */ if ((i >= 16) && !m[strspn(m, "\t ")]) sprintf(buf, "%d,%d,%d,%d %d,%d,%d,%d %d,%d,%d,%d %d,%d,%d,%d", map[0], map[1], map[2], map[3], map[4], map[5], map[6], map[7], map[8], map[9], map[10], map[11], map[12], map[13], map[14], map[15]); inifile_set("masterPattern", buf); } if (!buf[0]) memcpy(map, bayer_map, 16); /* Expand map into a set of 16 8x8 patterns */ for (i = 0; i < DEF_PATTERNS * 8 * 8; i++) patterns[i] = map[(i & 3) + ((i >> 1) & 0xC)] >= (i >> 6); return (!!buf[0]); } /* Create RGB dump of patterns to display: arranged as in their source file, * each 8x8 pattern repeated 4x4 with 2 pixels border and 4 pixels separation */ void render_patterns(unsigned char *buf) { png_color *p; unsigned char *dest, *src = pattern0; int j, x, y, h, rowl = patterns_grid_w * PATTERN_CELL * 3; dest = buf + rowl * 2 + 2 * 3; for (y = 0; y < patterns_grid_h; y++) { for (h = 0; h < 8; h++) { for (x = 0; x < patterns_grid_w; x++) { for (j = 0; j < 8; j++) { p = mem_col_24 + *src++; *dest++ = p->red; *dest++ = p->green; *dest++ = p->blue; } memcpy(dest, dest - 8 * 3, 8 * 3); memcpy(dest + 8 * 3, dest - 8 * 3, 8 * 3 * 2); src += 8 * 8 - 8; dest += (PATTERN_CELL - 8) * 3; } src -= patterns_grid_w * 8 * 8 - 8; } memcpy(dest, dest - rowl * 8, rowl * 8); memcpy(dest + rowl * 8 , dest - rowl * 8, rowl * 8 * 2); src += (patterns_grid_w - 1) * 8 * 8; dest += rowl * (PATTERN_CELL - 8); } } /* Test/set 0-1 indexed image as new patterns */ int set_patterns(ls_settings *settings) { unsigned char *dest = pattern0, *src = settings->img[CHN_IMAGE]; int j, l, ll, w = settings->width, h = settings->height; /* Check dimensions (2x2..16x16 of 8x8 cells) and depth */ if ((w % 8) || (w < 8 * 2) || (w > 8 * 16) || (h % 8) || (h < 8 * 2) || (h > 8 * 16) || (settings->bpp != 1)) return (0); // Forget it if (!src) return (-1); // Can try if (settings->colors != 2) return (0); // 0-1 it must be ll = l = (patterns_grid_w = w / 8) * (patterns_grid_h = h / 8); while (l-- > 0) { for (j = 8; j-- > 0; src += w , dest += 8) memcpy(dest, src, 8); src -= ((dest - pattern0) % (w * 8) ? w * 8 : w) - 8; } return (ll); } void mem_pat_update() // Update indexed and then RGB pattern preview { int i, j, k, l; if (!patterns_grid_w) /* Unpack the XBM */ { unsigned char *src = xbm_patterns_bits, *dest = pattern0; int w; patterns_grid_w = w = xbm_patterns_width / 8; l = w * (patterns_grid_h = xbm_patterns_height / 8); while (l-- > 0) { for (j = 8; j-- > 0; src += w) for (i = *src + 0x100; i > 1; i >>= 1) *dest++ = i & 1; src -= ((dest - pattern0) % (w * 8 * 8) ? w * 8 : w) - 1; } } /* Set up default Bayer 4x4 patterns */ if (!mem_pattern) set_master_pattern(NULL); if ( mem_img_bpp == 1 ) { mem_col_A24 = mem_pal[mem_col_A]; mem_col_B24 = mem_pal[mem_col_B]; } /* Set up pattern maps */ mem_pattern = pattern0 + mem_tool_pat * 8 * 8; for (i = 0; i < 8 * 8; i++) { j = mem_pattern[i]; mem_col_pat[i] = mem_col_[j]; mem_col_pat24[i * 3 + 0] = mem_col_24[j].red; mem_col_pat24[i * 3 + 1] = mem_col_24[j].green; mem_col_pat24[i * 3 + 2] = mem_col_24[j].blue; } k = PREVIEW_WIDTH * 32 * 3; for (i = 0; i < 16; i++) { for (j = 0; j < PREVIEW_WIDTH; j++ , k += 3) { l = ((i & 7) * 8 + (j & 7)) * 3; mem_prev[k + 0] = mem_col_pat24[l + 0]; mem_prev[k + 1] = mem_col_pat24[l + 1]; mem_prev[k + 2] = mem_col_pat24[l + 2]; } } } void update_top_swatch() // Update selected colours A & B { unsigned char AA[3], BB[3], *tmp; int i, j; AA[0] = mem_col_A24.red; AA[1] = mem_col_A24.green; AA[2] = mem_col_A24.blue; BB[0] = mem_col_B24.red; BB[1] = mem_col_B24.green; BB[2] = mem_col_B24.blue; #define dAB (10 * PREVIEW_WIDTH * 3 + 10 * 3) for (j = 1; j <= 20; j++) { tmp = (mem_prev + 1 * 3) + j * (PREVIEW_WIDTH * 3); for (i = 0; i < 20; i++ , tmp += 3) { tmp[0] = AA[0]; tmp[1] = AA[1]; tmp[2] = AA[2]; tmp[dAB + 0] = BB[0]; tmp[dAB + 1] = BB[1]; tmp[dAB + 2] = BB[2]; } } #undef dAB } mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/toolbar.h000066400000000000000000000071131471325446300225570ustar00rootroot00000000000000/* toolbar.h Copyright (C) 2006-2019 Mark Tyler and Dmitry Groshev This file is part of mtPaint. mtPaint 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. mtPaint 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 mtPaint in the file COPYING. */ // DEFINITIONS #define TOOLBAR_MAIN 1 #define TOOLBAR_TOOLS 2 #define TOOLBAR_SETTINGS 3 #define TOOLBAR_PALETTE 4 #define TOOLBAR_STATUS 5 #define TOOLBAR_MAX 6 #define TOOLBAR_LAYERS TOOLBAR_MAX #define PREVIEW_WIDTH 72 #define PREVIEW_HEIGHT 48 #define PREVIEW_BRUSH_X 40 #define PREVIEW_BRUSH_Y 0 #define PATTERN_CELL (8 * 4 + 4) #define DEF_PATTERNS 16 // Main toolbar buttons enum { MTB_NEW = 0, MTB_OPEN, MTB_SAVE, MTB_CUT, MTB_COPY, MTB_PASTE, MTB_UNDO, MTB_REDO, MTB_BRCOSA, MTB_PAN, TOTAL_ICONS_MAIN }; // Tools toolbar buttons enum { TTB_PAINT = 0, TTB_SHUFFLE, TTB_FLOOD, TTB_LINE, TTB_SMUDGE, TTB_CLONE, TTB_SELECT, TTB_POLY, TTB_GRAD, TOTAL_TOOLS, TTB_LASSO = TOTAL_TOOLS, TTB_TEXT, TTB_ELLIPSE, TTB_FELLIPSE, TTB_OUTLINE, TTB_FILL, TTB_SELFV, TTB_SELFH, TTB_SELRCW, TTB_SELRCCW, TOTAL_ICONS_TOOLS }; #define DEFAULT_TOOL_ICON TTB_SELECT #define SMUDGE_TOOL_ICON TTB_SMUDGE #define TTB_0 TOTAL_SETTINGS // Settings toolbar buttons enum { SETB_CONT = 0, SETB_OPAC, SETB_TINT, SETB_TSUB, SETB_CSEL, SETB_FILT, SETB_MASK, SETB_GRAD, TOTAL_SETTINGS }; // GLOBAL VARIABLES void **icon_buttons[TOTAL_TOOLS]; void **m_cursor[TOTAL_CURSORS]; // My mouse cursors void **move_cursor, **busy_cursor, **corner_cursor[4]; // System cursors int toolbar_status[TOOLBAR_MAX]; // True=show void **drawing_col_prev, **drawing_palette; void **toolbar_boxes[TOOLBAR_MAX], // Used for showing/hiding **toolbar_zoom_view; int patterns_grid_w, patterns_grid_h; // GLOBAL PROCEDURES extern void *toolbar_code[]; // Set up the widgets to the vbox extern void *toolbar_palette_code[]; // Set up the palette area void toolbar_showhide(); // Show/Hide all 4 toolbars void toolbar_zoom_update(); // Update the zoom combos to reflect current zoom void toolbar_update_settings(); // Update details in the settings toolbar void **create_settings_box(); void toolbar_settings_exit(void *dt, void **wdata); #define toolbar_viewzoom(V) cmd_showhide(toolbar_zoom_view, V) // Show/hide the view zoom combo void pressed_toolbar_toggle(int state, int which); // Menu toggle for toolbars void init_clone(); // Init clone tool void mem_set_brush(int val); // Set brush, update size/flow/preview void mem_pat_update(); // Update indexed and then RGB pattern preview void update_top_swatch(); // Update selected colours A & B int set_master_pattern(char *m); // Make 4x4 dither patterns from master void render_patterns(unsigned char *buf); // Create RGB dump of patterns to display int set_patterns(ls_settings *settings); // Test/set image as new patterns void mode_change(int setting, int state); // Drawing mode variables void flood_settings(); // Flood fill step void smudge_settings(); // Smudge opacity mode void clone_settings(); // Clone mode & position void lasso_settings(); // Lasso selection channel void step_settings(); // Brush spacing void blend_settings(); // Blend mode mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/vcode.c000066400000000000000000011511041471325446300222110ustar00rootroot00000000000000/* vcode.c Copyright (C) 2013-2024 Dmitry Groshev This file is part of mtPaint. mtPaint 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. mtPaint 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 mtPaint in the file COPYING. */ #include "global.h" #include "mygtk.h" #include "memory.h" #include "vcode.h" #include "inifile.h" #include "png.h" #include "mainwindow.h" #include "otherwindow.h" #include "canvas.h" #include "cpick.h" #include "icons.h" #include "fpick.h" #include "prefs.h" /// More of meaningless differences to hide #if GTK_MAJOR_VERSION == 3 #define gdk_rgb_init() /* Not needed anymore */ #define gtk_object_get_data(A,B) g_object_get_data(A,B) #define gtk_object_set_data(A,B,C) g_object_set_data(A,B,C) #define gtk_object_get_data_by_id(A,B) g_object_get_qdata(A,B) #define gtk_object_set_data_by_id(A,B,C) g_object_set_qdata(A,B,C) #define GtkObject GObject #define GTK_WIDGET_REALIZED(A) gtk_widget_get_realized(A) #define GTK_WIDGET_MAPPED(A) gtk_widget_get_mapped(A) #define GTK_WIDGET_SENSITIVE(A) gtk_widget_get_sensitive(A) #define GTK_WIDGET_IS_SENSITIVE(A) gtk_widget_is_sensitive(A) #define GTK_WIDGET_VISIBLE(A) gtk_widget_get_visible(A) #define gtk_notebook_set_page gtk_notebook_set_current_page #define gtk_accel_group_unref g_object_unref #define gtk_hpaned_new() gtk_paned_new(GTK_ORIENTATION_HORIZONTAL) #define gtk_vpaned_new() gtk_paned_new(GTK_ORIENTATION_VERTICAL) #define gtk_hseparator_new() gtk_separator_new(GTK_ORIENTATION_HORIZONTAL) #define gtk_vseparator_new() gtk_separator_new(GTK_ORIENTATION_VERTICAL) #define hbox_new(A) gtk_box_new(GTK_ORIENTATION_HORIZONTAL, (A)) #define vbox_new(A) gtk_box_new(GTK_ORIENTATION_VERTICAL, (A)) #define gtk_menu_item_right_justify(A) gtk_menu_item_set_right_justified((A), TRUE) #define gtk_radio_menu_item_group gtk_radio_menu_item_get_group #define gtk_widget_ref(A) g_object_ref(A) #define gtk_widget_unref(A) g_object_unref(A) static GQuark tool_key; #define TOOL_KEY "mtPaint.tool" /* Running in a wheel is for hamsters, and pointless churn is pointless */ G_GNUC_BEGIN_IGNORE_DEPRECATIONS #else #define gtk_selection_data_get_data(A) ((A)->data) #define gtk_selection_data_get_length(A) ((A)->length) #define gtk_selection_data_get_format(A) ((A)->format) #define gtk_selection_data_get_target(A) ((A)->target) #define gtk_selection_data_get_data_type(A) ((A)->type) #define gtk_bin_get_child(A) ((A)->child) #define gtk_text_view_get_buffer(A) ((A)->buffer) #define gtk_dialog_get_action_area(A) ((A)->action_area) #define gtk_dialog_get_content_area(A) ((A)->vbox) #define gtk_font_selection_get_preview_entry(A) ((A)->preview_entry) #define gtk_check_menu_item_get_active(A) ((A)->active) #define gtk_adjustment_get_value(A) ((A)->value) #define gtk_adjustment_get_upper(A) ((A)->upper) #define gtk_adjustment_get_page_size(A) ((A)->page_size) #define gtk_window_get_focus(A) ((A)->focus_widget) #define gtk_paned_get_child1(A) ((A)->child1) #define gtk_paned_get_child2(A) ((A)->child2) #define gtk_paned_get_position(A) ((A)->child1_size) #define gtk_menu_item_get_submenu(A) ((A)->submenu) #define hbox_new(A) gtk_hbox_new(FALSE, (A)) #define vbox_new(A) gtk_vbox_new(FALSE, (A)) #endif /* Make code not compile if it cannot work */ typedef char Opcodes_Too_Long[2 * (op_LAST <= WB_OPMASK) - 1]; /// V-CODE ENGINE /* Max V-code subroutine nesting */ #define CALL_DEPTH 16 /* Max container widget nesting */ #define CONT_DEPTH 128 /* Max columns in a list */ #define MAX_COLS 16 /* Max keys in keymap */ #define MAX_KEYS 512 #define VVS(N) (((N) + sizeof(void *) - 1) / sizeof(void *)) #define GET_OPF(S) ((int)*(void **)(S)[1]) #define GET_OP(S) (GET_OPF(S) & WB_OPMASK) #define GET_DESCV(S,N) (((void **)(S)[1])[(N)]) #define GET_HANDLER(S) GET_DESCV(S, 1) #if VSLOT_SIZE != 3 #error "Mismatched slot size" #endif // !!! V should never be NULL - IS_UNREAL() relies on that #define EVSLOT(P,S,V) { (V), &(P), NULL, (S) } #define EV_SIZE (VSLOT_SIZE + 1) #define EV_PARENT(S) S[VSLOT_SIZE] #define VCODE_KEY "mtPaint.Vcode" /* Internal datastore */ #define GET_VDATA(V) ((V)[1]) typedef struct { void *code; // Noop tag, must be first field void ***dv; // Pointer to dialog response void **destroy; // Pre-destruction event slot void **wantkey; // Slot of prioritized keyboard handler void **keymap; // KEYMAP slot void **smmenu; // SMARTMENU slot void **fupslot; // Slot which needs defocusing to update (only 1 for now) void **actmap; // Actmap array void *now_evt; // Keyboard event being handled (check against recursion) void *tparent; // Transient parent window char *ininame; // Prefix for inifile vars char **script; // Commands if simulated int xywh[5]; // Stored window position/size/state int actn; // Actmap slots count unsigned actmask; // Last actmap mask unsigned vismask; // Visibility mask char modal; // Set modal flag when displaying char raise; // Raise after displaying char unfocus; // Focus to NULL after displaying char done; // Set when destroyed char run; // Set when script is running char ref; // Set when killed through unref and need the ref back } v_dd; /* Actmap array */ #define ACT_SIZE 2 /* Pointers per actmap slot */ #define ADD_ACT(W,S,V) ((W)[0] = (S) , (W)[1] = (V)) static void act_state(v_dd *vdata, unsigned int mask) { void **map = vdata->actmap; unsigned int n, m, vm = vdata->vismask; int i; vdata->actmask = mask; i = vdata->actn; while (i-- > 0) { n = (unsigned)map[1]; if ((m = n & vm)) cmd_showhide(map[0], !!(m & mask)); if ((m = n & ~vm)) cmd_sensitive(map[0], !!(m & mask)); map += ACT_SIZE; } } /* Simulated widget - one struct for all kinds */ typedef struct { char insens; // Insensitivity flag short op; // Internal opcode short cnt; // Options count int value; // Integer value int range[2]; // Value range char *id; // Identifying string void *strs; // Option labels / string value / anything else } swdata; #define IS_UNREAL(S) ((S)[0] == (S)[2]) #define GET_UOP(S) (((swdata *)(S)[0])->op) static char *set_uentry(swdata *sd, char *s) { return (sd->strs = !s ? NULL : sd->value < 0 ? g_strdup(s) : g_strndup(s, sd->value)); } /* Command table */ typedef struct { short op, size, uop; } cmdef; static cmdef *cmds[op_LAST]; /* From widget to its wdata */ void **get_wdata(GtkWidget *widget, char *id) { return (gtk_object_get_data(GTK_OBJECT(widget), id ? id : VCODE_KEY)); } /* From slot to its wdata */ void **wdata_slot(void **slot) { while (TRUE) { int op = GET_OP(slot); // WDONE anchors wdata if (op == op_WDONE) return (slot); // EVTs link to it if ((op >= op_EVT_0) && (op <= op_EVT_LAST)) return (*slot); // EVs link to parent slot if ((op >= op_EV_0) && (op <= op_EV_LAST)) slot = EV_PARENT(slot); // Other slots just repose in sequence else slot = PREV_SLOT(slot); /* And if not valid wdata, die by SIGSEGV in the end */ } } /* From event to its originator */ void **origin_slot(void **slot) { while (TRUE) { int op = GET_OP(slot); if (op < op_EVT_0) return (slot); // EVs link to parent slot else if ((op >= op_EV_0) && (op <= op_EV_LAST)) slot = EV_PARENT(slot); else slot = PREV_SLOT(slot); /* And if not valid wdata, die by SIGSEGV in the end */ } } /* From slot to its storage location */ void *slot_data(void **slot, void *ddata) { void **desc = slot[1], **v = desc[1]; int opf = (int)desc[0]; if (opf & WB_FFLAG) v = (void *)(ddata + (int)v); if (opf & WB_NFLAG) v = *v; // dereference return (v); } /* Find specific V-code _after_ this slot */ static void **op_slot(void **slot, int op) { while ((slot = NEXT_SLOT(slot))[1]) { int n = GET_OP(slot); // Found if (n == op) return (slot); // Till another origin slot if (n < op_EVT_0) break; } // Not found return (NULL); } /* Find unreal slot before this one */ static void **prev_uslot(void **slot) { slot = origin_slot(PREV_SLOT(slot)); if (!IS_UNREAL(slot)) slot = op_slot(slot, op_uALTNAME); return (slot); } void dialog_event(void *ddata, void **wdata, int what, void **where) { v_dd *vdata = GET_VDATA(wdata); if (((int)vdata->code & WB_OPMASK) != op_WDONE) return; // Paranoia if (vdata->dv) *vdata->dv = where; } /* !!! Warning: handlers should not access datastore after window destruction! * GTK+ refs objects for signal duration, but no guarantee every other toolkit * will behave alike - WJ */ static void get_evt_1(GtkObject *widget, gpointer user_data) { void **slot = user_data; void **base = slot[0], **desc = slot[1]; ((evt_fn)desc[1])(GET_DDATA(base), base, (int)desc[0] & WB_OPMASK, slot); } static void get_evt_1_t(GtkObject *widget, gpointer user_data) { if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) get_evt_1(widget, user_data); } void do_evt_1_d(void **slot) { void **base = slot[0], **desc = slot[1]; if (!desc[1]) run_destroy(base); else ((evt_fn)desc[1])(GET_DDATA(base), base, (int)desc[0] & WB_OPMASK, slot); } static gboolean get_evt_del(GtkWidget *widget, GdkEvent *event, gpointer user_data) { do_evt_1_d(user_data); return (TRUE); // it is for handler to decide, destroy it or not } static gboolean get_evt_conf(GtkWidget *widget, GdkEventConfigure *event, gpointer user_data) { get_evt_1(NULL, user_data); return (TRUE); // no use of its propagating } static gboolean get_evt_key(GtkWidget *widget, GdkEventKey *event, gpointer user_data) { void **slot = user_data; void **base = slot[0], **desc = slot[1]; key_ext key = { event->keyval, low_key(event), real_key(event), event->state }; int res = ((evtxr_fn)desc[1])(GET_DDATA(base), base, (int)desc[0] & WB_OPMASK, slot, &key); #if GTK_MAJOR_VERSION == 1 /* Return value alone doesn't stop GTK1 from running other handlers */ if (res) gtk_signal_emit_stop_by_name(GTK_OBJECT(widget), "key_press_event"); #endif return (!!res); } static int check_smart_menu_keys(void *sdata, GdkEventKey *event); static gboolean window_evt_key(GtkWidget *widget, GdkEventKey *event, gpointer user_data) { void **slot = user_data; v_dd *vdata = GET_VDATA((void **)slot[0]); gint res, res2, stop; /* Do nothing if called recursively */ if ((void *)event == vdata->now_evt) return (FALSE); res = res2 = stop = 0; /* First, ask smart menu */ if (vdata->smmenu) res = check_smart_menu_keys(vdata->smmenu, event); /* Now, ask prioritized widget */ while (!res && vdata->wantkey) { void *was_evt, **wslot = origin_slot(vdata->wantkey); if (!GTK_WIDGET_MAPPED(wslot[0])) break; // not displayed // !!! Maybe this check is enough by itself? if (!cmd_checkv(wslot, SLOT_FOCUSED)) break; slot = NEXT_SLOT(vdata->wantkey); if (GET_HANDLER(slot) && (res = stop = get_evt_key(widget, event, slot))) break; #if GTK_MAJOR_VERSION >= 2 /* We let widgets in the focused part process the keys first */ res = gtk_window_propagate_key_event(GTK_WINDOW(widget), event); if (res) break; #endif /* Let default handlers have priority */ // !!! Be ready to handle nested events was_evt = vdata->now_evt; vdata->now_evt = event; gtk_signal_emit_by_name(GTK_OBJECT(widget), "key_press_event", event, &res); res2 = TRUE; // Default events checked already vdata->now_evt = was_evt; break; } /* And only now, run own handler */ slot = user_data; if (!res && GET_HANDLER(slot)) res = stop = get_evt_key(widget, event, slot); res |= res2; #if GTK_MAJOR_VERSION == 1 /* Return value alone doesn't stop GTK1 from running other handlers */ if (res && !stop) gtk_signal_emit_stop_by_name(GTK_OBJECT(widget), "key_press_event"); #endif return (res); } // Widget datastores typedef struct { GtkWidget *pane, *vbox; } dock_data; #define HVSPLIT_MAX 4 typedef struct { GtkWidget *box, *panes[2], *inbox[HVSPLIT_MAX]; int cnt; } hvsplit_data; // Text renderer #if GTK_MAJOR_VERSION >= 2 int texteng_aa = TRUE; #if (GTK_MAJOR_VERSION == 3) || (GTK2VERSION >= 6) #define FULLPANGO 1 int texteng_rot = TRUE; int texteng_spc = TRUE; #else #define FULLPANGO 0 #define PangoMatrix int /* For rotate_box() */ #define PANGO_MATRIX_INIT 0 int texteng_rot = FALSE; int texteng_spc = FALSE; #endif int texteng_lf = TRUE; int texteng_dpi = TRUE; #else /* GTK+1 */ #ifdef U_MTK int texteng_aa = TRUE; #else int texteng_aa = FALSE; #endif int texteng_rot = FALSE; int texteng_spc = FALSE; int texteng_lf = FALSE; int texteng_dpi = FALSE; #endif int texteng_con = FALSE; typedef struct { double sysdpi; int dpi; #if GTK_MAJOR_VERSION == 3 int lastsize, lastdpi, lastset; #endif } fontsel_data; #if GTK_MAJOR_VERSION >= 2 /* Pango coords to pixels, inclusive */ static void rotate_box(PangoRectangle *lr, PangoMatrix *m) { double xx[4] = { lr->x, lr->x + lr->width, lr->x, lr->x + lr->width }; double yy[4] = { lr->y, lr->y, lr->y + lr->height, lr->y + lr->height }; double x_min, x_max, y_min, y_max; int i; #if FULLPANGO if (m) for (i = 0; i < 4; i++) { double xt, yt; xt = xx[i] * m->xx + yy[i] * m->xy + m->x0; yt = xx[i] * m->yx + yy[i] * m->yy + m->y0; xx[i] = xt; yy[i] = yt; } #endif x_min = x_max = xx[0]; y_min = y_max = yy[0]; for (i = 1; i < 4; i++) { if (x_min > xx[i]) x_min = xx[i]; if (x_max < xx[i]) x_max = xx[i]; if (y_min > yy[i]) y_min = yy[i]; if (y_max < yy[i]) y_max = yy[i]; } lr->x = floor(x_min / PANGO_SCALE); lr->width = ceil(x_max / PANGO_SCALE) - lr->x; lr->y = floor(y_min / PANGO_SCALE); lr->height = ceil(y_max / PANGO_SCALE) - lr->y; } #if GTK_MAJOR_VERSION == 3 #define FONT_SIGNAL "style_updated" static void fontsel_style(GtkWidget *widget, gpointer user_data) { GtkStyleContext *ctx; PangoFontDescription *d; void **r = user_data; fontsel_data *fd = r[2]; int sz, fontsize; if (!fd->dpi || !fd->sysdpi) { fd->lastdpi = 0; // To force an update when DPI is set again return; // Do nothing else } ctx = gtk_widget_get_style_context(widget); gtk_style_context_get(ctx, gtk_style_context_get_state(ctx), "font", &d, NULL); sz = pango_font_description_get_size(d); fontsize = gtk_font_selection_get_size(GTK_FONT_SELECTION(r[0])); if ((sz != fd->lastset) || (fd->dpi != fd->lastdpi) || (fontsize != fd->lastsize)) { fd->lastdpi = fd->dpi; fd->lastsize = fontsize; sz = (fontsize * fd->dpi) / fd->sysdpi; pango_font_description_set_size(d, fd->lastset = sz); gtk_widget_override_font(widget, d); // To make widget show it } pango_font_description_free(d); } #else #define FONT_SIGNAL "style_set" /* In principle, similar approach can be used with GTK+1 too - but it would be * much less clean and less precise, and I am unsure about possibly wasting * a lot of X font resources; therefore, no DPI for GTK+1 - WJ */ static void fontsel_style(GtkWidget *widget, GtkStyle *previous_style, gpointer user_data) { PangoContext *c; PangoFontDescription *d; void **r = user_data; fontsel_data *fd = r[2]; int sz; if (!fd->dpi || !fd->sysdpi) return; // Leave alone c = gtk_widget_get_pango_context(widget); if (!c) return; d = pango_context_get_font_description(c); sz = (pango_font_description_get_size(d) * fd->dpi) / fd->sysdpi; /* !!! 1st is used for font render, 2nd for GtkEntry size calculation; * need to modify both the same way */ pango_font_description_set_size(d, sz); pango_font_description_set_size(widget->style->font_desc, sz); } #endif #endif /* GTK+2&3 */ static void fontsel_prepare(GtkWidget *widget, gpointer user_data) { char **ss = user_data; gtk_font_selection_set_font_name(GTK_FONT_SELECTION(widget), ss[0]); gtk_font_selection_set_preview_text(GTK_FONT_SELECTION(widget), ss[1]); ss[0] = ss[1] = NULL; } static GtkWidget *fontsel(void **r, void *v) { GtkWidget *widget = gtk_font_selection_new(); GtkWidget *entry = gtk_font_selection_get_preview_entry(GTK_FONT_SELECTION(widget)); accept_ctrl_enter(entry); /* !!! Setting initial values fails if no toplevel */ gtk_signal_connect(GTK_OBJECT(widget), "realize", GTK_SIGNAL_FUNC(fontsel_prepare), v); #if GTK_MAJOR_VERSION == 3 /* !!! Kill off animating size changes */ css_restyle(entry, ".mtPaint_fontentry { transition-duration: 0; " "transition-delay: 0; }", "mtPaint_fontentry", NULL); #endif #if GTK_MAJOR_VERSION >= 2 gtk_signal_connect(GTK_OBJECT(entry), FONT_SIGNAL, GTK_SIGNAL_FUNC(fontsel_style), r); #endif return (widget); } #define PAD_SIZE 2 static void do_render_text(texteng_dd *td) { GtkWidget *widget = main_window; #if GTK_MAJOR_VERSION == 3 cairo_surface_t *text_pixmap; cairo_t *cr; cairo_matrix_t cm; #else GdkPixmap *text_pixmap; #endif unsigned char *buf; int width, height, have_rgb = 0; #if GTK_MAJOR_VERSION >= 2 static const PangoAlignment align[3] = { PANGO_ALIGN_LEFT, PANGO_ALIGN_CENTER, PANGO_ALIGN_RIGHT }; PangoMatrix matrix = PANGO_MATRIX_INIT, *mp = NULL; PangoRectangle ink, rect; PangoContext *context; PangoLayout *layout; PangoFontDescription *font_desc; int tx, ty; context = gtk_widget_create_pango_context(widget); layout = pango_layout_new(context); font_desc = pango_font_description_from_string(td->font); if (td->dpi) pango_font_description_set_size(font_desc, (int)(pango_font_description_get_size(font_desc) * (td->dpi / window_dpi(widget)))); pango_layout_set_font_description(layout, font_desc); pango_font_description_free(font_desc); pango_layout_set_text(layout, td->text, -1); pango_layout_set_alignment(layout, align[td->align]); #if FULLPANGO if (td->spacing) { PangoAttrList *al = pango_attr_list_new(); PangoAttribute *a = pango_attr_letter_spacing_new( (td->spacing * PANGO_SCALE) / 100); pango_attr_list_insert(al, a); pango_layout_set_attributes(layout, al); pango_attr_list_unref(al); } if (td->angle) { pango_matrix_rotate(&matrix, td->angle * 0.01); pango_context_set_matrix(context, &matrix); pango_layout_context_changed(layout); mp = &matrix; } #endif pango_layout_get_extents(layout, &ink, &rect); // Adjust height of ink rectangle to logical tx = ink.y + ink.height; ty = rect.y + rect.height; if (tx < ty) tx = ty; if (ink.y > rect.y) ink.y = rect.y; ink.height = tx - ink.y; rotate_box(&rect, mp); // What gdk_draw_layout() uses rotate_box(&ink, mp); // What one should use tx = PAD_SIZE - ink.x + rect.x; ty = PAD_SIZE - ink.y + rect.y; width = ink.width + PAD_SIZE * 2; height = ink.height + PAD_SIZE * 2; #if GTK_MAJOR_VERSION == 3 text_pixmap = cairo_image_surface_create(CAIRO_FORMAT_RGB24, width, height); cr = cairo_create(text_pixmap); cairo_translate(cr, tx - rect.x, ty - rect.y); if (mp) { cm.xx = mp->xx; cm.yx = mp->yx; cm.xy = mp->xy; cm.yy = mp->yy; cm.x0 = mp->x0; cm.y0 = mp->y0; cairo_transform(cr, &cm); } cairo_set_source_rgb(cr, 1, 1, 1); pango_cairo_show_layout(cr, layout); cairo_destroy(cr); #else text_pixmap = gdk_pixmap_new(widget->window, width, height, -1); gdk_draw_rectangle(text_pixmap, widget->style->black_gc, TRUE, 0, 0, width, height); gdk_draw_layout(text_pixmap, widget->style->white_gc, tx, ty, layout); #endif g_object_unref(layout); g_object_unref(context); #else /* #if GTK_MAJOR_VERSION == 1 */ GdkFont *t_font = gdk_font_load(td->font); int lbearing, rbearing, f_width, ascent, descent; gdk_string_extents(t_font, td->text, &lbearing, &rbearing, &f_width, &ascent, &descent); width = rbearing - lbearing + PAD_SIZE * 2; height = ascent + descent + PAD_SIZE * 2; text_pixmap = gdk_pixmap_new(widget->window, width, height, -1); gdk_draw_rectangle(text_pixmap, widget->style->black_gc, TRUE, 0, 0, width, height); gdk_draw_string(text_pixmap, t_font, widget->style->white_gc, PAD_SIZE - lbearing, ascent + PAD_SIZE, td->text); gdk_font_unref(t_font); #endif buf = malloc(width * height * 3); if (buf) have_rgb = !!wj_get_rgb_image(gtk_widget_get_window(widget), text_pixmap, buf, 0, 0, width, height); // REMOVE PIXMAP #if GTK_MAJOR_VERSION == 3 cairo_surface_destroy(text_pixmap); #else gdk_pixmap_unref(text_pixmap); #endif memset(&td->ctx, 0, sizeof(td->ctx)); if (!have_rgb) free(buf); else { td->ctx.xy[2] = width; td->ctx.xy[3] = height; td->ctx.rgb = buf; } } // Mouse handling typedef struct { void *slot[EV_SIZE]; mouse_ext *mouse; int vport[4]; } mouse_den; static int do_evt_mouse(void **slot, void *event, mouse_ext *mouse) { static void *ev_MOUSE = WBh(EV_MOUSE, 0); void **orig = origin_slot(slot); void **base = slot[0], **desc = slot[1]; mouse_den den = { EVSLOT(ev_MOUSE, orig, event), mouse, { 0, 0, 0, 0 } }; GtkWidget *top = GET_REAL_WINDOW(base); int res, op = GET_OP(orig); #if GTK_MAJOR_VERSION >= 2 if ((((int)desc[0] & WB_OPMASK) >= op_EVT_XMOUSE0) && tablet_device) { gdouble pressure = 1.0; gdk_event_get_axis(event, GDK_AXIS_PRESSURE, &pressure); mouse->pressure = (int)(pressure * MAX_PRESSURE + 0.5); } #endif if ((op == op_CANVASIMG) || (op == op_CANVASIMGB) || (op == op_CANVAS)) { wjcanvas_get_vport(orig[0], den.vport); den.mouse->x += den.vport[0]; den.mouse->y += den.vport[1]; } /* !!! ddata should persist while the event is handled */ gtk_widget_ref(top); res = ((evtxr_fn)desc[1])(GET_DDATA(base), base, (int)desc[0] & WB_OPMASK, den.slot, mouse); gtk_widget_unref(top); return (res); } /* !!! After a drop, gtk_drag_end() sends to drag source a fake release event * with coordinates (0, 0); remember to ignore them where necessary - WJ */ static gboolean get_evt_mouse(GtkWidget *widget, GdkEventButton *event, gpointer user_data) { mouse_ext mouse = { event->x, event->y, event->button, event->type == GDK_BUTTON_PRESS ? 1 : event->type == GDK_2BUTTON_PRESS ? 2 : event->type == GDK_3BUTTON_PRESS ? 3 : event->type == GDK_BUTTON_RELEASE ? -1 : 0, event->state, MAX_PRESSURE }; #if GTK_MAJOR_VERSION == 1 if (GET_OP((void **)user_data) >= op_EVT_XMOUSE0) mouse.pressure = (int)(event->pressure * MAX_PRESSURE + 0.5); #endif return (do_evt_mouse(user_data, event, &mouse)); } // This peculiar encoding is historically used throughout mtPaint static inline int state_to_button(unsigned int state) { return ((state & _B13mask) == _B13mask ? 13 : state & _B1mask ? 1 : state & _B3mask ? 3 : state & _B2mask ? 2 : 0); } static gboolean get_evt_mmouse(GtkWidget *widget, GdkEventMotion *event, gpointer user_data) { mouse_ext mouse; int res; #if GTK_MAJOR_VERSION == 3 static int recurse; GdkEventMotion *e0 = event, *e1 = NULL; GdkEvent *e2 = NULL; int ate = 0; again: #endif mouse.pressure = MAX_PRESSURE; #if GTK_MAJOR_VERSION == 1 if (GET_OP((void **)user_data) >= op_EVT_XMOUSE0) { gdouble pressure = event->pressure; if (event->is_hint) gdk_input_window_get_pointer(event->window, event->deviceid, NULL, NULL, &pressure, NULL, NULL, NULL); mouse.pressure = (int)(pressure * MAX_PRESSURE + 0.5); } #endif while (TRUE) { #if GTK_MAJOR_VERSION == 3 if (event->is_hint) { gdk_event_request_motions(event); if (GET_OP((void **)user_data) < op_EVT_XMOUSE0) { gdk_window_get_device_position(event->window, event->device, &mouse.x, &mouse.y, &mouse.state); break; } } #else /* #if GTK_MAJOR_VERSION <= 2 */ if (!event->is_hint); #if GTK_MAJOR_VERSION == 2 else if (GET_OP((void **)user_data) >= op_EVT_XMOUSE0) { gdk_device_get_state(event->device, event->window, NULL, &mouse.state); } #endif else { gdk_window_get_pointer(event->window, &mouse.x, &mouse.y, &mouse.state); break; } #endif /* GTK+1&2 */ mouse.x = event->x; mouse.y = event->y; mouse.state = event->state; break; } mouse.button = state_to_button(mouse.state); mouse.count = 0; // motion res = do_evt_mouse(user_data, event, &mouse); #if GTK_MAJOR_VERSION == 3 /* In GTK+1&2, side effect of enable_events() is enabling motion hints, * so motion events cannot queue up; and the code is lean enough for it * to never matter in normal operation anyway. * In GTK+3 I keep its event compression disabled for canvas, and queuing * up sometimes can become an issue, with it being slower overall. * Therefore, limited event compression is done here instead (and what * remains is handled by twos at once, which seems to help too) - WJ */ #define ATE_MAX 2 /* Dropping 2 in 4 seems to be enough */ if (e1) { gdk_event_free((GdkEvent *)e1); e1 = NULL; } else while (!recurse && !e2 && gdk_events_pending()) { e2 = gdk_event_get(); if (e2 && (e2->any.type == GDK_MOTION_NOTIFY) && (e2->any.window == e0->window) && (e2->motion.state == e0->state) && (e2->motion.device == e0->device)) { if (e1) { ate++; gdk_event_free((GdkEvent *)e1); } e1 = (GdkEventMotion *)e2; e2 = NULL; if (ate >= ATE_MAX) break; } else break; } if (e1) { event = e1; goto again; } if (e2) { recurse = TRUE; gtk_main_do_event(e2); gdk_event_free(e2); recurse = FALSE; } #endif return (res); } static void enable_events(void **slot, int op) { #if GTK_MAJOR_VERSION == 3 /* Let's be granular, here */ GdkEventMask m; switch (op) { case op_EVT_KEY: m = GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK; break; /* Button release goes where button press went, b/c automatic grab */ case op_EVT_MOUSE: case op_EVT_RMOUSE: case op_EVT_XMOUSE: case op_EVT_RXMOUSE: m = GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK; break; case op_EVT_MMOUSE: case op_EVT_MXMOUSE: m = GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK; break; case op_EVT_CROSS: m = GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK; break; case op_EVT_SCROLL: m = GDK_SCROLL_MASK; break; default: return; } gtk_widget_add_events(*slot, m); #else /* #if GTK_MAJOR_VERSION <= 2 */ if ((op >= op_EVT_MOUSE) && (op <= op_EVT_RXMOUSE)) { if (op >= op_EVT_XMOUSE0) gtk_widget_set_extension_events(*slot, GDK_EXTENSION_EVENTS_CURSOR); #if GTK_MAJOR_VERSION == 1 if (GTK_WIDGET_NO_WINDOW(*slot)) return; #endif } else if (op != op_EVT_CROSS) return; // Ignore op_EVT_KEY & op_EVT_SCROLL /* No granularity at all, but it was always this way, and it worked */ gtk_widget_set_events(*slot, GDK_ALL_EVENTS_MASK); #endif /* GTK+1&2 */ } // !!! With GCC inlining this, weird size fluctuations can happen. Or not. static void add_mouse(void **r, int op) { static const char *sn[3] = { "button_press_event", "motion_notify_event", "button_release_event" }; void **slot = origin_slot(PREV_SLOT(r)); int cw = op - op_EVT_MOUSE + (op >= op_EVT_XMOUSE0); gtk_signal_connect(GTK_OBJECT(*slot), sn[cw & 3], cw & 1 ? GTK_SIGNAL_FUNC(get_evt_mmouse) : GTK_SIGNAL_FUNC(get_evt_mouse), r); enable_events(slot, op); } static gboolean get_evt_cross(GtkWidget *widget, GdkEventCrossing *event, gpointer user_data) { void **slot, **base, **desc; /* Skip grab/ungrab related events */ if (event->mode != GDK_CROSSING_NORMAL) return (FALSE); slot = user_data; base = slot[0]; desc = slot[1]; ((evtx_fn)desc[1])(GET_DDATA(base), base, (int)desc[0] & WB_OPMASK, slot, (void *)(event->type == GDK_ENTER_NOTIFY)); return (FALSE); // let it propagate } #if GTK_MAJOR_VERSION >= 2 static gboolean get_evt_scroll(GtkWidget *widget, GdkEventScroll *event, gpointer user_data) { void **slot = user_data, **base = slot[0], **desc = slot[1]; scroll_ext scroll = { event->direction == GDK_SCROLL_LEFT ? -1 : event->direction == GDK_SCROLL_RIGHT ? 1 : 0, event->direction == GDK_SCROLL_UP ? -1 : event->direction == GDK_SCROLL_DOWN ? 1 : 0, event->state }; ((evtx_fn)desc[1])(GET_DDATA(base), base, (int)desc[0] & WB_OPMASK, slot, &scroll); if (!(scroll.xscroll | scroll.yscroll)) return (TRUE); event->direction = scroll.xscroll < 0 ? GDK_SCROLL_LEFT : scroll.xscroll > 0 ? GDK_SCROLL_RIGHT : scroll.yscroll < 0 ? GDK_SCROLL_UP : /* scroll.yscroll > 0 ? */ GDK_SCROLL_DOWN; return (FALSE); } #endif // Drag handling typedef struct { int n; clipform_dd *src; GtkTargetList *targets; GtkTargetEntry ent[1]; } clipform_data; typedef struct { int x, y, may_drag; int color; void **r; clipform_data *cd; } drag_ctx; typedef struct { GdkDragContext *drag_context; GtkSelectionData *data; guint info; guint time; } drag_sel; typedef struct { void *slot[EV_SIZE]; drag_sel *ds; drag_ctx *dc; drag_ext d; } drag_den; static int drag_event(drag_sel *ds, drag_ctx *dc) { static void *ev_DRAGFROM = WBh(EV_DRAGFROM, 0); void **slot = dc->r, **orig = origin_slot(slot); void **base = slot[0], **desc = slot[1]; drag_den den = { EVSLOT(ev_DRAGFROM, orig, den.slot), ds, dc }; /* While technically, drag starts at current position, I use the saved * one - where user had clicked to begin drag - WJ */ // !!! Struct not stable yet, so init fields one by one memset(&den.d, 0, sizeof(den.d)); den.d.x = dc->x; den.d.y = dc->y; den.d.format = ds ? dc->cd->src + ds->info : NULL; return (((evtxr_fn)desc[1])(GET_DDATA(base), base, (int)desc[0] & WB_OPMASK, den.slot, &den.d)); } #define RGB_DND_W 48 #define RGB_DND_H 32 static void set_drag_icon(GdkDragContext *context, GtkWidget *src, int rgb) { #if GTK_MAJOR_VERSION == 3 GdkPixbuf *p = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, RGB_DND_W, RGB_DND_H); gdk_pixbuf_fill(p, ((unsigned)rgb << 8) + 0xFF); gtk_drag_set_icon_pixbuf(context, p, -2, -2); g_object_unref(p); #else /* #if GTK_MAJOR_VERSION <= 2 */ GdkGCValues sv; GdkPixmap *swatch; swatch = gdk_pixmap_new(src->window, RGB_DND_W, RGB_DND_H, -1); gdk_gc_get_values(src->style->black_gc, &sv); gdk_rgb_gc_set_foreground(src->style->black_gc, rgb); gdk_draw_rectangle(swatch, src->style->black_gc, TRUE, 0, 0, RGB_DND_W, RGB_DND_H); gdk_gc_set_foreground(src->style->black_gc, &sv.foreground); gtk_drag_set_icon_pixmap(context, gtk_widget_get_colormap(src), swatch, NULL, -2, -2); gdk_pixmap_unref(swatch); #endif /* GTK+1&2 */ } /* !!! In GTK+3 icon must be set in "drag_begin", setting it in try_start_drag() * somehow only sets it for not-valid-target case - WJ */ static void begin_drag(GtkWidget *widget, GdkDragContext *context, gpointer user_data) { drag_ctx *dc = user_data; if (dc->color >= 0) set_drag_icon(context, widget, dc->color); } static int try_start_drag(GtkWidget *widget, GdkEvent *event, gpointer user_data) { drag_ctx *dc = user_data; int rx, ry; GdkModifierType state; if (event->type == GDK_BUTTON_PRESS) { if (event->button.button == 1) // Only left button inits drag { dc->x = event->button.x; dc->y = event->button.y; dc->may_drag = TRUE; } } else if (event->type == GDK_BUTTON_RELEASE) { if (event->button.button == 1) dc->may_drag = FALSE; } else if (event->type == GDK_MOTION_NOTIFY) { if (event->motion.is_hint) #if GTK_MAJOR_VERSION == 3 gdk_window_get_device_position(event->motion.window, event->motion.device, &rx, &ry, &state); #else /* if GTK_MAJOR_VERSION <= 2 */ gdk_window_get_pointer(event->motion.window, &rx, &ry, &state); #endif else { rx = event->motion.x; ry = event->motion.y; state = event->motion.state; } /* May init drag */ if (state & GDK_BUTTON1_MASK) { /* No dragging without clicking on the widget first */ if (dc->may_drag && #if GTK_MAJOR_VERSION == 1 ((abs(rx - dc->x) > 3) || (abs(ry - dc->y) > 3)) #else /* if GTK_MAJOR_VERSION >= 2 */ gtk_drag_check_threshold(widget, dc->x, dc->y, rx, ry) #endif ) /* Initiate drag */ { dc->may_drag = FALSE; /* Call handler so it can decide if it wants * this drag, and maybe set icon color */ dc->color = -1; if (!drag_event(NULL, dc)) return (TRUE); // no drag #if GTK_MAJOR_VERSION == 3 gtk_drag_begin_with_coordinates(widget, dc->cd->targets, GDK_ACTION_COPY | GDK_ACTION_MOVE, 1, event, -1, -1); #else /* if GTK_MAJOR_VERSION <= 2 */ gtk_drag_begin(widget, dc->cd->targets, GDK_ACTION_COPY | GDK_ACTION_MOVE, 1, event); #endif return (TRUE); } } else dc->may_drag = FALSE; // Release events can be lost } return (FALSE); } static void get_evt_drag(GtkWidget *widget, GdkDragContext *drag_context, GtkSelectionData *data, guint info, guint time, gpointer user_data) { drag_sel ds = { drag_context, data, info, time }; drag_event(&ds, user_data); } static void fcimage_rxy(void **slot, int *xy); static void get_evt_drop(GtkWidget *widget, GdkDragContext *drag_context, gint x, gint y, GtkSelectionData *data, guint info, guint time, gpointer user_data) { void **dd = user_data, **orig = origin_slot(dd); void **slot, **base, **desc; clipform_data *cd = *dd; // from DRAGDROP slot int res, op = GET_OP(orig), xy[2] = { x, y }; drag_ext dx; #if GTK_MAJOR_VERSION == 1 /* GTK+1 provides window-relative coordinates, not widget-relative */ if (GTK_WIDGET_NO_WINDOW(*orig)) { xy[0] -= GTK_WIDGET(*orig)->allocation.x; xy[1] -= GTK_WIDGET(*orig)->allocation.y; } #endif /* Map widget-relative coordinates to inner window */ if (op == op_FCIMAGEP) fcimage_rxy(orig, xy); // !!! Struct not stable yet, so init fields one by one memset(&dx, 0, sizeof(dx)); dx.x = xy[0]; dx.y = xy[1]; dx.format = cd->src + info; dx.data = (void *)gtk_selection_data_get_data(data); dx.len = gtk_selection_data_get_length(data); /* Selection data format isn't checked because it's how GTK+2 does it, * reportedly to ignore a bug in (some versions of) KDE - WJ */ res = dx.format->size ? dx.len == dx.format->size : dx.len >= 0; slot = SLOT_N(dd, 2); // from DRAGDROP to its EVT_DROP base = slot[0]; desc = slot[1]; ((evtx_fn)desc[1])(GET_DDATA(base), base, (int)desc[0] & WB_OPMASK, slot, &dx); if (GET_DESCV(dd, 2)) // Accept move as a copy (disallow deleting source) gtk_drag_finish(drag_context, res, FALSE, time); } static gboolean tried_drop(GtkWidget *widget, GdkDragContext *context, gint x, gint y, guint time, gpointer user_data) { GdkAtom target; /* Check if drop could provide a supported format */ #if GTK_MAJOR_VERSION == 1 clipform_data *cd = user_data; GList *dest, *src; gpointer tp; for (dest = cd->targets->list; dest; dest = dest->next) { target = ((GtkTargetPair *)dest->data)->target; tp = GUINT_TO_POINTER(target); for (src = context->targets; src && (src->data != tp); src = src->next); if (src) break; } if (!dest) return (FALSE); #else /* if GTK_MAJOR_VERSION >= 2 */ target = gtk_drag_dest_find_target(widget, context, NULL); if (target == GDK_NONE) return (FALSE); #endif /* Trigger "drag_data_received" event */ gtk_drag_get_data(widget, context, target, time); return (TRUE); } void *dragdrop(void **r) { void *v = r[0], **pp = r[1], **slot = origin_slot(PREV_SLOT(r)); clipform_data *cd = **(void ***)v; if (pp[4]) // Have drag handler { drag_ctx *dc = r[2]; dc->r = NEXT_SLOT(r); dc->cd = cd; gtk_signal_connect(GTK_OBJECT(*slot), "button_press_event", GTK_SIGNAL_FUNC(try_start_drag), dc); gtk_signal_connect(GTK_OBJECT(*slot), "motion_notify_event", GTK_SIGNAL_FUNC(try_start_drag), dc); gtk_signal_connect(GTK_OBJECT(*slot), "button_release_event", GTK_SIGNAL_FUNC(try_start_drag), dc); gtk_signal_connect(GTK_OBJECT(*slot), "drag_begin", GTK_SIGNAL_FUNC(begin_drag), dc); gtk_signal_connect(GTK_OBJECT(*slot), "drag_data_get", GTK_SIGNAL_FUNC(get_evt_drag), dc); } if (pp[6]) // Have drop handler { int dmode = GTK_DEST_DEFAULT_HIGHLIGHT | GTK_DEST_DEFAULT_MOTION; if (!pp[2]) dmode |= GTK_DEST_DEFAULT_DROP; else gtk_signal_connect(GTK_OBJECT(*slot), "drag_drop", GTK_SIGNAL_FUNC(tried_drop), cd); gtk_drag_dest_set(*slot, dmode, cd->ent, cd->n, pp[2] ? GDK_ACTION_COPY | GDK_ACTION_MOVE : GDK_ACTION_COPY); gtk_signal_connect(GTK_OBJECT(*slot), "drag_data_received", GTK_SIGNAL_FUNC(get_evt_drop), r); } return (cd); // For drop handler } // Clipboard handling typedef struct { void *slot[EV_SIZE]; GtkSelectionData *data; guint info; clipform_data *cd; copy_ext c; } copy_den; static void clip_evt(GtkSelectionData *sel, guint info, void **slot) { static void *ev_COPY = WBh(EV_COPY, 0); void **base, **desc; clipform_data *cd = slot[0]; copy_den den = { EVSLOT(ev_COPY, slot, den.slot), sel, info, cd, { sel ? cd->src + info : NULL, NULL, 0 } }; slot = NEXT_SLOT(slot); // from CLIPBOARD to EVT_COPY base = slot[0]; desc = slot[1]; ((evtx_fn)desc[1])(GET_DDATA(base), base, (int)desc[0] & WB_OPMASK, den.slot, &den.c); } static int paste_evt(GtkSelectionData *sel, clipform_dd *format, void **slot) { void **base = slot[0], **desc = slot[1]; copy_ext c = { format, (void *)gtk_selection_data_get_data(sel), gtk_selection_data_get_length(sel) }; return (((evtxr_fn)desc[1])(GET_DDATA(base), base, (int)desc[0] & WB_OPMASK, slot, &c)); } static clipform_dd *clip_format(GtkSelectionData *sel, clipform_data *cd) { GdkAtom *targets; int i, n = gtk_selection_data_get_length(sel) / sizeof(GdkAtom); if ((n > 0) && (gtk_selection_data_get_format(sel) == 32) && (gtk_selection_data_get_data_type(sel) == GDK_SELECTION_TYPE_ATOM)) { #if GTK_MAJOR_VERSION == 3 guint res, res0 = G_MAXUINT; targets = (GdkAtom *)gtk_selection_data_get_data(sel); #if 0 /* #ifdef GDK_WINDOWING_QUARTZ */ /* !!! For debugging */ g_print("%d targets:\n", n); for (i = 0; i < n; i++) g_print("%s\n", gdk_atom_name(targets[i])); #endif /* Need to scan for each target, to return the earliest slot in * the array in case more than one match */ for (i = 0; i < n; i++) if (gtk_target_list_find(cd->targets, targets[i], &res) && (res < res0)) res0 = res; // Return the matching format if (res0 < G_MAXUINT) return (cd->src + res0); #else /* if GTK_MAJOR_VERSION <= 2 */ GList *dest; GdkAtom target; targets = (GdkAtom *)gtk_selection_data_get_data(sel); for (dest = cd->targets->list; dest; dest = dest->next) { target = ((GtkTargetPair *)dest->data)->target; for (i = 0; (i < n) && (targets[i] != target); i++); if (i < n) break; } // Return the matching format if (dest) return (cd->src + ((GtkTargetPair *)dest->data)->info); #endif } return (NULL); } #if GTK_MAJOR_VERSION == 1 #define CLIPMASK 3 /* 2 clipboards */ enum { TEXT_STRING = 0, TEXT_TEXT, TEXT_COMPOUND, TEXT_CNT }; static GtkTargetEntry text_targets[] = { { "STRING", 0, TEXT_STRING }, { "TEXT", 0, TEXT_TEXT }, { "COMPOUND_TEXT", 0, TEXT_COMPOUND } }; static GtkTargetList *text_tlist; typedef struct { char *what; int where; } text_offer; static text_offer text_on_offer[2]; static void clear_text_offer(int nw) { int i; for (i = 0; i < 2; i++) { if (text_on_offer[i].where &= ~nw) continue; free(text_on_offer[i].what); text_on_offer[i].what = NULL; } } static void selection_callback(GtkWidget *widget, GtkSelectionData *sel, guint time, gpointer user_data) { void **res = user_data; if (!res[1]) res[1] = clip_format(sel, res[0]); // check else if ((sel->length < 0) || !paste_evt(sel, res[1], res[0])) // paste res[1] = NULL; // fail res[0] = NULL; // done } static int process_clipboard(void **slot) { clipform_data *cd = slot[0]; void **desc = slot[1]; void *res[2] = { NULL, NULL }; clipform_dd *format; GdkAtom sel; guint sig = 0; int which, nw = (int)desc[2] & CLIPMASK; for (which = 0; (1 << which) <= nw; which++) { if (!((1 << which) & nw)) continue; // If we're who put data there // !!! No check if same program but another clipboard - no need for now if (internal_clipboard(which)) continue; sel = gdk_atom_intern(which ? "PRIMARY" : "CLIPBOARD", FALSE); res[0] = cd; res[1] = NULL; if (!sig) sig = gtk_signal_connect(GTK_OBJECT(main_window), "selection_received", GTK_SIGNAL_FUNC(selection_callback), &res); /* First, deciding on format... */ gtk_selection_convert(main_window, sel, gdk_atom_intern("TARGETS", FALSE), GDK_CURRENT_TIME); while (res[0]) gtk_main_iteration(); if (!(format = res[1])) continue; // no luck /* ...then, requesting the format */ res[0] = SLOT_N(slot, 2); // from CLIPBOARD to EVT_PASTE gtk_selection_convert(main_window, sel, gdk_atom_intern(format->target, FALSE), GDK_CURRENT_TIME); while (res[0]) gtk_main_iteration(); if (res[1]) break; // success } if (sig) gtk_signal_disconnect(GTK_OBJECT(main_window), sig); return (!!res[1]); } static void selection_get_callback(GtkWidget *widget, GtkSelectionData *sel, guint info, guint time, gpointer user_data) { void **slot = g_dataset_get_data(main_window, gdk_atom_name(sel->selection)); /* Text clipboard is handled right here */ if (slot == (void *)text_on_offer) { char *s; int i, which; which = sel->selection == gdk_atom_intern("PRIMARY", FALSE) ? 2 : 1; for (i = 0; i < 2; i++) if (text_on_offer[i].where & which) break; if (i > 1) return; // No text for this clipboard s = text_on_offer[i].what; if (!s) return; // Paranoia if (info == TEXT_STRING) gtk_selection_data_set(sel, sel->target, 8, s, strlen(s)); else if ((info == TEXT_TEXT) || (info == TEXT_COMPOUND)) { guchar *ns; GdkAtom target; gint format, len; gdk_string_to_compound_text(s, &target, &format, &ns, &len); gtk_selection_data_set(sel, target, format, ns, len); gdk_free_compound_text(ns); } } /* Other kinds get handled outside */ else if (slot) clip_evt(sel, info, slot); } static void selection_clear_callback(GtkWidget *widget, GdkEventSelection *event, gpointer user_data) { void **slot = g_dataset_get_data(main_window, gdk_atom_name(event->selection)); if (slot == (void *)text_on_offer) clear_text_offer( event->selection == gdk_atom_intern("PRIMARY", FALSE) ? 2 : 1); else if (slot) clip_evt(NULL, 0, slot); } // !!! GTK+ 1.2 internal type (gtk/gtkselection.c) typedef struct { GdkAtom selection; GtkTargetList *list; } GtkSelectionTargetList; static int offer_clipboard(void **slot, int text) { static int connected; void **desc = slot[1]; clipform_data *cd = slot[0]; GtkTargetEntry *targets = cd->ent; gpointer info = slot; GtkSelectionTargetList *slist; GList *list, *tmp; GdkAtom sel; int which, res = FALSE, nw = (int)desc[2] & CLIPMASK, ntargets = cd->n; if (text) targets = text_targets , ntargets = TEXT_CNT , info = text_on_offer; for (which = 0; (1 << which) <= nw; which++) { if (!((1 << which) & nw)) continue; sel = gdk_atom_intern(which ? "PRIMARY" : "CLIPBOARD", FALSE); if (!gtk_selection_owner_set(main_window, sel, GDK_CURRENT_TIME)) continue; /* Don't have gtk_selection_clear_targets() in GTK+1 - have to * reimplement */ list = gtk_object_get_data(GTK_OBJECT(main_window), "gtk-selection-handlers"); for (tmp = list; tmp; tmp = tmp->next) { if ((slist = tmp->data)->selection != sel) continue; list = g_list_remove_link(list, tmp); gtk_target_list_unref(slist->list); g_free(slist); break; } gtk_object_set_data(GTK_OBJECT(main_window), "gtk-selection-handlers", list); // !!! Have to resort to this to allow for multiple X clipboards g_dataset_set_data(main_window, which ? "PRIMARY" : "CLIPBOARD", info); if (!connected) { gtk_signal_connect(GTK_OBJECT(main_window), "selection_get", GTK_SIGNAL_FUNC(selection_get_callback), NULL); gtk_signal_connect(GTK_OBJECT(main_window), "selection_clear_event", GTK_SIGNAL_FUNC(selection_clear_callback), NULL); connected = TRUE; } gtk_selection_add_targets(main_window, sel, targets, ntargets); res = TRUE; } return (res); } static void offer_text(void **slot, char *s) { void **desc = slot[1]; int i, nw = (int)desc[2] & CLIPMASK; clear_text_offer(nw); i = !!text_on_offer[0].what; text_on_offer[i].what = strdup(s); text_on_offer[i].where = nw; if (!text_tlist) text_tlist = gtk_target_list_new(text_targets, TEXT_CNT); offer_clipboard(slot, TRUE); } #else /* if GTK_MAJOR_VERSION >= 2 */ #ifdef GDK_WINDOWING_X11 #define CLIPMASK 3 /* 2 clipboards */ #else #define CLIPMASK 1 /* 1 clipboard */ #endif /* While GTK+2 allows for synchronous clipboard handling, it's implemented * through copying the entire clipboard data - and when the data might be * a huge image which mtPaint is bound to allocate *yet again*, this would be * asking for trouble - WJ */ static void clip_paste(GtkClipboard *clipboard, GtkSelectionData *sel, gpointer user_data) { void **res = user_data; if ((gtk_selection_data_get_length(sel) < 0) || !paste_evt(sel, res[1], res[0])) res[1] = NULL; // fail res[0] = NULL; // done } static void clip_check(GtkClipboard *clipboard, GtkSelectionData *sel, gpointer user_data) { void **res = user_data; res[1] = clip_format(sel, res[0]); res[0] = NULL; // done } static int process_clipboard(void **slot) { GtkClipboard *clip; clipform_data *cd = slot[0]; void **desc = slot[1]; int which, nw = (int)desc[2] & CLIPMASK; for (which = 0; (1 << which) <= nw; which++) { if (!((1 << which) & nw)) continue; // If we're who put data there // !!! No check if same program but another clipboard - no need for now if (internal_clipboard(which)) continue; clip = gtk_clipboard_get(which ? GDK_SELECTION_PRIMARY : GDK_SELECTION_CLIPBOARD); { void *res[] = { cd, NULL }; clipform_dd *format; /* First, deciding on format... */ gtk_clipboard_request_contents(clip, gdk_atom_intern("TARGETS", FALSE), clip_check, res); while (res[0]) gtk_main_iteration(); if (!(format = res[1])) continue; // no luck /* ...then, requesting the format */ res[0] = SLOT_N(slot, 2); // from CLIPBOARD to EVT_PASTE gtk_clipboard_request_contents(clip, gdk_atom_intern(format->target, FALSE), clip_paste, res); while (res[0]) gtk_main_iteration(); if (res[1]) return (TRUE); // success } } return (FALSE); } #ifdef GDK_WINDOWING_QUARTZ /* GTK+/Quartz has a dummy stub for gdk_selection_owner_get(), so needs a * workaround to have a working internal_clipboard() */ static void* slot_on_offer; static void clip_copy(GtkClipboard *clipboard, GtkSelectionData *sel, guint info, gpointer user_data) { clip_evt(sel, info, slot_on_offer); } static void clip_clear(GtkClipboard *clipboard, gpointer user_data) { clip_evt(NULL, 0, slot_on_offer); } static int offer_clipboard(void **slot, int unused) { void **desc = slot[1]; clipform_data *cd = slot[0]; int i, res = FALSE; if ((int)desc[2] & CLIPMASK) // Paranoia // Two attempts, for GTK+ function can fail for strange reasons for (i = 0; i < 2; i++) { if (!gtk_clipboard_set_with_owner(gtk_clipboard_get( GDK_SELECTION_CLIPBOARD), cd->ent, cd->n, clip_copy, clip_clear, G_OBJECT(main_window))) continue; slot_on_offer = slot; res = TRUE; break; } return (res); } #else /* Anything but Quartz */ static void clip_copy(GtkClipboard *clipboard, GtkSelectionData *sel, guint info, gpointer user_data) { clip_evt(sel, info, user_data); } static void clip_clear(GtkClipboard *clipboard, gpointer user_data) { clip_evt(NULL, 0, user_data); } static int offer_clipboard(void **slot, int unused) { void **desc = slot[1]; clipform_data *cd = slot[0]; int i, which, res = FALSE, nw = (int)desc[2] & CLIPMASK; for (which = 0; (1 << which) <= nw; which++) { if (!((1 << which) & nw)) continue; // Two attempts, for GTK+2 function can fail for strange reasons for (i = 0; i < 2; i++) { if (!gtk_clipboard_set_with_data(gtk_clipboard_get( which ? GDK_SELECTION_PRIMARY : GDK_SELECTION_CLIPBOARD), cd->ent, cd->n, clip_copy, clip_clear, slot)) continue; res = TRUE; break; } } return (res); } #endif static void offer_text(void **slot, char *s) { void **desc = slot[1]; int which, nw = (int)desc[2] & CLIPMASK; for (which = 0; (1 << which) <= nw; which++) { if (!((1 << which) & nw)) continue; gtk_clipboard_set_text(gtk_clipboard_get(which ? GDK_SELECTION_PRIMARY : GDK_SELECTION_CLIPBOARD), s, -1); } } #endif #undef CLIPMASK // Keynames handling #if GTK_MAJOR_VERSION == 1 #include #endif static void get_keyname(char *buf, int buflen, guint key, guint state, int ui) { char tbuf[128], *name, *m1, *m2, *m3, *sp; guint u; if (!ui) /* For inifile */ { m1 = state & _Cmask ? "C" : ""; m2 = state & _Smask ? "S" : ""; m3 = state & _Amask ? "A" : ""; sp = "_"; name = gdk_keyval_name(key); } else /* For display */ { m1 = state & _Smask ? "Shift+" : ""; m2 = state & _Cmask ? "Ctrl+" : ""; m3 = state & _Amask ? "Alt+" : ""; sp = ""; name = tbuf; #if GTK_MAJOR_VERSION == 1 u = key; #else /* #if GTK_MAJOR_VERSION >= 2 */ u = gdk_keyval_to_unicode(key); if ((u < 0x80) && (u != key)) u = 0; // Alternative key #endif if (u == ' ') name = "Space"; else if (u == '\\') name = "Backslash"; #if GTK_MAJOR_VERSION == 1 else if (u < 0x100) { tbuf[0] = toupper(u); tbuf[1] = 0; } #else /* #if GTK_MAJOR_VERSION >= 2 */ else if (u && g_unichar_isgraph(u)) tbuf[g_unichar_to_utf8(g_unichar_toupper(u), tbuf)] = 0; #endif else { char *s = gdk_keyval_name(gdk_keyval_to_lower(key)); int c, i = 0; if (s) while (i < sizeof(tbuf) - 1) { if (!(c = s[i])) break; if (c == '_') c = ' '; tbuf[i++] = c; } tbuf[i] = 0; if ((i == 1) && (tbuf[0] >= 'a') && (tbuf[0] <= 'z')) tbuf[0] -= 'a' - 'A'; } } wjstrcat(buf, buflen, "", 0, m1, m2, m3, sp, name, NULL); } static guint parse_keyname(char *name, guint *mod) { guint m = 0; char c; while (TRUE) switch (c = *name++) { case 'C': m |= _Cmask; continue; case 'S': m |= _Smask; continue; case 'A': m |= _Amask; continue; case '_': *mod = m; return (gdk_keyval_from_name(name)); default: return (KEY(VoidSymbol)); } } #define SEC_KEYNAMES ">keys<" /* Impossible name */ static char *key_name(guint key, guint mod, int section) { char buf[256]; int nk, ns; /* Refer from unique ID to keyval */ get_keyname(buf, sizeof(buf), key, mod, FALSE); // !!! Maybe pack state into upper bits, like Qt does? nk = ini_setint(&main_ini, section, buf, key); /* Refer from display name to ID slot (the names cannot clash) */ get_keyname(buf, sizeof(buf), key, mod, TRUE); ns = ini_setref(&main_ini, section, buf, nk); return (INI_KEY(&main_ini, ns)); } // Keymap handling typedef struct { guint key, mod, keycode; int idx; } keyinfo; typedef struct { void **slot; int section; int idx; // Used for various mapping indices guint key, mod; // Last one labeled on menuitem } keyslot; typedef struct { GtkAccelGroup *ag; void ***res; // Pointer to response var int nkeys, nslots; // Counters int slotsec, keysec; // Sections int updated; // Already matches INI keyinfo map[MAX_KEYS]; // Keys keyslot slots[1]; // Widgets (slot #0 stays empty) } keymap_data; #define KEYMAP_SIZE(N) (sizeof(keymap_data) + (N) * sizeof(keyslot)) // !!! And with inlining this, problem also int add_sec_name(memx2 *mem, int base, int sec) { char *s, *stack[CONT_DEPTH]; int n = 0, h = mem->here; while (sec != base) { s = _(INI_KEY(&main_ini, sec)); stack[n++] = s + strspn(s, "/"); sec = INI_PARENT(&main_ini, sec); } while (n-- > 0) { addstr(mem, stack[n], 1); addchars(mem, '/', 1); } mem->buf[mem->here - 1] = '\0'; return (h); } static keymap_dd *keymap_export(keymap_data *keymap) { memx2 mem; keymap_dd *km; keyinfo *kf; int lp = sizeof(keymap_dd) + sizeof(char *) * (keymap->nslots + 1); int i, j, k, sec; memset(&mem, 0, sizeof(mem)); getmemx2(&mem, lp + sizeof(key_dd) * MAX_KEYS); /* First, stuff the names into memory block */ mem.here = lp; for (i = j = 1; i <= keymap->nslots; i++) { sec = keymap->slots[i].section; k = -1; if (sec > 0) { k = add_sec_name(&mem, keymap->slotsec, sec); ((char **)(mem.buf + sizeof(keymap_dd)))[j] = (char *)k; k = j++; } keymap->slots[i].idx = k; } lp = mem.here; getmemx2(&mem, sizeof(key_dd) * (MAX_KEYS + 1)); /* Now the block is at its final size, so set the pointers */ km = (void *)mem.buf; km->nslots = j - 1; km->nkeys = keymap->nkeys; km->maxkeys = MAX_KEYS; km->keys = ALIGNED(mem.buf + lp, ALIGNOF(key_dd)); km->slotnames = (char **)(mem.buf + sizeof(keymap_dd)); km->slotnames[0] = NULL; for (i = 1; i < j; i++) km->slotnames[i] = mem.buf + (int)km->slotnames[i]; /* Now fill the keys table */ sec = ini_setsection(&main_ini, 0, SEC_KEYNAMES); ini_transient(&main_ini, sec, NULL); for (kf = keymap->map , i = 0; i < keymap->nkeys; i++ , kf++) { km->keys[i].slot = keymap->slots[kf->idx].idx; km->keys[i].name = key_name(kf->key, kf->mod, sec); } return (km); } static int keymap_add(keymap_data *keymap, void **slot, char *name, int section) { keyslot *ks = keymap->slots + ++keymap->nslots; ks->section = !name ? 0 : ini_setint(&main_ini, section, name, keymap->nslots); ks->slot = slot; ks->idx = -1; // No mapping return (TRUE); } static int keymap_map(keymap_data *keymap, int idx, guint key, guint mod) { keyinfo *kf = keymap->map + keymap->nkeys; if (!key || (keymap->nkeys >= MAX_KEYS)) return (FALSE); kf->key = key; kf->mod = mod; kf->idx = idx; keymap->nkeys++; return (TRUE); } static void keymap_to_ini(keymap_data *keymap) { char buf[256]; keyinfo *ki, *kd; int i, sec, w = keymap->keysec, f = keymap->updated; kd = ki = keymap->map; for (i = keymap->nkeys; i-- > 0; ki++) { sec = keymap->slots[ki->idx].section; if (f && sec) continue; get_keyname(buf, sizeof(buf), ki->key, ki->mod, FALSE); /* Fixed key - clear the ref, preserve the key */ if (!sec) { ini_setref(&main_ini, w, buf, 0); *kd++ = *ki; } ini_getref(&main_ini, w, buf, sec); } keymap->nkeys = kd - keymap->map; keymap->updated = TRUE; } static void keymap_update(keymap_data *keymap, keymap_dd *keys) { char *nm; guint key, mod; int i, j, n, sec, w = keymap->keysec; /* Make default keys into INI defaults */ if (!keymap->updated) keymap_to_ini(keymap); /* Import keys into INI */ if (keys) { /* Clear everything existing */ for (i = INI_FIRST(&main_ini, w); i; i = INI_NEXT(&main_ini, i)) ini_setref(&main_ini, w, INI_KEY(&main_ini, i), 0); /* Prepare reverse map */ for (i = j = 1; i <= keymap->nslots; i++) if (keymap->slots[i].section > 0) keymap->slots[j++].idx = i; /* Stuff things into inifile */ sec = ini_setsection(&main_ini, 0, SEC_KEYNAMES); for (i = 0; i < keys->nkeys; i++) { j = keys->keys[i].slot; if (j < 0) continue; // Fixed key n = ini_getref(&main_ini, sec, keys->keys[i].name, 0); if (n <= 0) continue; // Invalid key ini_setref(&main_ini, w, INI_KEY(&main_ini, n), keymap->slots[keymap->slots[j].idx].section); } /* Overwrite fixed keys again */ keymap_to_ini(keymap); } /* Step through the section reading it in */ for (i = INI_FIRST(&main_ini, w); i; i = INI_NEXT(&main_ini, i)) { nm = INI_KEY(&main_ini, i); key = parse_keyname(nm, &mod); if (key == KEY(VoidSymbol)) continue; sec = ini_getref(&main_ini, w, nm, 0); if (sec <= 0) continue; sec = (int)INI_VALUE(&main_ini, sec); if ((sec > 0) && (sec <= keymap->nslots)) keymap_map(keymap, sec, key, mod); } } #define FAKE_ACCEL "/a/k/e" // !!! And with inlining this, problem also void keymap_init(keymap_data *keymap, keymap_dd *keys) { char buf[256], *nm; GtkWidget *w; keyslot *ks; guint key, mod, key0, mod0; int i, j, op; /* Ensure keys section */ nm = INI_KEY(&main_ini, keymap->slotsec); j = strlen(nm); wjstrcat(buf, sizeof(buf), nm, j, " keys" + !j, NULL); j = ini_getsection(&main_ini, 0, buf); keymap->keysec = ini_setsection(&main_ini, 0, buf); /* If nondefault keys are there */ if (keys || ((j > 0) && !keymap->updated)) keymap_update(keymap, keys); /* Label new key indices on slots - back to forth */ i = keymap->nslots + 1; while (--i > 0) keymap->slots[i].idx = -1; i = keymap->nkeys; while (i-- > 0) keymap->slots[keymap->map[i].idx].idx = i; /* Update keys on menuitems */ for (ks = keymap->slots + 1 , i = keymap->nslots; i > 0; i-- , ks++) { key = mod = 0; j = ks->idx; if (j >= 0) key = keymap->map[j].key , mod = keymap->map[j].mod; key0 = ks->key; mod0 = ks->mod; ks->key = key; ks->mod = mod; // Update if (!((key ^ key0) | (mod ^ mod0))) continue; // Unchanged // No matter, if not a menuitem op = GET_OP(ks->slot); if ((op < op_MENU_0) || (op >= op_MENU_LAST)) continue; // Tell widget about update w = ks->slot[0]; if (key0 | mod0) gtk_widget_remove_accelerator(w, keymap->ag, key0, mod0); #if GTK_MAJOR_VERSION >= 2 /* !!! It has to be there in place of key, for menu spacing */ gtk_widget_set_accel_path(w, j < 0 ? FAKE_ACCEL : NULL, keymap->ag); #endif if (j >= 0) gtk_widget_add_accelerator(w, "activate", keymap->ag, key, mod, GTK_ACCEL_VISIBLE); } } static void keymap_reset(keymap_data *keymap) { keyinfo *kf = keymap->map; int i = keymap->nkeys; while (i-- > 0) kf->keycode = keyval_key(kf->key) , kf++; } static void keymap_find(keymap_data *keymap, key_ext *key) { keyinfo *kf, *match = NULL; int i; for (kf = keymap->map , i = keymap->nkeys; i > 0; i-- , kf++) { /* Modifiers should match first */ if ((key->state & _CSAmask) != kf->mod) continue; /* Let keyval have priority; this is also a workaround for * GTK2 bug #136280 */ if (key->lowkey == kf->key) break; /* Let keycodes match when keyvals don't */ if (key->realkey == kf->keycode) match = kf; } /* Keyval match */ if (i > 0) match = kf; /* !!! If the starting layout has the keyval+mods combo mapped to one key, and * the current layout to another, both will work till "rebind keys" is done. * I like this better than shortcuts moving with every layout switch - WJ */ /* If we have at least a keycode match */ *(keymap->res) = match ? keymap->slots[match->idx].slot : NULL; } // KEYBUTTON widget typedef struct { int section; guint key, mod; } keybutton_data; static gboolean convert_key(GtkWidget *widget, GdkEventKey *event, gpointer user_data) { keybutton_data *dt = user_data; char buf[256]; /* Do nothing until button is pressed */ if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) return (FALSE); /* Store keypress, display its name */ if (event->type == GDK_KEY_PRESS) { get_keyname(buf, sizeof(buf), dt->key = low_key(event), dt->mod = event->state, TRUE); gtk_label_set_text(GTK_LABEL(gtk_bin_get_child(GTK_BIN(widget))), buf); } /* Depress button when key gets released */ else /* if (event->type == GDK_KEY_RELEASE) */ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), FALSE); return (TRUE); } static void add_del(void **r, GtkWidget *window) { gtk_signal_connect(GTK_OBJECT(window), "delete_event", GTK_SIGNAL_FUNC(get_evt_del), r); } static void **skip_if(void **pp) { int lp, mk; void **ifcode; ifcode = pp + 1 + (lp = WB_GETLEN((int)*pp)); if (lp > 1) // skip till corresponding ENDIF { mk = (int)pp[2]; while ((((int)*ifcode & WB_OPMASK) != op_ENDIF) || ((int)ifcode[1] != mk)) ifcode += 1 + WB_GETLEN((int)*ifcode); } return (ifcode + 1 + (WB_GETLEN((int)*ifcode))); } /* Trigger events which need triggering */ static void trigger_things(void **wdata) { char *data = GET_DDATA(wdata); void **slot, **base, **desc; for (wdata = GET_WINDOW(wdata); wdata[1]; wdata = NEXT_SLOT(wdata)) { int opf = GET_OPF(wdata), op = opf & WB_OPMASK; if (IS_UNREAL(wdata)) op = GET_UOP(wdata); /* Trigger events for nested widget */ if (op == op_MOUNT) { if ((slot = wdata[2])) trigger_things(slot); continue; } if (op == op_uMOUNT) { if ((slot = ((swdata *)*wdata)->strs)) trigger_things(slot); continue; } /* Prepare preset split widget */ if ((op == op_HVSPLIT) && WB_GETLEN(opf)) { cmd_set(wdata, (int)GET_DESCV(wdata, 1)); continue; } if (op != op_TRIGGER) continue; if (!WB_GETLEN(opf)) // Regular version { slot = PREV_SLOT(wdata); while (GET_OP(slot) > op_EVT_LAST) // Find EVT slot slot = PREV_SLOT(slot); base = slot; } else // Version for menu/toolbar items { /* Here, event is put into next slot, and widget is * in nearest widgetlike slot before */ base = NEXT_SLOT(wdata); slot = origin_slot(wdata); } desc = base[1]; ((evt_fn)desc[1])(data, base[0], (int)desc[0] & WB_OPMASK, slot); } } #if GTK_MAJOR_VERSION == 3 /* Wait till window is getting drawn to make it user-resizable */ static gboolean make_resizable(GtkWidget *widget, cairo_t *cr, gpointer user_data) { gtk_window_set_resizable(GTK_WINDOW(widget), TRUE); g_signal_handlers_disconnect_by_func(widget, make_resizable, user_data); return (FALSE); } /* Reintroduce sanity to sizing wrapped labels */ static void do_rewrap(GtkWidget *widget, gint vert, gint *min, gint *nat, gint for_width, gpointer user_data) { PangoLayout *layout; PangoRectangle r; GtkBorder pb; gint xpad; int wmax, w, h, ww, sw2, lines, w2l; //g_print("vert %d for_width %d min %d nat %d\n", vert, for_width, *min, *nat); if (vert) return; // Do nothing for vertical size /* Max wrap width */ layout = gtk_widget_create_pango_layout(widget, /* Let wrap width be 65 chars */ "88888888888888888888888888888888" "888888888888888888888888888888888"); pango_layout_get_size(layout, &ww, NULL); sw2 = PANGO_SCALE * ((gdk_screen_get_width(gtk_widget_get_screen(widget)) + 1) / 2); if (ww > sw2) ww = sw2; /* Full text width */ pango_layout_set_text(layout, gtk_label_get_text(GTK_LABEL(widget)), -1); pango_layout_set_alignment(layout, gtk_widget_get_direction(widget) == GTK_TEXT_DIR_RTL ? PANGO_ALIGN_RIGHT : PANGO_ALIGN_LEFT); pango_layout_set_wrap(layout, PANGO_WRAP_WORD); pango_layout_set_width(layout, -1); pango_layout_get_extents(layout, NULL, &r); wmax = r.width; if (wmax > ww) /* Wrap need happen */ { pango_layout_set_width(layout, ww); pango_layout_get_extents(layout, NULL, &r); w = r.width; h = r.height; /* Maybe make narrower, to rebalance lines */ lines = pango_layout_get_line_count(layout); w2l = (wmax + lines - 1) / lines; if (w2l < w) { pango_layout_set_width(layout, w2l); pango_layout_get_extents(layout, NULL, &r); if (r.height > h) // Extra line(s) got added - make wider { pango_layout_set_width(layout, (w2l + w) / 2); pango_layout_get_extents(layout, NULL, &r); } if (r.height <= h) w = r.width; // No extra lines happened } /* Full width in pixels */ w = w / PANGO_SCALE + 1; get_padding_and_border(gtk_widget_get_style_context(widget), NULL, NULL, &pb); gtk_misc_get_padding(GTK_MISC(widget), &xpad, NULL); w += pb.left + pb.right + 2 * xpad; } else w = *nat; /* Take what label wants */ //g_print("Want nat %d\n", w); if (w > *nat) w = *nat; // If widget wants even less if (w < *min) w = *min; // Respect the minsize /* Reduce natural width to this */ /* !!! Make minimum and natural width the same: otherwise, bug in GTK+3 * size negotiation causes labels be too tall; the longer the text, the * taller the label - WJ */ *min = *nat = w; //g_print("Now nat %d\n", *nat); g_object_unref(layout); } /* Apply minimum width from the given widget to this one */ static void do_shorten(GtkWidget *widget, gint vert, gint *min, gint *nat, gint for_width, gpointer user_data) { if (vert) return; // Do nothing for vertical size gtk_widget_get_preferred_width(user_data, min, NULL); } #if GTK3VERSION < 22 /* No gtk_scrolled_window_set_propagate_natural_*() */ /* Try to avoid scrolling - request natural size of contents */ static void do_wantmax(GtkWidget *widget, gint vert, gint *min, gint *nat, gint for_width, gpointer user_data) { GtkWidget *inside = gtk_bin_get_child(GTK_BIN(widget)); gint cmin = 0, cnat = 0; if (!inside) return; // Nothing to do if (((int)user_data & 1) && !vert) return; // Leave width be if (((int)user_data & 2) && vert) return; // Leave height be if (for_width >= 0) gtk_widget_get_preferred_height_for_width(inside, for_width, &cmin, &cnat); else (vert ? gtk_widget_get_preferred_height : gtk_widget_get_preferred_width)(inside, &cmin, &cnat); if (cnat > *nat) *nat = cnat; } #endif #else /* #if GTK_MAJOR_VERSION <= 2 */ /* Try to avoid scrolling - request full size of contents */ static void scroll_max_size_req(GtkWidget *widget, GtkRequisition *requisition, gpointer user_data) { GtkWidget *child = GTK_BIN(widget)->child; if (child && GTK_WIDGET_VISIBLE(child)) { GtkRequisition wreq; int n, border = GTK_CONTAINER(widget)->border_width * 2; gtk_widget_get_child_requisition(child, &wreq); n = wreq.width + border; if ((requisition->width < n) && !((int)user_data & 1)) requisition->width = n; n = wreq.height + border; if ((requisition->height < n) && !((int)user_data & 2)) requisition->height = n; } } #endif // !!! And with inlining this, problem also GtkWidget *scrollw(int vh) { static const int scrollp[3] = { GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS }; GtkWidget *widget = gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(widget), scrollp[vh & 255], scrollp[vh >> 8]); #if GTK3VERSION >= 22 /* To fix newly-broken sizing */ if (!(vh & 255)) gtk_scrolled_window_set_propagate_natural_width( GTK_SCROLLED_WINDOW(widget), TRUE); if (!(vh >> 8)) gtk_scrolled_window_set_propagate_natural_height( GTK_SCROLLED_WINDOW(widget), TRUE); #endif return (widget); } /* Toggle notebook pages */ static void toggle_vbook(GtkToggleButton *button, gpointer user_data) { gtk_notebook_set_page(**(void ***)user_data, !!gtk_toggle_button_get_active(button)); } #if GTK_MAJOR_VERSION == 3 // RGBIMAGE widget typedef struct { cairo_surface_t *s; unsigned char *rgb; int w, h, bkg; } rgbimage_data; static gboolean redraw_rgb(GtkWidget *widget, cairo_t *cr, gpointer user_data) { rgbimage_data *rd = user_data; GdkRectangle r; int x2, y2, rxy[4] = { 0, 0, rd->w, rd->h }; if (!gdk_cairo_get_clip_rectangle(cr, &r)) return (TRUE); // Nothing to do cairo_save(cr); cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); if (!clip(rxy, r.x, r.y, x2 = r.x + r.width, y2 = r.y + r.height, rxy) || !rd->rgb) rxy[2] = r.x , rxy[3] = y2; else { /* RGB image buffer */ if (!rd->s) rd->s = cairo_upload_rgb(NULL, gtk_widget_get_window(widget), rd->rgb, rd->w, rd->h, rd->w * 3); cairo_set_source_surface(cr, rd->s, 0, 0); cairo_unfilter(cr); cairo_rectangle(cr, 0, 0, rd->w, rd->h); // Let Cairo clip it cairo_fill(cr); } /* Opaque background outside image proper */ cairo_set_rgb(cr, rd->bkg); if (rxy[2] < x2) { cairo_rectangle(cr, rxy[2], r.y, x2 - rxy[2], rxy[3] - rxy[1]); cairo_fill(cr); } if (rxy[3] < y2) { cairo_rectangle(cr, r.x, rxy[3], r.width, y2 - rxy[3]); cairo_fill(cr); } cairo_restore(cr); return (TRUE); } static void reset_rgb(GtkWidget *widget, gpointer user_data) { rgbimage_data *rd = user_data; if (rd->s) cairo_surface_fdestroy(rd->s); rd->s = NULL; } GtkWidget *rgbimage(void **r, int *wh) { GtkWidget *widget; rgbimage_data *rd = r[2]; widget = gtk_drawing_area_new(); rd->rgb = r[0]; rd->w = wh[0]; rd->h = wh[1]; gtk_widget_set_size_request(widget, wh[0], wh[1]); g_signal_connect(G_OBJECT(widget), "unrealize", G_CALLBACK(reset_rgb), rd); g_signal_connect(G_OBJECT(widget), "draw", G_CALLBACK(redraw_rgb), rd); return (widget); } // RGBIMAGEP widget static gboolean redraw_rgbp(GtkWidget *widget, cairo_t *cr, gpointer user_data) { rgbimage_data *rd = user_data; GtkAllocation alloc; int x, y; if (!rd->s) return (TRUE); gtk_widget_get_allocation(widget, &alloc); x = (alloc.width - rd->w) / 2; y = (alloc.height - rd->h) / 2; cairo_save(cr); cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); cairo_set_source_surface(cr, rd->s, x, y); cairo_rectangle(cr, x, y, rd->w, rd->h); cairo_fill(cr); cairo_restore(cr); return (TRUE); } static void reset_rgbp(GtkWidget *widget, gpointer user_data) { rgbimage_data *rd = user_data; cairo_surface_t *s; cairo_t *cr; if (!rd->s) { GdkWindow *win = gtk_widget_get_window(widget); if (!win) win = gdk_screen_get_root_window(gtk_widget_get_screen(widget)); rd->s = gdk_window_create_similar_surface(win, CAIRO_CONTENT_COLOR, rd->w, rd->h); } s = cairo_upload_rgb(rd->s, NULL, rd->rgb, rd->w, rd->h, rd->w * 3); cr = cairo_create(rd->s); cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); cairo_set_source_surface(cr, s, 0, 0); cairo_unfilter(cr); cairo_paint(cr); cairo_destroy(cr); cairo_surface_fdestroy(s); gtk_widget_queue_draw(widget); } // !!! And with inlining this, problem also GtkWidget *rgbimagep(void **r, int w, int h) { rgbimage_data *rd = r[2]; GtkWidget *widget; /* With GtkImage unable to properly hold surfaces till GTK+ 3.20, have * to use a window-less container as substitute */ widget = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); gtk_widget_set_size_request(widget, w, h); rd->rgb = r[0]; rd->w = w; rd->h = h; g_signal_connect(G_OBJECT(widget), "realize", G_CALLBACK(reset_rgbp), rd); g_signal_connect(G_OBJECT(widget), "unrealize", G_CALLBACK(reset_rgb), rd); g_signal_connect(G_OBJECT(widget), "draw", G_CALLBACK(redraw_rgbp), rd); return (widget); } #else /* if GTK_MAJOR_VERSION <= 2 */ // RGBIMAGE widget typedef struct { unsigned char *rgb; int w, h, bkg; } rgbimage_data; static void expose_ext(GtkWidget *widget, GdkEventExpose *event, rgbimage_data *rd, int dx, int dy) { GdkGCValues sv; GdkGC *gc = widget->style->black_gc; unsigned char *src = rd->rgb; int w = rd->w, h = rd->h, bkg = 0; int x1, y1, x2, y2, rxy[4] = { 0, 0, w, h }; x2 = (x1 = event->area.x + dx) + event->area.width; y2 = (y1 = event->area.y + dy) + event->area.height; if (!clip(rxy, x1, y1, x2, y2, rxy) || !src) rxy[2] = x1 , rxy[3] = y2; else gdk_draw_rgb_image(widget->window, gc, event->area.x, event->area.y, rxy[2] - rxy[0], rxy[3] - rxy[1], GDK_RGB_DITHER_NONE, src + (y1 * w + x1) * 3, w * 3); /* With theme engines lurking out there, weirdest things can happen */ if (((rxy[2] < x2) || (rxy[3] < y2)) && (bkg = rd->bkg)) { gdk_gc_get_values(gc, &sv); gdk_rgb_gc_set_foreground(gc, bkg); } if (rxy[2] < x2) gdk_draw_rectangle(widget->window, gc, TRUE, rxy[2] - dx, event->area.y, x2 - rxy[2], rxy[3] - rxy[1]); if (rxy[3] < y2) gdk_draw_rectangle(widget->window, gc, TRUE, event->area.x, rxy[3] - dy, event->area.width, y2 - rxy[3]); if (bkg) gdk_gc_set_foreground(gc, &sv.foreground); } static gboolean expose_rgb(GtkWidget *widget, GdkEventExpose *event, gpointer user_data) { expose_ext(widget, event, user_data, 0, 0); return (TRUE); } // !!! And with inlining this, problem also GtkWidget *rgbimage(void **r, int *wh) { GtkWidget *widget; rgbimage_data *rd = r[2]; widget = gtk_drawing_area_new(); rd->rgb = r[0]; rd->w = wh[0]; rd->h = wh[1]; gtk_widget_set_usize(widget, wh[0], wh[1]); gtk_signal_connect(GTK_OBJECT(widget), "expose_event", GTK_SIGNAL_FUNC(expose_rgb), rd); return (widget); } // RGBIMAGEP widget static void reset_rgbp(GtkWidget *widget, gpointer user_data) { rgbimage_data *rd = user_data; GdkPixmap *pmap; gtk_pixmap_get(GTK_PIXMAP(widget), &pmap, NULL); gdk_draw_rgb_image(pmap, widget->style->black_gc, 0, 0, rd->w, rd->h, GDK_RGB_DITHER_NONE, rd->rgb, rd->w * 3); gtk_widget_queue_draw(widget); } // !!! And with inlining this, problem also GtkWidget *rgbimagep(void **r, int w, int h) { rgbimage_data *rd = r[2]; GdkPixmap *pmap; GtkWidget *widget; pmap = gdk_pixmap_new(main_window->window, w, h, -1); widget = gtk_pixmap_new(pmap, NULL); gdk_pixmap_unref(pmap); gtk_pixmap_set_build_insensitive(GTK_PIXMAP(widget), FALSE); rd->rgb = r[0]; rd->w = w; rd->h = h; gtk_signal_connect(GTK_OBJECT(widget), "realize", GTK_SIGNAL_FUNC(reset_rgbp), rd); return (widget); } #endif /* GTK+1&2 */ // CANVASIMG widget #if GTK_MAJOR_VERSION == 3 static void expose_canvasimg(GtkWidget *widget, cairo_region_t *clip_r, gpointer user_data) { rgbimage_data *rd = user_data; cairo_rectangle_int_t r; int x2, y2, rxy[4] = { 0, 0, rd->w, rd->h }; cairo_region_get_extents(clip_r, &r); if (!clip(rxy, r.x, r.y, x2 = r.x + r.width, y2 = r.y + r.height, rxy) || !rd->rgb) rxy[2] = r.x , rxy[3] = y2; /* RGB image buffer */ else wjcanvas_draw_rgb(widget, rxy[0], rxy[1], rxy[2] - rxy[0], rxy[3] - rxy[1], rd->rgb + (rxy[1] * rd->w + rxy[0]) * 3, rd->w * 3, 0, FALSE); /* Opaque background outside image proper */ if (rxy[2] < x2) wjcanvas_draw_rgb(widget, rxy[2], r.y, x2 - rxy[2], rxy[3] - rxy[1], NULL, 0, rd->bkg, FALSE); if (rxy[3] < y2) wjcanvas_draw_rgb(widget, r.x, rxy[3], r.width, y2 - rxy[3], NULL, 0, rd->bkg, FALSE); } #else /* if GTK_MAJOR_VERSION <= 2 */ static gboolean expose_canvasimg(GtkWidget *widget, GdkEventExpose *event, gpointer user_data) { int vport[4]; wjcanvas_get_vport(widget, vport); expose_ext(widget, event, user_data, vport[0], vport[1]); return (TRUE); } #endif /* GTK+1&2 */ GtkWidget *canvasimg(void **r, int w, int h, int bkg) { rgbimage_data *rd = r[2]; GtkWidget *widget, *frame; widget = wjcanvas_new(); rd->rgb = r[0]; rd->w = w; rd->h = h; rd->bkg = bkg; wjcanvas_size(widget, w, h); wjcanvas_set_expose(widget, GTK_SIGNAL_FUNC(expose_canvasimg), rd); frame = wjframe_new(); gtk_widget_show(frame); gtk_container_add(GTK_CONTAINER(frame), widget); return (widget); } // CANVAS widget #if GTK_MAJOR_VERSION == 3 typedef struct { int expose; } canvas_data; static void expose_canvas_(GtkWidget *widget, cairo_region_t *clip_r, gpointer user_data) { void **slot = user_data, **wslot = PREV_SLOT(slot); void **base = slot[0], **desc = slot[1]; canvas_data *cd = wslot[2]; cairo_rectangle_int_t re, rex; rgbcontext ctx; int m, s, sz, cost = (int)GET_DESCV(wslot, 2); int i, n, wh, r1 = 0; /* Analyze what we got */ cairo_region_get_extents(clip_r, &rex); wh = rex.width * rex.height; n = cairo_region_num_rectangles(clip_r); for (i = m = sz = 0; i < n; i++) { cairo_region_get_rectangle(clip_r, i, &re); sz += (s = re.width * re.height); if (m < s) m = s; } /* Only bother with regions if worth it */ if (wh - sz <= cost * (n - 1)) r1 = n = 1 , m = wh , re = rex; cd->expose++; ctx.rgb = malloc(m * 3); for (i = 0; i < n; i++) { if (!r1) cairo_region_get_rectangle(clip_r, i, &re); ctx.xy[2] = (ctx.xy[0] = re.x) + re.width; ctx.xy[3] = (ctx.xy[1] = re.y) + re.height; if (((evtxr_fn)desc[1])(GET_DDATA(base), base, (int)desc[0] & WB_OPMASK, slot, &ctx)) // !!! Allow drawing area to be reduced, or ignored altogether wjcanvas_draw_rgb(widget, ctx.xy[0], ctx.xy[1], ctx.xy[2] - ctx.xy[0], ctx.xy[3] - ctx.xy[1], ctx.rgb, (ctx.xy[2] - ctx.xy[0]) * 3, 0, FALSE); } free(ctx.rgb); cd->expose--; } #else /* if GTK_MAJOR_VERSION <= 2 */ static gboolean expose_canvas_(GtkWidget *widget, GdkEventExpose *event, gpointer user_data) { void **slot = user_data; void **base = slot[0], **desc = slot[1]; GdkRectangle *r = &event->area; rgbcontext ctx; int vport[4]; int i, cnt = 1, wh = r->width * r->height; #if GTK_MAJOR_VERSION == 2 /* Maybe use regions */ GdkRectangle *rects; gint nrects; int m, s, sz, cost = (int)GET_DESCV(PREV_SLOT(slot), 2); gdk_region_get_rectangles(event->region, &rects, &nrects); for (i = m = sz = 0; i < nrects; i++) { sz += (s = rects[i].width * rects[i].height); if (m < s) m = s; } /* Only bother with regions if worth it */ if (wh - sz > cost * (nrects - 1)) r = rects , cnt = nrects , wh = m; #endif wjcanvas_get_vport(widget, vport); ctx.rgb = malloc(wh * 3); for (i = 0; i < cnt; i++) { ctx.xy[2] = (ctx.xy[0] = vport[0] + r[i].x) + r[i].width; ctx.xy[3] = (ctx.xy[1] = vport[1] + r[i].y) + r[i].height; if (((evtxr_fn)desc[1])(GET_DDATA(base), base, (int)desc[0] & WB_OPMASK, slot, &ctx)) // !!! Allow drawing area to be reduced, or ignored altogether gdk_draw_rgb_image(widget->window, widget->style->black_gc, ctx.xy[0] - vport[0], ctx.xy[1] - vport[1], ctx.xy[2] - ctx.xy[0], ctx.xy[3] - ctx.xy[1], GDK_RGB_DITHER_NONE, ctx.rgb, (ctx.xy[2] - ctx.xy[0]) * 3); } free(ctx.rgb); #if GTK_MAJOR_VERSION == 2 g_free(rects); #endif return (FALSE); } #endif /* GTK+1&2 */ // FCIMAGEP widget typedef struct { void **mslot; unsigned char *rgb; int *xy; int w, h, cursor; } fcimage_data; static void reset_fcimage(GtkWidget *widget, gpointer user_data) { fcimage_data *fd = user_data; if (!wjpixmap_pixmap(widget)) return; wjpixmap_draw_rgb(widget, 0, 0, fd->w, fd->h, fd->rgb, fd->w * 3); if (!fd->xy) return; if (!fd->cursor) wjpixmap_set_cursor(widget, xbm_ring4_bits, xbm_ring4_mask_bits, xbm_ring4_width, xbm_ring4_height, xbm_ring4_x_hot, xbm_ring4_y_hot, FALSE); fd->cursor = TRUE; wjpixmap_move_cursor(widget, fd->xy[0], fd->xy[1]); } static gboolean click_fcimage(GtkWidget *widget, GdkEventButton *event, gpointer user_data) { gtk_widget_grab_focus(widget); return (FALSE); } // !!! And with inlining this, problem also GtkWidget *fcimagep(void **r, char *ddata) { fcimage_data *fd = r[2]; void **pp = r[1]; GtkWidget *widget; int w, h, *xy; xy = (void *)(ddata + (int)pp[3]); w = xy[0]; h = xy[1]; xy = pp[2] == (void *)(-1) ? NULL : (void *)(ddata + (int)pp[2]); widget = wjpixmap_new(w, h); fd->xy = xy; fd->rgb = r[0]; fd->w = w; fd->h = h; gtk_signal_connect(GTK_OBJECT(widget), "realize", GTK_SIGNAL_FUNC(reset_fcimage), fd); gtk_signal_connect(GTK_OBJECT(widget), "button_press_event", GTK_SIGNAL_FUNC(click_fcimage), NULL); return (widget); } static void fcimage_rxy(void **slot, int *xy) { fcimage_data *fd = slot[2]; wjpixmap_rxy(slot[0], xy[0], xy[1], xy + 0, xy + 1); xy[0] = xy[0] < 0 ? 0 : xy[0] >= fd->w ? fd->w - 1 : xy[0]; xy[1] = xy[1] < 0 ? 0 : xy[1] >= fd->h ? fd->h - 1 : xy[1]; } // OPT* widgets #if GTK_MAJOR_VERSION == 3 /* !!! Limited to 256 choices max, by using id[0] for index */ static void opt_reset(void **slot, char *ddata, int idx) { void **pp = slot[1]; char **names, id[2] = { 0, 0 }; int i, j, k, cnt, opf = GET_OPF(slot), op = opf & WB_OPMASK; if (op == op_OPTD) cnt = -1 , names = *(char ***)(ddata + (int)pp[2]); else cnt = (int)pp[3] , names = pp[2]; if (!cnt) cnt = -1; g_signal_handlers_disconnect_by_func(slot[0], get_evt_1, NEXT_SLOT(slot)); gtk_combo_box_text_remove_all(GTK_COMBO_BOX_TEXT(slot[0])); for (i = j = k = 0; (i != cnt) && names[i]; i++) { if (!names[i][0]) continue; id[0] = i; gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(slot[0]), id, _(names[i])); if (i == idx) j = k; k++; } gtk_combo_box_set_active(GTK_COMBO_BOX(slot[0]), j); if (WB_GETREF(opf) > 1) g_signal_connect(slot[0], "changed", G_CALLBACK(get_evt_1), NEXT_SLOT(slot)); } static int wj_option_menu_get_history(GtkWidget *cbox) { const char *id = gtk_combo_box_get_active_id(GTK_COMBO_BOX(cbox)); return (id ? id[0] : 0); } #define wj_option_menu_set_history(W,N) gtk_combo_box_set_active(W,N) #else /* if GTK_MAJOR_VERSION <= 2 */ #if GTK_MAJOR_VERSION == 2 /* Cause the size to be properly reevaluated */ static void opt_size_fix(GtkWidget *widget) { gtk_signal_emit_by_name(GTK_OBJECT(gtk_option_menu_get_menu( GTK_OPTION_MENU(widget))), "selection_done"); } #endif static void opt_reset(void **slot, char *ddata, int idx) { GtkWidget *menu, *item; void **pp = slot[1]; char **names; int i, j, k, cnt, opf = GET_OPF(slot), op = opf & WB_OPMASK; if (op == op_OPTD) cnt = -1 , names = *(char ***)(ddata + (int)pp[2]); else cnt = (int)pp[3] , names = pp[2]; if (!cnt) cnt = -1; menu = gtk_menu_new(); for (i = j = k = 0; (i != cnt) && names[i]; i++) { if (!names[i][0]) continue; item = gtk_menu_item_new_with_label(_(names[i])); gtk_object_set_user_data(GTK_OBJECT(item), (gpointer)i); if (WB_GETREF(opf) > 1) gtk_signal_connect(GTK_OBJECT(item), "activate", GTK_SIGNAL_FUNC(get_evt_1), NEXT_SLOT(slot)); gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); if (i == idx) j = k; k++; } gtk_widget_show_all(menu); gtk_menu_set_active(GTK_MENU(menu), j); gtk_option_menu_set_menu(GTK_OPTION_MENU(slot[0]), menu); #if GTK_MAJOR_VERSION == 2 opt_size_fix(slot[0]); #endif } static int wj_option_menu_get_history(GtkWidget *optmenu) { optmenu = gtk_option_menu_get_menu(GTK_OPTION_MENU(optmenu)); optmenu = gtk_menu_get_active(GTK_MENU(optmenu)); return (optmenu ? (int)gtk_object_get_user_data(GTK_OBJECT(optmenu)) : 0); } #define wj_option_menu_set_history(W,N) gtk_option_menu_set_history(W,N) #endif /* GTK+1&2 */ // RPACK* and COMBO widgets static GtkWidget *mkpack(int mode, int d, int ref, char *ddata, void **r) { void **pp = r[1]; char **src = pp[2]; int nh, n, v = *(int *)r[0]; nh = (n = (int)pp[3]) & 255; if (mode) n >>= 8; if (d) n = -1 , src = *(char ***)(ddata + (int)pp[2]); if (!n) n = -1; return ((mode ? wj_radio_pack : wj_combo_box)(src, n, nh, v, NEXT_SLOT(r), ref < 2 ? NULL : mode ? GTK_SIGNAL_FUNC(get_evt_1_t) : GTK_SIGNAL_FUNC(get_evt_1))); } #if GTK_MAJOR_VERSION == 3 static gboolean col_expose(GtkWidget *widget, cairo_t *cr, unsigned char *col) { cairo_save(cr); cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); cairo_set_rgb(cr, MEM_2_INT(col, 0)); cairo_paint(cr); cairo_restore(cr); return (TRUE); } #else /* if GTK_MAJOR_VERSION <= 2 */ // !!! ref to RGB[3] static gboolean col_expose(GtkWidget *widget, GdkEventExpose *event, unsigned char *col) { GdkGCValues sv; gdk_gc_get_values(widget->style->black_gc, &sv); gdk_rgb_gc_set_foreground(widget->style->black_gc, MEM_2_INT(col, 0)); gdk_draw_rectangle(widget->window, widget->style->black_gc, TRUE, event->area.x, event->area.y, event->area.width, event->area.height); gdk_gc_set_foreground(widget->style->black_gc, &sv.foreground); return (TRUE); } #endif /* GTK+1&2 */ // COLORLIST widget typedef struct { unsigned char *col; int cnt, *idx; } colorlist_data; #ifdef U_LISTS_GTK1 static gboolean colorlist_click(GtkWidget *widget, GdkEventButton *event, gpointer user_data) { void **slot = user_data; void **base = slot[0], **desc = slot[1]; colorlist_ext xdata; if (event->type == GDK_BUTTON_PRESS) { xdata.idx = (int)gtk_object_get_user_data(GTK_OBJECT(widget)); xdata.button = event->button; ((evtx_fn)desc[1])(GET_DDATA(base), base, (int)desc[0] & WB_OPMASK, slot, &xdata); } /* Let click processing continue */ return (FALSE); } static void colorlist_select(GtkList *list, GtkWidget *widget, gpointer user_data) { void **orig = user_data, **slot = SLOT_N(orig, 2); void **base = slot[0], **desc = slot[1]; colorlist_data *dt = orig[2]; /* Update the value */ *dt->idx = (int)gtk_object_get_user_data(GTK_OBJECT(widget)); /* Call the handler */ if (desc[1]) ((evt_fn)desc[1])(GET_DDATA(base), base, (int)desc[0] & WB_OPMASK, slot); } // !!! And with inlining this, problem also GtkWidget *colorlist(void **r, char *ddata) { GtkWidget *list, *item, *col, *label, *box; colorlist_data *dt = r[2]; void *v, **pp = r[1]; char txt[64], *t, **sp = NULL; int i, cnt = 0, *idx = r[0]; list = gtk_list_new(); // Fill datablock v = ddata + (int)pp[2]; if (((int)pp[0] & WB_OPMASK) == op_COLORLIST) // array of names { sp = *(char ***)v; while (sp[cnt]) cnt++; } else cnt = *(int *)v; // op_COLORLISTN - number dt->cnt = cnt; dt->col = (void *)(ddata + (int)pp[3]); // palette dt->idx = idx; for (i = 0; i < cnt; i++) { item = gtk_list_item_new(); gtk_object_set_user_data(GTK_OBJECT(item), (gpointer)i); if (pp[5]) gtk_signal_connect(GTK_OBJECT(item), "button_press_event", GTK_SIGNAL_FUNC(colorlist_click), NEXT_SLOT(r)); gtk_container_add(GTK_CONTAINER(list), item); box = gtk_hbox_new(FALSE, 3); gtk_widget_show(box); gtk_container_set_border_width(GTK_CONTAINER(box), 3); gtk_container_add(GTK_CONTAINER(item), box); col = pack(box, gtk_drawing_area_new()); gtk_drawing_area_size(GTK_DRAWING_AREA(col), 20, 20); gtk_signal_connect(GTK_OBJECT(col), "expose_event", GTK_SIGNAL_FUNC(col_expose), dt->col + i * 3); /* Name or index */ if (sp) t = _(sp[i]); else sprintf(t = txt, "%d", i); label = xpack(box, gtk_label_new(t)); gtk_misc_set_alignment(GTK_MISC(label), 0.0, 1.0); gtk_widget_show_all(item); } gtk_list_set_selection_mode(GTK_LIST(list), GTK_SELECTION_BROWSE); /* gtk_list_select_*() don't work in GTK_SELECTION_BROWSE mode */ gtk_container_set_focus_child(GTK_CONTAINER(list), GTK_WIDGET(g_list_nth(GTK_LIST(list)->children, *idx)->data)); gtk_signal_connect(GTK_OBJECT(list), "select_child", GTK_SIGNAL_FUNC(colorlist_select), r); return (list); } static void colorlist_reset_color(void **slot, int idx) { colorlist_data *dt = slot[2]; unsigned char *rgb = dt->col + idx * 3; GdkColor c; c.pixel = 0; c.red = rgb[0] * 257; c.green = rgb[1] * 257; c.blue = rgb[2] * 257; // In case of some really ancient system with indexed display mode gdk_colormap_alloc_color(gdk_colormap_get_system(), &c, FALSE, TRUE); /* Redraw the item displaying the color */ gtk_widget_queue_draw( GTK_WIDGET(g_list_nth(GTK_LIST(slot[0])->children, idx)->data)); } static void list_scroll_in(GtkWidget *widget, gpointer user_data) { GtkContainer *list = GTK_CONTAINER(widget); GtkAdjustment *adj = user_data; int y; if (!list->focus_child) return; // Paranoia if (adj->upper <= adj->page_size) return; // Nothing to scroll y = list->focus_child->allocation.y + list->focus_child->allocation.height / 2 - adj->page_size / 2; adj->value = y < 0 ? 0 : y > adj->upper - adj->page_size ? adj->upper - adj->page_size : y; gtk_adjustment_value_changed(adj); } #endif #ifndef U_LISTS_GTK1 static gboolean colorlist_click(GtkWidget *widget, GdkEventButton *event, gpointer user_data) { void **slot = user_data; void **base = slot[0], **desc = slot[1]; colorlist_ext xdata; GtkTreePath *tp; if ((event->type == GDK_BUTTON_PRESS) && (event->window == gtk_tree_view_get_bin_window(GTK_TREE_VIEW(widget))) && gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(widget), event->x, event->y, &tp, NULL, NULL, NULL)) { xdata.idx = gtk_tree_path_get_indices(tp)[0]; gtk_tree_path_free(tp); xdata.button = event->button; ((evtx_fn)desc[1])(GET_DDATA(base), base, (int)desc[0] & WB_OPMASK, slot, &xdata); } /* Let click processing continue */ return (FALSE); } static void colorlist_select(GtkTreeView *tree, gpointer user_data) { void **orig = user_data, **slot = SLOT_N(orig, 2); void **base = slot[0], **desc = slot[1]; colorlist_data *dt = orig[2]; GtkTreePath *tp; /* Update the value */ gtk_tree_view_get_cursor(tree, &tp, NULL); *dt->idx = gtk_tree_path_get_indices(tp)[0]; gtk_tree_path_free(tp); /* Call the handler */ if (desc[1]) ((evt_fn)desc[1])(GET_DDATA(base), base, (int)desc[0] & WB_OPMASK, slot); } // !!! And with inlining this, problem also GtkWidget *colorlist(void **r, char *ddata) { GtkListStore *ls; GtkCellRenderer *ren; GtkTreePath *tp; GtkWidget *w; colorlist_data *dt = r[2]; void *v, **pp = r[1]; char txt[64], *t, **sp = NULL; int i, cnt = 0, *idx = r[0]; // Fill datablock v = ddata + (int)pp[2]; if (((int)pp[0] & WB_OPMASK) == op_COLORLIST) // array of names { sp = *(char ***)v; while (sp[cnt]) cnt++; } else cnt = *(int *)v; // op_COLORLISTN - number dt->cnt = cnt; dt->col = (void *)(ddata + (int)pp[3]); // palette dt->idx = idx; ls = gtk_list_store_new(2, GDK_TYPE_PIXBUF, G_TYPE_STRING); for (i = 0; i < cnt; i++) { GtkTreeIter it; GdkPixbuf *p = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, 20, 20); gdk_pixbuf_fill(p, ((unsigned)MEM_2_INT(dt->col, i * 3) << 8) + 0xFF); gtk_list_store_append(ls, &it); /* Name or index */ if (sp) t = _(sp[i]); else sprintf(t = txt, "%d", i); gtk_list_store_set(ls, &it, 0, p, 1, t, -1); g_object_unref(p); } w = gtk_tree_view_new_with_model(GTK_TREE_MODEL(ls)); gtk_tree_view_set_enable_search(GTK_TREE_VIEW(w), FALSE); gtk_tree_selection_set_mode(gtk_tree_view_get_selection(GTK_TREE_VIEW(w)), GTK_SELECTION_BROWSE); ren = gtk_cell_renderer_pixbuf_new(); g_object_set(ren, "width", 20 + 3, "xalign", 1.0, "ypad", 3, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(w), gtk_tree_view_column_new_with_attributes("Color", ren, "pixbuf", 0, NULL)); ren = gtk_cell_renderer_text_new(); g_object_set(ren, "xalign", 0.0, "yalign", 1.0, "xpad", 3, "ypad", 3, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(w), gtk_tree_view_column_new_with_attributes("Index", ren, "text", 1, NULL)); gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(w), FALSE); tp = gtk_tree_path_new_from_indices(*idx, -1); gtk_tree_view_set_cursor_on_cell(GTK_TREE_VIEW(w), tp, NULL, NULL, FALSE); /* Seems safe to do w/o scrolledwindow too */ gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(w), tp, NULL, TRUE, 0.5, 0.0); gtk_tree_path_free(tp); if (pp[5]) g_signal_connect(w, "button_press_event", G_CALLBACK(colorlist_click), NEXT_SLOT(r)); g_signal_connect(w, "cursor_changed", G_CALLBACK(colorlist_select), r); return (w); } static void colorlist_reset_color(void **slot, int idx) { colorlist_data *dt = slot[2]; unsigned char *rgb = dt->col + idx * 3; GtkTreeModel *tm = gtk_tree_view_get_model(GTK_TREE_VIEW(slot[0])); GtkTreePath *tp = gtk_tree_path_new_from_indices(idx, -1); GtkTreeIter it; if (gtk_tree_model_get_iter(tm, &it, tp)) { GdkPixbuf *p; gtk_tree_model_get(tm, &it, 0, &p, -1); gdk_pixbuf_fill(p, ((unsigned)MEM_2_INT(rgb, 0) << 8) + 0xFF); g_object_unref(p); // !!! After get() ref'd it /* Redraw the row displaying the color */ gtk_tree_model_row_changed(tm, tp, &it); } gtk_tree_path_free(tp); } #endif // GRADBAR widget #define GRADBAR_LEN 16 #define SLOT_SIZE 15 typedef struct { unsigned char *map, *rgb; GtkWidget *lr[2]; void **r; int ofs, lim, *idx, *len; unsigned char idxs[GRADBAR_LEN]; } gradbar_data; static void gradbar_scroll(GtkWidget *btn, gpointer user_data) { unsigned char *idx = user_data; gradbar_data *dt = (void *)(idx - offsetof(gradbar_data, idxs) - *idx); int dir = *idx * 2 - 1; dt->ofs += dir; *dt->idx += dir; // self-reading gtk_widget_set_sensitive(dt->lr[0], !!dt->ofs); gtk_widget_set_sensitive(dt->lr[1], dt->ofs < dt->lim - GRADBAR_LEN); gtk_widget_queue_draw(gtk_widget_get_parent(btn)); get_evt_1(NULL, (gpointer)dt->r); } static void gradbar_slot(GtkWidget *btn, gpointer user_data) { unsigned char *idx = user_data; gradbar_data *dt; if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(btn))) return; dt = (void *)(idx - offsetof(gradbar_data, idxs) - *idx); *dt->idx = *idx + dt->ofs; // self-reading get_evt_1(NULL, (gpointer)dt->r); } #if GTK_MAJOR_VERSION == 3 static gboolean gradbar_draw(GtkWidget *widget, cairo_t *cr, gpointer user_data) { unsigned char *rp, *idx = user_data; gradbar_data *dt = (void *)(idx - offsetof(gradbar_data, idxs) - *idx); int n = *idx + dt->ofs; cairo_save(cr); cairo_rectangle(cr, 0, 0, SLOT_SIZE, SLOT_SIZE); if (n < *dt->len) // Filled slot { rp = dt->rgb ? dt->rgb + dt->map[n] * 3 : dt->map + n * 3; cairo_set_rgb(cr, MEM_2_INT(rp, 0)); } else // Empty slot - show that { cairo_set_rgb(cr, RGB_2_INT(178, 178, 178)); cairo_fill(cr); cairo_set_rgb(cr, RGB_2_INT(128, 128, 128)); cairo_move_to(cr, 0, 0); cairo_line_to(cr, 0, SLOT_SIZE); cairo_line_to(cr, SLOT_SIZE, SLOT_SIZE); cairo_close_path(cr); } cairo_fill(cr); cairo_restore(cr); return (TRUE); } #else /* if GTK_MAJOR_VERSION <= 2 */ static gboolean gradbar_draw(GtkWidget *widget, GdkEventExpose *event, gpointer user_data) { unsigned char rgb[SLOT_SIZE * 2 * 3], *idx = user_data; gradbar_data *dt = (void *)(idx - offsetof(gradbar_data, idxs) - *idx); int i, n = *idx + dt->ofs; if (n < *dt->len) // Filled slot { memcpy(rgb, dt->rgb ? dt->rgb + dt->map[n] * 3 : dt->map + n * 3, 3); for (i = 3; i < SLOT_SIZE * 2 * 3; i++) rgb[i] = rgb[i - 3]; } else // Empty slot - show that { memset(rgb, 178, sizeof(rgb)); memset(rgb, 128, SLOT_SIZE * 3); } gdk_draw_rgb_image(widget->window, widget->style->black_gc, 0, 0, SLOT_SIZE, SLOT_SIZE, GDK_RGB_DITHER_NONE, rgb + SLOT_SIZE * 3, -3); return (TRUE); } #endif /* GTK+1&2 */ // !!! With inlining this, problem also GtkWidget *gradbar(void **r, char *ddata) { GtkWidget *hbox, *btn, *sw; gradbar_data *dt = r[2]; void **pp = r[1]; int i; hbox = gtk_hbox_new(TRUE, 0); dt->r = NEXT_SLOT(r); dt->idx = r[0]; dt->len = (void *)(ddata + (int)pp[3]); // length dt->map = (void *)(ddata + (int)pp[4]); // gradient map if (*(int *)(ddata + (int)pp[2])) // mode not-RGB dt->rgb = (void *)(ddata + (int)pp[5]); // colormap dt->lim = (int)pp[6]; dt->lr[0] = btn = xpack(hbox, gtk_button_new()); add_css_class(btn, "mtPaint_gradbar_button"); gtk_container_add(GTK_CONTAINER(btn), gtk_arrow_new(GTK_ARROW_LEFT, #if GTK_MAJOR_VERSION == 1 // !!! Arrow w/o shadow is invisible in plain GTK+1 GTK_SHADOW_OUT)); #else /* #if GTK_MAJOR_VERSION >= 2 */ GTK_SHADOW_NONE)); #endif gtk_widget_set_sensitive(btn, FALSE); gtk_signal_connect(GTK_OBJECT(btn), "clicked", GTK_SIGNAL_FUNC(gradbar_scroll), dt->idxs + 0); btn = NULL; for (i = 0; i < GRADBAR_LEN; i++) { dt->idxs[i] = i; btn = xpack(hbox, gtk_radio_button_new_from_widget( GTK_RADIO_BUTTON_0(btn))); add_css_class(btn, "mtPaint_gradbar_button"); gtk_toggle_button_set_mode(GTK_TOGGLE_BUTTON(btn), FALSE); gtk_signal_connect(GTK_OBJECT(btn), "toggled", GTK_SIGNAL_FUNC(gradbar_slot), dt->idxs + i); sw = gtk_drawing_area_new(); gtk_container_add(GTK_CONTAINER(btn), sw); #if GTK_MAJOR_VERSION == 3 gtk_widget_set_valign(sw, GTK_ALIGN_CENTER); gtk_widget_set_halign(sw, GTK_ALIGN_CENTER); gtk_widget_set_size_request(sw, SLOT_SIZE, SLOT_SIZE); g_signal_connect(G_OBJECT(sw), "draw", G_CALLBACK(gradbar_draw), dt->idxs + i); #else /* if GTK_MAJOR_VERSION <= 2 */ gtk_widget_set_usize(sw, SLOT_SIZE, SLOT_SIZE); gtk_signal_connect(GTK_OBJECT(sw), "expose_event", GTK_SIGNAL_FUNC(gradbar_draw), dt->idxs + i); #endif /* GTK+1&2 */ } dt->lr[1] = btn = xpack(hbox, gtk_button_new()); add_css_class(btn, "mtPaint_gradbar_button"); gtk_container_add(GTK_CONTAINER(btn), gtk_arrow_new(GTK_ARROW_RIGHT, #if GTK_MAJOR_VERSION == 1 // !!! Arrow w/o shadow is invisible in plain GTK+1 GTK_SHADOW_OUT)); #else /* #if GTK_MAJOR_VERSION >= 2 */ GTK_SHADOW_NONE)); #endif gtk_signal_connect(GTK_OBJECT(btn), "clicked", GTK_SIGNAL_FUNC(gradbar_scroll), dt->idxs + 1); gtk_widget_show_all(hbox); return (hbox); } // COMBOENTRY widget #if GTK_MAJOR_VERSION == 3 static void comboentry_reset(GtkWidget *cbox, char **v, char **src) { GtkWidget *entry = gtk_bin_get_child(GTK_BIN(cbox)); gtk_entry_set_text(GTK_ENTRY(entry), *(char **)v); // Replace transient buffer *(const char **)v = gtk_entry_get_text(GTK_ENTRY(entry)); gtk_combo_box_text_remove_all(GTK_COMBO_BOX_TEXT(cbox)); while (*src) gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(cbox), *src++); } static void comboentry_chg(GtkComboBox *cbox, gpointer user_data) { /* Only react to selecting from list */ if (gtk_combo_box_get_active(cbox) >= 0) get_evt_1(G_OBJECT(cbox), user_data); } // !!! With inlining this, problem also GtkWidget *comboentry(char *ddata, void **r) { void **pp = r[1]; GtkWidget *cbox = gtk_combo_box_text_new_with_entry(); GtkWidget *entry = gtk_bin_get_child(GTK_BIN(cbox)); comboentry_reset(cbox, r[0], *(char ***)(ddata + (int)pp[2])); g_signal_connect(G_OBJECT(cbox), "changed", G_CALLBACK(comboentry_chg), NEXT_SLOT(r)); g_signal_connect(G_OBJECT(entry), "activate", G_CALLBACK(get_evt_1), NEXT_SLOT(r)); return (cbox); } #define comboentry_get_text(A) \ gtk_entry_get_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(A)))) #define comboentry_set_text(A,B) \ gtk_entry_set_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(A))), B) #else /* if GTK_MAJOR_VERSION <= 2 */ static void comboentry_reset(GtkCombo *combo, char **v, char **src) { GList *list = NULL; gtk_entry_set_text(GTK_ENTRY(combo->entry), *(char **)v); // Replace transient buffer *(const char **)v = gtk_entry_get_text(GTK_ENTRY(combo->entry)); // NULL-terminated array of pointers while (*src) list = g_list_append(list, *src++); #if GTK_MAJOR_VERSION == 1 if (!list) gtk_list_clear_items(GTK_LIST(combo->list), 0, -1); else /* Fails if list is empty in GTK+1 */ #endif gtk_combo_set_popdown_strings(combo, list); g_list_free(list); } // !!! With inlining this, problem also GtkWidget *comboentry(char *ddata, void **r) { void **pp = r[1]; GtkWidget *w = gtk_combo_new(); GtkCombo *combo = GTK_COMBO(w); gtk_combo_disable_activate(combo); comboentry_reset(combo, r[0], *(char ***)(ddata + (int)pp[2])); gtk_signal_connect(GTK_OBJECT(combo->popwin), "hide", GTK_SIGNAL_FUNC(get_evt_1), NEXT_SLOT(r)); gtk_signal_connect(GTK_OBJECT(combo->entry), "activate", GTK_SIGNAL_FUNC(get_evt_1), NEXT_SLOT(r)); return (w); } #define comboentry_get_text(A) gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(A)->entry)) #define comboentry_set_text(A,B) gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(A)->entry), B) #endif /* GTK+1&2 */ // PCTCOMBO widget #if GTK_MAJOR_VERSION == 3 // !!! Even with inlining this, some space gets wasted GtkWidget *pctcombo(void **r) { GtkWidget *cbox, *entry, *button; char buf[32]; int i, n = 0, v = *(int *)r[0], *ns = GET_DESCV(r, 2); /* Uses 0-terminated array of ints */ while (ns[n] > 0) n++; cbox = gtk_combo_box_text_new_with_entry(); /* Find the button */ button = combobox_button(cbox); gtk_widget_set_can_focus(button, FALSE); /* Make it small enough */ css_restyle(button, ".mtPaint_pctbutton { padding: 0; }", "mtPaint_pctbutton", NULL); gtk_widget_set_size_request(button, 18, -1); entry = gtk_bin_get_child(GTK_BIN(cbox)); gtk_widget_set_can_focus(entry, FALSE); gtk_editable_set_editable(GTK_EDITABLE(entry), FALSE); gtk_entry_set_width_chars(GTK_ENTRY(entry), 6); gtk_entry_set_max_width_chars(GTK_ENTRY(entry), 6); for (i = 0; i < n; i++) { sprintf(buf, "%d%%", ns[i]); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(cbox), buf); } sprintf(buf, "%d%%", v); gtk_entry_set_text(GTK_ENTRY(entry), buf); g_signal_connect(G_OBJECT(entry), "changed", G_CALLBACK(get_evt_1), NEXT_SLOT(r)); return (cbox); } #define pctcombo_entry(A) gtk_bin_get_child(GTK_BIN(A)) #else /* if GTK_MAJOR_VERSION <= 2 */ #if (GTK_MAJOR_VERSION == 2) && (GTK2VERSION < 12) /* GTK+ 2.10 or earlier */ static void pctcombo_chg(GtkWidget *entry, gpointer user_data) { /* Filter out spurious deletions */ if (strlen(gtk_entry_get_text(GTK_ENTRY(entry)))) get_evt_1(NULL, user_data); } #endif // !!! Even with inlining this, some space gets wasted GtkWidget *pctcombo(void **r) { GtkWidget *w, *entry; GList *list = NULL; char *ts, *s; int i, n = 0, v = *(int *)r[0], *ns = GET_DESCV(r, 2); /* Uses 0-terminated array of ints */ while (ns[n] > 0) n++; w = gtk_combo_new(); gtk_combo_set_value_in_list(GTK_COMBO(w), FALSE, FALSE); entry = GTK_COMBO(w)->entry; GTK_WIDGET_UNSET_FLAGS(entry, GTK_CAN_FOCUS); gtk_widget_set_usize(GTK_COMBO(w)->button, 18, -1); #if GTK_MAJOR_VERSION == 1 gtk_widget_set_usize(w, 75, -1); #else /* #if GTK_MAJOR_VERSION == 2 */ gtk_entry_set_width_chars(GTK_ENTRY(entry), 6); #endif gtk_entry_set_editable(GTK_ENTRY(entry), FALSE); ts = s = calloc(n, 32); // 32 chars per int for (i = 0; i < n; i++) { list = g_list_append(list, s); s += sprintf(s, "%d%%", ns[i]) + 1; } gtk_combo_set_popdown_strings(GTK_COMBO(w), list); g_list_free(list); sprintf(ts, "%d%%", v); gtk_entry_set_text(GTK_ENTRY(entry), ts); free(ts); /* In GTK1, combo box entry is updated continuously */ #if GTK_MAJOR_VERSION == 1 gtk_signal_connect(GTK_OBJECT(GTK_COMBO(w)->popwin), "hide", GTK_SIGNAL_FUNC(get_evt_1), NEXT_SLOT(r)); #elif GTK2VERSION < 12 /* GTK+ 2.10 or earlier */ gtk_signal_connect(GTK_OBJECT(entry), "changed", GTK_SIGNAL_FUNC(pctcombo_chg), NEXT_SLOT(r)); #else /* GTK+ 2.12+ */ gtk_signal_connect(GTK_OBJECT(entry), "changed", GTK_SIGNAL_FUNC(get_evt_1), NEXT_SLOT(r)); #endif return (w); } #define pctcombo_entry(A) (GTK_COMBO(A)->entry) #endif /* GTK+1&2 */ // TEXT widget static GtkWidget *textarea(char *init) { GtkWidget *scroll, *text; #if GTK_MAJOR_VERSION == 1 text = gtk_text_new(NULL, NULL); gtk_text_set_editable(GTK_TEXT(text), TRUE); if (init) gtk_text_insert(GTK_TEXT(text), NULL, NULL, NULL, init, -1); scroll = gtk_scrolled_window_new(NULL, GTK_TEXT(text)->vadj); #else /* #if GTK_MAJOR_VERSION >= 2 */ GtkTextBuffer *texbuf = gtk_text_buffer_new(NULL); if (init) gtk_text_buffer_set_text(texbuf, init, -1); text = gtk_text_view_new_with_buffer(texbuf); #if GTK_MAJOR_VERSION == 3 scroll = gtk_scrolled_window_new( gtk_scrollable_get_hadjustment(GTK_SCROLLABLE(text)), gtk_scrollable_get_vadjustment(GTK_SCROLLABLE(text))); #else scroll = gtk_scrolled_window_new(GTK_TEXT_VIEW(text)->hadjustment, GTK_TEXT_VIEW(text)->vadjustment); #endif #endif gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_container_add(GTK_CONTAINER(scroll), text); gtk_widget_show_all(scroll); return (text); } static char *read_textarea(GtkWidget *text) { #if GTK_MAJOR_VERSION == 1 return (gtk_editable_get_chars(GTK_EDITABLE(text), 0, -1)); #else /* #if GTK_MAJOR_VERSION >= 2 */ GtkTextIter begin, end; GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text)); gtk_text_buffer_get_start_iter(buffer, &begin); gtk_text_buffer_get_end_iter(buffer, &end); return (gtk_text_buffer_get_text(buffer, &begin, &end, TRUE)); #endif } static void set_textarea(GtkWidget *text, char *init) { #if GTK_MAJOR_VERSION == 1 gtk_editable_delete_text(GTK_EDITABLE(text), 0, -1); if (init) gtk_text_insert(GTK_TEXT(text), NULL, NULL, NULL, init, -1); #else /* #if GTK_MAJOR_VERSION >= 2 */ gtk_text_buffer_set_text(gtk_text_view_get_buffer(GTK_TEXT_VIEW(text)), init ? init : "", -1); #endif } // Columns for LIST* widgets typedef struct { char *ddata; // datastruct void **dcolumn; // datablock "column" if any void **columns[MAX_COLS]; // column slots void **r; // slot int ncol; // columns } col_data; static void *get_cell(col_data *c, int row, int col) { void **cp = c->columns[col][1]; char *v; int op, kind, ofs = 0; kind = (int)cp[3] >> COL_LSHIFT; if (!cp[2]) // relative { ofs = (int)cp[1]; cp = c->dcolumn; } op = (int)cp[0]; v = cp[1]; if (op & WB_FFLAG) v = c->ddata + (int)v; if (op & WB_NFLAG) v = *(void **)v; // array dereference if (!v) return (NULL); // Paranoia v += ofs + row * (int)cp[2]; if (kind == col_PTR) v = *(char **)v; // cell dereference else if (kind == col_REL) v += *(int *)v; return (v); } static void set_columns(col_data *c, col_data *src, char *ddata, void **r) { int i; /* Copy & clear the source */ *c = *src; memset(src, 0, sizeof(*src)); c->ddata = ddata; c->r = r; /* Link columns to group */ for (i = 0; i < c->ncol; i++) ((swdata *)c->columns[i][0])->strs = (void *)c; } // LISTCC widget typedef struct { int lock; // against in-reset signals int wantfoc; // delayed focus int h; // max height int *idx; // result field int *cnt; // length field col_data c; } listcc_data; #ifdef U_LISTS_GTK1 static void listcc_select(GtkList *list, GtkWidget *widget, gpointer user_data) { listcc_data *dt = user_data; void **base, **desc, **slot = NEXT_SLOT(dt->c.r); if (dt->lock) return; /* Update the value */ *dt->idx = (int)gtk_object_get_user_data(GTK_OBJECT(widget)); // !!! No touching slot outside lock: uninitialized the first time base = slot[0]; desc = slot[1]; /* Call the handler */ if (desc[1]) ((evt_fn)desc[1])(GET_DDATA(base), base, (int)desc[0] & WB_OPMASK, slot); } static void listcc_select_item(void **slot) { GtkWidget *item, *win, *list = slot[0], *fw = NULL; listcc_data *dt = slot[2]; int idx = *dt->idx, n = dt->h - idx - 1; // backward if (!(item = g_list_nth_data(GTK_LIST(list)->children, n))) return; /* Move focus if sensitive, flag to be moved later if not */ if (!(dt->wantfoc = !GTK_WIDGET_IS_SENSITIVE(list))) { dt->lock++; // this is strictly a visual update win = gtk_widget_get_toplevel(list); if (GTK_IS_WINDOW(win)) fw = GTK_WINDOW(win)->focus_widget; /* Focus is somewhere in list - move it, selection will follow */ if (fw && gtk_widget_is_ancestor(fw, list)) gtk_widget_grab_focus(item); else /* Focus is elsewhere - move whatever remains, then */ { /* !!! For simplicity, an undocumented field is used; a bit less hacky * but longer is to set focus child to item, NULL, and item again - WJ */ gtk_container_set_focus_child(GTK_CONTAINER(list), item); GTK_LIST(list)->last_focus_child = item; } /* Clear stuck selections when possible */ gtk_list_item_select(GTK_LIST_ITEM(item)); dt->lock--; } /* Signal must be reliable even with focus delayed */ listcc_select(NULL, item, dt); } static void listcc_update(GtkWidget *widget, GtkStateType state, gpointer user_data) { if (state == GTK_STATE_INSENSITIVE) { void **slot = user_data; listcc_data *dt = slot[2]; if (!dt->wantfoc) return; dt->lock++; // strictly a visual update listcc_select_item(slot); dt->lock--; } } static void listcc_toggled(GtkWidget *widget, gpointer user_data) { listcc_data *dt = user_data; void **slot, **base, **desc; char *v; int col, row; if (dt->lock) return; /* Find out what happened to what, and where */ col = (int)gtk_object_get_user_data(GTK_OBJECT(widget)); row = (int)gtk_object_get_user_data(GTK_OBJECT(widget->parent->parent)); /* Self-updating */ v = get_cell(&dt->c, row, col); *(int *)v = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); /* Now call the handler */ slot = dt->c.columns[col]; slot = NEXT_SLOT(slot); base = slot[0]; desc = slot[1]; if (desc[1]) ((evtx_fn)desc[1])(GET_DDATA(base), base, (int)desc[0] & WB_OPMASK, slot, (void *)row); } static void listcc_reset(void **slot, int row) { GtkWidget *list = slot[0]; GList *col, *curr = GTK_LIST(list)->children; listcc_data *ld = slot[2]; int cnt = *ld->cnt; if (row >= 0) // specific row, not whole list curr = g_list_nth(curr, ld->h - row - 1); // backward ld->lock = TRUE; for (; curr; curr = curr->next) { GtkWidget *item = curr->data; int j, n = (int)gtk_object_get_user_data(GTK_OBJECT(item)); if (n >= cnt) { gtk_widget_hide(item); /* !!! To stop arrow keys handler from selecting this */ gtk_widget_set_sensitive(item, FALSE); continue; } col = GTK_BOX(GTK_BIN(item)->child)->children; for (j = 0; j < ld->c.ncol; col = col->next , j++) { GtkWidget *widget = ((GtkBoxChild *)(col->data))->widget; char *v = get_cell(&ld->c, n, j); void **cp = ld->c.columns[j][1]; int op = (int)cp[0] & WB_OPMASK; if ((op == op_TXTCOLUMN) || (op == op_XTXTCOLUMN)) gtk_label_set_text(GTK_LABEL(widget), v); else if (op == op_CHKCOLUMN) gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(widget), *(int *)v); } gtk_widget_set_sensitive(item, TRUE); gtk_widget_show(item); if (row >= 0) break; // one row only } if (row < 0) listcc_select_item(slot); // only when full reset ld->lock = FALSE; } // !!! With inlining this, problem also GtkWidget *listcc(void **r, char *ddata, col_data *c) { char txt[128]; GtkWidget *widget, *list, *item, *uninit_(hbox); listcc_data *ld = r[2]; void **pp = r[1]; int j, n, h, *cnt, *idx = r[0]; cnt = (void *)(ddata + (int)pp[2]); // length pointer h = (int)pp[3]; // max for variable length if (h < *cnt) h = *cnt; list = gtk_list_new(); gtk_list_set_selection_mode(GTK_LIST(list), GTK_SELECTION_BROWSE); /* Fill datastruct */ ld->idx = idx; ld->cnt = cnt; ld->h = h; set_columns(&ld->c, c, ddata, r); for (n = h - 1; n >= 0; n--) // Reverse numbering { item = gtk_list_item_new(); gtk_object_set_user_data(GTK_OBJECT(item), (gpointer)n); gtk_container_add(GTK_CONTAINER(list), item); // !!! Spacing = 3 hbox = gtk_hbox_new(FALSE, 3); gtk_container_add(GTK_CONTAINER(item), hbox); for (j = 0; j < ld->c.ncol; j++) { void **cp = ld->c.columns[j][1]; int op = (int)cp[0] & WB_OPMASK, jw = (int)cp[3]; if (op == op_CHKCOLUMN) { #if GTK_MAJOR_VERSION == 1 /* !!! Vertical spacing is too small without the label */ widget = gtk_check_button_new_with_label(""); #else /* if GTK_MAJOR_VERSION == 2 */ /* !!! Focus frame is placed wrong with the empty label */ widget = gtk_check_button_new(); #endif gtk_object_set_user_data(GTK_OBJECT(widget), (gpointer)j); gtk_signal_connect(GTK_OBJECT(widget), "toggled", GTK_SIGNAL_FUNC(listcc_toggled), ld); } else { if ((op == op_TXTCOLUMN) || (op == op_XTXTCOLUMN)) txt[0] = '\0'; // Init to empty string else /* if (op == op_IDXCOLUMN) */ // Constant sprintf(txt, "%d", (int)cp[1] + (int)cp[2] * n); widget = gtk_label_new(txt); gtk_misc_set_alignment(GTK_MISC(widget), ((jw >> 16) & 3) * 0.5, 0.5); } if (jw & 0xFFFF) gtk_widget_set_usize(widget, jw & 0xFFFF, -2); (op == op_XTXTCOLUMN ? xpack : pack)(hbox, widget); } gtk_widget_show_all(hbox); } r[0] = list; // Fix up slot if (*cnt) listcc_reset(r, -1); gtk_signal_connect(GTK_OBJECT(list), "select_child", GTK_SIGNAL_FUNC(listcc_select), ld); /* To move focus when delayed by insensitivity */ widget = pack(hbox, gtk_label_new("")); // canary: updated last gtk_signal_connect(GTK_OBJECT(widget), "state_changed", GTK_SIGNAL_FUNC(listcc_update), r); return (list); } #endif #ifndef U_LISTS_GTK1 #define LISTCC_KEY "mtPaint.listcc" static void listcc_select(GtkTreeView *tree, gpointer user_data) { listcc_data *dt = user_data; void **base, **desc, **slot = NEXT_SLOT(dt->c.r); GtkTreePath *tp; int l; if (dt->lock) return; /* Update the value */ l = gtk_tree_model_iter_n_children(gtk_tree_view_get_model(tree), NULL); gtk_tree_view_get_cursor(tree, &tp, NULL); *dt->idx = l - 1 - gtk_tree_path_get_indices(tp)[0]; // Backward gtk_tree_path_free(tp); base = slot[0]; desc = slot[1]; /* Call the handler */ if (desc[1]) ((evt_fn)desc[1])(GET_DDATA(base), base, (int)desc[0] & WB_OPMASK, slot); } static void listcc_select_item(void **slot) { GtkTreeView *tr = slot[0]; GtkTreeModel *tm = gtk_tree_view_get_model(tr); GtkTreePath *tp; listcc_data *dt = slot[2]; int l, idx = *dt->idx; l = gtk_tree_model_iter_n_children(tm, NULL); if ((idx < 0) || (idx >= l)) return; dt->lock++; // this is strictly a visual update tp = gtk_tree_path_new_from_indices(l - idx - 1, -1); // backward gtk_tree_view_set_cursor_on_cell(tr, tp, NULL, NULL, FALSE); gtk_tree_path_free(tp); dt->lock--; /* Signal must be reliable whatever happens */ listcc_select(tr, dt); } void listcc_toggled(GtkCellRendererToggle *ren, gchar *path, gpointer user_data) { void **slot = g_object_get_data(G_OBJECT(ren), LISTCC_KEY); void **base, **desc; listcc_data *dt = slot[2]; GtkTreeView *tr = slot[0]; GtkTreeModel *tm; GtkTreeIter it; gint yf; char *v; int col, row; if (dt->lock) return; /* Find out what happened to what, and where */ tm = gtk_tree_view_get_model(tr); if (!gtk_tree_model_get_iter_from_string(tm, &it, path)) return; // Paranoia col = (int)user_data; gtk_tree_model_get(tm, &it, col, &yf, -1); gtk_list_store_set(GTK_LIST_STORE(tm), &it, col, yf ^= 1, -1); // Update list row = yf >> 1; /* Self-updating */ v = get_cell(&dt->c, row, col); *(int *)v = yf & 1; /* Now call the handler */ slot = dt->c.columns[col]; slot = NEXT_SLOT(slot); base = slot[0]; desc = slot[1]; if (desc[1]) ((evtx_fn)desc[1])(GET_DDATA(base), base, (int)desc[0] & WB_OPMASK, slot, (void *)row); } static void listcc_reset(void **slot, int row) { GtkTreeView *tree = GTK_TREE_VIEW(slot[0]); listcc_data *ld = slot[2]; GtkListStore *ls; GtkTreeIter it; char txt[64]; int j, n = 0, ncol = ld->c.ncol, cnt = *ld->cnt; ld->lock = TRUE; if (row >= 0) // specific row, not whole list { GtkTreePath *tp; GtkTreeModel *tm = gtk_tree_view_get_model(tree); int l = gtk_tree_model_iter_n_children(tm, NULL); ls = GTK_LIST_STORE(tm); #if 0 /* LISTCC_RESET_ROW currently is NOT used on added/removed ones */ /* Add/remove existing rows; expecting one row only so let updates be */ if ((row >= cnt) && (row < l)) { gtk_tree_model_get_iter_first(tm, &it); while (row < l--) gtk_list_store_remove(ls, &it); } else if ((row < cnt) && (row >= l)) { while (row >= l++) gtk_list_store_prepend(ls, &it); } #endif tp = gtk_tree_path_new_from_indices(l - 1 - row, -1); if (!gtk_tree_model_get_iter(tm, &it, tp)) cnt = 0; // !!! Row out of range, do nothing gtk_tree_path_free(tp); n = row; } else // prepare new model { GType ctypes[MAX_COLS]; for (j = 0; j < ncol; j++) { void **cp = ld->c.columns[j][1]; int op = (int)cp[0] & WB_OPMASK; ctypes[j] = op == op_CHKCOLUMN ? G_TYPE_INT : G_TYPE_STRING; } ls = gtk_list_store_newv(ncol, ctypes); } for (; n < cnt; n++) { if (row < 0) gtk_list_store_prepend(ls, &it); for (j = 0; j < ncol; j++) { char *v = get_cell(&ld->c, n, j); void **cp = ld->c.columns[j][1]; int op = (int)cp[0] & WB_OPMASK; if (op == op_CHKCOLUMN) // index * 2 + flag gtk_list_store_set(ls, &it, j, n * 2 + !!*(int *)v, -1); else { if (op == op_IDXCOLUMN) // Constant sprintf(v = txt, "%d", (int)cp[1] + (int)cp[2] * n); // op_TXTCOLUMN/op_XTXTCOLUMN otherwise gtk_list_store_set(ls, &it, j, v, -1); } } if (row >= 0) break; // one row only } if (row < 0) { gtk_tree_view_set_model(tree, GTK_TREE_MODEL(ls)); listcc_select_item(slot); // only when full reset /* !!! Sometimes it shows the wrong part and redraw doesn't help */ gtk_adjustment_value_changed(gtk_tree_view_get_vadjustment(tree)); } ld->lock = FALSE; } static void listcc_chk(GtkTreeViewColumn *col, GtkCellRenderer *ren, GtkTreeModel *tm, GtkTreeIter *it, gpointer data) { gint yf; gtk_tree_model_get(tm, it, (int)data, &yf, -1); g_object_set(ren, "active", yf & 1, NULL); } static void listcc_scroll_in(GtkWidget *widget, gpointer user_data) { GtkTreePath *tp; gtk_tree_view_get_cursor(GTK_TREE_VIEW(widget), &tp, NULL); if (!tp) return; // Paranoia gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(widget), tp, NULL, FALSE, 0, 0); gtk_tree_path_free(tp); } // !!! With inlining this, problem also GtkWidget *listcc(void **r, char *ddata, col_data *c) { GtkWidget *w; listcc_data *ld = r[2]; void **pp = r[1]; int j, h, *cnt, *idx = r[0]; cnt = (void *)(ddata + (int)pp[2]); // length pointer h = (int)pp[3]; // max for variable length if (h < *cnt) h = *cnt; /* Fill datastruct */ ld->idx = idx; ld->cnt = cnt; ld->h = h; set_columns(&ld->c, c, ddata, r); w = gtk_tree_view_new(); gtk_tree_view_set_enable_search(GTK_TREE_VIEW(w), FALSE); gtk_tree_selection_set_mode(gtk_tree_view_get_selection(GTK_TREE_VIEW(w)), GTK_SELECTION_BROWSE); for (j = 0; j < ld->c.ncol; j++) { GtkCellRenderer *ren; GtkTreeViewColumn *col; void **cp = ld->c.columns[j][1]; int op = (int)cp[0] & WB_OPMASK, jw = (int)cp[3]; if (op == op_CHKCOLUMN) { ren = gtk_cell_renderer_toggle_new(); /* To preserve spacing, need a height of a GtkLabel here; * but waiting for realize to get & set it is a hassle, * and the layers box looks perfectly OK as is - WJ */ // g_object_set(ren, "height", 10, NULL); col = gtk_tree_view_column_new_with_attributes("", ren, NULL); gtk_tree_view_column_set_cell_data_func(col, ren, listcc_chk, (gpointer)j, NULL); g_object_set_data(G_OBJECT(ren), LISTCC_KEY, r); g_signal_connect(ren, "toggled", G_CALLBACK(listcc_toggled), (gpointer)j); } else /* op_TXTCOLUMN/op_XTXTCOLUMN/op_IDXCOLUMN */ { ren = gtk_cell_renderer_text_new(); gtk_cell_renderer_set_alignment(ren, ((jw >> 16) & 3) * 0.5, 0.5); col = gtk_tree_view_column_new_with_attributes("", ren, "text", j, NULL); if (op == op_XTXTCOLUMN) gtk_tree_view_column_set_expand(col, TRUE); } if (jw & 0xFFFF) g_object_set(ren, "width", jw & 0xFFFF, NULL); // !!! Maybe gtk_tree_view_column_set_fixed_width(col, jw & 0xFFFF) instead? g_object_set(ren, "xpad", 2, NULL); // Looks good enough gtk_tree_view_append_column(GTK_TREE_VIEW(w), col); } gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(w), FALSE); /* This will scroll selected row in on redisplay */ g_signal_connect(w, "map", G_CALLBACK(listcc_scroll_in), NULL); r[0] = w; // Fix up slot if (*cnt) listcc_reset(r, -1); g_signal_connect(w, "cursor_changed", G_CALLBACK(listcc_select), ld); return (w); } #endif // LISTC widget typedef struct { int kind; // type of list int update; // delayed update flags int lock; // against in-reset signals int cntmax; // maximum value from row map int *idx; // result field int *cnt; // length field int *sort; // sort column & direction int **map; // row map vector field void **change; // slot for EVT_CHANGE void **ok; // slot for EVT_OK #ifdef U_LISTS_GTK1 GtkWidget *sort_arrows[MAX_COLS]; GdkPixmap *icons[2]; GdkBitmap *masks[2]; #endif col_data c; } listc_data; #ifdef U_LISTS_GTK1 static gboolean listcx_key(GtkWidget *widget, GdkEventKey *event, gpointer user_data) { listc_data *dt = user_data; GtkCList *clist = GTK_CLIST(widget); int row = 0; if (dt->lock) return (FALSE); // Paranoia switch (event->keyval) { case GDK_End: case GDK_KP_End: row = clist->rows - 1; // Fallthrough case GDK_Home: case GDK_KP_Home: clist->focus_row = row; gtk_clist_select_row(clist, row, 0); gtk_clist_moveto(clist, row, 0, 0.5, 0); return (TRUE); case GDK_Return: case GDK_KP_Enter: if (!dt->ok) break; get_evt_1(NULL, dt->ok); return (TRUE); } return (FALSE); } static gboolean listcx_click(GtkWidget *widget, GdkEventButton *event, gpointer user_data) { listc_data *dt = user_data; GtkCList *clist = GTK_CLIST(widget); void **slot, **base, **desc; gint row, col; if (dt->lock) return (FALSE); // Paranoia if ((event->button != 3) || (event->type != GDK_BUTTON_PRESS)) return (FALSE); if (!gtk_clist_get_selection_info(clist, event->x, event->y, &row, &col)) return (FALSE); if (clist->focus_row != row) { clist->focus_row = row; gtk_clist_select_row(clist, row, 0); } slot = SLOT_N(dt->c.r, 2); base = slot[0]; desc = slot[1]; if (desc[1]) ((evtx_fn)desc[1])(GET_DDATA(base), base, (int)desc[0] & WB_OPMASK, slot, (void *)row); return (TRUE); } static void listcx_done(GtkCList *clist, listc_data *ld) { int j; /* Free pixmaps */ gdk_pixmap_unref(ld->icons[0]); gdk_pixmap_unref(ld->icons[1]); if (ld->masks[0]) gdk_pixmap_unref(ld->masks[0]); if (ld->masks[1]) gdk_pixmap_unref(ld->masks[1]); /* Remember column widths */ for (j = 0; j < ld->c.ncol; j++) { void **cp = ld->c.columns[j][1]; int op = (int)cp[0]; int l = WB_GETLEN(op); // !!! -2 for each extra ref if (l > 4) inifile_set_gint32(cp[5], clist->column[j].width); } } static void listc_select_row(GtkCList *clist, gint row, gint column, GdkEventButton *event, gpointer user_data) { listc_data *dt = user_data; void **slot = NEXT_SLOT(dt->c.r), **base = slot[0], **desc = slot[1]; int dclick; if (dt->lock) return; dclick = dt->ok && event && (event->type == GDK_2BUTTON_PRESS); /* Update the value */ *dt->idx = (int)gtk_clist_get_row_data(clist, row); /* Call the handler */ if (desc[1]) ((evt_fn)desc[1])(GET_DDATA(base), base, (int)desc[0] & WB_OPMASK, slot); /* Call the other handler */ if (dclick) get_evt_1(NULL, dt->ok); } static void listc_update(GtkWidget *w, gpointer user_data) { GtkCList *clist = GTK_CLIST(w); listc_data *ld = user_data; int what = ld->update; if (!GTK_WIDGET_MAPPED(w)) /* Is frozen anyway */ { // Flag a waiting refresh if (what & 1) ld->update = (what & 2) | 4; return; } ld->update = 0; if (what & 4) /* Do a delayed refresh */ { gtk_clist_freeze(clist); gtk_clist_thaw(clist); } if ((what & 2) && clist->selection) /* Do a scroll */ gtk_clist_moveto(clist, (int)(clist->selection->data), 0, 0.5, 0); } static int listc_collect(gchar **row_text, gchar **row_pix, col_data *c, int row) { int j, res = FALSE, ncol = c->ncol; if (row_pix) memset(row_pix, 0, ncol * sizeof(*row_pix)); for (j = 0; j < ncol; j++) { char *v = get_cell(c, row, j); void **cp = c->columns[j][1]; int op = (int)cp[0] & WB_OPMASK; // !!! IDXCOLUMN not supported if (op == op_FILECOLUMN) { if (!row_pix || (v[0] == ' ')) v++; else row_pix[j] = v , v = "" , res = TRUE; } row_text[j] = v; } return (res); } static void listc_get_order(GtkCList *clist, int *res, int l) { int i; for (i = 0; i < l; i++) res[i] = -1; // nowhere by default if (l > clist->rows) l = clist->rows; for (i = 0; i < l; i++) res[(int)gtk_clist_get_row_data(clist, i)] = i; } static int listc_sort(GtkCList *clist, listc_data *ld, int reselect) { void **slot; /* Do nothing if empty */ if (!*ld->cnt) return (0); /* Call & apply external sort */ if ((slot = ld->change)) { GList *tmp, *cur, **ll, *pos = NULL; int i, cnt, *map; /* Call the EVT_CHANGE handler, to sort map vector */ get_evt_1(NULL, slot); /* !!! Directly rearrange widget's internals; it's deprecated * so nothing inside will change anymore */ gtk_clist_freeze(clist); if (clist->selection) pos = g_list_nth(clist->row_list, GPOINTER_TO_INT(clist->selection->data)); ll = calloc(ld->cntmax + 1, sizeof(*ll)); for (cur = clist->row_list; cur; cur = cur->next) { GtkCListRow *row = cur->data; ll[(int)row->data] = cur; } /* Rearrange rows */ cnt = *ld->cnt; map = *ld->map; clist->row_list = cur = ll[map[0]]; cur->prev = NULL; for (i = 1; i < cnt; i++) { cur->next = tmp = ll[map[i]]; tmp->prev = cur; cur = tmp; } clist->row_list_end = cur; cur->next = NULL; free(ll); if (pos) /* Relocate existing selection */ { int n = g_list_position(clist->row_list, pos); clist->selection->data = GINT_TO_POINTER(n); clist->focus_row = n; } } /* Do builtin sort */ else gtk_clist_sort(clist); if (!reselect || !clist->selection) { int n = gtk_clist_find_row_from_data(clist, (gpointer)*ld->idx); if (n < 0) *ld->idx = (int)gtk_clist_get_row_data(clist, n = 0); clist->focus_row = n; gtk_clist_select_row(clist, n, 0); } /* Done rearranging rows */ if (slot) { gtk_clist_thaw(clist); return (1); // Refresh later if invisible now } /* !!! Builtin sort doesn't move focus along with selection, do it here */ if (clist->selection) { int n = GPOINTER_TO_INT(clist->selection->data); if (clist->focus_row != n) { clist->focus_row = n; if (GTK_WIDGET_HAS_FOCUS((GtkWidget *)clist)) return (4); // Refresh } } return (0); } static void listc_select_index(GtkWidget *widget, int v) { GtkCList *clist = GTK_CLIST(widget); int row = gtk_clist_find_row_from_data(clist, (gpointer)v); if (row < 0) return; // Paranoia gtk_clist_select_row(clist, row, 0); /* !!! Focus fails to follow selection in browse mode - have to * move it here, but a full redraw is necessary afterwards */ if (clist->focus_row == row) return; clist->focus_row = row; if (GTK_WIDGET_HAS_FOCUS(widget) && !clist->freeze_count) gtk_widget_queue_draw(widget); } static void listc_reset_row(GtkCList *clist, listc_data *ld, int n) { gchar *row_text[MAX_COLS]; int i, row, ncol = ld->c.ncol; // !!! No support for anything but text columns listc_collect(row_text, NULL, &ld->c, n); row = gtk_clist_find_row_from_data(clist, (gpointer)n); for (i = 0; i < ncol; i++) gtk_clist_set_text(clist, row, i, row_text[i]); } /* !!! Should not redraw old things while resetting - or at least, not refer * outside of new data if doing it */ static void listc_reset(GtkCList *clist, listc_data *ld) { int i, j, m, n, ncol = ld->c.ncol, cnt = *ld->cnt, *map = NULL; ld->lock = TRUE; gtk_clist_freeze(clist); gtk_clist_clear(clist); if (ld->map) map = *ld->map; for (m = i = 0; i < cnt; i++) { gchar *row_text[MAX_COLS], *row_pix[MAX_COLS]; int row, pix; n = map ? map[i] : i; if (m < n) m = n; pix = listc_collect(row_text, row_pix, &ld->c, n); row = gtk_clist_append(clist, row_text); gtk_clist_set_row_data(clist, row, (gpointer)n); if (!pix) continue; for (j = 0; j < ncol; j++) { char *s = row_pix[j]; if (!s) continue; pix = s[0] == 'D'; // !!! Spacing = 4 gtk_clist_set_pixtext(clist, row, j, s + 1, 4, ld->icons[pix], ld->masks[pix]); } } ld->cntmax = m; /* Adjust column widths (not for draggable list) */ if ((ld->kind != op_LISTCd) && (ld->kind != op_LISTCX)) { for (j = 0; j < ncol; j++) { // !!! Spacing = 5 gtk_clist_set_column_width(clist, j, 5 + gtk_clist_optimal_column_width(clist, j)); } } i = *ld->idx; if (i >= cnt) i = cnt - 1; if (!cnt) *ld->idx = 0; /* Safer than -1 for empty list */ /* Draggable and unordered lists aren't sorted */ else if ((ld->kind == op_LISTCd) || (ld->kind == op_LISTCu)) { if (i < 0) i = 0; gtk_clist_select_row(clist, i, 0); *ld->idx = i; } else { *ld->idx = i; listc_sort(clist, ld, FALSE); } gtk_clist_thaw(clist); /* !!! Otherwise the newly empty rows are not cleared on Windows */ gtk_widget_queue_draw((GtkWidget *)clist); ld->update |= 3; listc_update((GtkWidget *)clist, ld); ld->lock = FALSE; } static void listc_column_button(GtkCList *clist, gint col, gpointer user_data) { listc_data *dt = user_data; int sort = *dt->sort; if (col < 0) col = abs(sort) - 1; /* Sort as is */ else if (abs(sort) == col + 1) sort = -sort; /* Reverse same column */ else /* Select another column */ { gtk_widget_hide(dt->sort_arrows[abs(sort) - 1]); gtk_widget_show(dt->sort_arrows[col]); sort = col + 1; } *dt->sort = sort; gtk_clist_set_sort_column(clist, col); gtk_clist_set_sort_type(clist, sort > 0 ? GTK_SORT_ASCENDING : GTK_SORT_DESCENDING); gtk_arrow_set(GTK_ARROW(dt->sort_arrows[col]), sort > 0 ? GTK_ARROW_DOWN : GTK_ARROW_UP, GTK_SHADOW_IN); /* Sort and maybe redraw */ dt->update |= listc_sort(clist, dt, TRUE); /* Scroll to selected row */ dt->update |= 2; listc_update((GtkWidget *)clist, dt); } static void listc_sort_by(GtkCList *clist, listc_data *ld, int n) { if (!*ld->sort) return; *ld->sort = n; listc_column_button(clist, -1, ld); } static void listc_prepare(GtkWidget *w, gpointer user_data) { listc_data *ld = user_data; GtkCList *clist = GTK_CLIST(w); int j; if (ld->kind == op_LISTCX) { /* Ensure enough space for pixmaps */ gtk_clist_set_row_height(clist, 0); if (clist->row_height < 16) gtk_clist_set_row_height(clist, 16); } /* Adjust width for columns which use sample text */ for (j = 0; j < ld->c.ncol; j++) { void **cp = ld->c.columns[j][1]; int op = (int)cp[0]; int l = WB_GETLEN(op); // !!! -2 for each extra ref if (l < 6) continue; l = gdk_string_width( #if GTK_MAJOR_VERSION == 1 w->style->font, #else /* if GTK_MAJOR_VERSION == 2 */ gtk_style_get_font(w->style), #endif cp[6]); if (clist->column[j].width < l) gtk_clist_set_column_width(clist, j, l); } /* To avoid repeating after unrealize (likely won't happen anyway) */ // gtk_signal_disconnect_by_func(GTK_OBJECT(w), // GTK_SIGNAL_FUNC(listc_prepare), user_data); } // !!! With inlining this, problem also likely GtkWidget *listc(void **r, char *ddata, col_data *c) { static int zero = 0; GtkWidget *list, *hbox; GtkCList *clist; listc_data *ld = r[2]; void **pp = r[1]; int *cntv, *sort = &zero, **map = NULL; int j, w, sm, kind, heads = 0; cntv = (void *)(ddata + (int)pp[2]); // length var kind = (int)pp[0] & WB_OPMASK; // kind of list if ((kind == op_LISTCS) || (kind == op_LISTCX)) { sort = (void *)(ddata + (int)pp[3]); // sort mode if (kind == op_LISTCX) map = (void *)(ddata + (int)pp[4]); // row map } list = gtk_clist_new(c->ncol); /* Fill datastruct */ ld->kind = kind; ld->idx = r[0]; ld->cnt = cntv; ld->sort = sort; ld->map = map; set_columns(&ld->c, c, ddata, r); sm = *sort; clist = GTK_CLIST(list); for (j = 0; j < ld->c.ncol; j++) { void **cp = ld->c.columns[j][1]; int op = (int)cp[0], jw = (int)cp[3]; int l = WB_GETLEN(op); // !!! -2 for each extra ref gtk_clist_set_column_resizeable(clist, j, kind == op_LISTCX); if ((w = jw & 0xFFFF)) { if (l > 4) w = inifile_get_gint32(cp[5], w); gtk_clist_set_column_width(clist, j, w); } /* Left justification is default */ jw = (jw >> 16) & 3; if (jw) gtk_clist_set_column_justification(clist, j, jw == 1 ? GTK_JUSTIFY_CENTER : GTK_JUSTIFY_RIGHT); hbox = gtk_hbox_new(FALSE, 0); (!jw ? pack : jw == 1 ? xpack : pack_end)(hbox, gtk_label_new((l > 3) && *(char *)cp[4] ? _(cp[4]) : "")); heads += l > 3; gtk_widget_show_all(hbox); // !!! Must be before gtk_clist_column_title_passive() gtk_clist_set_column_widget(clist, j, hbox); if (sm) ld->sort_arrows[j] = pack_end(hbox, gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_IN)); else gtk_clist_column_title_passive(clist, j); if (kind == op_LISTCX) GTK_WIDGET_UNSET_FLAGS( GTK_CLIST(clist)->column[j].button, GTK_CAN_FOCUS); } if (sm) { int c = abs(sm) - 1; gtk_widget_show(ld->sort_arrows[c]); // Show sort arrow gtk_clist_set_sort_column(clist, c); gtk_clist_set_sort_type(clist, sm > 0 ? GTK_SORT_ASCENDING : GTK_SORT_DESCENDING); gtk_arrow_set(GTK_ARROW(ld->sort_arrows[c]), sm > 0 ? GTK_ARROW_DOWN : GTK_ARROW_UP, GTK_SHADOW_IN); gtk_signal_connect(GTK_OBJECT(clist), "click_column", GTK_SIGNAL_FUNC(listc_column_button), ld); } if (sm || heads) gtk_clist_column_titles_show(clist); // Hide if useless gtk_clist_set_selection_mode(clist, GTK_SELECTION_BROWSE); if (kind == op_LISTCX) { #ifdef GTK_STOCK_DIRECTORY ld->icons[1] = render_stock_pixmap(main_window, GTK_STOCK_DIRECTORY, &ld->masks[1]); #endif #ifdef GTK_STOCK_FILE ld->icons[0] = render_stock_pixmap(main_window, GTK_STOCK_FILE, &ld->masks[0]); #endif if (!ld->icons[1]) ld->icons[1] = gdk_pixmap_create_from_xpm_d( main_window->window, &ld->masks[1], NULL, xpm_open_xpm); if (!ld->icons[0]) ld->icons[0] = gdk_pixmap_create_from_xpm_d( main_window->window, &ld->masks[0], NULL, xpm_new_xpm); gtk_signal_connect(GTK_OBJECT(clist), "key_press_event", GTK_SIGNAL_FUNC(listcx_key), ld); gtk_signal_connect(GTK_OBJECT(clist), "button_press_event", GTK_SIGNAL_FUNC(listcx_click), ld); } /* For some finishing touches */ gtk_signal_connect(GTK_OBJECT(clist), "realize", GTK_SIGNAL_FUNC(listc_prepare), ld); /* This will apply delayed updates when they can take effect */ gtk_signal_connect(GTK_OBJECT(clist), "map", GTK_SIGNAL_FUNC(listc_update), ld); if (*cntv) listc_reset(clist, ld); gtk_signal_connect(GTK_OBJECT(clist), "select_row", GTK_SIGNAL_FUNC(listc_select_row), ld); if (kind == op_LISTCd) clist_enable_drag(list); // draggable rows return (list); } #endif #ifndef U_LISTS_GTK1 static GQuark listc_key; /* Low 8 bits is column index, others denote type */ #define CELL_TEXT 0x000 #define CELL_FTEXT 0x100 #define CELL_ICON 0x200 #define CELL_TMASK 0xF00 #define CELL_XMASK 0x0FF static gboolean listcx_click(GtkWidget *widget, GdkEventButton *event, gpointer user_data) { listc_data *dt = user_data; GtkTreeView *tree = GTK_TREE_VIEW(widget); GtkTreePath *tp, *tp0; void **slot, **base, **desc; int row; if (dt->lock) return (FALSE); // Paranoia if ((event->button != 3) || (event->type != GDK_BUTTON_PRESS) || (event->window != gtk_tree_view_get_bin_window(tree)) || !gtk_tree_view_get_path_at_pos(tree, event->x, event->y, &tp, NULL, NULL, NULL)) return (FALSE); row = gtk_tree_path_get_indices(tp)[0]; gtk_tree_view_get_cursor(tree, &tp0, NULL); /* Move cursor to where the click was */ if (!tp0 || (row != gtk_tree_path_get_indices(tp0)[0])) gtk_tree_view_set_cursor_on_cell(tree, tp, NULL, NULL, FALSE); gtk_tree_path_free(tp0); gtk_tree_path_free(tp); slot = SLOT_N(dt->c.r, 2); base = slot[0]; desc = slot[1]; if (desc[1]) ((evtx_fn)desc[1])(GET_DDATA(base), base, (int)desc[0] & WB_OPMASK, slot, (void *)row); return (TRUE); } static void listcx_done(GtkTreeView *tree, listc_data *ld) { int j; /* Remember column widths */ for (j = 0; j < ld->c.ncol; j++) { void **cp = ld->c.columns[j][1]; int op = (int)cp[0]; int l = WB_GETLEN(op); // !!! -2 for each extra ref if (l > 4) inifile_set_gint32(cp[5], gtk_tree_view_column_get_width( gtk_tree_view_get_column(tree, j))); } } static void listcx_act(GtkTreeView *tree, GtkTreePath *tp, GtkTreeViewColumn *col, gpointer user_data) { listc_data *dt = user_data; if (dt->lock) return; // Paranoia if (dt->ok) get_evt_1(NULL, dt->ok); } static void listc_select_row(GtkTreeView *tree, gpointer user_data) { listc_data *dt = user_data; void **slot = NEXT_SLOT(dt->c.r), **base = slot[0], **desc = slot[1]; GtkTreeModel *tm; GtkTreePath *tp; GtkTreeIter it; gint row; if (dt->lock) return; /* Update the value */ gtk_tree_view_get_cursor(tree, &tp, NULL); tm = gtk_tree_view_get_model(tree); row = tp && gtk_tree_model_get_iter(tm, &it, tp); gtk_tree_path_free(tp); if (!row) return; // Paranoia gtk_tree_model_get(tm, &it, 0, &row, -1); *dt->idx = row; /* Call the handler */ if (desc[1]) ((evt_fn)desc[1])(GET_DDATA(base), base, (int)desc[0] & WB_OPMASK, slot); } static void listc_select_item(GtkTreeView *tree, int idx) { GtkTreePath *tp = gtk_tree_path_new_from_indices(idx, -1); gtk_tree_view_set_cursor_on_cell(tree, tp, NULL, NULL, FALSE); gtk_tree_view_scroll_to_cell(tree, tp, NULL, TRUE, 0.5, 0.0); gtk_tree_path_free(tp); } /* If no such index, return row 0 with its index */ static void listc_find_index(GtkTreeModel *tm, int idx, int *whatwhere) { GtkTreeIter it; int n = 0; gint pos; whatwhere[0] = whatwhere[1] = 0; if (!gtk_tree_model_get_iter_first(tm, &it)) return; gtk_tree_model_get(tm, &it, 0, &pos, -1); whatwhere[0] = pos; if (idx < 0) return; while (pos != idx) { if (!gtk_tree_model_iter_next(tm, &it)) return; gtk_tree_model_get(tm, &it, 0, &pos, -1); n++; } /* Found! */ whatwhere[0] = idx; whatwhere[1] = n; } static void listc_select_index(GtkTreeView *tree, int idx) { GtkTreeModel *tm = gtk_tree_view_get_model(tree); int whatwhere[2]; listc_find_index(tm, idx, whatwhere); listc_select_item(tree, whatwhere[1]); } static void listc_get_order(GtkTreeView *tree, int *res, int l) { GtkTreeModel *tm = gtk_tree_view_get_model(tree); GtkTreeIter it; int i, n = gtk_tree_model_iter_n_children(tm, NULL); gint pos; for (i = 0; i < l; i++) res[i] = -1; // nowhere by default if (l > n) l = n; if (!gtk_tree_model_get_iter_first(tm, &it)) return; for (i = 0; i < l; i++) { gtk_tree_model_get(tm, &it, 0, &pos, -1); res[pos] = i; if (!gtk_tree_model_iter_next(tm, &it)) return; } } static gint listc_sort_func(GtkTreeModel *tm, GtkTreeIter *a, GtkTreeIter *b, gpointer user_data) { listc_data *ld = user_data; char *v0, *v1; int n, dir, cell, sort = *ld->sort; gint row0, row1; sort += !sort; // Default is column 0 in ascending order dir = sort > 0 ? 1 : -1; cell = sort * dir - 1; gtk_tree_model_get(tm, a, 0, &row0, -1); gtk_tree_model_get(tm, b, 0, &row1, -1); v0 = get_cell(&ld->c, row0, cell); v1 = get_cell(&ld->c, row1, cell); n = strcmp(v0 ? v0 : "", v1 ? v1 : ""); // Better safe than sorry if (!n) n = row0 - row1; return (n * dir); } static int listc_sort(GtkTreeView *tree, listc_data *ld, int reselect) { GtkTreeModel *tm = gtk_tree_view_get_model(tree); GtkListStore *ls; GtkTreePath *tp; GtkTreeIter it; void **slot; int whatwhere[2]; int i, have_pos, cnt = *ld->cnt, *map = NULL; gint pos = 0; /* Do nothing if empty */ if (!cnt) return (0); ls = GTK_LIST_STORE(tm); /* Get current position if any */ gtk_tree_view_get_cursor(tree, &tp, NULL); if ((have_pos = tp && gtk_tree_model_get_iter(tm, &it, tp))) gtk_tree_model_get(tm, &it, 0, &pos, -1); gtk_tree_path_free(tp); /* Call & apply external sort */ if ((slot = ld->change)) { /* Call the EVT_CHANGE handler, to sort map vector */ get_evt_1(NULL, slot); /* Rearrange rows */ // !!! On unfreezed widget cnt = *ld->cnt; map = *ld->map; gtk_tree_model_get_iter_first(tm, &it); for (i = 0; i < cnt; i++) { gtk_list_store_set(ls, &it, 0, map[i], -1); gtk_tree_model_iter_next(tm, &it); } } /* Do builtin sort */ else { // Tell it it's unsorted, first gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(tm), GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID, GTK_SORT_ASCENDING); // Then set to sorted again; real sort order is in *ld->sort gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(tm), 1, GTK_SORT_ASCENDING); } /* Relocate existing position (visual update) */ if (reselect && have_pos) { listc_find_index(tm, pos, whatwhere); ld->lock++; listc_select_item(tree, whatwhere[1]); ld->lock--; } /* Set position anew */ else { listc_find_index(tm, *ld->idx, whatwhere); *ld->idx = whatwhere[0]; listc_select_item(tree, whatwhere[1]); } /* Done rearranging rows */ return (!!slot); } /* !!! This will brutally recalculate the entire list; may be slow if large */ static void listc_optimal_width(GtkTreeView *tree, listc_data *ld) { GtkTreeModel *tm = gtk_tree_view_get_model(tree); int i, j; #if GTK_MAJOR_VERSION == 3 /* !!! GTK+2 accounts for vertical separators, and resizes columns to fit * header buttons; GTK+3 does neither */ int hvis = gtk_tree_view_get_headers_visible(tree); gint vsep; gtk_widget_style_get(GTK_WIDGET(tree), "vertical-separator", &vsep, NULL); #endif for (j = 0; j < ld->c.ncol; j++) { GtkTreeViewColumn *col = gtk_tree_view_get_column(tree, j); GtkTreeIter it; gint width; gtk_tree_view_column_queue_resize(col); // Reset width if (!gtk_tree_model_get_iter_first(tm, &it)) continue; for (i = 0; i < 500; i++) // Stop early if overlarge { gtk_tree_view_column_cell_set_cell_data(col, tm, &it, FALSE, FALSE); gtk_tree_view_column_cell_get_size(col, NULL, NULL, NULL, &width, NULL); // It returns max of all if (!gtk_tree_model_iter_next(tm, &it)) break; } #if GTK_MAJOR_VERSION == 3 if (hvis) { GtkWidget *button = gtk_tree_view_column_get_button(col); if (button) { gint bw; gtk_widget_get_preferred_width(button, &bw, NULL); if (width < bw) width = bw; } } width += vsep; #endif gtk_tree_view_column_set_fixed_width(col, width); } } /* GtkTreeView here displays everything by reference, refill not needed */ #define listc_reset_row(A,B,C) gtk_widget_queue_draw(A) /* !!! Should not redraw old things while resetting - or at least, not refer * outside of new data if doing it */ static void listc_reset(GtkTreeView *tree, listc_data *ld) { GtkTreeModel *tm; int i, cnt = *ld->cnt, sort = *ld->sort; ld->lock = TRUE; tm = gtk_tree_view_get_model(tree); /* Rebuild the index vector, unless it surely stays the same */ if (!tm || (gtk_tree_model_iter_n_children(tm, NULL) != cnt) || (ld->kind == op_LISTCd) || ld->map) { GtkListStore *ls = gtk_list_store_new(1, G_TYPE_INT); GtkTreeIter it; int m, n, *map = ld->map ? *ld->map : NULL; for (m = i = 0; i < cnt; i++) { n = map ? map[i] : i; if (m < n) m = n; gtk_list_store_append(ls, &it); gtk_list_store_set(ls, &it, 0, n, -1); } tm = GTK_TREE_MODEL(ls); ld->cntmax = m; /* Let it sit there in case it's needed */ gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(ls), 1, listc_sort_func, ld, NULL); } gtk_tree_view_set_model(tree, tm); /* !!! Sort arrow gets lost after resetting model */ if (sort) { GtkTreeViewColumn *col = gtk_tree_view_get_column(tree, abs(sort) - 1); gtk_tree_view_column_set_sort_indicator(col, TRUE); // Show sort arrow } /* Adjust column widths (not for draggable list) */ if ((ld->kind != op_LISTCd) && (ld->kind != op_LISTCX)) { if (gtk_widget_get_mapped(GTK_WIDGET(tree))) listc_optimal_width(tree, ld); else ld->update |= 1; // Do it later } i = *ld->idx; if (i >= cnt) i = cnt - 1; if (!cnt) *ld->idx = 0; /* Safer than -1 for empty list */ /* Draggable and unordered lists aren't sorted */ else if ((ld->kind == op_LISTCd) || (ld->kind == op_LISTCu)) { if (i < 0) i = 0; listc_select_item(tree, i); *ld->idx = i; } else { *ld->idx = i; listc_sort(tree, ld, FALSE); } /* !!! Sometimes it shows the wrong part and redraw doesn't help */ gtk_adjustment_value_changed(gtk_tree_view_get_vadjustment(tree)); ld->lock = FALSE; } void listc_getcell(GtkTreeViewColumn *col, GtkCellRenderer *ren, GtkTreeModel *tm, GtkTreeIter *it, gpointer data) { listc_data *dt = g_object_get_qdata(G_OBJECT(ren), listc_key); char *s; int cell = (int)data; gint row; gtk_tree_model_get(tm, it, 0, &row, -1); s = get_cell(&dt->c, row, cell & CELL_XMASK); if (!s) s = "\0"; // NULL is used for empty cells in some places cell &= CELL_TMASK; /* TEXT/FTEXT */ if (cell != CELL_ICON) g_object_set(ren, "text", s + (cell == CELL_FTEXT), NULL); /* ICON */ else g_object_set(ren, "visible", s[0] != ' ', #if GTK_MAJOR_VERSION == 2 "stock-id", (s[0] == 'D' ? GTK_STOCK_DIRECTORY : GTK_STOCK_FILE), NULL); #else "icon-name", (s[0] == 'D' ? "folder" : "text-x-generic"), NULL); #endif } #if GTK_MAJOR_VERSION == 2 #define gtk_tree_view_column_get_button(A) ((A)->button) #endif /* Use of sort arrows should NOT cause sudden redirect of keyboard input */ static void listc_defocus(GObject *obj, GParamSpec *pspec, gpointer user_data) { GtkWidget *button = gtk_tree_view_column_get_button(GTK_TREE_VIEW_COLUMN(obj)); if (!button || !gtk_widget_get_can_focus(button)) return; gtk_widget_set_can_focus(button, FALSE); } static void listc_column_button(GtkTreeViewColumn *col, gpointer user_data) { listc_data *dt = g_object_get_qdata(G_OBJECT(col), listc_key); GtkTreeView *tree = GTK_TREE_VIEW(gtk_tree_view_column_get_tree_view(col)); int sort = *dt->sort, idx = (int)user_data; if (idx > CELL_XMASK); /* Sort as is */ else if (abs(sort) == idx + 1) sort = -sort; /* Reverse same column */ else /* Select another column */ { GtkTreeViewColumn *col0 = gtk_tree_view_get_column(tree, abs(sort) - 1); gtk_tree_view_column_set_sort_indicator(col0, FALSE); gtk_tree_view_column_set_sort_indicator(col, TRUE); sort = idx + 1; } *dt->sort = sort; gtk_tree_view_column_set_sort_order(col, sort > 0 ? GTK_SORT_ASCENDING : GTK_SORT_DESCENDING); /* Sort and maybe redraw */ listc_sort(tree, dt, TRUE); } static void listc_sort_by(GtkTreeView *tree, listc_data *ld, int n) { GtkTreeViewColumn *col; if (!*ld->sort) return; col = gtk_tree_view_get_column(tree, abs(*ld->sort) - 1); *ld->sort = n; listc_column_button(col, (gpointer)CELL_XMASK + 1); // Impossible index as flag } static void listc_update(GtkWidget *widget, gpointer user_data) { listc_data *ld = user_data; int what = ld->update; ld->update = 0; if (what & 1) listc_optimal_width(GTK_TREE_VIEW(widget), ld); } static void listc_prepare(GtkWidget *widget, gpointer user_data) { listc_data *ld = user_data; GtkTreeView *tree = GTK_TREE_VIEW(widget); PangoContext *context = gtk_widget_create_pango_context(widget); PangoLayout *layout = pango_layout_new(context); int j; for (j = 0; j < ld->c.ncol; j++) { void **cp = ld->c.columns[j][1]; int op = (int)cp[0]; int l = WB_GETLEN(op); // !!! -2 for each extra ref GtkTreeViewColumn *col = gtk_tree_view_get_column(tree, j); GtkWidget *button = gtk_tree_view_column_get_button(col); gint width, lw; /* Prevent sort buttons' narrowing down */ if (ld->kind == op_LISTCS) widget_set_keepsize(button, FALSE); /* Adjust width for columns which use sample text */ if (l < 6) continue; pango_layout_set_text(layout, cp[6], -1); pango_layout_get_pixel_size(layout, &lw, NULL); gtk_tree_view_column_cell_get_size(col, NULL, NULL, NULL, &width, NULL); if (width < lw) gtk_tree_view_column_set_fixed_width(col, lw); } g_object_unref(layout); g_object_unref(context); /* To avoid repeating after unrealize (likely won't happen anyway) */ // g_signal_handlers_disconnect_by_func(widget, listc_prepare, user_data); } #define LISTC_XPAD 2 GtkWidget *listc(void **r, char *ddata, col_data *c) { static int zero = 0; GtkWidget *w; GtkTreeView *tree; listc_data *ld = r[2]; void **pp = r[1]; int *cntv, *sort = &zero, **map = NULL; int j, sm, kind, heads = 0; listc_key = g_quark_from_static_string(LISTCC_KEY); cntv = (void *)(ddata + (int)pp[2]); // length var kind = (int)pp[0] & WB_OPMASK; // kind of list if ((kind == op_LISTCS) || (kind == op_LISTCX)) { sort = (void *)(ddata + (int)pp[3]); // sort mode if (kind == op_LISTCX) map = (void *)(ddata + (int)pp[4]); // row map } w = gtk_tree_view_new(); gtk_tree_view_set_enable_search(GTK_TREE_VIEW(w), FALSE); gtk_tree_selection_set_mode(gtk_tree_view_get_selection(GTK_TREE_VIEW(w)), GTK_SELECTION_BROWSE); /* Fill datastruct */ ld->kind = kind; ld->idx = r[0]; ld->cnt = cntv; ld->sort = sort; ld->map = map; set_columns(&ld->c, c, ddata, r); sm = *sort; tree = GTK_TREE_VIEW(w); for (j = 0; j < ld->c.ncol; j++) { GtkCellRenderer *ren; GtkTreeViewColumn *col = gtk_tree_view_column_new(); void **cp = ld->c.columns[j][1]; int op = (int)cp[0], jw = (int)cp[3]; int width, l = WB_GETLEN(op); // !!! -2 for each extra ref op &= WB_OPMASK; gtk_tree_view_column_set_resizable(col, kind == op_LISTCX); if (kind == op_LISTCX) gtk_tree_view_column_set_sizing(col, GTK_TREE_VIEW_COLUMN_FIXED); if ((width = jw & 0xFFFF)) { if (l > 4) width = inifile_get_gint32(cp[5], width); gtk_tree_view_column_set_fixed_width(col, width); } /* Left/center/right justification */ jw = (jw >> 16) & 3; gtk_tree_view_column_set_alignment(col, jw * 0.5); gtk_tree_view_column_set_title(col, (l > 3) && *(char *)cp[4] ? _(cp[4]) : ""); heads += l > 3; gtk_tree_view_column_set_expand(col, op == op_XTXTCOLUMN); if (sm) { g_signal_connect(col, "notify", G_CALLBACK(listc_defocus), NULL); g_signal_connect(col, "clicked", G_CALLBACK(listc_column_button), (gpointer)j); g_object_set_qdata(G_OBJECT(col), listc_key, ld); } if (op == op_FILECOLUMN) { ren = gtk_cell_renderer_pixbuf_new(); g_object_set(ren, "stock-size", GTK_ICON_SIZE_SMALL_TOOLBAR, "xpad", LISTC_XPAD, NULL); // g_object_set(col, "spacing", 2); // !!! If ever needed gtk_tree_view_column_pack_start(col, ren, FALSE); gtk_tree_view_column_set_cell_data_func(col, ren, listc_getcell, (gpointer)(CELL_ICON + j), NULL); g_object_set_qdata(G_OBJECT(ren), listc_key, ld); } ren = gtk_cell_renderer_text_new(); gtk_cell_renderer_set_alignment(ren, jw * 0.5, 0.5); g_object_set(ren, "xpad", LISTC_XPAD, NULL); gtk_tree_view_column_pack_start(col, ren, TRUE); gtk_tree_view_column_set_cell_data_func(col, ren, listc_getcell, (gpointer)((op == op_FILECOLUMN ? CELL_FTEXT : CELL_TEXT) + j), NULL); g_object_set_qdata(G_OBJECT(ren), listc_key, ld); gtk_tree_view_append_column(GTK_TREE_VIEW(w), col); } if (sm) { GtkTreeViewColumn *col = gtk_tree_view_get_column(tree, abs(sm) - 1); gtk_tree_view_column_set_sort_indicator(col, TRUE); // Show sort arrow gtk_tree_view_column_set_sort_order(col, sm > 0 ? GTK_SORT_ASCENDING : GTK_SORT_DESCENDING); gtk_tree_view_set_headers_clickable(tree, TRUE); } gtk_tree_view_set_headers_visible(tree, sm || heads); // Hide if useless if (kind == op_LISTCX) { g_signal_connect(w, "button_press_event", G_CALLBACK(listcx_click), ld); g_signal_connect(w, "row-activated", G_CALLBACK(listcx_act), ld); } /* For some finishing touches */ g_signal_connect(w, "realize", G_CALLBACK(listc_prepare), ld); /* This will apply delayed updates when they can take effect */ g_signal_connect(w, "map", G_CALLBACK(listc_update), ld); if (*cntv) listc_reset(tree, ld); g_signal_connect(w, "cursor_changed", G_CALLBACK(listc_select_row), ld); gtk_tree_view_set_reorderable(tree, kind == op_LISTCd); // draggable rows gtk_widget_show(w); /* !!! Need this for sizing-on-realize */ return (w); } #endif // uLISTC widget typedef struct { swdata s; col_data c; } lswdata; static int ulistc_reset(void **wdata) { lswdata *ld = wdata[2]; int l = *(int *)(ld->c.ddata + (int)GET_DESCV(wdata, 2)); int idx = *(int *)ld->s.strs; /* Constrain the index */ if (idx >= l) idx = l - 1; if (idx < 0) idx = 0; *(int *)ld->s.strs = idx; return (idx); } // PATH widget static void pathbox_button(GtkWidget *widget, gpointer user_data) { void **slot = user_data, **desc = slot[1]; void *xdata[2] = { _(desc[2]), slot }; // title and slot file_selector_x((int)desc[3], xdata); } // !!! With inlining this, problem also GtkWidget *pathbox(void **r, int border) { GtkWidget *hbox, *entry, *button; hbox = hbox_new(5 - 2); gtk_widget_show(hbox); gtk_container_set_border_width(GTK_CONTAINER(hbox), border); entry = xpack(hbox, gtk_entry_new()); button = pack(hbox, gtk_button_new_with_label(_("Browse"))); gtk_container_set_border_width(GTK_CONTAINER(button), 2); gtk_widget_show(button); gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(pathbox_button), r); return (entry); } /* Set value of path widget */ static void set_path(GtkWidget *widget, char *s, int mode) { char path[PATHTXT]; if (mode == PATH_VALUE) s = gtkuncpy(path, s, PATHTXT); gtk_entry_set_text(GTK_ENTRY(widget), s); } // SPINPACK widget #define TLSPINPACK_SIZE(P) (((int)(P)[2] * 2 + 1) * sizeof(void **)) static void spinpack_evt(GtkAdjustment *adj, gpointer user_data) { void **tp = user_data, **vp = *tp, **r = *vp; void **slot, **base, **desc; char *ddata; int *v, idx = (tp - vp) / 2 - 1; if (!r) return; // Lock /* Locate the data */ slot = NEXT_SLOT(r); base = slot[0]; ddata = GET_DDATA(base); /* Locate the cell in array */ desc = r[1]; v = desc[1]; if ((int)desc[0] & WB_FFLAG) v = (void *)(ddata + (int)v); v += idx * 3; /* Read the value */ *v = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(*(tp - 1))); /* Call the handler */ desc = slot[1]; if (desc[1]) ((evtx_fn)desc[1])(ddata, base, (int)desc[0] & WB_OPMASK, slot, (void *)idx); } // !!! With inlining this, problem also GtkWidget *tlspinpack(void **r, void **vp, GtkWidget *table, int wh) { GtkWidget *widget = NULL; void **tp = vp, **pp = r[1]; int row, column, i, l, n, *np = r[0]; n = (int)pp[2]; row = wh & 255; column = (wh >> 8) & 255; l = (wh >> 16) + 1; *tp++ = r; for (i = 0; i < n; i++ , np += 3) { int x = i % l, y = i / l; *tp++ = widget = add_a_spin(np[0], np[1], np[2]); /* Value might get clamped, and slot is self-reading so should * reflect that */ np[0] = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget)); spin_connect(widget, GTK_SIGNAL_FUNC(spinpack_evt), tp); // !!! Spacing = 2 gtk_table_attach(GTK_TABLE(table), widget, column + x, column + x + 1, row + y, row + y + 1, GTK_EXPAND | GTK_FILL, 0, 0, 2); *tp++ = vp; } return (widget); } // TLTEXT widget // !!! Even with inlining this, some space gets wasted void tltext(char *v, void **pp, GtkWidget *table, int pad) { GtkWidget *label; char *tmp, *s; int x, wh, row, column; tmp = s = strdup(v); wh = (int)pp[2]; row = wh & 255; x = column = (wh >> 8) & 255; while (TRUE) { int i = strcspn(tmp, "\t\n"); int c = tmp[i]; tmp[i] = '\0'; label = gtk_label_new(tmp); gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT); gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); gtk_widget_show(label); gtk_table_attach(GTK_TABLE(table), label, x, x + 1, row, row + 1, GTK_FILL, 0, pad, pad); x++; if (!c) break; if (c == '\n') x = column , row++; tmp += i + 1; } free(s); } // TOOLBAR widget /* !!! These pass the button slot, not event slot, as event source */ static void toolbar_lclick(GtkWidget *widget, gpointer user_data) { void **slot = user_data; void **base = slot[0], **desc = slot[1]; /* Ignore radio buttons getting depressed */ #if GTK_MAJOR_VERSION == 3 if (GTK_IS_RADIO_TOOL_BUTTON(widget) && !gtk_toggle_tool_button_get_active( GTK_TOGGLE_TOOL_BUTTON(widget))) return; slot = g_object_get_qdata(G_OBJECT(widget), tool_key); // if initialized #else /* #if GTK_MAJOR_VERSION <= 2 */ if (GTK_IS_RADIO_BUTTON(widget) && !GTK_TOGGLE_BUTTON(widget)->active) return; slot = gtk_object_get_user_data(GTK_OBJECT(widget)); // if initialized #endif if (slot) ((evt_fn)desc[1])(GET_DDATA(base), base, (int)desc[0] & WB_OPMASK, slot); } static gboolean toolbar_rclick(GtkWidget *widget, GdkEventButton *event, gpointer user_data) { void **slot = user_data; void **base = slot[0], **desc = slot[1]; /* Handle only right clicks */ if ((event->type != GDK_BUTTON_PRESS) || (event->button != 3)) return (FALSE); #if GTK_MAJOR_VERSION == 3 slot = g_object_get_qdata(G_OBJECT(widget), tool_key); // if initialized #else /* #if GTK_MAJOR_VERSION <= 2 */ slot = gtk_object_get_user_data(GTK_OBJECT(widget)); // if initialized #endif if (slot) ((evt_fn)desc[1])(GET_DDATA(base), base, (int)desc[0] & WB_OPMASK, slot); return (TRUE); } // SMARTTBAR widget #if GTK_MAJOR_VERSION == 3 /* This one handler, for keeping overflow menu untouchable */ static gboolean leave_be(GtkToolItem *tool_item, gpointer user_data) { return (TRUE); } #else /* #if GTK_MAJOR_VERSION <= 2 */ /* The following is main toolbars auto-sizing code. If toolbar is too long for * the window, some of its items get hidden, but remain accessible through an * "overflow box" - a popup with 5xN grid of buttons inside. This way, we can * support small-screen devices without penalizing large-screen ones. - WJ */ typedef struct { void **r, **r2; // slot and end-of-items slot GtkWidget *button, *tbar, *vport, *popup, *bbox; } smarttbar_data; #define WRAPBOX_W 5 static void wrapbox_size_req(GtkWidget *widget, GtkRequisition *req, gpointer user_data) { GtkBox *box = GTK_BOX(widget); GtkBoxChild *child; GList *chain; GtkRequisition wreq; int cnt, nr, w, h, l, spacing; cnt = w = h = spacing = 0; for (chain = box->children; chain; chain = chain->next) { child = chain->data; if (!GTK_WIDGET_VISIBLE(child->widget)) continue; gtk_widget_size_request(child->widget, &wreq); if (w < wreq.width) w = wreq.width; if (h < wreq.height) h = wreq.height; cnt++; } if (cnt) spacing = box->spacing; nr = (cnt + WRAPBOX_W - 1) / WRAPBOX_W; cnt = nr > 1 ? WRAPBOX_W : cnt; l = GTK_CONTAINER(widget)->border_width * 2 - spacing; req->width = (w + spacing) * cnt + l; req->height = (h + spacing) * nr + l; } static void wrapbox_size_alloc(GtkWidget *widget, GtkAllocation *alloc, gpointer user_data) { GtkBox *box = GTK_BOX(widget); GtkBoxChild *child; GList *chain; GtkRequisition wreq; GtkAllocation wall; int idx, cnt, nr, l, w, h, ww, wh, spacing; widget->allocation = *alloc; /* Count widgets */ cnt = w = h = 0; for (chain = box->children; chain; chain = chain->next) { child = chain->data; if (!GTK_WIDGET_VISIBLE(child->widget)) continue; gtk_widget_get_child_requisition(child->widget, &wreq); if (w < wreq.width) w = wreq.width; if (h < wreq.height) h = wreq.height; cnt++; } if (!cnt) return; // Nothing needs positioning in here nr = (cnt + WRAPBOX_W - 1) / WRAPBOX_W; cnt = nr > 1 ? WRAPBOX_W : cnt; /* Adjust sizes (homogeneous, shrinkable, no expand, no fill) */ l = GTK_CONTAINER(widget)->border_width; spacing = box->spacing; ww = alloc->width - l * 2 + spacing; wh = alloc->height - l * 2 + spacing; if ((w + spacing) * cnt > ww) w = ww / cnt - spacing; if (w < 1) w = 1; if ((h + spacing) * nr > wh) h = wh / nr - spacing; if (h < 1) h = 1; /* Now position the widgets */ wall.height = h; wall.width = w; idx = 0; for (chain = box->children; chain; chain = chain->next) { child = chain->data; if (!GTK_WIDGET_VISIBLE(child->widget)) continue; wall.x = alloc->x + l + (w + spacing) * (idx % WRAPBOX_W); wall.y = alloc->y + l + (h + spacing) * (idx / WRAPBOX_W); gtk_widget_size_allocate(child->widget, &wall); idx++; } } static int split_toolbar_at(GtkWidget *tbar, int w) { GList *chain; GtkToolbarChild *child; GtkAllocation *alloc; int border, x = 0; if (w < 1) w = 1; if (!tbar) return (w); border = GTK_CONTAINER(tbar)->border_width; for (chain = GTK_TOOLBAR(tbar)->children; chain; chain = chain->next) { child = chain->data; if (child->type == GTK_TOOLBAR_CHILD_SPACE) continue; if (!GTK_WIDGET_VISIBLE(child->widget)) continue; alloc = &child->widget->allocation; if (alloc->x < w) { if (alloc->x + alloc->width <= w) { x = alloc->x + alloc->width; continue; } w = alloc->x; } if (!x) return (1); // Nothing to see here return (x + border > w ? x : x + border); } return (w); // Toolbar is empty } static void htoolbox_size_req(GtkWidget *widget, GtkRequisition *req, gpointer user_data) { smarttbar_data *sd = user_data; GtkBox *box = GTK_BOX(widget); GtkBoxChild *child; GList *chain; GtkRequisition wreq; int cnt, w, h, l; cnt = w = h = 0; for (chain = box->children; chain; chain = chain->next) { child = chain->data; if (!GTK_WIDGET_VISIBLE(child->widget)) continue; gtk_widget_size_request(child->widget, &wreq); if (h < wreq.height) h = wreq.height; /* Button adds no extra width */ if (child->widget == sd->button) continue; w += wreq.width + child->padding * 2; cnt++; } if (cnt > 1) w += (cnt - 1) * box->spacing; l = GTK_CONTAINER(widget)->border_width * 2; req->width = w + l; req->height = h + l; } static void htoolbox_size_alloc(GtkWidget *widget, GtkAllocation *alloc, gpointer user_data) { smarttbar_data *sd = user_data; GtkBox *box = GTK_BOX(widget); GtkBoxChild *child; GList *chain; GtkRequisition wreq; GtkAllocation wall; int vw, bw, xw, dw, pad, spacing; int cnt, l, x, wrkw; widget->allocation = *alloc; /* Calculate required size */ cnt = 0; vw = bw = xw = 0; spacing = box->spacing; for (chain = box->children; chain; chain = chain->next) { GtkWidget *w; child = chain->data; pad = child->padding * 2; w = child->widget; if (w == sd->button) { gtk_widget_size_request(w, &wreq); bw = wreq.width + pad + spacing; // Button } else if (GTK_WIDGET_VISIBLE(w)) { gtk_widget_get_child_requisition(w, &wreq); if (w == sd->vport) vw = wreq.width; // Viewport else xw += wreq.width; // Extra widgets xw += pad; cnt++; } } if (cnt > 1) xw += (cnt - 1) * spacing; cnt -= !!vw; // Now this counts visible extra widgets l = GTK_CONTAINER(widget)->border_width; xw += l * 2; if (vw && (xw + vw > alloc->width)) /* If viewport doesn't fit */ vw = split_toolbar_at(sd->tbar, alloc->width - xw - bw); else bw = 0; /* Calculate how much to reduce extra widgets' sizes */ dw = 0; if (cnt) dw = (xw + bw + vw - alloc->width + cnt - 1) / cnt; if (dw < 0) dw = 0; /* Now position the widgets */ x = alloc->x + l; wall.y = alloc->y + l; wall.height = alloc->height - l * 2; if (wall.height < 1) wall.height = 1; for (chain = box->children; chain; chain = chain->next) { GtkWidget *w; child = chain->data; pad = child->padding; w = child->widget; /* Button uses size, the others, visibility */ if (w == sd->button ? !bw : !GTK_WIDGET_VISIBLE(w)) continue; gtk_widget_get_child_requisition(w, &wreq); wrkw = w == sd->vport ? vw : w == sd->button ? wreq.width : wreq.width - dw; if (wrkw < 1) wrkw = 1; wall.width = wrkw; x = (wall.x = x + pad) + wrkw + pad + spacing; gtk_widget_size_allocate(w, &wall); } if (sd->button) widget_showhide(sd->button, bw); } static void htoolbox_popup(GtkWidget *button, gpointer user_data) { smarttbar_data *sd = user_data; GtkWidget *popup = sd->popup; GtkAllocation *alloc = &button->allocation; GtkRequisition req; GtkBox *box; GtkBoxChild *child; GList *chain; gint x, y, w, h, vl; /* Pre-grab; use an already visible widget */ if (!do_grab(GRAB_PROGRAM, button, NULL)) return; /* Position the popup */ #if GTK2VERSION >= 2 /* GTK+ 2.2+ */ { GdkScreen *screen = gtk_widget_get_screen(button); w = gdk_screen_get_width(screen); h = gdk_screen_get_height(screen); /* !!! To have styles while unrealized, need at least this */ gtk_window_set_screen(GTK_WINDOW(popup), screen); } #else w = gdk_screen_width(); h = gdk_screen_height(); #endif vl = sd->vport->allocation.width; box = GTK_BOX(sd->bbox); for (chain = box->children; chain; chain = chain->next) { GtkWidget *btn, *tool; void **slot; child = chain->data; btn = child->widget; slot = gtk_object_get_user_data(GTK_OBJECT(btn)); if (!slot) continue; // Paranoia tool = slot[0]; /* Copy button relief setting of toolbar buttons */ gtk_button_set_relief(GTK_BUTTON(btn), gtk_button_get_relief(GTK_BUTTON(tool))); /* Copy their sensitivity */ gtk_widget_set_sensitive(GTK_WIDGET(btn), GTK_WIDGET_SENSITIVE(GTK_WIDGET(tool))); /* Copy their state (feedback is disabled while invisible) */ if (GTK_IS_TOGGLE_BUTTON(btn)) gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(btn), GTK_TOGGLE_BUTTON(tool)->active); // gtk_widget_set_style(btn, gtk_rc_get_style(tool)); /* Set visibility */ widget_showhide(btn, GTK_WIDGET_VISIBLE(tool) && (tool->allocation.x >= vl)); } gtk_widget_size_request(popup, &req); gdk_window_get_origin(GTK_WIDGET(sd->r[0])->window, &x, &y); x += alloc->x + (alloc->width - req.width) / 2; y += alloc->y + alloc->height; if (x + req.width > w) x = w - req.width; if (x < 0) x = 0; if (y + req.height > h) y -= alloc->height + req.height; if (y + req.height > h) y = h - req.height; if (y < 0) y = 0; #if GTK_MAJOR_VERSION == 1 gtk_widget_realize(popup); gtk_window_reposition(GTK_WINDOW(popup), x, y); #else /* #if GTK_MAJOR_VERSION == 2 */ gtk_window_move(GTK_WINDOW(popup), x, y); #endif /* Actually popup it */ gtk_widget_show(popup); gtk_window_set_focus(GTK_WINDOW(popup), NULL); // Nothing is focused gdk_flush(); // !!! To accept grabs, window must be actually mapped /* Transfer grab to it */ do_grab(GRAB_WIDGET, popup, NULL); } static void htoolbox_popdown(GtkWidget *widget) { undo_grab(widget); gtk_widget_hide(widget); } static void htoolbox_unrealize(GtkWidget *widget, gpointer user_data) { GtkWidget *popup = user_data; if (GTK_WIDGET_VISIBLE(popup)) htoolbox_popdown(popup); gtk_widget_unrealize(popup); } static gboolean htoolbox_popup_key(GtkWidget *widget, GdkEventKey *event, gpointer user_data) { if ((event->keyval != GDK_Escape) || (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK | GDK_MOD1_MASK))) return (FALSE); htoolbox_popdown(widget); return (TRUE); } static gboolean htoolbox_popup_click(GtkWidget *widget, GdkEventButton *event, gpointer user_data) { GtkWidget *ev = gtk_get_event_widget((GdkEvent *)event); /* Clicks on popup's descendants are OK; otherwise, remove the popup */ if (ev != widget) { while (ev) { ev = ev->parent; if (ev == widget) return (FALSE); } } htoolbox_popdown(widget); return (TRUE); } static void htoolbox_tool_clicked(GtkWidget *button, gpointer user_data) { smarttbar_data *sd = user_data; void **slot; /* Invisible buttons don't send (virtual) clicks to toolbar */ if (!GTK_WIDGET_VISIBLE(sd->popup)) return; /* Ignore radio buttons getting depressed */ if (GTK_IS_RADIO_BUTTON(button) && !GTK_TOGGLE_BUTTON(button)->active) return; htoolbox_popdown(sd->popup); slot = gtk_object_get_user_data(GTK_OBJECT(button)); gtk_button_clicked(GTK_BUTTON(slot[0])); } static gboolean htoolbox_tool_rclick(GtkWidget *widget, GdkEventButton *event, gpointer user_data) { smarttbar_data *sd = user_data; void **slot; /* Handle only right clicks */ if ((event->type != GDK_BUTTON_PRESS) || (event->button != 3)) return (FALSE); htoolbox_popdown(sd->popup); slot = gtk_object_get_user_data(GTK_OBJECT(widget)); return (toolbar_rclick(slot[0], event, SLOT_N(sd->r, 2))); } // !!! With inlining this, problem also GtkWidget *smarttbar_button(smarttbar_data *sd, char *v) { GtkWidget *box = sd->r[0], *ritem = NULL; GtkWidget *button, *arrow, *popup, *ebox, *frame, *bbox, *item; void **slot, *rvar = MEM_NONE; sd->button = button = pack(box, gtk_button_new()); #if GTK_MAJOR_VERSION == 1 // !!! Arrow w/o shadow is invisible in plain GTK+1 arrow = gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_OUT); #else /* #if GTK_MAJOR_VERSION == 2 */ arrow = gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_NONE); #endif gtk_widget_show(arrow); gtk_container_add(GTK_CONTAINER(button), arrow); #if GTK2VERSION >= 4 /* GTK+ 2.4+ */ gtk_button_set_focus_on_click(GTK_BUTTON(button), FALSE); #endif if (v) gtk_tooltips_set_tip(GTK_TOOLBAR(sd->tbar)->tooltips, button, _(v), "Private"); sd->popup = popup = gtk_window_new(GTK_WINDOW_POPUP); gtk_window_set_policy(GTK_WINDOW(popup), FALSE, FALSE, TRUE); #if GTK2VERSION >= 10 /* GTK+ 2.10+ */ gtk_window_set_type_hint(GTK_WINDOW(popup), GDK_WINDOW_TYPE_HINT_COMBO); #endif gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(htoolbox_popup), sd); gtk_signal_connect(GTK_OBJECT(box), "unrealize", GTK_SIGNAL_FUNC(htoolbox_unrealize), popup); gtk_signal_connect_object(GTK_OBJECT(box), "destroy", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(popup)); /* Eventbox covers the popup, and popup has a grab; then, all clicks * inside the popup get its descendant as event widget; anything else, * including popup window itself, means click was outside, and triggers * popdown (solution from GtkCombo) - WJ */ ebox = gtk_event_box_new(); gtk_container_add(GTK_CONTAINER(popup), ebox); frame = gtk_frame_new(NULL); gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_OUT); gtk_container_add(GTK_CONTAINER(ebox), frame); sd->bbox = bbox = wj_size_box(); gtk_signal_connect(GTK_OBJECT(bbox), "size_request", GTK_SIGNAL_FUNC(wrapbox_size_req), NULL); gtk_signal_connect(GTK_OBJECT(bbox), "size_allocate", GTK_SIGNAL_FUNC(wrapbox_size_alloc), NULL); gtk_container_add(GTK_CONTAINER(frame), bbox); gtk_widget_show_all(ebox); gtk_signal_connect(GTK_OBJECT(popup), "key_press_event", GTK_SIGNAL_FUNC(htoolbox_popup_key), NULL); gtk_signal_connect(GTK_OBJECT(popup), "button_press_event", GTK_SIGNAL_FUNC(htoolbox_popup_click), NULL); for (slot = sd->r; slot - sd->r2 < 0; slot = NEXT_SLOT(slot)) { void **desc = slot[1]; int l, op = (int)desc[0]; l = WB_GETLEN(op); op &= WB_OPMASK; if (op == op_TBBUTTON) item = gtk_button_new(); else if (op == op_TBTOGGLE) item = gtk_toggle_button_new(); else if (op == op_TBRBUTTON) { ritem = item = gtk_radio_button_new_from_widget( rvar != desc[1] ? NULL : GTK_RADIO_BUTTON(ritem)); rvar = desc[1]; /* !!! Flags are ignored; can XOR desc[0]'s to compare * them too, but false match improbable anyway - WJ */ gtk_toggle_button_set_mode(GTK_TOGGLE_BUTTON(item), FALSE); } else continue; // Not a regular toolbar button #if GTK2VERSION >= 4 /* GTK+ 2.4+ */ gtk_button_set_focus_on_click(GTK_BUTTON(item), FALSE); #endif gtk_container_add(GTK_CONTAINER(item), xpm_image(desc[4])); pack(bbox, item); gtk_tooltips_set_tip(GTK_TOOLBAR(sd->tbar)->tooltips, item, _(desc[3]), "Private"); gtk_object_set_user_data(GTK_OBJECT(item), slot); gtk_signal_connect(GTK_OBJECT(item), "clicked", GTK_SIGNAL_FUNC(htoolbox_tool_clicked), sd); if (l > 4) gtk_signal_connect(GTK_OBJECT(item), "button_press_event", GTK_SIGNAL_FUNC(htoolbox_tool_rclick), sd); } return (button); } // TWOBOX widget #define TWOBAR_KEY "mtPaint.twobar" static void twobar_size_req(GtkWidget *widget, GtkRequisition *req, gpointer user_data) { GtkBox *box = GTK_BOX(widget); GtkBoxChild *child; GtkRequisition wreq1, wreq2; int l; wreq1.width = wreq1.height = 0; wreq2 = wreq1; if (box->children) { child = box->children->data; if (GTK_WIDGET_VISIBLE(child->widget)) gtk_widget_size_request(child->widget, &wreq1); if (box->children->next) { child = box->children->next->data; if (GTK_WIDGET_VISIBLE(child->widget)) gtk_widget_size_request(child->widget, &wreq2); } } l = box->spacing; /* One or none */ if (!wreq2.width); else if (!wreq1.width) wreq1 = wreq2; /* Two in one row */ else if (gtk_object_get_data(GTK_OBJECT(widget), TWOBAR_KEY)) { wreq1.width += wreq2.width + l; if (wreq1.height < wreq2.height) wreq1.height = wreq2.height; } /* Two rows (default) */ else { wreq1.height += wreq2.height + l; if (wreq1.width < wreq2.width) wreq1.width = wreq2.width; } /* !!! Children' padding is ignored (it isn't used anyway) */ l = GTK_CONTAINER(widget)->border_width * 2; #if GTK_MAJOR_VERSION == 1 /* !!! GTK+1 doesn't want to reallocate upper-level containers when * something on lower level gets downsized */ if (widget->requisition.height > wreq1.height + l) force_resize(widget); #endif req->width = wreq1.width + l; req->height = wreq1.height + l; } static void twobar_size_alloc(GtkWidget *widget, GtkAllocation *alloc, gpointer user_data) { GtkBox *box = GTK_BOX(widget); GtkBoxChild *child, *child2 = NULL; GtkRequisition wreq1, wreq2; GtkAllocation wall; int l, h, w2, ww, wh, bar, oldbar; widget->allocation = *alloc; if (!box->children) return; // Empty child = box->children->data; if (box->children->next) { child2 = box->children->next->data; if (!GTK_WIDGET_VISIBLE(child2->widget)) child2 = NULL; } if (!GTK_WIDGET_VISIBLE(child->widget)) child = child2 , child2 = NULL; if (!child) return; l = GTK_CONTAINER(widget)->border_width; wall.x = alloc->x + l; wall.y = alloc->y + l; l *= 2; ww = alloc->width - l; if (ww < 1) ww = 1; wall.width = ww; wh = alloc->height - l; if (wh < 1) wh = 1; wall.height = wh; if (!child2) /* Place one, and be done */ { gtk_widget_size_allocate(child->widget, &wall); return; } /* Need to arrange two */ gtk_widget_get_child_requisition(child->widget, &wreq1); gtk_widget_get_child_requisition(child2->widget, &wreq2); l = box->spacing; w2 = wreq1.width + wreq2.width + l; h = wreq1.height; if (h < wreq2.height) h = wreq2.height; bar = w2 <= ww; /* Can do one row */ if (bar) { if (wall.height > h) wall.height = h; l += (wall.width = wreq1.width); gtk_widget_size_allocate(child->widget, &wall); wall.x += l; wall.width = ww - l; } else /* Two rows */ { l += (wall.height = wreq1.height); gtk_widget_size_allocate(child->widget, &wall); wall.y += l; wall.height = wh - l; if (wall.height < 1) wall.height = 1; } gtk_widget_size_allocate(child2->widget, &wall); oldbar = (int)gtk_object_get_data(GTK_OBJECT(widget), TWOBAR_KEY); if (bar != oldbar) /* Shape change */ { gtk_object_set_data(GTK_OBJECT(widget), TWOBAR_KEY, (gpointer)bar); /* !!! GTK+1 doesn't handle requeued resizes properly */ #if GTK_MAJOR_VERSION == 1 force_resize(widget); #else gtk_widget_queue_resize(widget); #endif } } #endif /* GTK+1&2 */ // MENUBAR widget /* !!! This passes the item slot, not event slot, as event source */ static void menu_evt(GtkWidget *widget, gpointer user_data) { void **slot = user_data; void **base = slot[0], **desc = slot[1]; /* Ignore radio buttons getting depressed */ #if GTK_MAJOR_VERSION == 3 if (GTK_IS_RADIO_MENU_ITEM(widget) && !gtk_check_menu_item_get_active( GTK_CHECK_MENU_ITEM(widget))) return; slot = g_object_get_qdata(G_OBJECT(widget), tool_key); // if initialized #else /* #if GTK_MAJOR_VERSION <= 2 */ if (GTK_IS_RADIO_MENU_ITEM(widget) && !GTK_CHECK_MENU_ITEM(widget)->active) return; slot = gtk_object_get_user_data(GTK_OBJECT(widget)); #endif ((evt_fn)desc[1])(GET_DDATA(base), base, (int)desc[0] & WB_OPMASK, slot); } #if (GTK_MAJOR_VERSION == 3) || (GTK2VERSION >= 4) /* Not needed before GTK+ 2.4 */ /* Ignore shortcut key only when item itself is insensitive or hidden */ static gboolean menu_allow_key(GtkWidget *widget, guint signal_id, gpointer user_data) { return (GTK_WIDGET_IS_SENSITIVE(widget) && GTK_WIDGET_VISIBLE(widget)); } #endif // SMARTMENU widget /* The following is main menu auto-rearrange code. If the menu is too long for * the window, some of its items are moved into "overflow" submenu - and moved * back to menubar when the window is made wider. This way, we can support * small-screen devices without penalizing large-screen ones. - WJ */ #define MENU_RESIZE_MAX 16 typedef struct { void **slot; GtkWidget *fallback; guint key; int width; } r_menu_slot; typedef struct { void **r; // own slot GtkWidget *mbar; int r_menu_state; int in_alloc; r_menu_slot r_menu[MENU_RESIZE_MAX]; } smartmenu_data; /* Handle keyboard accels for overflow menu */ static int check_smart_menu_keys(void *sdata, GdkEventKey *event) { smartmenu_data *sd = sdata; r_menu_slot *slot; guint lowkey; int l = sd->r_menu_state; /* No overflow - nothing to do */ if (!l) return (FALSE); /* Menu hidden - do nothing */ if (!GTK_WIDGET_VISIBLE(sd->r[0])) return (FALSE); /* Alt+key only */ if ((event->state & _CSAmask) != _Amask) return (FALSE); lowkey = low_key(event); for (slot = sd->r_menu + 1; slot->key != lowkey; slot++) if (--l <= 0) return (FALSE); // No such key in overflow /* Just popup - if we're here, overflow menu is offscreen anyway */ gtk_menu_popup(GTK_MENU(gtk_menu_item_get_submenu(GTK_MENU_ITEM(slot->fallback))), NULL, NULL, NULL, NULL, 0, 0); return (TRUE); } #if GTK_MAJOR_VERSION <= 2 /* !!! FOR NOW */ /* Invalidate width cache after width-affecting change */ static void check_width_cache(smartmenu_data *sd, int width) { r_menu_slot *slot, *sm = sd->r_menu + sd->r_menu_state; if (sm->width == width) return; if (sm->width) for (slot = sd->r_menu; slot->slot; slot++) slot->width = 0; sm->width = width; } /* Show/hide widgets according to new state */ static void change_to_state(smartmenu_data *sd, int state) { GtkWidget *w; r_menu_slot *r_menu = sd->r_menu; int i, oldst = sd->r_menu_state; if (oldst < state) { for (i = oldst + 1; i <= state; i++) gtk_widget_hide(r_menu[i].slot[0]); if (oldst == 0) { w = r_menu[0].slot[0]; gtk_widget_set_state(w, GTK_STATE_NORMAL); gtk_widget_show(w); } } else { for (i = oldst; i > state; i--) { w = r_menu[i].slot[0]; gtk_widget_set_state(w, GTK_STATE_NORMAL); gtk_widget_show(w); } if (state == 0) gtk_widget_hide(r_menu[0].slot[0]); } sd->r_menu_state = state; } /* Move submenus between menubar and overflow submenu */ static void switch_states(smartmenu_data *sd, int newstate, int oldstate) { r_menu_slot *r_menu = sd->r_menu; GtkWidget *submenu; GtkMenuItem *item; int i; if (newstate < oldstate) /* To main menu */ { for (i = oldstate; i > newstate; i--) { gtk_widget_hide(r_menu[i].fallback); item = GTK_MENU_ITEM(r_menu[i].fallback); gtk_widget_ref(submenu = item->submenu); gtk_menu_item_remove_submenu(item); item = GTK_MENU_ITEM(r_menu[i].slot[0]); gtk_menu_item_set_submenu(item, submenu); gtk_widget_unref(submenu); } } else /* To overflow submenu */ { for (i = oldstate + 1; i <= newstate; i++) { item = GTK_MENU_ITEM(r_menu[i].slot[0]); gtk_widget_ref(submenu = item->submenu); gtk_menu_item_remove_submenu(item); item = GTK_MENU_ITEM(r_menu[i].fallback); gtk_menu_item_set_submenu(item, submenu); gtk_widget_unref(submenu); gtk_widget_show(r_menu[i].fallback); } } } /* Get width request for default state */ static int smart_menu_full_width(smartmenu_data *sd, GtkWidget *widget, int width) { check_width_cache(sd, width); if (!sd->r_menu[0].width) { GtkRequisition req; GtkWidget *child = sd->mbar; /* aka BOX_CHILD_0(widget) */ int oldst = sd->r_menu_state; gpointer lock = toggle_updates(widget, NULL); change_to_state(sd, 0); gtk_widget_size_request(child, &req); sd->r_menu[0].width = req.width; change_to_state(sd, oldst); child->requisition.width = width; toggle_updates(widget, lock); } return (sd->r_menu[0].width); } /* Switch to the state which best fits the allocated width */ static void smart_menu_state_to_width(smartmenu_data *sd, GtkWidget *widget, int rwidth, int awidth) { r_menu_slot *slot; GtkWidget *child = BOX_CHILD_0(widget); gpointer lock = NULL; int state, oldst, newst; check_width_cache(sd, rwidth); state = oldst = sd->r_menu_state; while (TRUE) { newst = rwidth < awidth ? state - 1 : state + 1; slot = sd->r_menu + newst; if ((newst < 0) || !slot->slot) break; if (!slot->width) { GtkRequisition req; if (!lock) lock = toggle_updates(widget, NULL); change_to_state(sd, newst); gtk_widget_size_request(child, &req); slot->width = req.width; } state = newst; if ((rwidth < awidth) ^ (slot->width <= awidth)) break; } while ((sd->r_menu[state].width > awidth) && sd->r_menu[state + 1].slot) state++; if (state != sd->r_menu_state) { if (!lock) lock = toggle_updates(widget, NULL); change_to_state(sd, state); child->requisition.width = sd->r_menu[state].width; } if (state != oldst) switch_states(sd, state, oldst); if (lock) toggle_updates(widget, lock); } static void smart_menu_size_req(GtkWidget *widget, GtkRequisition *req, gpointer user_data) { smartmenu_data *sd = user_data; GtkRequisition child_req; GtkWidget *child; int fullw; req->width = req->height = GTK_CONTAINER(widget)->border_width * 2; if (!GTK_BOX(widget)->children) return; child = BOX_CHILD_0(widget); if (!GTK_WIDGET_VISIBLE(child)) return; gtk_widget_size_request(child, &child_req); fullw = smart_menu_full_width(sd, widget, child_req.width); req->width += fullw; req->height += child_req.height; } static void smart_menu_size_alloc(GtkWidget *widget, GtkAllocation *alloc, gpointer user_data) { smartmenu_data *sd = user_data; GtkRequisition child_req; GtkAllocation child_alloc; GtkWidget *child; int border = GTK_CONTAINER(widget)->border_width, border2 = border * 2; widget->allocation = *alloc; if (!GTK_BOX(widget)->children) return; child = BOX_CHILD_0(widget); if (!GTK_WIDGET_VISIBLE(child)) return; /* Maybe recursive calls to this cannot happen, but if they can, * crash would be quite spectacular - so, better safe than sorry */ if (sd->in_alloc) /* Postpone reaction */ { sd->in_alloc |= 2; return; } /* !!! Always keep child widget requisition set according to its * !!! mode, or this code will break down in interesting ways */ gtk_widget_get_child_requisition(child, &child_req); /* !!! Alternative approach - reliable but slow */ // gtk_widget_size_request(child, &child_req); while (TRUE) { sd->in_alloc = 1; child_alloc.x = alloc->x + border; child_alloc.y = alloc->y + border; child_alloc.width = alloc->width > border2 ? alloc->width - border2 : 0; child_alloc.height = alloc->height > border2 ? alloc->height - border2 : 0; if ((child_alloc.width != child->allocation.width) && (sd->r_menu_state > 0 ? child_alloc.width != child_req.width : child_alloc.width < child_req.width)) smart_menu_state_to_width(sd, widget, child_req.width, child_alloc.width); if (sd->in_alloc < 2) break; alloc = &widget->allocation; } sd->in_alloc = 0; gtk_widget_size_allocate(child, &child_alloc); } #endif /* Fill smart menu structure */ // !!! With inlining this, problem also void *smartmenu_done(void **tbar, void **r) { #if GTK_MAJOR_VERSION == 3 GtkWidget *tl = gtk_label_new(""); char c, *ts, *src, *dest; #endif smartmenu_data *sd = tbar[2]; GtkWidget *parent, *item; void **rr; char *s; int i, l, n = 0; /* Find items */ for (rr = tbar; rr - r < 0; rr = NEXT_SLOT(rr)) { if (GET_OP(rr) != op_SSUBMENU) continue; sd->r_menu[n++].slot = rr; } /* Setup overflow submenu */ parent = gtk_menu_item_get_submenu(GTK_MENU_ITEM(sd->r_menu[--n].slot[0])); for (i = 0; i < n; i++) { sd->r_menu[i].fallback = item = gtk_menu_item_new_with_label(""); gtk_container_add(GTK_CONTAINER(parent), item); rr = sd->r_menu[i].slot[1]; l = strspn(s = rr[1], "/"); if (s[l]) s = _(s); // Translate s += l; #if GTK_MAJOR_VERSION == 3 /* Due to crippled API, cannot set & display a mnemonic without it * attaching in the regular way; need to strip them from items */ gtk_label_set_text_with_mnemonic(GTK_LABEL(tl), s); sd->r_menu[i].key = gtk_label_get_mnemonic_keyval(GTK_LABEL(tl)); ts = strdup(s); src = dest = ts; while (TRUE) { c = *src++; if (c != '_') *dest++ = c; if (!c) break; } gtk_label_set_text(GTK_LABEL(gtk_bin_get_child(GTK_BIN(item))), ts); free(ts); #else /* #if GTK_MAJOR_VERSION <= 2 */ sd->r_menu[i].key = gtk_label_parse_uline( GTK_LABEL(GTK_BIN(item)->child), s); #endif } for (i = 0; i <= n / 2; i++) // Swap ends { r_menu_slot tmp = sd->r_menu[i]; sd->r_menu[i] = sd->r_menu[n - i]; sd->r_menu[n - i] = tmp; } gtk_widget_hide(sd->r_menu[0].slot[0]); #if GTK_MAJOR_VERSION == 3 g_object_ref_sink(tl); g_object_unref(tl); #endif return (sd); } #if GTK_MAJOR_VERSION <= 2 /* Heightbar: increase own height to max height of invisible neighbors */ typedef struct { GtkWidget *self; GtkRequisition *req; } heightbar_data; static void heightbar_req(GtkWidget *widget, gpointer data) { heightbar_data *hd = data; GtkRequisition req; if (widget == hd->self) return; // Avoid recursion if (GTK_WIDGET_VISIBLE(widget)) return; // Let GTK+ handle it, for now gtk_widget_size_request(widget, &req); // Ask what invisible ones want if (req.height > hd->req->height) hd->req->height = req.height; } static void heightbar_size_req(GtkWidget *widget, GtkRequisition *req, gpointer user_data) { heightbar_data hd = { widget, req }; if (widget->parent) gtk_container_foreach(GTK_CONTAINER(widget->parent), (GtkCallback)heightbar_req, &hd); } #endif /* Get/set window position & size from/to inifile */ void rw_pos(v_dd *vdata, int set) { char name[128]; int i, l = strlen(vdata->ininame); memcpy(name, vdata->ininame, l); name[l++] = '_'; name[l + 1] = '\0'; for (i = 0; i < 5; i++) { name[l] = "xywhm"[i]; if (set) inifile_set_gint32(name, vdata->xywh[i]); else if (vdata->xywh[i] || (i < 2) || (i > 3)) // 0 means auto-size vdata->xywh[i] = inifile_get_gint32(name, vdata->xywh[i]); } } static GtkWidget *get_wrap(void **slot) { GtkWidget *w = slot[0]; int op = GET_OP(slot); if ((op == op_SPINSLIDE) || (op == op_SPINSLIDEa) || // (op == op_CANVASIMG) || (op == op_CANVASIMGB) || // Leave frame be (op == op_PATHs) || (op == op_PATH) || (op == op_TEXT)) w = gtk_widget_get_parent(w); return (w); } /* More specialized packing modes */ enum { pk_PACKEND1 = pk_LAST, pk_TABLE0p, pk_TABLEp, pk_SCROLLVP, pk_SCROLLVPv, pk_SCROLLVPm, pk_SCROLLVPn, pk_CONT, pk_BIN, pk_SHOW, /* No packing needed, just show the widget */ pk_UNREAL, /* Pseudo widget - no packing, just finish creation */ pk_UNREALV, /* Pseudo widget with int value */ }; #define pk_MASK 0xFF #define pkf_PARENT 0x100 #define pkf_CANVAS 0x200 /* Make code not compile where it cannot run */ typedef char Too_Many_Packing_Modes[2 * (pk_LAST <= WB_PKMASK + 1) - 1]; /* Packing modifiers */ typedef struct { int cw; int minw, minh; int maxw, maxh; int wantmax; } pkmods; /* Prepare widget for packing according to settings */ GtkWidget *do_prepare(GtkWidget *widget, int pk, pkmods *mods) { /* Show this */ if (pk) gtk_widget_show(widget); /* Unwrap this */ if (pk & pkf_PARENT) while (gtk_widget_get_parent(widget)) widget = gtk_widget_get_parent(widget); /* Border this */ if (mods->cw) gtk_container_set_border_width(GTK_CONTAINER(widget), mods->cw); #if GTK_MAJOR_VERSION == 3 /* Set fixed width/height for this */ /* !!! The call below does MINIMUM size; later, separate out the cases where UPPER * limit is desired, make a wrapper for that, and use maxw/maxh for them */ if ((mods->minw > 0) || (mods->minh > 0)) gtk_widget_set_size_request(widget, mods->minw > 0 ? mods->minw : -1, mods->minh > 0 ? mods->minh : -1); /* And/or min ones; this, GTK+3 can do naturally */ if ((mods->minw < 0) || (mods->minh < 0)) gtk_widget_set_size_request(widget, mods->minw < 0 ? -mods->minw : -1, mods->minh < 0 ? -mods->minh : -1); /* Make this scrolled window request max size */ if (mods->wantmax) { #if GTK3VERSION >= 22 /* Use the new functions */ if (!((mods->wantmax - 1) & 1)) gtk_scrolled_window_set_propagate_natural_width( GTK_SCROLLED_WINDOW(widget), TRUE); if (!((mods->wantmax - 1) & 2)) gtk_scrolled_window_set_propagate_natural_height( GTK_SCROLLED_WINDOW(widget), TRUE); #else /* Add a wrapper doing it */ GtkWidget *wrap = wjsizebin_new(G_CALLBACK(do_wantmax), NULL, (gpointer)(mods->wantmax - 1)); gtk_widget_show(wrap); gtk_container_add(GTK_CONTAINER(wrap), widget); widget = wrap; #endif } #else /* #if GTK_MAJOR_VERSION <= 2 */ /* Set fixed width/height for this */ if ((mods->minw > 0) || (mods->minh > 0)) gtk_widget_set_usize(widget, mods->minw > 0 ? mods->minw : -2, mods->minh > 0 ? mods->minh : -2); /* And/or min ones */ // !!! For now, always use wrapper if ((mods->minw < 0) || (mods->minh < 0)) widget = widget_align_minsize(widget, mods->minw < 0 ? -mods->minw : -2, mods->minh < 0 ? -mods->minh : -2); /* Make this scrolled window request max size */ if (mods->wantmax) gtk_signal_connect(GTK_OBJECT(widget), "size_request", GTK_SIGNAL_FUNC(scroll_max_size_req), (gpointer)(mods->wantmax - 1)); #endif return (widget); } /* Container stack */ typedef struct { void *widget; int group; // in inifile int type; // how to stuff things into it } ctslot; /* Types of containers */ enum { ct_NONE = 0, ct_BOX, ct_TABLE, ct_CONT, /* Generic container, like menubar and menu */ ct_BIN, ct_SCROLL, ct_TBAR, ct_NBOOK, ct_HVSPLIT, ct_SGROUP, ct_SMARTMENU, }; /* !!! Limited to rows & columns 0-255 per wh composition l16:col8:row8 */ static void table_it(ctslot *ct, GtkWidget *it, int wh, int pad, int pack) { int row = wh & 255, column = (wh >> 8) & 255, l = (wh >> 16) + 1; int r0 = (ct->type >> 8) & 255, r1 = ct->type >> 16; /* Track height of columns 0 & 1 in bytes 1 & 2 of type field */ if (!column && (r0 <= row)) r0 = row + 1; if ((column <= 1) && (column + l > 1) && (r1 <= row)) r1 = row + 1; ct->type = (r1 << 16) + (r0 << 8) + (ct->type & 255); gtk_table_attach(GTK_TABLE(ct->widget), it, column, column + l, row, row + 1, pack == pk_TABLEx ? GTK_EXPAND | GTK_FILL : GTK_FILL, 0, pack == pk_TABLEp ? pad : 0, pad); } /* Pack widget into container according to settings */ int do_pack(GtkWidget *widget, ctslot *ct, void **pp, int n, int tpad) { GtkScrolledWindow *sw; GtkAdjustment *adj = adj; GtkWidget *box = ct->widget; int what = ct->type & 255; int l = WB_GETLEN((int)pp[0]); #if GTK_MAJOR_VERSION == 3 /* Apply size group */ if (what == ct_SGROUP) { gtk_size_group_add_widget((GtkSizeGroup *)box, widget); /* Real container is above it */ ct++; box = ct->widget; what = ct->type & 255; } #endif /* Remember what & when goes into HVSPLIT */ if (what == ct_HVSPLIT) { hvsplit_data *hd = (void *)ct->widget; box = hd->box; if (hd->cnt < HVSPLIT_MAX) hd->inbox[hd->cnt++] = widget; } #if GTK_MAJOR_VERSION == 3 /* Protect canvas widgets from external painting-over, with CSS nodes * or without */ if ((n & pkf_CANVAS) && GTK_IS_SCROLLED_WINDOW(box)) css_restyle(box, (gtk3version >= 20 ? ".mtPaint_cscroll overshoot,.mtPaint_cscroll undershoot" " { background:none; }" : ".mtPaint_cscroll .overshoot,.mtPaint_cscroll .undershoot" " { background:none; }"), "mtPaint_cscroll", NULL); #endif n &= pk_MASK; // Strip flags /* Adapt packing mode to container type */ if (n <= pk_DEF) switch (what) { case ct_SMARTMENU: case ct_CONT: n = pk_CONT; break; case ct_BIN: n = pk_BIN; break; case ct_SCROLL: n = pk_SCROLLVP; break; } switch (n) { case pk_PACK: gtk_box_pack_start(GTK_BOX(box), widget, FALSE, FALSE, tpad); break; case pk_XPACK: case pk_EPACK: gtk_box_pack_start(GTK_BOX(box), widget, TRUE, n != pk_EPACK, tpad); break; case pk_PACKEND: case pk_PACKEND1: gtk_box_pack_end(GTK_BOX(box), widget, FALSE, FALSE, tpad); break; case pk_TABLE: case pk_TABLEx: case pk_TABLEp: table_it(ct, widget, (int)pp[l], tpad, n); break; case pk_TABLE0p: table_it(ct, widget, (ct->type >> 8) & 255, tpad, pk_TABLEp); break; case pk_TABLE1x: table_it(ct, widget, 0x100 + (ct->type >> 16), tpad, pk_TABLEx); break; case pk_SCROLLVP: case pk_SCROLLVPv: case pk_SCROLLVPm: case pk_SCROLLVPn: sw = GTK_SCROLLED_WINDOW(box); gtk_scrolled_window_add_with_viewport(sw, widget); #ifdef U_LISTS_GTK1 adj = gtk_scrolled_window_get_vadjustment(sw); if ((n == pk_SCROLLVPv) || (n == pk_SCROLLVPm)) gtk_container_set_focus_vadjustment(GTK_CONTAINER(widget), adj); if (n == pk_SCROLLVPm) { gtk_signal_connect(GTK_OBJECT(widget), "map", GTK_SIGNAL_FUNC(list_scroll_in), adj); } #endif if (n == pk_SCROLLVPn) { /* Set viewport to shadowless */ box = gtk_bin_get_child(GTK_BIN(box)); gtk_viewport_set_shadow_type(GTK_VIEWPORT(box), GTK_SHADOW_NONE); vport_noshadow_fix(box); } return (1); // unstack case pk_CONT: case pk_BIN: gtk_container_add(GTK_CONTAINER(box), widget); if (n == pk_BIN) return (1); // unstack break; } if (n == pk_PACKEND1) gtk_box_reorder_child(GTK_BOX(box), widget, 1); return (0); } /* Remap opcodes for script mode */ static int in_script(int op, char **script) { int r = WB_GETREF(op); op &= WB_OPMASK; /* No script - leave as is */ if (!script); /* Remap backend-dependent opcodes */ else if ((op < op_CTL_0) || (op >= op_CTL_LAST)) { int uop = cmds[op] ? cmds[op]->uop : 0; op = uop > 0 ? uop : uop < 0 ? op : r ? op_uOP : op_TRIGGER; } /* No need to connect event handlers in script mode - except DESTROY */ else if ((op != op_EVT_DESTROY) && (op >= op_EVT_0) && (op <= op_EVT_LAST)) op = op_TRIGGER; return (op); } typedef struct { int slots; // total slots int top; // total on-top allocation, in *void's int keys; // keymap slots int act; // ACTMAP slots } sizedata; /* Predict how many _void pointers_ a V-code sequence could need */ // !!! And with inlining this, same problem void predict_size(sizedata *sz, void **ifcode, char *ddata, char **script) { sizedata s; void **v, **pp, *rstack[CALL_DEPTH], **rp = rstack; int scripted = FALSE; int op, opf, ref, uop; memset(&s, 0, sizeof(s)); while (TRUE) { opf = op = (int)*ifcode++; ifcode = (pp = ifcode) + WB_GETLEN(op); s.slots += ref = WB_GETREF(op); op = in_script(op, script); if (op < op_END_LAST) break; // End // Livescript start/stop if (!script && (op == op_uOPNAME) && (opf & WB_SFLAG)) scripted = !ref; // Subroutine return if (op == op_RET) ifcode = *--rp; // Jump or subroutine call else if ((op == op_GOTO) || (op == op_CALL)) { if (op == op_CALL) *rp++ = ifcode; v = *pp; if (opf & WB_FFLAG) v = (void *)(ddata + (int)v); if (opf & WB_NFLAG) v = *v; // dereference ifcode = v; } // Keymap else if (op == op_KEYMAP) s.keys = 1; // Allocation else if (op == op_ACTMAP) s.act++; else { s.top += VVS((op == op_TALLOC) || (op == op_TCOPY) ? *(int *)(ddata + (int)pp[1]) : op == op_TLSPINPACK ? TLSPINPACK_SIZE(pp - 1) : cmds[op] ? cmds[op]->size : 0); /* Nothing else happens to unreferrable things, neither * to those that simulation ignores */ if (!ref || !cmds[op]) continue; uop = cmds[op]->uop; // Name for scripting if (scripted && (uop > 0)) { s.slots++; s.top += VVS(sizeof(swdata)); } // Slot in keymap if (s.keys && (((op >= op_uMENU_0) && (op < op_uMENU_LAST)) || ((uop >= op_uMENU_0) && (uop < op_uMENU_LAST)))) s.keys++; } } if (s.keys) s.top += VVS(KEYMAP_SIZE(s.keys)); s.top += s.act * ACT_SIZE; s.slots += 2; // safety margin *sz = s; } static cmdef cmddefs[] = { #if GTK_MAJOR_VERSION == 3 { op_CANVAS, sizeof(canvas_data) }, #endif { op_RGBIMAGE, sizeof(rgbimage_data) }, { op_RGBIMAGEP, sizeof(rgbimage_data) }, { op_CANVASIMG, sizeof(rgbimage_data) }, { op_CANVASIMGB, sizeof(rgbimage_data) }, { op_FCIMAGEP, sizeof(fcimage_data) }, { op_KEYBUTTON, sizeof(keybutton_data) }, { op_FONTSEL, sizeof(fontsel_data), op_uENTRY }, // !!! Beware - COLORLIST is self-reading and uOPTD is not { op_COLORLIST, sizeof(colorlist_data), op_uOPTD }, { op_COLORLISTN, sizeof(colorlist_data), op_uLISTCC }, { op_GRADBAR, sizeof(gradbar_data) }, { op_LISTCCr, sizeof(listcc_data), op_uLISTCC }, { op_LISTC, sizeof(listc_data), op_uLISTC }, { op_LISTCd, sizeof(listc_data), op_uLISTC }, { op_LISTCu, sizeof(listc_data) }, { op_LISTCS, sizeof(listc_data), op_uLISTC }, { op_LISTCX, sizeof(listc_data) }, { op_DOCK, sizeof(dock_data) }, { op_HVSPLIT, sizeof(hvsplit_data) }, #if GTK_MAJOR_VERSION <= 2 { op_SMARTTBAR, sizeof(smarttbar_data), op_uMENUBAR }, #endif { op_SMARTMENU, sizeof(smartmenu_data), op_uMENUBAR }, { op_DRAGDROP, sizeof(drag_ctx) }, /* In this, data slot points to dependent widget's wdata */ { op_MOUNT, 0, op_uMOUNT }, /* In these, data slot points to menu/toolbar slot */ { op_TBBUTTON, 0, op_uMENUITEM }, { op_TBTOGGLE, 0, op_uMENUCHECK }, { op_TBRBUTTON, 0, op_uMENURITEM }, { op_TBBOXTOG, 0, op_uMENUCHECK }, { op_MENUITEM, 0, op_uMENUITEM }, { op_MENUCHECK, 0, op_uMENUCHECK }, { op_MENURITEM, 0, op_uMENURITEM }, { op_WEND, 0, op_uWEND }, { op_WSHOW, 0, op_uWSHOW }, { op_MAINWINDOW, 0, op_uWINDOW }, { op_WINDOW, 0, op_uWINDOW }, { op_WINDOWm, 0, op_uWINDOW }, { op_FPICKpm, 0, op_uFPICK }, { op_TOPVBOX, 0, op_uTOPBOX }, { op_TOPVBOXV, 0, op_uTOPBOX }, { op_PAGE, 0, op_uFRAME }, { op_FRAME, 0, op_uFRAME }, { op_LABEL, 0, op_uLABEL }, { op_SPIN, 0, op_uSPIN }, { op_SPINc, 0, op_uSPIN }, { op_FSPIN, 0, op_uFSPIN }, { op_SPINa, 0, op_uSPINa }, { op_SPINSLIDE, 0, op_uSPIN }, { op_SPINSLIDEa, 0, op_uSPINa }, { op_CHECK, 0, op_uCHECK }, { op_CHECKb, 0, op_uCHECKb }, { op_RPACK, 0, op_uRPACK }, { op_RPACKD, 0, op_uRPACKD }, { op_OPT, 0, op_uOPT }, { op_OPTD, 0, op_uOPTD }, { op_COMBO, 0, op_uOPT }, { op_ENTRY, 0, op_uENTRY }, { op_MLENTRY, 0, op_uENTRY }, { op_COLOR, 0, op_uCOLOR }, // and various others between op_OPTD and op_OKBTN { op_OKBTN, 0, op_uOKBTN }, { op_BUTTON, 0, op_uBUTTON }, { op_TOOLBAR, 0, op_uMENUBAR }, { op_ACTMAP, 0, -1 }, { op_INSENS, 0, -1 }, { op_uWINDOW, sizeof(swdata), -1 }, { op_uFPICK, sizeof(swdata), -1 }, { op_uTOPBOX, sizeof(swdata), -1 }, { op_uOP, sizeof(swdata), -1 }, { op_uFRAME, sizeof(swdata), -1 }, { op_uLABEL, sizeof(swdata), -1 }, { op_uCHECK, sizeof(swdata), -1 }, { op_uCHECKb, sizeof(swdata), -1 }, { op_uSPIN, sizeof(swdata), -1 }, { op_uFSPIN, sizeof(swdata), -1 }, { op_uSPINa, sizeof(swdata), -1 }, { op_uSCALE, sizeof(swdata), -1 }, { op_uOPT, sizeof(swdata), -1 }, { op_uOPTD, sizeof(swdata), -1 }, { op_uRPACK, sizeof(swdata), -1 }, { op_uRPACKD, sizeof(swdata), -1 }, { op_uENTRY, sizeof(swdata), -1 }, { op_uPATHSTR, sizeof(swdata), -1 }, { op_uCOLOR, sizeof(swdata), -1 }, { op_uLISTCC, sizeof(swdata), -1 }, { op_uLISTC, sizeof(lswdata), -1 }, { op_uOKBTN, sizeof(swdata), -1 }, { op_uBUTTON, sizeof(swdata), -1 }, { op_uMENUBAR, sizeof(swdata), -1 }, { op_uMENUITEM, sizeof(swdata), -1 }, { op_uMENUCHECK, sizeof(swdata), -1 }, { op_uMENURITEM, sizeof(swdata), -1 }, { op_uMOUNT, sizeof(swdata), -1 }, { op_IDXCOLUMN, sizeof(swdata), -1 }, { op_TXTCOLUMN, sizeof(swdata), -1 }, { op_XTXTCOLUMN, sizeof(swdata), -1 }, { op_FILECOLUMN, sizeof(swdata), -1 }, { op_CHKCOLUMN, sizeof(swdata), -1 }, { op_uALTNAME, sizeof(swdata), -1 }, }; static void do_destroy(void **wdata); /* V-code is really simple-minded; it can do 0-tests but no arithmetics, and * naturally, can inline only constants. Everything else must be prepared either * in global variables, or in fields of "ddata" structure. * Parameters of codes should be arrayed in fixed order: * result location first; table location last; builtin event(s) before that */ #define DEF_BORDER 5 #define GET_BORDER(T) (borders[op_BOR_##T - op_BOR_0] + DEF_BORDER) /* Create a new slot */ #define PREP_SLOT(R,W,D,T) (R)[0] = (W) , (R)[1] = (D) , (R)[2] = (T) #define ADD_SLOT(R,W,D,T) PREP_SLOT(R, W, D, T) , (R) += VSLOT_SIZE /* Finalize a prepared slot */ #define FIX_SLOT(R,W) (R)[0] = (W) , (R) += VSLOT_SIZE /* Accessors for container stack */ #define CT_PUSH(SP,W,T) ((SP)-- , (SP)->widget = (W) , (SP)->type = (T) , \ (SP)->group = keygroup) #define CT_POP(SP) ((SP)++) #define CT_DROP(SP) (keygroup = ((SP)++)->group) #define CT_TOP(SP) ((SP)->widget) #define CT_N(SP,N) ((SP)[(N)].widget) #define CT_WHAT(SP) ((SP)->type & 255) #if GTK_MAJOR_VERSION == 3 static void free_wdata(void **wdata) { free(GET_DDATA(wdata)); } #endif void **run_create_(void **ifcode, void *ddata, int ddsize, char **script) { char *ident = VCODE_KEY; /* Avoid complex typecast - not initing GType in cmdline mode */ GtkWindow *tparent = (GtkWindow *)main_window; #if GTK_MAJOR_VERSION == 1 int have_sliders = FALSE; #endif int scripted = FALSE, part = FALSE, accel = 0; int borders[op_BOR_LAST - op_BOR_0], wpos = GTK_WIN_POS_CENTER; ctslot wstack[CONT_DEPTH], *wp = wstack + CONT_DEPTH; int keygroup = 0; keymap_data *keymap = NULL; GtkWidget *window = NULL, *widget = NULL; GtkAccelGroup* ag = NULL; v_dd *vdata; sizedata sz; col_data c; pkmods mods; void *rstack[CALL_DEPTH], **rp = rstack; void *v, **pp, **dtail, **r = NULL, **res = NULL, *sw = NULL; void **tbar = NULL, **rslot = NULL, *rvar = NULL; char *wid = NULL, *gid = NULL; int ld, dsize; int i, n, op, lp, ref, pk, cw, tpad, ct = 0; // Per-command allocations memset(cmds, 0, sizeof(cmds)); for (i = 0; i < sizeof(cmddefs) / sizeof(cmddefs[0]); i++) cmds[cmddefs[i].op] = cmddefs + i; // Allocation size predict_size(&sz, ifcode, ddata, script); ld = VVS(ddsize); n = VVS(sizeof(v_dd)); dsize = ld + n + ++sz.slots * VSLOT_SIZE + sz.top; if (!(res = calloc(dsize, sizeof(void *)))) return (NULL); // failed dtail = res + dsize; // Locate tail of block memcpy(res, ddata, ddsize); // Copy datastruct ddata = res; // And switch to using it vdata = (void *)(res += ld); // Locate where internal data go r = res += n; // Anchor after it vdata->code = WDONE; // Make internal datastruct a noop // Allocate actmap vdata->actmap = dtail -= sz.act * ACT_SIZE; // Store struct ref at anchor, use datastruct as tag for it ADD_SLOT(r, ddata, vdata, dtail); // Border sizes are DEF_BORDER-based memset(borders, 0, sizeof(borders)); // Column data memset(&c, 0, sizeof(c)); // Packing modifiers memset(&mods, 0, sizeof(mods)); if (!script) ag = gtk_accel_group_new(); while (TRUE) { op = (int)*ifcode; ifcode = (pp = ifcode) + 1 + (lp = WB_GETLEN(op)); pk = WB_GETPK(op); /* Table loc is outside the token proper */ { int p = pk & pk_MASK; // !!! To prevent GCC misoptimizing lp -= (p >= pk_TABLE) && (p <= pk_TABLEx); } v = lp > 0 ? pp[1] : NULL; if (op & WB_FFLAG) v = (void *)((char *)ddata + (int)v); if (op & WB_NFLAG) v = *(char **)v; // dereference a string ref = WB_GETREF(op); op = in_script(op, script); if (cmds[op]) dtail -= VVS(cmds[op]->size); /* Prepare slot, with data pointer in widget's place */ PREP_SLOT(r, v, pp, dtail); tpad = cw = 0; gid = NULL; switch (op) { /* Terminate */ case op_WEND: case op_WSHOW: case op_WDIALOG: /* Terminate the list */ ADD_SLOT(r, NULL, NULL, NULL); /* Apply keymap */ if (keymap) { keymap->ag = ag; keymap_init(keymap, NULL); accel |= 1; } /* !!! In GTK+1, doing it earlier makes any following * gtk_widget_add_accelerator() calls to silently fail */ if (accel > 1) gtk_accel_group_lock(ag); /* Add accel group, or drop it if unused */ if (!accel) gtk_accel_group_unref(ag); else gtk_window_add_accel_group(GTK_WINDOW(window), ag); /* !!! Freeing the datastruct is best to happen only when * all refs to underlying object are safely dropped */ #if GTK_MAJOR_VERSION == 3 /* !!! GObject's weakrefs trigger NOT on finalize, but on * dispose (the docs lie), so, use a finalizer on our * wdata value instead */ g_object_set_data_full(G_OBJECT(window), ident, (gpointer)res, (GDestroyNotify)free_wdata); #else /* if GTK_MAJOR_VERSION <= 2 */ /* GtkObject's weakrefs do trigger on finalize */ gtk_object_weakref(GTK_OBJECT(window), (GtkDestroyNotify)free, (gpointer)ddata); gtk_object_set_data(GTK_OBJECT(window), ident, (gpointer)res); #endif gtk_signal_connect_object(GTK_OBJECT(window), "destroy", GTK_SIGNAL_FUNC(do_destroy), (gpointer)res); #if GTK_MAJOR_VERSION == 1 /* To make Smooth theme engine render sliders properly */ if (have_sliders) gtk_signal_connect( GTK_OBJECT(window), "show", GTK_SIGNAL_FUNC(gtk_widget_queue_resize), NULL); #endif /* Init actmap to insensitive */ act_state(vdata, 0); /* Add finishing touches to a toplevel */ if (!part) { vdata->tparent = tparent; /* Trigger remembered events */ trigger_things(res); } /* Display */ if (op != op_WEND) cmd_showhide(GET_WINDOW(res), TRUE); /* Dialogs must be immune to stuck pointer grabs */ if (op == op_WDIALOG) { // Paranoia GtkWidget *grab = gtk_grab_get_current(); if (grab && (grab != GET_REAL_WINDOW(res))) gtk_grab_add(GET_REAL_WINDOW(res)); // Real concern - a server grab release_grab(); } /* Wait for input */ if (op == op_WDIALOG) { *(void ***)v = NULL; // clear result slot vdata->dv = v; // announce it while (!*(void ***)v) gtk_main_iteration(); } /* Return anchor position */ return (res); /* Terminate in script mode */ case op_uWEND: case op_uWSHOW: /* Terminate the list */ ADD_SLOT(r, NULL, NULL, NULL); /* Trigger remembered events */ if (!part) trigger_things(res); /* Init actmap to insensitive */ act_state(vdata, 0); /* Activate */ if (op != op_uWEND) cmd_showhide(GET_WINDOW(res), TRUE); /* Return anchor position - maybe already freed */ return (res); /* Script mode fileselector */ case op_uFPICK: ((swdata *)dtail)->strs = resolve_path(NULL, PATHBUF, v); // Fallthrough /* Script mode pseudo window */ case op_uWINDOW: case op_uTOPBOX: part = op == op_uTOPBOX; // not toplevel /* Store script ref, to run it when done */ vdata->script = script; wid = ""; // First unnamed field gets to be default pk = pk_UNREAL; if (op == op_uFPICK) pk = pk_UNREALV; break; /* Script mode alternate identifier */ case op_uALTNAME: if (!script && !scripted) continue; wid = v; pk = pk_UNREALV; break; /* Script mode identifier (forced) */ case op_uOPNAME: /* If flagged as livescript start/stop marker */ if ((int)pp[0] & WB_SFLAG) { widget = NULL; scripted = FALSE; if (ref) break; // stop if ref wid = ""; // default scripted = !script; continue; // start if no ref } /* If inside script and having something to set */ if ((script || scripted) && v) { void **slot = prev_uslot(r); if (slot) ((swdata *)slot[0])->id = v; } wid = NULL; // Clear current identifier continue; /* Script mode frame, as identifier to next control */ case op_uFRAME: wid = v; // Fallthrough /* Script mode OK button, as placeholder */ case op_uOKBTN: /* Script mode generic placeholder / group marker */ case op_uOP: pk = pk_UNREAL; /* If a group ID and inside script */ if ((((int)pp[0] & WB_OPMASK) == op_uOP) && lp && (script || scripted)) { void **slot; if (v) wid = v; if (!wid && (slot = prev_uslot(r))) wid = ((swdata *)slot[0])->id; pk = pk_UNREALV; } break; /* Script mode button */ case op_uBUTTON: wid = v; pk = pk_UNREALV; // Not scriptable by default if ((int)pp[0] & WB_SFLAG) break; op = op_uOP; pk = pk_UNREAL; // Leave identifier for next widget break; /* Script mode checkbox */ case op_uCHECKb: *(int *)v = inifile_get_gboolean(pp[3], *(int *)v); // Fallthrough case op_uCHECK: wid = pp[2]; tpad = !!*(int *)v; pk = pk_UNREALV; break; /* Script mode spinbutton */ case op_uSPIN: case op_uFSPIN: case op_uSPINa: case op_uSCALE: { int a, b; if (op != op_uSPINa) a = (int)pp[2] , b = (int)pp[3]; else a = ((int *)v)[1] , b = ((int *)v)[2]; ((swdata *)dtail)->range[0] = a; ((swdata *)dtail)->range[1] = b; tpad = *(int *)v; tpad = tpad > b ? b : tpad < a ? a : tpad; if (op == op_uSCALE) // Backup original value ((swdata *)dtail)->strs = (void *)tpad; pk = pk_UNREALV; break; } /* Script mode option pack */ case op_uOPT: case op_uOPTD: case op_uRPACK: case op_uRPACKD: { char **strs = pp[2]; int n = (int)pp[3]; if (op == op_uRPACK) n >>= 8; else if (op == op_uOPT); else /* OPTD/RPACKD */ { strs = *(char ***)((char *)ddata + (int)strs); n = 0; } if (n <= 0) for (n = 0; strs[n]; n++); // Count strings ((swdata *)dtail)->cnt = n; ((swdata *)dtail)->strs = strs; tpad = *(int *)v; if ((tpad >= n) || (tpad < 0) || !strs[tpad][0]) tpad = 0; pk = pk_UNREALV; break; } /* Script mode entry - fill from drop-away buffer */ case op_uENTRY: case op_uPATHSTR: // Length limit (not including 0) tpad = ((swdata *)dtail)->value = lp > 1 ? (int)pp[2] : -1; // Replace transient buffer - it may get freed on return *(char **)v = set_uentry((swdata *)dtail, *(char **)v); pk = pk_UNREALV; break; /* Script mode color picker - leave unfilled (?) */ case op_uCOLOR: pk = pk_UNREALV; break; /* Script mode list with columns */ case op_uLISTC: set_columns(&((lswdata *)dtail)->c, &c, ddata, r); ((swdata *)dtail)->strs = v; // Pointer to index tpad = ulistc_reset(r); pk = pk_UNREALV; break; /* Script mode list */ case op_uLISTCC: ((swdata *)dtail)->strs = v; // Pointer to index tpad = *(int *)v; pk = pk_UNREALV; break; /* Script mode menubar */ case op_uMENUBAR: tbar = r; rvar = rslot = NULL; pk = pk_UNREAL; break; /* Script mode menu item/toggle */ case op_uMENURITEM: /* Chain to previous */ if (rvar == v) ((swdata *)rslot[0])->range[1] = ((swdata *)dtail)->range[0] = r - rslot; /* Now this represents group */ rslot = r; rvar = v; // Fallthrough case op_uMENUCHECK: tpad = *(int *)v; tpad = op == op_uMENURITEM ? tpad == (int)pp[2] : !!tpad; // Fallthrough case op_uMENUITEM: wid = pp[3]; ((swdata *)dtail)->strs = tbar; pk = pk_UNREALV; break; /* Script mode mount socket */ case op_uMOUNT: { void **what = ((mnt_fn)pp[2])(res); *(int *)v = TRUE; ((swdata *)dtail)->strs = what; pk = pk_UNREAL; break; } /* Done with a container */ case op_WDONE: #if GTK_MAJOR_VERSION == 3 if (CT_WHAT(wp) == ct_SGROUP) CT_POP(wp); #endif /* Prepare smart menubar when done */ if (CT_WHAT(wp) == ct_SMARTMENU) vdata->smmenu = smartmenu_done(tbar, r); CT_DROP(wp); continue; /* Create the main window */ case op_MAINWINDOW: { int wh = (int)pp[3]; gdk_rgb_init(); init_tablet(); // Set up the tablet widget = window = gtk_window_new(GTK_WINDOW_TOPLEVEL); // !!! Better to use WIDTH() and HEIGHT() as elsewhere // Set minimum width/height #if GTK_MAJOR_VERSION == 3 gtk_widget_set_size_request(window, wh >> 16, wh & 0xFFFF); /* Global initialization */ tool_key = g_quark_from_static_string(TOOL_KEY); #else gtk_widget_set_usize(window, wh >> 16, wh & 0xFFFF); #endif // Set name _without_ translating gtk_window_set_title(GTK_WINDOW(window), v); /* !!! If main window receives these events, GTK+ will be able to * direct them to current modal window. Which makes it possible to * close popups by clicking on the main window outside popup - WJ */ gtk_widget_add_events(window, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK); // we need to realize the window because we use pixmaps // for items on the toolbar & menus in the context of it gtk_widget_realize(window); #if GTK_MAJOR_VERSION == 1 { GdkPixmap *icon_pix = gdk_pixmap_create_from_xpm_d( window->window, NULL, NULL, pp[2]); gdk_window_set_icon(window->window, NULL, icon_pix, NULL); // gdk_pixmap_unref(icon_pix); } #else /* #if GTK_MAJOR_VERSION >= 2 */ { GdkPixbuf *p = gdk_pixbuf_new_from_xpm_data(pp[2]); gtk_window_set_icon(GTK_WINDOW(window), p); g_object_unref(p); } #endif // For use as anchor and context main_window = window; ct = ct_BIN; break; } /* Create a toplevel window, and put a vertical box inside it */ case op_WINDOW: case op_WINDOWm: vdata->modal = op != op_WINDOW; widget = window = add_a_window(GTK_WINDOW_TOPLEVEL, *(char *)v ? _(v) : v, wpos); sw = add_vbox(window); ct = ct_BOX; break; /* Create a dialog window, with vertical & horizontal box */ case op_DIALOGm: vdata->modal = TRUE; widget = window = gtk_dialog_new(); gtk_window_set_title(GTK_WINDOW(window), _(v)); gtk_window_set_position(GTK_WINDOW(window), wpos); // !!! Border = 6 gtk_container_set_border_width(GTK_CONTAINER(window), 6); /* Both boxes go onto stack, with vbox on top */ CT_PUSH(wp, gtk_dialog_get_action_area(GTK_DIALOG(window)), ct_BOX); CT_PUSH(wp, gtk_dialog_get_content_area(GTK_DIALOG(window)), ct_BOX); break; /* Create a fileselector window (with horizontal box inside) */ case op_FPICKpm: { GtkWidget *box; vdata->modal = TRUE; widget = window = fpick(&box, *(char **)((char *)ddata + (int)pp[2]), *(int *)((char *)ddata + (int)pp[3]), r); #ifdef U_FPICK_GTKFILESEL add_del(SLOT_N(r, 2), window); #endif sw = box; ct = ct_BOX; /* Initialize */ fpick_set_filename(window, v, FALSE); break; } /* Create a popup window */ case op_POPUP: vdata->modal = TRUE; widget = window = add_a_window(GTK_WINDOW_POPUP, *(char *)v ? _(v) : v, wpos); cw = GET_BORDER(POPUP); ct = ct_BIN; break; /* Create a vbox which will serve as separate widget */ case op_TOPVBOX: part = TRUE; // not toplevel widget = window = vbox_new(0); cw = GET_BORDER(TOPVBOX); ct = ct_BOX; pk = pk_SHOW; break; /* Create a widget vbox with special sizing behaviour */ case op_TOPVBOXV: part = TRUE; // not toplevel // Fill space vertically but not horizontally widget = window = gtk_alignment_new(0.0, 0.5, 0.0, 1.0); // Keep max vertical size widget_set_keepsize(window, TRUE); sw = add_vbox(window); ct = ct_BOX; gtk_container_set_border_width(GTK_CONTAINER(sw), GET_BORDER(TOPVBOX)); pk = pk_SHOW; break; /* Add a dock widget */ case op_DOCK: { GtkWidget *p0, *p1, *pane; dock_data *dd = (void *)dtail; widget = hbox_new(0); gtk_widget_show(widget); /* First, create the dock pane - hidden for now */ dd->pane = pane = gtk_hpaned_new(); paned_mouse_fix(pane); gtk_box_pack_end(GTK_BOX(widget), pane, TRUE, TRUE, 0); /* Create the right pane */ p1 = vbox_new(0); gtk_widget_show(p1); gtk_paned_pack2(GTK_PANED(pane), p1, FALSE, TRUE); #if GTK_MAJOR_VERSION == 1 /* !!! Hack - but nothing else seems to prevent a sorry mess when * a widget gets REMOUNT'ed from a never-yet displayed pane */ gtk_container_set_resize_mode(GTK_CONTAINER(p1), GTK_RESIZE_QUEUE); #endif /* Now, create the left pane - for now, separate */ dd->vbox = p0 = xpack(widget, vbox_new(0)); gtk_widget_show(p0); /* Pack everything */ if (do_pack(widget, wp, pp, pk, tpad)) CT_POP(wp); CT_PUSH(wp, p1, ct_BOX); // right page second CT_PUSH(wp, p0, ct_BOX); // left page first // !!! Maybe pk_SHOW ? pk = 0; break; } /* Add a horizontal/vertical split widget */ case op_HVSPLIT: { GtkWidget *p; hvsplit_data *hd = (void *)dtail; hd->box = widget = vbox_new(0); /* Create the two panes - hidden for now */ hd->panes[0] = p = gtk_hpaned_new(); paned_mouse_fix(p); gtk_box_pack_end(GTK_BOX(widget), p, TRUE, TRUE, 0); hd->panes[1] = p = gtk_vpaned_new(); paned_mouse_fix(p); gtk_box_pack_end(GTK_BOX(widget), p, TRUE, TRUE, 0); sw = hd; // Datastruct in place of widget ct = ct_HVSPLIT; break; } /* Add a notebook page */ case op_PAGE: case op_PAGEi: { GtkWidget *label = op == op_PAGE ? gtk_label_new(_(v)) : xpm_image(v); gtk_widget_show(label); widget = vbox_new(op == op_PAGE ? 0 : (int)pp[2]); gtk_notebook_append_page(GTK_NOTEBOOK(CT_TOP(wp)), widget, label); ct = ct_BOX; pk = pk_SHOW; break; } /* Add a table */ case op_TABLE: widget = gtk_table_new((int)v & 0xFFFF, (int)v >> 16, FALSE); if (lp > 1) { int s = (int)pp[2]; gtk_table_set_row_spacings(GTK_TABLE(widget), s); gtk_table_set_col_spacings(GTK_TABLE(widget), s); } // !!! Padding = 0 cw = GET_BORDER(TABLE); ct = ct_TABLE; break; /* Add an equal-spaced horizontal box */ case op_EQBOX: /* Add a box */ case op_VBOX: case op_HBOX: #if GTK_MAJOR_VERSION == 3 widget = gtk_box_new((op == op_VBOX ? GTK_ORIENTATION_VERTICAL : GTK_ORIENTATION_HORIZONTAL), (int)v & 255); gtk_box_set_homogeneous(GTK_BOX(widget), op == op_EQBOX); #else widget = (op == op_VBOX ? gtk_vbox_new : gtk_hbox_new)(op == op_EQBOX, (int)v & 255); #endif if (lp) { cw = ((int)v >> 8) & 255; tpad = ((int)v >> 16) & 255; } ct = ct_BOX; break; /* Add a frame */ case op_FRAME: wid = v; // Fallthrough case op_EFRAME: widget = gtk_frame_new(v && *(char *)v ? _(v) : v); if (op == op_EFRAME) gtk_frame_set_shadow_type( GTK_FRAME(widget), GTK_SHADOW_ETCHED_OUT); // !!! Padding = 0 cw = GET_BORDER(FRAME); ct = ct_BIN; break; /* Add a scrolled window */ case op_SCROLL: widget = scrollw((int)v); tpad = GET_BORDER(SCROLL); ct = ct_SCROLL; break; /* Add a control-like scrolled window */ case op_CSCROLL: { int *xp = v; xp[0] = xp[1] = 0; // initial position widget = scrollw(0x101); // auto/auto // !!! Padding = 0 Border = 0 ct = ct_SCROLL; break; } /* Add a normal notebook */ case op_NBOOKl: case op_NBOOK: widget = gtk_notebook_new(); if (op == op_NBOOKl) gtk_notebook_set_tab_pos( GTK_NOTEBOOK(widget), GTK_POS_LEFT); if ((CT_WHAT(wp) == ct_SCROLL) && (pk <= pk_DEF)) pk = pk_SCROLLVPn; // no border // !!! Padding = 0 cw = GET_BORDER(NBOOK); ct = ct_NBOOK; break; /* Add a plain notebook */ case op_PLAINBOOK: { int n = v ? (int)v : 2; // 2 pages by default widget = gtk_notebook_new(); gtk_notebook_set_show_tabs(GTK_NOTEBOOK(widget), FALSE); gtk_notebook_set_show_border(GTK_NOTEBOOK(widget), FALSE); // !!! Border = 0 if (do_pack(widget, wp, pp, pk, tpad)) CT_POP(wp); while (n-- > 0) { GtkWidget *page = vbox_new(0); gtk_notebook_prepend_page(GTK_NOTEBOOK(widget), page, NULL); // stack pages back to front CT_PUSH(wp, page, ct_BOX); } gtk_widget_show_all(widget); pk = 0; break; } /* Add a toggle button for controlling 2-paged notebook */ case op_BOOKBTN: widget = gtk_toggle_button_new_with_label(_(pp[2])); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), FALSE); gtk_signal_connect(GTK_OBJECT(widget), "toggled", GTK_SIGNAL_FUNC(toggle_vbook), v); // !!! Padding = 0 cw = GET_BORDER(BUTTON); break; /* Add a statusbar box */ case op_STATUSBAR: { GtkWidget *w, *label = gtk_label_new(""); GtkRequisition req; w = widget = hbox_new(0); #if GTK_MAJOR_VERSION == 3 /* Do not let statusbar crowd anything else (unnecessary * on GTK+1&2 due to different sizing method there) */ w = wjsizebin_new(G_CALLBACK(do_shorten), NULL, label); gtk_widget_show(w); gtk_container_add(GTK_CONTAINER(w), widget); #endif /* !!! The following is intended to give enough height to the bar * even in case no items are shown. It depends on GTK+ setting * proper height (and zero width) for a label containing an empty * string. And size fixing isn't sure to set the right value if * the toplevel isn't yet realized (unlike MAINWINDOW) - WJ */ if (do_pack(w, wp, pp, pk, tpad)) CT_POP(wp); pack(widget, label); gtk_widget_show(label); /* To prevent statusbar wobbling */ #if GTK_MAJOR_VERSION == 3 /* !!! May need keepsize or maxsize */ gtk_widget_get_preferred_size(widget, &req, NULL); gtk_widget_set_size_request(widget, -1, req.height); #else /* if GTK_MAJOR_VERSION <= 2 */ gtk_widget_size_request(widget, &req); gtk_widget_set_usize(widget, -1, req.height); #endif ct = ct_BOX; pk = pk_SHOW; break; } /* Add a statusbar label */ case op_STLABEL: { int paw = (int)v; widget = gtk_label_new(""); gtk_misc_set_alignment(GTK_MISC(widget), ((paw >> 16) & 255) / 2.0, 0.0); if (paw & 0xFFFF) mods.minw = paw & 0xFFFF; // usize // Label-specific packing if (pk == pk_PACKEND) pk = pk_PACKEND1; // !!! Padding = 0 Border = 0 break; } /* Add a horizontal line */ case op_HSEP: widget = gtk_hseparator_new(); if ((int)v >= 0) // usize { if (lp) mods.minw = (int)v; // !!! Height = 10 mods.minh = 10; #if GTK_MAJOR_VERSION == 3 /* With CSS nodes, separators get rendered as * background-color boxes, which is fugly here */ if (gtk3version >= 20) css_restyle(widget, "separator.mtPaint_hsep" " { margin-top:5px; margin-bottom:4px; }", "mtPaint_hsep", NULL); #endif } // !!! Padding = 0 break; /* Add a label */ case op_LABEL: case op_uLABEL: { char *wi0 = wid; wid = v; // Maybe the preceding slot needs a label if (!wi0 && (script || scripted)) { void **slot = prev_uslot(r); if (slot) { swdata *sd = slot[0]; if (!sd->id && (sd->op != op_uOP)) sd->id = wid , wid = NULL; } } if (op == op_uLABEL) // Script mode label { pk = pk_UNREAL; break; } // Fallthrough } case op_WLABEL: { int z = lp > 1 ? (int)pp[2] : 0; widget = gtk_label_new(*(char *)v ? _(v) : v); if (z & 0xFFFF) gtk_misc_set_padding(GTK_MISC(widget), (z >> 8) & 255, z & 255); gtk_label_set_justify(GTK_LABEL(widget), GTK_JUSTIFY_LEFT); gtk_misc_set_alignment(GTK_MISC(widget), (z >> 16) / 10.0, 0.5); tpad = GET_BORDER(LABEL); // Label-specific packing if (pk == pk_TABLE1x) pk = pk_TABLE0p; if (pk == pk_TABLE) pk = pk_TABLEp; if (op == op_WLABEL) { #if GTK_MAJOR_VERSION == 3 /* Code to keep wrapping width sane is absent in * GTK+3, need be re-added as a wrapper */ GtkWidget *wrap = wjsizebin_new(G_CALLBACK(do_rewrap), NULL, NULL); gtk_widget_show(wrap); gtk_container_add(GTK_CONTAINER(wrap), widget); pk |= pkf_PARENT; #endif gtk_label_set_line_wrap(GTK_LABEL(widget), TRUE); } break; } /* Add a helptext label */ case op_HLABEL: case op_HLABELm: widget = gtk_label_new(v); #if GTK_MAJOR_VERSION == 3 gtk_widget_set_can_focus(widget, TRUE); #else GTK_WIDGET_SET_FLAGS(widget, GTK_CAN_FOCUS); #endif #if GTK_MAJOR_VERSION >= 2 gtk_label_set_selectable(GTK_LABEL(widget), TRUE); #endif #if GTK_MAJOR_VERSION == 3 /* "font-size" stopped being broken only in GTK+ 3.22, and * nagging about "Pango syntax" started - WJ */ if (op == op_HLABELm) css_restyle(widget, (gtk3version >= 22 ? ".mtPaint_hlabel { font-family: Monospace; font-size:9pt; }" : ".mtPaint_hlabel { font: Monospace 9; }" ), "mtPaint_hlabel", NULL); #elif GTK_MAJOR_VERSION == 2 if (op == op_HLABELm) { PangoFontDescription *pfd = pango_font_description_from_string("Monospace 9"); // Courier also works gtk_widget_modify_font(widget, pfd); pango_font_description_free(pfd); } #endif gtk_label_set_justify(GTK_LABEL(widget), GTK_JUSTIFY_LEFT); gtk_label_set_line_wrap(GTK_LABEL(widget), TRUE); gtk_misc_set_alignment(GTK_MISC(widget), 0, 0); // !!! Padding = 5/5 gtk_misc_set_padding(GTK_MISC(widget), 5, 5); break; /* Add to table a batch of labels generated from text string */ case op_TLTEXT: tltext(v, pp, CT_TOP(wp), GET_BORDER(LABEL)); pk = 0; break; /* Add a progressbar */ case op_PROGRESS: widget = gtk_progress_bar_new(); #if GTK_MAJOR_VERSION == 3 gtk_progress_bar_set_text(GTK_PROGRESS_BAR(widget), _(v)); #else /* if GTK_MAJOR_VERSION <= 2 */ gtk_progress_set_format_string(GTK_PROGRESS(widget), _(v)); gtk_progress_set_show_text(GTK_PROGRESS(widget), TRUE); #endif // !!! Padding = 0 break; /* Add a color patch renderer */ case op_COLORPATCH: widget = gtk_drawing_area_new(); #if GTK_MAJOR_VERSION == 3 gtk_widget_set_size_request(widget, (int)pp[2] >> 16, (int)pp[2] & 0xFFFF); g_signal_connect(G_OBJECT(widget), "draw", G_CALLBACK(col_expose), v); #else /* if GTK_MAJOR_VERSION <= 2 */ gtk_drawing_area_size(GTK_DRAWING_AREA(widget), (int)pp[2] >> 16, (int)pp[2] & 0xFFFF); gtk_signal_connect(GTK_OBJECT(widget), "expose_event", GTK_SIGNAL_FUNC(col_expose), v); #endif // !!! Padding = 0 break; /* Add an RGB renderer */ case op_RGBIMAGE: widget = rgbimage(r, (int *)((char *)ddata + (int)pp[2])); // !!! Padding = 0 break; /* Add a buffered (by pixmap) RGB renderer */ case op_RGBIMAGEP: widget = rgbimagep(r, (int)pp[2] >> 16, (int)pp[2] & 0xFFFF); // !!! Padding = 0 break; /* Add a framed canvas-based renderer */ case op_CANVASIMG: widget = canvasimg(r, (int)pp[2] >> 16, (int)pp[2] & 0xFFFF, 0); if ((CT_WHAT(wp) == ct_SCROLL) && (pk <= pk_DEF)) pk = pk_BIN; // !!! Padding = 0 pk |= pkf_PARENT | pkf_CANVAS; break; /* Add a framed canvas-based renderer with background */ case op_CANVASIMGB: { int *xp = (int *)((char *)ddata + (int)pp[2]); widget = canvasimg(r, xp[0], xp[1], xp[2]); if ((CT_WHAT(wp) == ct_SCROLL) && (pk <= pk_DEF)) pk = pk_BIN; // !!! Padding = 0 pk |= pkf_PARENT | pkf_CANVAS; break; } /* Add a canvas widget */ case op_CANVAS: { GtkWidget *frame; widget = wjcanvas_new(); wjcanvas_size(widget, (int)v >> 16, (int)v & 0xFFFF); wjcanvas_set_expose(widget, GTK_SIGNAL_FUNC(expose_canvas_), NEXT_SLOT(r)); frame = wjframe_new(); gtk_widget_show(frame); gtk_container_add(GTK_CONTAINER(frame), widget); // !!! For now, connection to scrollbars is automatic if ((CT_WHAT(wp) == ct_SCROLL) && (pk <= pk_DEF)) pk = pk_BIN; pk |= pkf_PARENT | pkf_CANVAS; break; } /* Add a focusable buffered RGB renderer with cursor */ case op_FCIMAGEP: widget = fcimagep(r, ddata); // !!! Padding = 0 break; /* Add a non-spinning spin to table slot */ case op_NOSPIN: { int n = *(int *)v; widget = add_a_spin(n, n, n); #if GTK_MAJOR_VERSION == 3 gtk_widget_set_can_focus(widget, FALSE); #else GTK_WIDGET_UNSET_FLAGS(widget, GTK_CAN_FOCUS); #endif tpad = GET_BORDER(SPIN); break; } /* Add a spin, fill from field/var */ case op_SPIN: case op_SPINc: widget = add_a_spin(*(int *)v, (int)pp[2], (int)pp[3]); #if (GTK_MAJOR_VERSION == 3) || (GTK2VERSION >= 4) /* GTK+ 2.4+ */ if (op == op_SPINc) gtk_entry_set_alignment( GTK_ENTRY(&(GTK_SPIN_BUTTON(widget)->entry)), 0.5); #endif tpad = GET_BORDER(SPIN); break; /* Add float spin, fill from field/var */ case op_FSPIN: widget = add_float_spin(*(int *)v / 100.0, (int)pp[2] / 100.0, (int)pp[3] / 100.0); tpad = GET_BORDER(SPIN); break; /* Add a spin, fill from array */ case op_SPINa: { int *xp = v; widget = add_a_spin(xp[0], xp[1], xp[2]); tpad = GET_BORDER(SPIN); break; } /* Add a grid of spins, fill from array of arrays */ // !!! Presents one widget out of all grid (the last one) case op_TLSPINPACK: r[2] = dtail -= VVS(TLSPINPACK_SIZE(pp)); widget = tlspinpack(r, dtail, CT_TOP(wp), (int)pp[lp + 1]); pk = 0; break; /* Add a spinslider */ case op_SPINSLIDE: case op_SPINSLIDEa: { int z = lp > 3 ? (int)pp[4] : 0; widget = mt_spinslide_new(z > 0xFFFF ? z >> 16 : -1, z & 0xFFFF ? z & 0xFFFF : -1); if (op == op_SPINSLIDEa) spin_set_range(widget, ((int *)v)[1], ((int *)v)[2]); else spin_set_range(widget, (int)pp[2], (int)pp[3]); gtk_spin_button_set_value(GTK_SPIN_BUTTON(widget), *(int *)v); tpad = GET_BORDER(SPINSLIDE); #if GTK_MAJOR_VERSION == 1 have_sliders = TRUE; #endif pk |= pkf_PARENT; break; } /* Add a named checkbox, fill from field/var/inifile */ case op_CHECKb: *(int *)v = inifile_get_gboolean(pp[3], *(int *)v); // Fallthrough case op_CHECK: widget = gtk_check_button_new_with_label(_(wid = pp[2])); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), *(int *)v); // !!! Padding = 0 cw = GET_BORDER(CHECK); break; /* Add a pack of radio buttons for field/var */ case op_RPACK: case op_RPACKD: /* Add a combobox for field/var */ case op_COMBO: widget = mkpack(op != op_COMBO, op == op_RPACKD, ref, ddata, r); // !!! Padding = 0 cw = GET_BORDER(RPACK); if (op != op_COMBO) break; cw = GET_BORDER(OPT); #if GTK2VERSION >= 4 /* GTK+ 2.4+ */ /* !!! GtkComboBox ignores its border setting, and is * easier to wrap than fix */ if (cw) { GtkWidget *w = gtk_alignment_new(0.5, 0.5, 1.0, 1.0); gtk_container_add(GTK_CONTAINER(w), widget); gtk_widget_show(w); pk |= pkf_PARENT; } #endif break; /* Add an option menu for field/var */ case op_OPT: case op_OPTD: #if GTK_MAJOR_VERSION == 3 widget = r[0] = gtk_combo_box_text_new(); // Fix up slot #else /* if GTK_MAJOR_VERSION <= 2 */ widget = r[0] = gtk_option_menu_new(); // Fix up slot /* !!! Show now - or size won't be set properly */ gtk_widget_show(widget); #endif #if GTK_MAJOR_VERSION == 2 gtk_signal_connect(GTK_OBJECT(widget), "realize", GTK_SIGNAL_FUNC(opt_size_fix), NULL); #endif opt_reset(r, ddata, *(int *)v); /* !!! Border is better left alone - to avoid a drawing * glitch in GTK+1 */ tpad = GET_BORDER(OPT); break; /* Add an entry widget, fill from drop-away buffer */ case op_ENTRY: case op_MLENTRY: widget = gtk_entry_new(); if (lp > 1) gtk_entry_set_max_length(GTK_ENTRY(widget), (int)pp[2]); if (*(char **)v) gtk_entry_set_text(GTK_ENTRY(widget), *(char **)v); if (op == op_MLENTRY) accept_ctrl_enter(widget); // Replace transient buffer - it may get freed on return *(const char **)v = gtk_entry_get_text(GTK_ENTRY(widget)); tpad = GET_BORDER(ENTRY); break; /* Add a path entry or box to table */ case op_PENTRY: #if GTK_MAJOR_VERSION == 3 widget = gtk_entry_new(); gtk_entry_set_max_length(GTK_ENTRY(widget), (int)pp[2]); #else widget = gtk_entry_new_with_max_length((int)pp[2]); #endif set_path(widget, v, PATH_VALUE); tpad = GET_BORDER(ENTRY); break; /* Add a path box to table */ case op_PATHs: v = inifile_get(v, ""); // read and fallthrough case op_PATH: widget = pathbox(r, GET_BORDER(PATH)); set_path(widget, v, PATH_VALUE); // !!! Padding = 0 Border = 0 pk |= pkf_PARENT; break; /* Add a text widget, fill from drop-away buffer at pointer */ case op_TEXT: widget = textarea(*(char **)v); *(char **)v = NULL; // !!! Padding = 0 Border = 0 pk |= pkf_PARENT; // wrapped break; /* Add a font selector, fill from array: font name/test string */ case op_FONTSEL: widget = fontsel(r, v); // !!! Border = 4 cw = 4; break; #ifdef U_CPICK_MTPAINT /* Add a hex color entry */ case op_HEXENTRY: widget = hexentry(*(int *)v, r); // !!! Padding = 0 Border = 0 break; /* Add an eyedropper button */ case op_EYEDROPPER: widget = eyedropper(r); // !!! Padding = 2 Border = 0 tpad = 2; if (pk == pk_TABLE) pk = pk_TABLEp; break; #endif /* Add a togglebutton for selecting shortcut keys */ case op_KEYBUTTON: { keybutton_data *dt = (void *)dtail; dt->section = ini_setsection(&main_ini, 0, SEC_KEYNAMES); ini_transient(&main_ini, dt->section, NULL); widget = gtk_toggle_button_new_with_label(_("New key ...")); #if GTK_MAJOR_VERSION == 1 gtk_widget_add_events(widget, GDK_KEY_RELEASE_MASK); #endif gtk_signal_connect(GTK_OBJECT(widget), "key_press_event", GTK_SIGNAL_FUNC(convert_key), dt); gtk_signal_connect(GTK_OBJECT(widget), "key_release_event", GTK_SIGNAL_FUNC(convert_key), dt); cw = GET_BORDER(BUTTON); break; } /* Add a button for tablet config dialog */ case op_TABLETBTN: widget = gtk_button_new_with_label(_(v)); gtk_signal_connect_object(GTK_OBJECT(widget), "clicked", GTK_SIGNAL_FUNC(conf_tablet), (gpointer)r); cw = GET_BORDER(BUTTON); break; /* Add a combo-entry for text strings */ case op_COMBOENTRY: widget = comboentry(ddata, r); // !!! Padding = 5 tpad = 5; break; /* Add a color picker box, w/field array, & leave unfilled (?) */ case op_COLOR: case op_TCOLOR: widget = cpick_create(op == op_TCOLOR); vdata->fupslot = r; // "Hex" needs defocus to update // !!! Padding = 0 break; /* Add a colorlist box, fill from fields */ case op_COLORLIST: case op_COLORLISTN: widget = colorlist(r, ddata); if ((CT_WHAT(wp) == ct_SCROLL) && (pk <= pk_DEF)) #ifdef U_LISTS_GTK1 pk = pk_SCROLLVPm; #else pk = pk_BIN; // auto-connects to scrollbars #endif break; /* Add a buttonbar for gradient */ case op_GRADBAR: widget = gradbar(r, ddata); // !!! Padding = 0 break; /* Add a combo for percent values */ case op_PCTCOMBO: widget = pctcombo(r); // !!! Padding = 0 break; /* Add a list with pre-defined columns */ case op_LISTCCr: widget = listcc(r, ddata, &c); /* !!! For GtkTreeView this does not do anything in GTK+2 * and produces background-colored border in GTK+3; * need to fix the coloring OR ignore the border: list in * "Configure Animation" looks good without it too - WJ */ cw = GET_BORDER(LISTCC); if ((CT_WHAT(wp) == ct_SCROLL) && (pk <= pk_DEF)) #ifdef U_LISTS_GTK1 pk = pk_SCROLLVPv; #else pk = pk_BIN; // auto-connects to scrollbars #endif break; /* Add a clist with pre-defined columns */ case op_LISTC: case op_LISTCd: case op_LISTCu: case op_LISTCS: case op_LISTCX: widget = listc(r, ddata, &c); // !!! Border = 0 if ((CT_WHAT(wp) == ct_SCROLL) && (pk <= pk_DEF)) pk = pk_BIN; // auto-connects to scrollbars break; /* Add a clickable button */ case op_BUTTON: wid = (int)pp[0] & WB_SFLAG ? v : "="; // Hide by default // Fallthrough case op_OKBTN: case op_CANCELBTN: case op_DONEBTN: { widget = gtk_button_new_with_label(_(v)); if ((op == op_OKBTN) || (op == op_DONEBTN)) { gtk_widget_add_accelerator(widget, "clicked", ag, KEY(Return), 0, (GtkAccelFlags)0); gtk_widget_add_accelerator(widget, "clicked", ag, KEY(KP_Enter), 0, (GtkAccelFlags)0); accel |= 1; } if ((op == op_CANCELBTN) || (op == op_DONEBTN)) { gtk_widget_add_accelerator(widget, "clicked", ag, KEY(Escape), 0, (GtkAccelFlags)0); add_del(NEXT_SLOT(r), window); accel |= 1; } /* Click-event */ if ((op != op_BUTTON) || pp[3]) gtk_signal_connect_object(GTK_OBJECT(widget), "clicked", GTK_SIGNAL_FUNC(do_evt_1_d), (gpointer)NEXT_SLOT(r)); cw = GET_BORDER(BUTTON); break; } /* Add a toggle button to OK-box */ case op_TOGGLE: widget = gtk_toggle_button_new_with_label(_(pp[2])); if (pp[4]) gtk_signal_connect(GTK_OBJECT(widget), "toggled", GTK_SIGNAL_FUNC(get_evt_1), NEXT_SLOT(r)); cw = GET_BORDER(BUTTON); break; /* Add a toolbar */ case op_TOOLBAR: case op_SMARTTBAR: { GtkWidget *bar; #if GTK_MAJOR_VERSION <= 2 GtkWidget *vport; smarttbar_data *sd; #endif tbar = r; rvar = rslot = NULL; #if GTK_MAJOR_VERSION == 1 widget = gtk_toolbar_new(GTK_ORIENTATION_HORIZONTAL, GTK_TOOLBAR_ICONS); #else /* #if GTK_MAJOR_VERSION >= 2 */ widget = gtk_toolbar_new(); gtk_toolbar_set_style(GTK_TOOLBAR(widget), GTK_TOOLBAR_ICONS); #endif ct = ct_TBAR; if (op != op_SMARTTBAR) { tpad = GET_BORDER(TOOLBAR); break; } // !!! Toolbar is what sits on stack till SMARTTBMORE sw = bar = widget; gtk_widget_show(bar); #if GTK_MAJOR_VERSION == 3 /* Just add a box, to hold extra things at end */ widget = hbox_new(0); pack(widget, bar); #else /* #if GTK_MAJOR_VERSION <= 2 */ widget = wj_size_box(); /* Make datastruct */ sd = (void *)dtail; sd->tbar = bar; sd->r = r; gtk_signal_connect(GTK_OBJECT(widget), "size_request", GTK_SIGNAL_FUNC(htoolbox_size_req), sd); gtk_signal_connect(GTK_OBJECT(widget), "size_allocate", GTK_SIGNAL_FUNC(htoolbox_size_alloc), sd); vport = pack(widget, gtk_viewport_new(NULL, NULL)); gtk_viewport_set_shadow_type(GTK_VIEWPORT(vport), GTK_SHADOW_NONE); gtk_widget_show(vport); vport_noshadow_fix(vport); sd->vport = vport; gtk_container_add(GTK_CONTAINER(vport), bar); #endif /* GTK+1&2 */ // !!! Padding = 0 break; } /* Add the arrow button to smart toolbar */ case op_SMARTTBMORE: { GtkWidget *box = tbar[0]; // !!! Box replaces toolbar on stack CT_POP(wp); CT_PUSH(wp, box, ct_BOX); #if GTK_MAJOR_VERSION == 3 /* Button is builtin */ widget = NULL; pk = pk_NONE; #else /* #if GTK_MAJOR_VERSION <= 2 */ { smarttbar_data *sd = tbar[2]; sd->r2 = r; // remember where the slots end widget = smarttbar_button(sd, v); pk = pk_SHOW; } #endif /* GTK+1&2 */ break; } /* Add a container-toggle beside toolbar */ case op_TBBOXTOG: widget = pack(CT_N(wp, 1), gtk_toggle_button_new()); #if GTK_MAJOR_VERSION == 3 gtk_widget_set_tooltip_text(widget, _(wid = pp[3])); #else /* Parasite tooltip on toolbar */ gtk_tooltips_set_tip(GTK_TOOLBAR(CT_TOP(wp))->tooltips, widget, _(wid = pp[3]), "Private"); #endif #if (GTK_MAJOR_VERSION == 3) || (GTK2VERSION >= 4) /* GTK+ 2.4+ */ gtk_button_set_focus_on_click(GTK_BUTTON(widget), FALSE); #endif gtk_signal_connect(GTK_OBJECT(widget), "clicked", GTK_SIGNAL_FUNC(toolbar_lclick), NEXT_SLOT(tbar)); ct = ct_BIN; pk = pk_SHOW; // Fallthrough /* Add a toolbar button/toggle */ case op_TBBUTTON: case op_TBTOGGLE: case op_TBRBUTTON: { GtkWidget *rb = NULL; #if GTK_MAJOR_VERSION == 3 GtkToolItem *it = NULL; GtkWidget *m; #endif if (keygroup) keymap_add(keymap, r, pp[3], keygroup); r[2] = tbar; // link to toolbar slot if (op == op_TBRBUTTON) { static int set = TRUE; if (rvar == v) rb = rslot[0]; /* Now this represents group */ rslot = r; rvar = v; /* Activate the one button whose ID matches var */ v = *(int *)v == (int)pp[2] ? &set : NULL; } #if GTK_MAJOR_VERSION == 3 if (op == op_TBRBUTTON) it = gtk_radio_tool_button_new_from_widget( GTK_RADIO_TOOL_BUTTON(rb)); else if (op == op_TBTOGGLE) it = gtk_toggle_tool_button_new(); else if (op == op_TBBUTTON) it = gtk_tool_button_new(NULL, NULL); if (it) { gtk_tool_item_set_tooltip_text(it, _(wid = pp[3])); gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(it), xpm_image(pp[4])); g_signal_connect(G_OBJECT(it), op == op_TBBUTTON ? "clicked" : "toggled", G_CALLBACK(toolbar_lclick), NEXT_SLOT(tbar)); gtk_toolbar_insert(GTK_TOOLBAR(CT_TOP(wp)), it, -1); widget = GTK_WIDGET(it); pk = pk_SHOW; /* Set overflow menu to usable state */ if (GET_OP(tbar) == op_SMARTTBAR) { m = gtk_tool_item_retrieve_proxy_menu_item(it); gtk_container_remove(GTK_CONTAINER(m), gtk_bin_get_child(GTK_BIN(m))); gtk_container_add(GTK_CONTAINER(m), xpm_image(pp[4])); gtk_widget_set_tooltip_text(m, _(pp[3])); /* Prevent item's re-creation */ g_signal_connect(G_OBJECT(it), "create_menu_proxy", G_CALLBACK(leave_be), NULL); } if (v) gtk_toggle_tool_button_set_active( GTK_TOGGLE_TOOL_BUTTON(widget), *(int *)v); } else if (v) gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(widget), *(int *)v); g_object_set_qdata(G_OBJECT(widget), tool_key, r); #else /* #if GTK_MAJOR_VERSION <= 2 */ if (op != op_TBBOXTOG) widget = gtk_toolbar_append_element( GTK_TOOLBAR(CT_TOP(wp)), (op == op_TBBUTTON ? GTK_TOOLBAR_CHILD_BUTTON : op == op_TBRBUTTON ? GTK_TOOLBAR_CHILD_RADIOBUTTON : GTK_TOOLBAR_CHILD_TOGGLEBUTTON), rb, NULL, _(wid = pp[3]), "Private", xpm_image(pp[4]), GTK_SIGNAL_FUNC(toolbar_lclick), NEXT_SLOT(tbar)); if (v) gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(widget), *(int *)v); gtk_object_set_user_data(GTK_OBJECT(widget), r); #endif /* GTK+1&2 */ if (lp > 4) gtk_signal_connect(GTK_OBJECT(widget), "button_press_event", GTK_SIGNAL_FUNC(toolbar_rclick), SLOT_N(tbar, 2)); break; } /* Add a toolbar separator */ case op_TBSPACE: { #if GTK_MAJOR_VERSION == 3 GtkToolItem *it = gtk_separator_tool_item_new(); gtk_widget_show(GTK_WIDGET(it)); gtk_toolbar_insert(GTK_TOOLBAR(CT_TOP(wp)), it, -1); #else /* #if GTK_MAJOR_VERSION <= 2 */ gtk_toolbar_append_space(GTK_TOOLBAR(CT_TOP(wp))); #endif break; } /* Add a two/one row container for 2 toolbars */ case op_TWOBOX: #if GTK_MAJOR_VERSION == 3 widget = gtk_flow_box_new(); gtk_flow_box_set_selection_mode(GTK_FLOW_BOX(widget), GTK_SELECTION_NONE); ct = ct_CONT; #else /* #if GTK_MAJOR_VERSION <= 2 */ widget = wj_size_box(); gtk_signal_connect(GTK_OBJECT(widget), "size_request", GTK_SIGNAL_FUNC(twobar_size_req), NULL); gtk_signal_connect(GTK_OBJECT(widget), "size_allocate", GTK_SIGNAL_FUNC(twobar_size_alloc), NULL); ct = ct_BOX; #endif // !!! Padding = 0 break; /* Add a menubar */ case op_MENUBAR: case op_SMARTMENU: { GtkWidget *bar; smartmenu_data *sd; // Stop dynamic allocation of accelerators during runtime accel |= 3; tbar = r; rvar = rslot = NULL; widget = gtk_menu_bar_new(); ct = ct_CONT; // !!! Padding = 0 if (op != op_SMARTMENU) break; ct = ct_SMARTMENU; // !!! Menubar is what sits on stack sw = bar = widget; gtk_widget_show(bar); /* Make datastruct */ sd = (void *)dtail; sd->mbar = bar; sd->r = r; #if GTK_MAJOR_VERSION <= 2 widget = wj_size_box(); gtk_signal_connect(GTK_OBJECT(widget), "size_request", GTK_SIGNAL_FUNC(smart_menu_size_req), sd); gtk_signal_connect(GTK_OBJECT(widget), "size_allocate", GTK_SIGNAL_FUNC(smart_menu_size_alloc), sd); pack(widget, bar); #endif break; } /* Add a dropdown submenu */ case op_SUBMENU: case op_ESUBMENU: case op_SSUBMENU: { GtkWidget *label, *menu; char *s; #if GTK_MAJOR_VERSION <= 2 guint keyval; #endif int l; gid = v; /* For keymap */ widget = gtk_menu_item_new_with_label(""); if (op == op_ESUBMENU) gtk_menu_item_right_justify(GTK_MENU_ITEM(widget)); l = strspn(s = v, "/"); if (s[l]) s = _(s); // Translate s += l; label = gtk_bin_get_child(GTK_BIN(widget)); #if GTK_MAJOR_VERSION == 3 gtk_label_set_text_with_mnemonic(GTK_LABEL(label), s); /* !!! In case any non-toplevel submenu has an underline, * in GTK+3 it'll have to be cut out from string beforehand */ #else /* #if GTK_MAJOR_VERSION <= 2 */ keyval = gtk_label_parse_uline(GTK_LABEL(label), s); /* Toplevel submenus can have Alt+letter shortcuts */ if ((l < 2) && (keyval != GDK_VoidSymbol)) #if GTK_MAJOR_VERSION == 1 gtk_widget_add_accelerator(widget, "activate_item", ag, keyval, GDK_MOD1_MASK, GTK_ACCEL_LOCKED); #else gtk_label_set_text_with_mnemonic(GTK_LABEL(label), s); #endif #endif /* GTK+1&2 */ sw = menu = gtk_menu_new(); ct = ct_CONT; gtk_menu_set_accel_group(GTK_MENU(menu), ag); gtk_menu_item_set_submenu(GTK_MENU_ITEM(widget), menu); break; } /* Add a menu item/toggle */ case op_MENUITEM: case op_MENUCHECK: case op_MENURITEM: { char *s; int l; if (keygroup) keymap_add(keymap, r, pp[3], keygroup); r[2] = tbar; // link to menu slot if (op == op_MENUCHECK) widget = gtk_check_menu_item_new_with_label(""); else if (op == op_MENURITEM) { GSList *group = NULL; if (rvar == v) group = gtk_radio_menu_item_group( rslot[0]); /* Now this represents group */ rslot = r; rvar = v; widget = gtk_radio_menu_item_new_with_label(group, ""); } #if GTK_MAJOR_VERSION >= 2 else if ((lp > 3) && show_menu_icons) { widget = gtk_image_menu_item_new_with_label(""); gtk_image_menu_item_set_image( GTK_IMAGE_MENU_ITEM(widget), xpm_image(pp[4])); } #endif else widget = gtk_menu_item_new_with_label(""); if (v) /* Initialize a check/radio item */ { int f = *(int *)v; /* Activate the one button whose ID matches var */ if ((op != op_MENURITEM) || (f = f == (int)pp[2])) gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM(widget), f); #if GTK_MAJOR_VERSION <= 2 gtk_check_menu_item_set_show_toggle( GTK_CHECK_MENU_ITEM(widget), TRUE); #endif } l = strspn(s = pp[3], "/"); if (s[l]) s = _(s); // Translate s += l; #if GTK_MAJOR_VERSION == 3 /* !!! In case any regular menuitem has an underline, * in GTK+3 it'll have to be cut out from string beforehand */ gtk_label_set_text(GTK_LABEL(gtk_bin_get_child(GTK_BIN(widget))), s); g_object_set_qdata(G_OBJECT(widget), tool_key, r); #else /* #if GTK_MAJOR_VERSION <= 2 */ gtk_label_parse_uline(GTK_LABEL(GTK_BIN(widget)->child), s); gtk_object_set_user_data(GTK_OBJECT(widget), r); #endif gtk_signal_connect(GTK_OBJECT(widget), "activate", GTK_SIGNAL_FUNC(menu_evt), NEXT_SLOT(tbar)); #if GTK_MAJOR_VERSION >= 2 /* !!! Otherwise GTK+ won't add spacing to an empty accel field */ gtk_widget_set_accel_path(widget, FAKE_ACCEL, ag); #endif #if (GTK_MAJOR_VERSION == 3) || (GTK2VERSION >= 4) /* !!! GTK+ 2.4+ ignores invisible menu items' keys by default */ gtk_signal_connect(GTK_OBJECT(widget), "can_activate_accel", GTK_SIGNAL_FUNC(menu_allow_key), NULL); #endif break; } /* Add a tearoff menu item */ case op_MENUTEAR: widget = gtk_tearoff_menu_item_new(); break; /* Add a separator menu item */ case op_MENUSEP: #if GTK_MAJOR_VERSION == 3 /* The olden separators recognition logic does not work * since switch to CSS nodes */ if (gtk3version >= 20) widget = gtk_separator_menu_item_new(); else #endif { widget = gtk_menu_item_new(); gtk_widget_set_sensitive(widget, FALSE); } break; /* Add a mount socket with custom-built separable widget */ case op_MOUNT: { void **what = r[2] = ((mnt_fn)pp[2])(res); *(int *)v = TRUE; widget = gtk_alignment_new(0.5, 0.5, 1.0, 1.0); gtk_container_add(GTK_CONTAINER(widget), GET_REAL_WINDOW(what)); // !!! Padding = 0 if (lp > 2 + 2) // put socket in pane w/preset size { GtkWidget *pane = gtk_vpaned_new(); paned_mouse_fix(pane); gtk_paned_set_position(GTK_PANED(pane), inifile_get_gint32(pp[3], (int)pp[4])); gtk_paned_pack2(GTK_PANED(pane), vbox_new(0), TRUE, TRUE); gtk_widget_show_all(pane); gtk_paned_pack1(GTK_PANED(pane), widget, FALSE, TRUE); pk |= pkf_PARENT; } break; } /* Steal a widget from its mount socket by slot ref */ case op_REMOUNT: { void **where = *(void ***)v; GtkWidget *what = gtk_bin_get_child(GTK_BIN(where[0])); widget = gtk_alignment_new(0.5, 0.5, 1.0, 1.0); gtk_widget_hide(where[0]); gtk_widget_reparent(what, widget); get_evt_1(where[0], NEXT_SLOT(where)); break; } /* Add a height-limiter item */ case op_HEIGHTBAR: { widget = gtk_label_new(""); // Gives useful lower limit #if GTK_MAJOR_VERSION == 3 GtkSizeGroup *sg = gtk_size_group_new(GTK_SIZE_GROUP_VERTICAL); gtk_size_group_set_ignore_hidden(sg, FALSE); CT_PUSH(wp, sg, ct_SGROUP); #else /* #if GTK_MAJOR_VERSION <= 2 */ gtk_signal_connect(GTK_OBJECT(widget), "size_request", GTK_SIGNAL_FUNC(heightbar_size_req), NULL); #endif break; } #if 0 /* Call a function */ case op_EXEC: r = ((ext_fn)v)(r, &wp, res); continue; #endif /* Call a V-code subroutine */ case op_CALL: *rp++ = ifcode; // Fallthrough /* Do a V-code jump */ case op_GOTO: ifcode = v; continue; /* Return from V-code subroutine */ case op_RET: ifcode = *--rp; continue; /* Skip next token(s) if/unless field/var is unset */ case op_IF: case op_UNLESS: if (!*(int *)v ^ (op != op_IF)) ifcode = skip_if(pp); continue; /* Skip next token(s) unless inifile var, set by default, is unset */ case op_UNLESSbt: if (inifile_get_gboolean(v, TRUE)) ifcode = skip_if(pp); continue; /* Put last referrable widget into activation map */ case op_ACTMAP: if (lp > 1) vdata->vismask = (unsigned)v; // VISMASK else { void **where = vdata->actmap + vdata->actn++ * ACT_SIZE; ADD_ACT(where, origin_slot(PREV_SLOT(r)), v); } continue; /* Set up a configurable keymap for widgets */ case op_KEYMAP: vdata->keymap = r; r[2] = dtail -= VVS(KEYMAP_SIZE(sz.keys)); keymap = (void *)dtail; keymap->res = v; keymap->slotsec = keygroup = ini_setsection(&main_ini, 0, pp[2]); ini_transient(&main_ini, keygroup, NULL); // Not written out widget = NULL; break; /* Add a shortcut, from text desc, to last referrable widget */ case op_SHORTCUT: { void **slot = origin_slot(PREV_SLOT(r)); int op = GET_OP(slot); guint keyval = 0, mods = 0; if (!lp); // Do nothing else if (lp < 2) gtk_accelerator_parse(v, &keyval, &mods); else keyval = (guint)v , mods = (guint)pp[2]; if (keygroup && // Already mapped ((keymap->slots[keymap->nslots].slot == slot) || // On-demand mapping for script mode menuitems ((op >= op_uMENU_0) && (op < op_uMENU_LAST) && keymap_add(keymap, slot, GET_DESCV(slot, 3), keygroup)))) { if (lp) keymap_map(keymap, keymap->nslots, keyval, mods); continue; } #if GTK_MAJOR_VERSION >= 2 /* !!! In case one had been set (for menu spacing) */ gtk_widget_set_accel_path(*slot, NULL, ag); #endif gtk_widget_add_accelerator(*slot, "activate", ag, keyval, mods, GTK_ACCEL_VISIBLE); accel |= 1; continue; } /* Install priority key handler for when widget is focused */ case op_WANTKEYS: vdata->wantkey = r; widget = NULL; break; /* Store a reference to whatever is next into field */ case op_REF: *(void **)v = r; continue; /* Make toplevel window shrinkable */ case op_MKSHRINK: #if GTK_MAJOR_VERSION == 3 /* Just do smarter initial sizing, here it is enough */ gtk_window_set_resizable(GTK_WINDOW(window), FALSE); g_signal_connect(window, "draw", G_CALLBACK(make_resizable), NULL); #else /* #if GTK_MAJOR_VERSION <= 2 */ gtk_window_set_policy(GTK_WINDOW(window), TRUE, TRUE, FALSE); #endif continue; /* Make toplevel window non-resizable */ case op_NORESIZE: #if GTK_MAJOR_VERSION == 3 gtk_window_set_resizable(GTK_WINDOW(window), FALSE); #else gtk_window_set_policy(GTK_WINDOW(window), FALSE, FALSE, TRUE); #endif continue; /* Make scrolled window request max size */ case op_WANTMAX: mods.wantmax = (int)v + 1; continue; /* Make widget keep max requested width/height */ case op_KEEPSIZE: widget_set_keepsize(widget, lp); continue; /* Use saved size & position for window */ case op_WXYWH: { unsigned int n = (unsigned)pp[2]; vdata->ininame = v; vdata->xywh[2] = n >> 16; vdata->xywh[3] = n & 0xFFFF; if (v) rw_pos(vdata, FALSE); continue; } /* Make toplevel window be positioned at mouse */ case op_WPMOUSE: wpos = GTK_WIN_POS_MOUSE; continue; /* Make toplevel window be positioned anywhere WM pleases */ case op_WPWHEREVER: wpos = GTK_WIN_POS_NONE; continue; /* Make last referrable widget hidden */ case op_HIDDEN: gtk_widget_hide(get_wrap(origin_slot(PREV_SLOT(r)))); continue; /* Make last referrable widget insensitive */ case op_INSENS: cmd_sensitive(origin_slot(PREV_SLOT(r)), FALSE); continue; /* Make last referrable widget focused */ case op_FOCUS: { void **orig = origin_slot(PREV_SLOT(r)); /* !!! For GtkFontSelection, focusing needs be done after * window is shown - in GTK+ 2.24.10, at least */ if (GET_OP(orig) == op_FONTSEL) gtk_signal_connect_object( GTK_OBJECT(window), "show", GTK_SIGNAL_FUNC(gtk_widget_grab_focus), (gpointer)gtk_font_selection_get_preview_entry( GTK_FONT_SELECTION(*orig))); else gtk_widget_grab_focus(*orig); continue; } /* Set fixed/minimum width for next widget */ case op_WIDTH: mods.minw = (int)v; continue; /* Set fixed/minimum height for next widget */ case op_HEIGHT: mods.minh = (int)v; continue; /* Make window transient to given widget-map */ case op_ONTOP: tparent = !v ? NULL : GTK_WINDOW(GET_REAL_WINDOW(*(void ***)v)); continue; /* Change identifier, for reusable toplevels */ case op_IDENT: ident = v; continue; /* Raise window after displaying */ case op_RAISED: vdata->raise = TRUE; continue; /* Start group of list columns */ case op_WLIST: memset(&c, 0, sizeof(c)); continue; /* Add a datablock pseudo-column */ case op_COLUMNDATA: c.dcolumn = pp; continue; /* Add a regular list column */ case op_IDXCOLUMN: case op_TXTCOLUMN: case op_XTXTCOLUMN: case op_FILECOLUMN: case op_CHKCOLUMN: ((swdata *)dtail)->cnt = c.ncol; c.columns[c.ncol++] = r; pk = pk_UNREAL; if ((script || scripted) && (lp - ref * 2 > 1)) { wid = pp[4]; tpad = 0; pk = pk_UNREALV; } break; /* Create an XBM cursor */ case op_XBMCURSOR: { int xyl = (int)pp[3], l = xyl >> 16; widget = (void *)make_cursor(v, pp[2], l, l, (xyl >> 8) & 255, xyl & 255); break; } /* Create a system cursor */ case op_SYSCURSOR: widget = (void *)gdk_cursor_new((int)v); break; /* Add a group of clipboard formats */ case op_CLIPFORM: { int i, n = (int)pp[2], l = sizeof(clipform_data) + sizeof(GtkTargetEntry) * (n - 1); clipform_data *cd = calloc(1, l); cd->n = n; cd->src = v; for (i = 0; i < n; i++) { cd->ent[i].target = cd->src[i].target; cd->ent[i].info = i; /* cd->ent[i].flags = 0; */ } cd->targets = gtk_target_list_new(cd->ent, n); widget = (void *)cd; break; } /* Install drag/drop handlers */ // !!! For drag, this must be done before mouse event handlers case op_DRAGDROP: widget = dragdrop(r); break; /* Add a clipboard control slot */ case op_CLIPBOARD: widget = **(void ***)v; // from CLIPFORM break; /* Install activate event handler */ case op_EVT_OK: { void **slot = origin_slot(PREV_SLOT(r)); int what = GET_OP(slot); // !!! Support only what actually used on, and their brethren switch (what) { case op_ENTRY: case op_MLENTRY: case op_PENTRY: case op_PATH: case op_PATHs: gtk_signal_connect(GTK_OBJECT(*slot), "activate", GTK_SIGNAL_FUNC(get_evt_1), r); break; case op_LISTC: case op_LISTCd: case op_LISTCu: case op_LISTCS: case op_LISTCX: { listc_data *ld = slot[2]; ld->ok = r; break; } } widget = NULL; break; } /* Install destroy event handler (onto window) */ case op_EVT_CANCEL: add_del(r, window); widget = NULL; break; /* Install deallocation event handler */ case op_EVT_DESTROY: vdata->destroy = r; widget = NULL; break; /* Install key event handler */ case op_EVT_KEY: { void **slot = origin_slot(PREV_SLOT(r)); int toplevel = (slot == GET_WINDOW(res)) && GTK_IS_WINDOW(slot[0]); gtk_signal_connect(GTK_OBJECT(*slot), "key_press_event", // Special handler for toplevels toplevel ? GTK_SIGNAL_FUNC(window_evt_key) : GTK_SIGNAL_FUNC(get_evt_key), r); enable_events(slot, op); widget = NULL; break; } /* Install mouse event handler */ case op_EVT_MOUSE: case op_EVT_MMOUSE: case op_EVT_RMOUSE: case op_EVT_XMOUSE: case op_EVT_MXMOUSE: case op_EVT_RXMOUSE: add_mouse(r, op); widget = NULL; break; /* Install crossing event handler */ case op_EVT_CROSS: { void **slot = origin_slot(PREV_SLOT(r)); gtk_signal_connect(GTK_OBJECT(*slot), "enter_notify_event", GTK_SIGNAL_FUNC(get_evt_cross), r); gtk_signal_connect(GTK_OBJECT(*slot), "leave_notify_event", GTK_SIGNAL_FUNC(get_evt_cross), r); enable_events(slot, op); widget = NULL; break; } #if GTK_MAJOR_VERSION >= 2 /* Install scroll event handler */ case op_EVT_SCROLL: { void **slot = origin_slot(PREV_SLOT(r)); gtk_signal_connect(GTK_OBJECT(*slot), "scroll_event", GTK_SIGNAL_FUNC(get_evt_scroll), r); /* !!! The classical scroll events cannot be reliably received on any * GdkWindow with GDK_SMOOTH_SCROLL_MASK set (such as the ones of GTK+3 * builtin scrollable widgets); if that is ever needed, enable_events() * will need install a realize handler which forcibly removes the flag * from all widget's GdkWindows - WJ */ enable_events(slot, op); widget = NULL; break; } #endif /* Install Change-event handler */ case op_EVT_CHANGE: { void **slot = origin_slot(PREV_SLOT(r)); int what = GET_OP(slot); // !!! Support only what actually used on, and their brethren switch (what) { case op_SPINSLIDE: case op_SPINSLIDEa: case op_SPIN: case op_SPINc: case op_SPINa: case op_FSPIN: spin_connect(*slot, GTK_SIGNAL_FUNC(get_evt_1), r); break; case op_CHECK: case op_CHECKb: gtk_signal_connect(*slot, "toggled", GTK_SIGNAL_FUNC(get_evt_1), r); break; case op_COLOR: case op_TCOLOR: cpick_set_evt(*slot, r); break; case op_CSCROLL: { GtkAdjustment *xa, *ya; get_scroll_adjustments(*slot, &xa, &ya); gtk_signal_connect(GTK_OBJECT(xa), "value_changed", GTK_SIGNAL_FUNC(get_evt_1), r); gtk_signal_connect(GTK_OBJECT(ya), "value_changed", GTK_SIGNAL_FUNC(get_evt_1), r); break; } case op_CANVAS: /* !!! This is sent after realize, or resize while realized */ gtk_signal_connect(*slot, "configure_event", GTK_SIGNAL_FUNC(get_evt_conf), r); break; case op_TEXT: #if GTK_MAJOR_VERSION >= 2 /* In GTK+1, same handler as for GtkEntry */ g_signal_connect(gtk_text_view_get_buffer( GTK_TEXT_VIEW(*slot)), "changed", GTK_SIGNAL_FUNC(get_evt_1), r); break; #endif case op_ENTRY: case op_MLENTRY: case op_PENTRY: case op_PATH: case op_PATHs: gtk_signal_connect(*slot, "changed", GTK_SIGNAL_FUNC(get_evt_1), r); break; case op_LISTCX: { listc_data *ld = slot[2]; ld->change = r; break; } } } // fallthrough /* Remember that event needs triggering here */ /* Or remember a cleanup location */ case op_EVT_SCRIPT: case op_EVT_MULTI: case op_TRIGGER: case op_CLEANUP: widget = NULL; break; /* Allocate/copy memory */ case op_TALLOC: case op_TCOPY: { int l = *(int *)((char *)ddata + (int)pp[2]); if (!l) continue; dtail -= VVS(l); if (op == op_TCOPY) memcpy(dtail, *(void **)v, l); *(void **)v = dtail; continue; } default: /* Set nondefault border size */ if ((op >= op_BOR_0) && (op < op_BOR_LAST)) borders[op - op_BOR_0] = lp ? (int)v - DEF_BORDER : 0; continue; } if (ref) { /* Finish pseudo widget */ if (pk == pk_UNREALV) { ((swdata *)dtail)->value = tpad; ((swdata *)dtail)->id = wid; wid = NULL; pk = pk_UNREAL; } if (pk == pk_UNREAL) { widget = (void *)dtail; ((swdata *)dtail)->op = op; pk = 0; } /* Remember this */ FIX_SLOT(r, widget ? (void *)widget : res); /* Remember events */ if (ref > 2) ADD_SLOT(r, res, pp + lp - 3, NULL); if (ref > 1) ADD_SLOT(r, res, pp + lp - 1, NULL); /* Remember name */ if (scripted && cmds[op] && (cmds[op]->uop > 0) && (cmds[op]->uop != op_uLABEL)) { static void *id_ALTNAME = WBrh(uALTNAME, 0); dtail -= VVS(sizeof(swdata)); ADD_SLOT(r, dtail, &id_ALTNAME, dtail); ((swdata *)dtail)->op = op_uALTNAME; ((swdata *)dtail)->id = wid; wid = NULL; } } /* Pack this according to mode flags */ if (script) continue; // no packing in script mode mods.cw = cw; { GtkWidget *w = do_prepare(widget, pk, &mods); memset(&mods, 0, sizeof(mods)); if (((pk & pk_MASK) != pk_NONE) && do_pack(w, wp, pp, pk, tpad)) CT_POP(wp); // unstack } /* Stack this */ if (ct) CT_PUSH(wp, sw ? sw : widget, ct); ct = 0; sw = NULL; if (gid && keygroup) // Nested group keygroup = ini_setsection(&main_ini, keygroup, gid); } } static void do_destroy(void **wdata) { void **pp, *v = NULL; char *data = GET_DDATA(wdata); v_dd *vdata = GET_VDATA(wdata); int op; if (vdata->done) return; // Paranoia vdata->done = TRUE; if (vdata->ref) { vdata->ref = 0; gtk_widget_ref(GET_REAL_WINDOW(wdata)); // Put the ref back } if (vdata->destroy) { void **base = vdata->destroy[0], **desc = vdata->destroy[1]; ((evt_fn)desc[1])(GET_DDATA(base), base, (int)desc[0] & WB_OPMASK, vdata->destroy); } for (wdata = GET_WINDOW(wdata); (pp = wdata[1]); wdata = NEXT_SLOT(wdata)) { op = (int)*pp++; v = pp[0]; if (op & WB_FFLAG) v = data + (int)v; if (IS_UNREAL(wdata)) op = GET_UOP(wdata); op &= WB_OPMASK; switch (op) { case op_uFPICK: v = &((swdata *)*wdata)->strs; // Fallthrough case op_CLEANUP: free(*(void **)v); break; case op_CLIPFORM: { clipform_data *cd = *wdata; gtk_target_list_unref(cd->targets); free(cd); break; } case op_uENTRY: case op_uPATHSTR: v = &((swdata *)*wdata)->strs; // Fallthrough case op_TEXT: case op_FONTSEL: g_free(*(char **)v); break; case op_TABLETBTN: conf_done(NULL); break; case op_uMOUNT: // !!! REMOUNT not expected in unreal state run_destroy(((swdata *)*wdata)->strs); break; case op_REMOUNT: { void **where = *(void ***)v; GtkWidget *what = gtk_bin_get_child(GTK_BIN(*wdata)); gtk_widget_reparent(what, where[0]); gtk_widget_show(where[0]); get_evt_1(where[0], NEXT_SLOT(where)); break; } case op_LISTCX: listcx_done(*wdata, wdata[2]); break; case op_MAINWINDOW: gtk_main_quit(); break; } } } static void *do_query(char *data, void **wdata, int mode) { void **pp, *v = NULL; int op; for (; (pp = wdata[1]); wdata = NEXT_SLOT(wdata)) { op = (int)*pp++; v = op & (~0U << WB_LSHIFT) ? pp[0] : NULL; if (op & WB_FFLAG) v = data + (int)v; if (op & WB_NFLAG) v = *(void **)v; // dereference if (IS_UNREAL(wdata)) op = GET_UOP(wdata); op &= WB_OPMASK; switch (op) { case op_FPICKpm: fpick_get_filename(*wdata, v, PATHBUF, FALSE); break; case op_uFPICK: strncpy0(v, ((swdata *)*wdata)->strs, PATHBUF); break; case op_SPINSLIDE: case op_SPINSLIDEa: case op_SPIN: case op_SPINc: case op_SPINa: *(int *)v = mode & 1 ? gtk_spin_button_get_value_as_int( GTK_SPIN_BUTTON(*wdata)) : read_spin(*wdata); break; case op_uSPIN: case op_uFSPIN: case op_uSPINa: case op_uSCALE: case op_uCHECK: case op_uCHECKb: case op_uOPT: case op_uOPTD: case op_uRPACK: case op_uRPACKD: case op_uCOLOR: case op_uMENUCHECK: *(int *)v = ((swdata *)*wdata)->value; if (op == op_uCHECKb) inifile_set_gboolean(pp[2], *(int *)v); break; case op_FSPIN: *(int *)v = rint((mode & 1 ? #if GTK_MAJOR_VERSION == 3 gtk_spin_button_get_value(GTK_SPIN_BUTTON(*wdata)) : #else GTK_SPIN_BUTTON(*wdata)->adjustment->value : #endif read_float_spin(*wdata)) * 100); break; case op_TBTOGGLE: #if GTK_MAJOR_VERSION == 3 /* In GTK+1&2, same handler as for GtkToggleButton */ *(int *)v = gtk_toggle_tool_button_get_active(*wdata); break; #endif case op_CHECK: case op_CHECKb: case op_TOGGLE: case op_TBBOXTOG: *(int *)v = gtk_toggle_button_get_active(*wdata); if (op == op_CHECKb) inifile_set_gboolean(pp[2], *(int *)v); break; case op_TBRBUTTON: { GSList *group; void **slot = wdata; /* If reading radio group through an inactive slot */ #if GTK_MAJOR_VERSION == 3 if (!gtk_toggle_tool_button_get_active(*wdata)) { /* Let outer loop find active item */ if (mode <= 1) break; /* Otherwise, find active item here */ group = gtk_radio_tool_button_get_group(*wdata); /* !!! The ugly thing returns a group of _regular_ * radiobuttons which sit inside toolbuttons */ while (group && !gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(group->data))) group = group->next; if (!group) break; // impossible happened slot = g_object_get_qdata(G_OBJECT( gtk_widget_get_parent(group->data)), tool_key); } #else /* #if GTK_MAJOR_VERSION <= 2 */ if (!gtk_toggle_button_get_active(*wdata)) { /* Let outer loop find active item */ if (mode <= 1) break; /* Otherwise, find active item here */ group = gtk_radio_button_group(*wdata); while (group && !GTK_TOGGLE_BUTTON(group->data)->active) group = group->next; if (!group) break; // impossible happened slot = gtk_object_get_user_data( GTK_OBJECT(group->data)); } #endif *(int *)v = TOOL_ID(slot); break; } case op_MENUCHECK: *(int *)v = gtk_check_menu_item_get_active( GTK_CHECK_MENU_ITEM(*wdata)); break; case op_MENURITEM: { GSList *group; void **slot = wdata; /* If reading radio group through an inactive slot */ if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(*wdata))) { /* Let outer loop find active item */ if (mode <= 1) break; /* Otherwise, find active item here */ group = gtk_radio_menu_item_group(*wdata); while (group && !gtk_check_menu_item_get_active( GTK_CHECK_MENU_ITEM(group->data))) group = group->next; if (!group) break; // impossible happened #if GTK_MAJOR_VERSION == 3 slot = g_object_get_qdata(G_OBJECT(group->data), tool_key); #else slot = gtk_object_get_user_data( GTK_OBJECT(group->data)); #endif } *(int *)v = TOOL_ID(slot); break; } case op_uMENURITEM: { void **slot = wdata; int n; /* If reading radio group through an inactive slot */ if (!((swdata *)*wdata)->value) { /* Let outer loop find active item */ if (mode <= 1) break; /* Otherwise, find active item here */ while ((n = ((swdata *)slot[0])->range[0])) slot -= n; while (TRUE) { if (((swdata *)slot[0])->value) break; if (!(n = ((swdata *)slot[0])->range[1])) break; slot += n; } if (!n) break; // impossible happened } *(int *)v = TOOL_ID(slot); break; } case op_TLSPINPACK: case op_HEXENTRY: case op_EYEDROPPER: case op_COLORLIST: case op_COLORLISTN: case op_GRADBAR: case op_LISTCCr: case op_uLISTCC: case op_LISTC: case op_LISTCd: case op_LISTCu: case op_LISTCS: case op_LISTCX: case op_uLISTC: break; // self-reading case op_KEYBUTTON: { keybutton_data *dt = wdata[2]; *(char **)v = !dt->key ? NULL : key_name(dt->key, dt->mod, dt->section); break; } case op_COLOR: *(int *)v = cpick_get_colour(*wdata, NULL); break; case op_TCOLOR: *(int *)v = cpick_get_colour(*wdata, (int *)v + 1); break; case op_CSCROLL: { GtkAdjustment *xa, *ya; int *xp = v; get_scroll_adjustments(*wdata, &xa, &ya); xp[0] = gtk_adjustment_get_value(xa); xp[1] = gtk_adjustment_get_value(ya); break; } case op_RPACK: case op_RPACKD: *(int *)v = wj_radio_pack_get_active(*wdata); break; case op_OPT: case op_OPTD: *(int *)v = wj_option_menu_get_history(*wdata); break; case op_COMBO: *(int *)v = wj_combo_box_get_history(*wdata); break; case op_PCTCOMBO: *(int *)v = 0; // default for error sscanf(gtk_entry_get_text( GTK_ENTRY(pctcombo_entry(*wdata))), "%d%%", (int *)v); break; case op_COMBOENTRY: *(const char **)v = comboentry_get_text(*wdata); break; case op_ENTRY: case op_MLENTRY: *(const char **)v = gtk_entry_get_text(GTK_ENTRY(*wdata)); break; case op_uENTRY: case op_uPATHSTR: *(char **)v = ((swdata *)*wdata)->strs; break; case op_PENTRY: case op_PATH: gtkncpy(v, gtk_entry_get_text(GTK_ENTRY(*wdata)), op != op_PATH ? (int)pp[1] : PATHBUF); break; case op_PATHs: { char path[PATHBUF]; gtkncpy(path, gtk_entry_get_text(GTK_ENTRY(*wdata)), PATHBUF); inifile_set(v, path); break; } case op_TEXT: g_free(*(char **)v); *(char **)v = read_textarea(*wdata); break; case op_FONTSEL: { char **ss = v; g_free(ss[0]); #if GTK_MAJOR_VERSION == 1 ss[0] = NULL; if (gtk_font_selection_get_font(*wdata)) #endif ss[0] = gtk_font_selection_get_font_name(*wdata); *(const char **)(ss + 1) = gtk_font_selection_get_preview_text(*wdata); break; } case op_MOUNT: *(int *)v = !!gtk_bin_get_child(GTK_BIN(*wdata)); break; case op_uMOUNT: *(int *)v = !!((swdata *)*wdata)->strs; break; default: v = NULL; break; } if (mode > 1) return (v); } return (NULL); } void run_query(void **wdata) { v_dd *vdata = GET_VDATA(wdata); /* Prod a focused widget which needs defocusing to update */ if (!vdata->script) { GtkWidget *w = GET_REAL_WINDOW(wdata); GtkWidget *f = gtk_window_get_focus(GTK_WINDOW(w)); /* !!! No use to check if "fupslot" has focus - all dialogs with * such widget get destroyed after query anyway */ if (f && (GTK_IS_SPIN_BUTTON(f) || vdata->fupslot)) gtk_window_set_focus(GTK_WINDOW(w), NULL); } do_query(GET_DDATA(wdata), GET_WINDOW(wdata), 0); } void run_destroy(void **wdata) { v_dd *vdata = GET_VDATA(wdata); if (vdata->done) return; // already destroyed if (vdata->script) // simulated { do_destroy(wdata); free(GET_DDATA(wdata)); return; } /* Work around WM misbehaviour, and save position & size if needed */ cmd_showhide(GET_WINDOW(wdata), FALSE); #if 0 /* Destroy the contents right now */ gtk_widget_destroy(GET_REAL_WINDOW(wdata)); #else /* Do delayed destruction, by borrowing the structural ref */ if (vdata->ref) return; vdata->ref = 1; gtk_widget_unref(GET_REAL_WINDOW(wdata)); #endif } void cmd_reset(void **slot, void *ddata) { // !!! Support only what actually used on, and their brethren void *v, **pp, **wdata = slot; int op, opf, group = FALSE; for (; (pp = wdata[1]); wdata = NEXT_SLOT(wdata)) { opf = op = (int)*pp++; v = WB_GETLEN(op) ? pp[0] : NULL; if (op & WB_FFLAG) v = (char *)ddata + (int)v; if (op & WB_NFLAG) v = *(void **)v; // dereference if (IS_UNREAL(wdata)) op = GET_UOP(wdata); op &= WB_OPMASK; switch (op) { case op_uOP: /* If GROUP, reset up to one w/o script flag */ if ((opf & WB_OPMASK) == op_uOP) group = !group || (opf & WB_SFLAG); break; case op_SPINSLIDE: case op_SPINSLIDEa: case op_SPIN: case op_SPINc: case op_SPINa: gtk_spin_button_set_value(*wdata, *(int *)v); break; case op_TLSPINPACK: { void **vp = wdata[2]; int i, n = (int)pp[1]; *vp = NULL; // Lock for (i = 0; i < n; i++) { GtkSpinButton *spin = vp[i * 2 + 1]; int *p = (int *)v + i * 3; gtk_spin_button_set_value(spin, *p); /* Value might get clamped, and slot is * self-reading so should reflect that */ *p = gtk_spin_button_get_value_as_int(spin); } *vp = wdata; // Unlock break; } case op_uSPIN: case op_uSPINa: { swdata *sd = *wdata; int n = *(int *)v; sd->value = n > sd->range[1] ? sd->range[1] : n < sd->range[0] ? sd->range[0] : n; break; } case op_TBTOGGLE: #if GTK_MAJOR_VERSION == 3 /* In GTK+1&2, same handler as for GtkToggleButton */ gtk_toggle_tool_button_set_active(*wdata, *(int *)v); break; #endif case op_CHECK: case op_CHECKb: case op_TOGGLE: case op_TBBOXTOG: gtk_toggle_button_set_active(*wdata, *(int *)v); break; case op_uCHECK: case op_uCHECKb: ((swdata *)*wdata)->value = !!*(int *)v; break; case op_OPT: /* !!! No support for discontinuous lists, for now */ wj_option_menu_set_history(*wdata, *(int *)v); break; case op_OPTD: opt_reset(wdata, ddata, *(int *)v); break; case op_uOPT: case op_uOPTD: { swdata *sd = *wdata; int n; if (op == op_uOPTD) { char **strs = sd->strs = *(char ***)((char *)ddata + (int)pp[1]); for (n = 0; strs[n]; n++); // Count strings sd->cnt = n; } n = *(int *)v; sd->value = (n < 0) || (n >= sd->cnt) || !((char **)sd->strs)[n][0] ? 0 : n; break; } case op_LISTCCr: listcc_reset(wdata, -1); #ifdef U_LISTS_GTK1 /* !!! Or the changes will be ignored if the list wasn't * yet displayed (as in inactive dock tab) - WJ */ gtk_widget_queue_resize(*wdata); #endif break; /* op_uLISTCC needs no resetting */ case op_LISTC: case op_LISTCd: case op_LISTCu: case op_LISTCS: case op_LISTCX: listc_reset(*wdata, wdata[2]); break; case op_uLISTC: ulistc_reset(wdata); break; case op_CSCROLL: { GtkAdjustment *xa, *ya; int *xp = v; get_scroll_adjustments(*wdata, &xa, &ya); #if GTK_MAJOR_VERSION == 3 { /* This is to change both before triggering any */ guint id = g_signal_lookup("value_changed", G_TYPE_FROM_INSTANCE(xa)); g_signal_handlers_block_matched(G_OBJECT(xa), G_SIGNAL_MATCH_ID, id, 0, NULL, NULL, NULL); g_signal_handlers_block_matched(G_OBJECT(ya), G_SIGNAL_MATCH_ID, id, 0, NULL, NULL, NULL); gtk_adjustment_set_value(xa, xp[0]); gtk_adjustment_set_value(ya, xp[1]); g_signal_handlers_unblock_matched(G_OBJECT(xa), G_SIGNAL_MATCH_ID, id, 0, NULL, NULL, NULL); g_signal_handlers_unblock_matched(G_OBJECT(ya), G_SIGNAL_MATCH_ID, id, 0, NULL, NULL, NULL); } #else /* #if GTK_MAJOR_VERSION <= 2 */ xa->value = xp[0]; ya->value = xp[1]; #endif gtk_adjustment_value_changed(xa); gtk_adjustment_value_changed(ya); break; } case op_COMBOENTRY: comboentry_reset(*wdata, v, *(char ***)(ddata + (int)pp[1])); break; case op_ENTRY: case op_MLENTRY: gtk_entry_set_text(*wdata, *(char **)v); // Replace transient buffer - it may get freed on return *(const char **)v = gtk_entry_get_text(*wdata); break; case op_PATHs: v = inifile_get(v, ""); // read and fallthrough case op_PENTRY: case op_PATH: set_path(*wdata, v, PATH_VALUE); break; case op_RGBIMAGEP: { rgbimage_data *rd = wdata[2]; rd->rgb = v; // Size is fixed, but update source if (GTK_WIDGET_REALIZED(*wdata)) reset_rgbp(*wdata, rd); break; } case op_CANVASIMGB: { rgbimage_data *rd = wdata[2]; int nw, *xp = (int *)(ddata + (int)pp[1]); nw = (rd->w ^ xp[0]) | (rd->h ^ xp[1]); rd->rgb = v; rd->w = xp[0]; rd->h = xp[1]; rd->bkg = xp[2]; if (nw) wjcanvas_size(*wdata, xp[0], xp[1]); wjcanvas_redraw(*wdata, NULL); break; } case op_FCIMAGEP: { fcimage_data *fd = wdata[2]; fd->rgb = v; // Update source, leave other parts be if (GTK_WIDGET_REALIZED(*wdata)) reset_fcimage(*wdata, fd); break; } case op_KEYMAP: keymap_reset(wdata[2]); #if GTK_MAJOR_VERSION >= 2 gtk_signal_emit_by_name(GTK_OBJECT(gtk_widget_get_toplevel( GET_REAL_WINDOW(wdata_slot(wdata)))), "keys_changed", NULL); #endif break; #if 0 /* Not needed for now */ case op_FPICKpm: fpick_set_filename(*wdata, v, FALSE); break; case op_FSPIN: gtk_spin_button_set_value(*wdata, *(int *)v * 0.01); break; case op_uENTRY: case op_uPATHSTR: // Replace transient buffer - it may get freed on return *(char **)v = set_uentry(*wdata, *(char **)v); cmd_event(wdata, op_EVT_CHANGE); break; case op_TBRBUTTON: if (*(int *)v == TOOL_ID(wdata)) #if GTK_MAJOR_VERSION == 3 gtk_toggle_tool_button_set_active(*wdata, TRUE); #else gtk_toggle_button_set_active(*wdata, TRUE); #endif break; case op_MENURITEM: if (*(int *)v != TOOL_ID(wdata)) break; // Fallthrough case op_MENUCHECK: gtk_check_menu_item_set_active(*wdata, op == op_MENURITEM ? TRUE : *(int *)v); break; case op_PCTCOMBO: /* Same as in cmd_set() */ break; case op_RPACK: case op_RPACKD: case op_COLORLIST: case op_COLORLISTN: // !!! No ready setter functions for these (and no need of them yet) break; case op_COLOR: cpick_set_colour(*wdata, *(int *)v, 255); break; case op_TCOLOR: cpick_set_colour(*wdata, ((int *)v)[0], ((int *)v)[1]); break; case op_RGBIMAGE: { rgbimage_data *rd = wdata[2]; int *wh = (int *)(ddata + (int)pp[1]); rd->rgb = v; rd->w = wh[0]; rd->h = wh[1]; cmd_repaint(wdata); break; } #endif } if (!group) return; } } void cmd_sensitive(void **slot, int state) { int op; if (IS_UNREAL(slot)) { // !!! COLUMNs should redirect to their list slot instead ((swdata *)slot[0])->insens = !state; return; } op = GET_OP(slot); if (op >= op_EVT_0) return; // only widgets gtk_widget_set_sensitive(get_wrap(slot), state); } static int midmatch(const char *s, const char *v, int l) { while ((s = strchr(s, ' '))) { s += strspn(s, " ("); if (!strncasecmp(s, v, l)) break; } return (!!s); } static int find_string(swdata *sd, char *s, int l, int column); void **find_slot(void **slot, char *id, int l, int mlevel) { void **start = slot, **where = NULL; char buf[64], *nm, *ts; int op, n, p = INT_MAX; for (; slot[1]; slot = NEXT_SLOT(slot)) { op = GET_OP(slot); if (op == op_uOPNAME) break; // ENDSCRIPT marker if (mlevel >= 0) // Searching menu items { /* Reading the descriptors, so ignore unreal state */ // !!! Or maybe switch/case? if ((op == op_uALTNAME) || (op == op_uMENUITEM)) nm = ((swdata *)slot[0])->id; else if ((op == op_SUBMENU) || (op == op_ESUBMENU) || (op == op_SSUBMENU)) { nm = GET_DESCV(slot, 1); // Remove shortcut marker from toplevel items if ((ts = strchr(nm, '_'))) nm = wjstrcat(buf, sizeof(buf), nm, ts - nm, ts + 1, NULL); } else if ((op == op_MENUITEM) || (op == op_MENUCHECK) || (op == op_MENURITEM)) nm = GET_DESCV(slot, 3); else continue; if (mlevel) // Searching a sublevel { n = strspn(nm, "/"); if ((n < mlevel) && (op != op_uALTNAME)) break; // level end else if (n != mlevel) continue; // submenu or direct altname nm += n; } } else // Searching pseudo widgets { if (!IS_UNREAL(slot)) continue; if (GET_UOP(slot) == op_uOP) { // Ignore dummy slots if (op != op_uOP) continue; // Skip groups in flat search if (mlevel == MLEVEL_FLAT) continue; // Stop on new group in block search if (mlevel == MLEVEL_BLOCK) break; } // Ignore anything but groups in group search else if (mlevel == MLEVEL_GROUP) continue; nm = ((swdata *)slot[0])->id; if (!nm) continue; // No name } /* Match empty option name to an empty ID (default) */ if (!l) { if (nm[0]) continue; where = slot; break; } /* In a flattened widget, match contents */ if ((nm[0] == ':') && !nm[1] && (op == op_uALTNAME)) { void **w = origin_slot(slot); if (!IS_UNREAL(w)) continue; n = GET_UOP(w); // Allow only static lists for now if ((n != op_uOPT) && (n != op_uRPACK)) continue; n = find_string(w[0], id, l, FALSE); if (n < 0) continue; // Use matched string as widget name nm = ((char **)((swdata *)w[0])->strs)[n]; } /* Match at beginning, preferring shortest word */ if (!strncasecmp(nm, id, l)) { int d = l + strcspn(nm + l, " .,()"); // Prefer if no other words d = d + d + !!nm[d + strcspn(nm + d, " .,()")]; if (d >= p) continue; p = d; where = slot; } else if (where); /* Match at word beginning */ else if (mlevel && midmatch(nm, id, l)) where = slot; } /* Resolve alternative name */ if (where && (GET_OP(where) == op_uALTNAME)) { nm = ((swdata *)where[0])->id; if ((nm[0] != ':') || nm[1]) // Leave flattening markers be where = origin_slot(where); } /* Try in-group searching */ if (!where && (mlevel == MLEVEL_FLAT) && (ts = memchr(id, '/', l)) && (ts != id) && (id + l - ts > 1)) { where = find_slot(start, id, ts - id, MLEVEL_GROUP); if (where) where = find_slot(NEXT_SLOT(where), ts + 1, id + l - ts - 1, MLEVEL_BLOCK); } return (where); } /* Match string to list column of strings, or to widget's string list */ static int find_string(swdata *sd, char *s, int l, int column) { char *tmp; col_data *c = NULL; int i, ll, p = INT_MAX, n = sd->cnt; if (!s || !l) return (-1); // Error if (column) { c = sd->strs; if (!c) return (-1); // Not linked column = n; /* List length */ n = *(int *)(c->ddata + (int)GET_DESCV(c->r, 2)); } for (ll = -1 , i = 0; i < n; i++) { tmp = c ? get_cell(c, i, column) : ((char **)sd->strs)[i]; if (!tmp[0]) continue; /* Match at beginning */ if (!strncasecmp(tmp, s, l)) { int k = strlen(tmp); if (k >= p) continue; p = k; } else if (ll >= 0) continue; /* Match at word beginning */ else if (!midmatch(tmp, s, l)) continue; ll = i; } return (ll); } /* Resolve parameter chaining */ static char **unchain_p(char **strs) { while (*strs == (void *)strs) strs = (void *)strs[1]; return (strs); } /* Parse a parenthesized list of tuples into an array of ints * List may continue in next script positions */ static multi_ext *multi_parse(char *s0) { multi_ext *mx = NULL; char st, *ss, *tmp, **strs; int sc = 0, n = 0, cnt = 0, w = 0, mw = INT_MAX, fp = -1; int v, *uninit_(ix), **uninit_(rows); if (s0[0] != '(') return (NULL); // Wrong strs = script_cmds; ss = s0 + 1; st = '('; while (TRUE) { if (!ss[0]) // End of string - get next part { if (st == '1') st = ' '; // After a number - is whitespace strs = unchain_p(strs); ss = *strs++; if (!ss) return (NULL); // Unterminated - fail continue; } if ((ss[0] == ')') && !ss[1]) // Lone ')' - done { if (mx) // 2nd pass - return the struct { /* Finalize */ script_cmds = strs; return (mx); } if (!cnt) return (NULL); // Empty - fail if (st == ',') return (NULL); // After comma - fail if (mw > n) mw = n; // Min columns sc++; // Total rows /* Allocate the struct, now that we know what it'll hold */ mx = calloc(1, sizeof(multi_ext) + sizeof(int *) * (sc + 1) + sizeof(int) * (cnt + sc + 1)); if (!mx) return (NULL); // No memory - fail /* Init the struct */ mx->nrows = sc; mx->ncols = w; mx->mincols = mw; mx->fractcol = fp; /* Prepare */ rows = mx->rows; ix = (void *)(rows + sc + 1); // Extremely unlikely, but why not make sure if (ALIGNOF(int) > ALIGNOF(int *)) ix = ALIGNED(ix, ALIGNOF(int)); /* Restart */ sc = n = cnt = 0; // Row, column, count strs = script_cmds; ss = s0 + 1; st = '('; // State continue; } if ((ss[0] == ' ') || (ss[0] == '\t') || (ss[0] == '\n')) // Whitespace - skip { if (st == '1') st = ' '; // After a number - remember ss++; continue; } if (ss[0] == ',') // Comma - remember { if ((st == '(') || (st == ',')) return (NULL); // After a marker - fail st = ','; ss++; continue; } // Something else - must be a number if (cnt == INT_MAX) return (NULL); // Paranoia if (st == '1') return (NULL); // Right after a number - fail if (st == ' ') // After whitespace - new row { if (mw > n) mw = n; // Min columns sc++; n = 0; } // !!! Only one fixedpoint column allowed for now if (n != fp) // Regular integer column { v = strtol(ss, &tmp, 10); // Try parsing as int if (*tmp == '.') // Maybe floating { if (fp >= 0) return (NULL); // Wrong column - fail fp = n; } } if (n == fp) // Fixedpoint column v = (int)(g_strtod(ss, &tmp) * MAX_PRESSURE + 0.5); if (tmp == ss) return (NULL); // Error - fail ss = tmp; // Skip the parsed chars if (mx) // Store the number we got { if (!n) rows[sc] = ix++; rows[sc][0] = n + 1; *ix++ = v; } st = '1'; // It was a number n++; // Next column if (n > w) w = n; // Max column cnt++; // One more number } } int cmd_setstr(void **slot, char *s) { void *v; char *tmp, *st = NULL; int op, ll = 0, res = 1; /* If see a list and prepared to handle it, do so */ if (s && (s[0] == '(') && (v = op_slot(slot, op_EVT_MULTI))) slot = v; op = GET_OP(slot); if (IS_UNREAL(slot)) op = GET_UOP(slot); switch (op) { case op_uFPICK: case op_uPATHSTR: if (!s) s = ""; // Commandline is already in system encoding if (!cmd_mode) s = st = gtkncpy(NULL, s, PATHBUF); cmd_setv(slot, s, op == op_uFPICK ? FPICK_VALUE : ENTRY_VALUE); g_free(st); goto done; case op_ENTRY: case op_uENTRY: if (!s) s = ""; // Commandline is in system encoding if (cmd_mode) s = st = gtkuncpy(NULL, s, 0); cmd_setv(slot, s, ENTRY_VALUE); g_free(st); goto done; case op_CHECK: case op_CHECKb: case op_TOGGLE: case op_TBTOGGLE: case op_TBBOXTOG: case op_TBRBUTTON: case op_MENUCHECK: case op_MENURITEM: case op_uCHECK: case op_uCHECKb: case op_uMENUCHECK: case op_uMENURITEM: ll = !s ? TRUE : !s[0] ? FALSE : str2bool(s); if (ll < 0) return (-1); // Error break; case op_TXTCOLUMN: case op_XTXTCOLUMN: ll = TRUE; // Fallthrough case op_uOPT: case op_uOPTD: case op_uRPACK: case op_uRPACKD: if (!s) return (-1); // Error ll = find_string(slot[0], s, strlen(s), ll); if (ll < 0) return (-1); // Error break; case op_BUTTON: case op_TBBUTTON: case op_uBUTTON: case op_MENUITEM: case op_uMENUITEM: ll = res = 0; // No use for parameter break; case op_FSPIN: case op_uFSPIN: if (s && s[0]) { double a = g_strtod(s, &tmp); if (*tmp) return (-1); // Error ll = rint(a * 100); break; } // Fallthrough case op_SPIN: case op_SPINc: case op_SPINa: case op_SPINSLIDE: case op_SPINSLIDEa: case op_uSPIN: case op_uSPINa: case op_LISTCCr: case op_uLISTCC: case op_uLISTC: case op_IDXCOLUMN: if (!s) return (-1); // Error ll = 0; // Default if (s[0]) { ll = strtol(s, &tmp, 10); if (*tmp) return (-1); // Error } break; case op_uCOLOR: ll = parse_color(s); if (ll < 0) return (-1); // Error break; case op_uSCALE: { swdata *sd = slot[0]; if (!s || !s[0]) return (-1); // Error if (strchr(s, '%')) /* "w=125%" */ { ll = strtol(s, &tmp, 10); if (*tmp != '%') return (-1); // Error ll = (ll * (int)sd->strs) / 100; } else if ((s[0] == 'x') || (s[0] == 'X')) /* "w=x1.25" */ { double a = g_strtod(s + 1, &tmp); if (*tmp) return (-1); // Error ll = rint((int)sd->strs * a); } else /* "w=200" */ { ll = strtol(s, &tmp, 10); if (*tmp) return (-1); // Error } sd->cnt = 3; // Value is being set directly break; } case op_EVT_MULTI: if ((v = multi_parse(s))) { void **base = slot[0], **desc = slot[1]; res = ((evtxr_fn)desc[1])(GET_DDATA(base), base, (int)desc[0] & WB_OPMASK, slot, v); if (res >= 0) free(v); // Handler can ask to keep it if (res) return (1); } // !!! Fallthrough to fail default: return (-1); // Error: cannot handle } /* From column to list */ if ((op >= op_COLUMN_0) && (op < op_COLUMN_LAST)) slot = ((col_data *)((swdata *)slot[0])->strs)->r; /* Set value to widget */ cmd_set(slot, ll); done: cmd_event(slot, op_EVT_SCRIPT); // Notify return (res); } static int tbar_event(void **slot, int what) { void **base, **desc, **tbar = NULL; int op = GET_OP(slot); if (IS_UNREAL(slot)) op = GET_UOP(slot); switch (op) { case op_TBBUTTON: case op_TBTOGGLE: case op_TBRBUTTON: case op_TBBOXTOG: case op_MENUITEM: case op_MENUCHECK: case op_MENURITEM: tbar = slot[2]; break; case op_uMENUITEM: case op_uMENUCHECK: case op_uMENURITEM: tbar = ((swdata *)slot[0])->strs; break; } if (tbar) tbar = op_slot(tbar, what); if (!tbar || ((what == op_EVT_CLICK) && (WB_GETLEN(GET_OPF(slot)) < 5))) return (-1); // Fail /* Call event at saved slot, for this slot */ base = tbar[0]; desc = tbar[1]; ((evt_fn)desc[1])(GET_DDATA(base), base, (int)desc[0] & WB_OPMASK, slot); return (0); } int cmd_run_script(void **slot, char **strs) { char *opt, *tmp, **err = NULL; void **wdata; int op, ll, maybe; /* Resolve slot */ op = GET_OP(slot); if (IS_UNREAL(slot)) op = GET_UOP(slot); if (op == op_uMOUNT) slot = ((swdata *)*slot)->strs; else if (op == op_MOUNT) slot = slot[2]; if (!slot) return (1); // Paranoia /* Step through options */ while (strs = unchain_p(strs) , opt = *strs) { /* Stop on commands and empty strings */ if (!opt[0] || (opt[0] == '-')) break; strs++; /* Stop on dialog close */ if ((opt[0] == ':') && !opt[1]) break; /* Have option: first, parse it */ opt += (maybe = opt[0] == '.'); // Optional if preceded by "." // Expect "(list)", "name=value", or "name:" ll = opt[0] == '(' ? 0 : strcspn(opt, "=:"); /* Now, find target for the option */ wdata = find_slot(slot, opt, ll, MLEVEL_FLAT); /* Raise an error if no match */ if (!wdata) { if (maybe) continue; // Ignore optional options err = strs; break; } /* For flattened lists, uALTNAME gets returned */ op = GET_OP(wdata); wdata = origin_slot(wdata); /* Leave insensitive slots alone */ if (!cmd_checkv(wdata, SLOT_SENSITIVE)) continue; // !!! Or maybe raise an error, too? script_cmds = strs; // For nested dialog /* Set value to flattened list */ if (op == op_uALTNAME) { ll = find_string(wdata[0], opt, ll, FALSE); // Cannot fail cmd_set(wdata, ll); cmd_event(wdata, op_EVT_SCRIPT); // Notify } /* Activate right-click handler */ else if (opt[ll] == ':') ll = tbar_event(wdata, op_EVT_CLICK); /* Set value to slot */ else ll = cmd_setstr(wdata, !opt[ll] ? NULL : opt + ll + (opt[ll] == '=')); /* Raise an error if invalid value */ if (ll < 0) { err = strs; break; } strs = script_cmds; // Nested dialogs can consume options if (user_break) break; } script_cmds = strs; // Stopped at here /* An error happened - report it */ if (err) { err--; // Previous option caused the error /* Find name-bearing slot */ slot = wdata; if (slot && !IS_UNREAL(slot)) slot = op_slot(wdata, op_uALTNAME); tmp = g_strdup_printf(!wdata ? _("'%s' does not match any widget") : _("'%s' value does not fit '%s' widget"), *err, slot ? ((swdata *)slot[0])->id : NULL); alert_box(_("Error"), tmp, NULL); g_free(tmp); return (-1); } /* Now activate the OK handler if any */ for (wdata = slot; wdata[1]; wdata = NEXT_SLOT(wdata)) if (IS_UNREAL(wdata) && ((GET_UOP(wdata) == op_uOKBTN) || (GET_UOP(wdata) == op_uFPICK))) break; if (wdata[1]) { cmd_event(wdata, op_EVT_OK); /* !!! The memory block is likely to be freed at this point */ return (0); } return (1); } void cmd_showhide(void **slot, int state) { GtkWidget *wrap, *ws = NULL; void **keymap = NULL; int raise = FALSE, unfocus = FALSE, mx = FALSE; if (GET_OP(slot) == op_WDONE) slot = NEXT_SLOT(slot); // skip head noop if (IS_UNREAL(slot)) { if ((GET_OP(PREV_SLOT(slot)) == op_WDONE) && state) { v_dd *vdata = GET_VDATA(PREV_SLOT(slot)); /* Script is run when the window is first displayed */ if (vdata->run) return; // Redisplay vdata->run = TRUE; if ((cmd_run_script(slot, vdata->script) < 0) && (GET_UOP(slot) == op_uWINDOW)) run_destroy(PREV_SLOT(slot)); // On error } return; } if (GET_OP(slot) >= op_EVT_0) return; // only widgets wrap = get_wrap(slot); // For *some* pkf_PARENT widgets, hide/show their parent if (!GTK_WIDGET_VISIBLE(wrap) ^ !!state) return; // no use if (GET_OP(PREV_SLOT(slot)) == op_WDONE) // toplevels are special { v_dd *vdata = GET_VDATA(PREV_SLOT(slot)); GtkWidget *w = GTK_WIDGET(slot[0]); if (state) // show - apply stored size, position, raise, unfocus { gtk_window_set_transient_for(GTK_WINDOW(w), vdata->tparent); #if GTK_MAJOR_VERSION == 3 if (vdata->ininame) gtk_window_move(GTK_WINDOW(w), #else if (vdata->ininame) gtk_widget_set_uposition(w, #endif vdata->xywh[0], vdata->xywh[1]); else vdata->ininame = ""; // first time gtk_window_set_default_size(GTK_WINDOW(w), vdata->xywh[2] ? vdata->xywh[2] : -1, vdata->xywh[3] ? vdata->xywh[3] : -1); if (vdata->modal) gtk_window_set_modal(GTK_WINDOW(w), TRUE); /* Prepare to do postponed actions */ mx = vdata->xywh[4]; #if GTK_MAJOR_VERSION >= 2 /* !!! When doing maximize, we have to display window * contents after window itself, or some widgets may get * locked into wrong size by premature first-time size * request & allocation within unmaximized window. * On GTK+1 the resize mechanism is quite different and * such reordering only makes the result even worse; what * can cause proper resizing there, isn't found yet - WJ */ if (mx) { ws = gtk_bin_get_child(GTK_BIN(w)); if (ws && GTK_WIDGET_VISIBLE(ws)) widget_showhide(ws, FALSE); else ws = NULL; } #endif keymap = vdata->keymap; raise = vdata->raise; unfocus = vdata->unfocus; vdata->raise = vdata->unfocus = FALSE; } else // hide - remember size & position { /* !!! These reads also do gdk_flush() which, followed by * set_transient(NULL), KDE somehow needs for restoring * focus from fileselector back to pref window - WJ */ if (!(vdata->xywh[4] = is_maximized(w))) { #if GTK_MAJOR_VERSION == 3 gtk_window_get_size(GTK_WINDOW(w), #else gdk_window_get_size(w->window, #endif vdata->xywh + 2, vdata->xywh + 3); gdk_window_get_root_origin(gtk_widget_get_window(w), vdata->xywh + 0, vdata->xywh + 1); } if (vdata->ininame && vdata->ininame[0]) rw_pos(vdata, TRUE); /* Needed for "dialogparent" effect in KDE4 to not misbehave */ if (vdata->modal) gtk_window_set_modal(GTK_WINDOW(w), FALSE); /* Needed in Windows to stop GTK+ lowering the main window, * and everywhere to avoid forcing focus to main window */ gtk_window_set_transient_for(GTK_WINDOW(w), NULL); } } widget_showhide(wrap, state); /* !!! Window must be visible, or maximize fails if either dimension is * already at max, with KDE3 & 4 at least - WJ */ if (mx) set_maximized(slot[0]); if (ws) widget_showhide(ws, TRUE); if (raise) gdk_window_raise(gtk_widget_get_window(GTK_WIDGET(slot[0]))); if (unfocus) gtk_window_set_focus(slot[0], NULL); /* !!! Have to wait till canvas is displayed, to init keyboard */ if (keymap) keymap_reset(keymap[2]); } void cmd_set(void **slot, int v) { swdata *sd; int op; slot = origin_slot(slot); op = GET_OP(slot); if (IS_UNREAL(slot)) op = GET_UOP(slot); sd = slot[0]; // !!! Support only what actually used on, and their brethren switch (op) { case op_DOCK: { dock_data *dd = slot[2]; GtkWidget *window, *vbox = dd->vbox, *pane = dd->pane; char *ini = ((void **)slot[1])[1]; int w, w2; if (!v ^ !!gtk_paned_get_child1(GTK_PANED(pane))) return; // nothing to do window = gtk_widget_get_toplevel(slot[0]); #if GTK_MAJOR_VERSION == 3 if (gtk_widget_get_visible(window)) gtk_window_get_size(GTK_WINDOW(window), &w2, NULL); /* Window size isn't yet valid */ else g_object_get(G_OBJECT(window), "default_width", &w2, NULL); #else if (GTK_WIDGET_VISIBLE(window)) gdk_window_get_size(window->window, &w2, NULL); /* Window size isn't yet valid */ else gtk_object_get(GTK_OBJECT(window), "default_width", &w2, NULL); #endif if (v) { /* Restore dock size if set, autodetect otherwise */ w = inifile_get_gint32(ini, -1); if (w >= 0) gtk_paned_set_position(GTK_PANED(pane), w2 - w); /* Now, let's juggle the widgets */ gtk_widget_ref(vbox); gtk_container_remove(GTK_CONTAINER(slot[0]), vbox); gtk_paned_pack1(GTK_PANED(pane), vbox, TRUE, TRUE); gtk_widget_show(pane); } else { inifile_set_gint32(ini, w2 - gtk_paned_get_position( GTK_PANED(pane))); gtk_widget_hide(pane); // vbox = gtk_paned_get_child1(GTK_PANED(pane)); gtk_widget_ref(vbox); gtk_container_remove(GTK_CONTAINER(pane), vbox); xpack(slot[0], vbox); } gtk_widget_unref(vbox); break; } case op_HVSPLIT: { hvsplit_data *hd = slot[2]; GtkWidget *pane, **p = hd->panes, *w = NULL, *box = slot[0]; int v0, v1; v0 = GTK_WIDGET_VISIBLE(p[0]) ? 1 : GTK_WIDGET_VISIBLE(p[1]) ? 2 : 0; v1 = (int)v < 1 ? 0 : (int)v > 1 ? 2 : 1; if (v1 == v0) break; // nothing to do if (!v1) // hide 2nd part { pane = p[v0 - 1]; gtk_widget_hide(pane); w = gtk_paned_get_child1(GTK_PANED(pane)); gtk_widget_ref(w); gtk_container_remove(GTK_CONTAINER(pane), w); xpack(box, w); } else if (!v0) // show 2nd part { pane = p[v1 - 1]; if (!gtk_paned_get_child2(GTK_PANED(pane))) // move { w = hd->inbox[1]; gtk_widget_ref(w); gtk_container_remove(GTK_CONTAINER( gtk_widget_get_parent(w)), w); gtk_paned_pack2(GTK_PANED(pane), w, TRUE, TRUE); gtk_widget_unref(w); gtk_widget_show(w); } w = hd->inbox[0]; gtk_widget_ref(w); gtk_container_remove(GTK_CONTAINER(box), w); gtk_paned_pack1(GTK_PANED(pane), w, TRUE, TRUE); gtk_widget_show(pane); } else // swap direction { pane = p[v0 - 1]; gtk_widget_hide(pane); w = gtk_paned_get_child1(GTK_PANED(pane)); gtk_widget_ref(w); gtk_container_remove(GTK_CONTAINER(pane), w); gtk_paned_pack1(GTK_PANED(p[2 - v0]), w, TRUE, TRUE); gtk_widget_unref(w); w = gtk_paned_get_child2(GTK_PANED(pane)); gtk_widget_ref(w); gtk_container_remove(GTK_CONTAINER(pane), w); gtk_paned_pack2(GTK_PANED(p[2 - v0]), w, TRUE, TRUE); gtk_widget_show(p[2 - v0]); } gtk_widget_unref(w); break; } case op_NOSPIN: spin_set_range(slot[0], v, v); break; case op_SPINSLIDE: case op_SPINSLIDEa: case op_SPIN: case op_SPINc: case op_SPINa: gtk_spin_button_set_value(slot[0], v); break; case op_uSCALE: /* uSCALE ignores indirect writes after a direct one */ if (sd->cnt == 2) break; sd->cnt &= 2; // Fallthrough case op_uSPIN: case op_uFSPIN: case op_uSPINa: case op_uCHECK: case op_uCHECKb: v = (op == op_uCHECK) || (op == op_uCHECKb) ? !!v : v > sd->range[1] ? sd->range[1] : v < sd->range[0] ? sd->range[0] : v; if (v == sd->value) break; // Fallthrough case op_uCOLOR: sd->value = v; cmd_event(slot, op_EVT_CHANGE); break; case op_uOPT: case op_uOPTD: case op_uRPACK: case op_uRPACKD: if ((v < 0) || (v >= sd->cnt) || !((char **)sd->strs)[v][0]) v = 0; if (v == sd->value) break; sd->value = v; cmd_event(slot, op_EVT_SELECT); break; case op_BUTTON: case op_uBUTTON: cmd_event(slot, op_EVT_CLICK); // for any value break; case op_TBBUTTON: #if GTK_MAJOR_VERSION == 3 g_signal_emit_by_name(slot[0], "clicked"); // for any value #else gtk_button_clicked(slot[0]); // for any value #endif break; case op_uMENURITEM: // Cannot unset itself, and no use to set twice if (!v || sd->value) break; /* Unset the whole group */ { void **r = slot; int n; while ((n = ((swdata *)r[0])->range[0])) r -= n; while (TRUE) { ((swdata *)r[0])->value = FALSE; if (!(n = ((swdata *)r[0])->range[1])) break; r += n; } } // Fallthrough case op_uMENUCHECK: v = !!v; if (sd->value == v) break; sd->value = v; // Fallthrough case op_uMENUITEM: tbar_event(slot, op_EVT_CHANGE); break; case op_FSPIN: gtk_spin_button_set_value(slot[0], v / 100.0); break; case op_TBTOGGLE: case op_TBRBUTTON: #if GTK_MAJOR_VERSION == 3 /* In GTK+1&2, same handler as for GtkToggleButton */ gtk_toggle_tool_button_set_active(slot[0], v); break; #endif case op_CHECK: case op_CHECKb: case op_TOGGLE: case op_TBBOXTOG: gtk_toggle_button_set_active(slot[0], v); break; case op_MENUITEM: gtk_menu_item_activate(slot[0]); // for any value break; case op_MENUCHECK: case op_MENURITEM: gtk_check_menu_item_set_active(slot[0], v); break; case op_OPT: case op_OPTD: /* !!! No support for discontinuous lists, for now */ wj_option_menu_set_history(slot[0], v); break; case op_PCTCOMBO: { char buf[32]; sprintf(buf, "%d%%", v); gtk_entry_set_text(GTK_ENTRY(pctcombo_entry(slot[0])), buf); #if GTK_MAJOR_VERSION == 1 /* Call the handler, for consistency */ get_evt_1(NULL, NEXT_SLOT(slot)); #endif break; } #ifdef U_CPICK_MTPAINT case op_HEXENTRY: *(int *)slot_data(slot, GET_DDATA(wdata_slot(NEXT_SLOT(slot)))) = v; set_hexentry(slot[0], v); break; #endif case op_PLAINBOOK: gtk_notebook_set_page(slot[0], v); break; case op_LISTCCr: { listcc_data *dt = slot[2]; if ((v < 0) || (v >= *dt->cnt)) break; // Ensure sanity *dt->idx = v; listcc_select_item(slot); break; } case op_uLISTCC: case op_uLISTC: { char *ddata = GET_DDATA(wdata_slot(slot)); int *cnt = (void *)(ddata + (int)GET_DESCV(slot, 2)); if ((v < 0) || (v >= *cnt)) break; // Ensure sanity *(int *)(sd->strs) = v; cmd_event(slot, op_EVT_SELECT); break; } case op_LISTC: case op_LISTCd: case op_LISTCu: case op_LISTCS: case op_LISTCX: listc_select_index(slot[0], v); break; } } /* Passively query one slot, show where the result went */ void *cmd_read(void **slot, void *ddata) { return (do_query(ddata, origin_slot(slot), 3)); } void cmd_peekv(void **slot, void *res, int size, int idx) { // !!! Support only what actually used on int op = GET_OP(slot); if (size <= 0) return; if (op == op_WDONE) { if (idx == WDATA_TABLET) { if (size >= sizeof(char *)) *(char **)res = tablet_device ? (char *)gdk_device_get_name(tablet_device) : NULL; return; } // skip to toplevel slot slot = NEXT_SLOT(slot) , op = GET_OP(slot); } if (IS_UNREAL(slot)) op = GET_UOP(slot); switch (op) { case op_uWINDOW: case op_MAINWINDOW: case op_WINDOW: case op_WINDOWm: case op_DIALOGm: if ((idx == WINDOW_DPI) && (size >= sizeof(int))) { GtkWidget *w = op == op_uWINDOW ? main_window : slot[0]; *(int *)res = cmd_mode ? 72 : // Use FreeType's default DPI (int)(window_dpi(w) / window_scale(w) + 0.5); } break; case op_FPICKpm: fpick_get_filename(slot[0], res, size, idx); break; case op_uFPICK: { char *s = ((swdata *)slot[0])->strs; /* !!! Pseudo widget uses system encoding in all modes */ if (idx == FPICK_RAW) s = strrchr(s, DIR_SEP) + 1; // Guaranteed strncpy0(res, s, size); break; } case op_PENTRY: case op_PATH: case op_PATHs: { char *s = (char *)gtk_entry_get_text(slot[0]); if (idx == PATH_VALUE) gtkncpy(res, s, size); else strncpy0(res, s, size); // PATH_RAW break; } case op_CSCROLL: { GtkAdjustment *xa, *ya; int *v = res; get_scroll_adjustments(slot[0], &xa, &ya); if (idx == CSCROLL_XYSIZE) { switch (size / sizeof(int)) { default: case 4: v[3] = gtk_adjustment_get_page_size(ya); case 3: v[2] = gtk_adjustment_get_page_size(xa); case 2: v[1] = gtk_adjustment_get_value(ya); case 1: v[0] = gtk_adjustment_get_value(xa); case 0: break; } } else if (idx == CSCROLL_LIMITS) { if (size >= sizeof(int)) v[0] = gtk_adjustment_get_upper(xa) - gtk_adjustment_get_page_size(xa); if (size >= sizeof(int) * 2) v[1] = gtk_adjustment_get_upper(ya) - gtk_adjustment_get_page_size(ya); } break; } case op_CANVAS: { GtkWidget *w = slot[0]; if (idx == CANVAS_SIZE) { int *v = res; #if GTK_MAJOR_VERSION == 3 GtkAllocation alloc; gtk_widget_get_allocation(w, &alloc); if (size >= sizeof(int)) v[0] = alloc.width; if (size >= sizeof(int) * 2) v[1] = alloc.height; #else if (size >= sizeof(int)) v[0] = w->allocation.width; if (size >= sizeof(int) * 2) v[1] = w->allocation.height; #endif } else if (idx == CANVAS_VPORT) { if (size < sizeof(int) * 4) break; wjcanvas_get_vport(w, res); } else if (idx == CANVAS_FIND_MOUSE) { mouse_ext *m = res; gint x, y; int vport[4]; // No reason to parcel the data if (size < sizeof(mouse_ext)) break; gdk_window_get_pointer(gtk_widget_get_window(w), &x, &y, &m->state); wjcanvas_get_vport(w, vport); m->x = x + vport[0]; m->y = y + vport[1]; m->button = state_to_button(m->state); m->count = 0; m->pressure = MAX_PRESSURE; } break; } case op_LISTC: case op_LISTCd: case op_LISTCu: case op_LISTCS: case op_LISTCX: /* if (idx == LISTC_ORDER) */ listc_get_order(slot[0], res, size / sizeof(int)); break; #if 0 /* Getting raw selection - not needed for now */ *(int *)res = (clist->selection ? (int)clist->selection->data : 0); #endif case op_KEYMAP: if (size >= sizeof(keymap_dd *)) *(keymap_dd **)res = keymap_export(slot[2]); break; } } /* These cannot be peeked just by calling do_query() with a preset int* var: op_TBRBUTTON op_MENURITEM op_TCOLOR op_COMBOENTRY op_ENTRY, op_MLENTRY op_TEXT * Others can, if need be */ /* If window manager does not support iconifying, you can try to make do with * lowering mtPaint's windows instead, enabling NO_ICONIFY. * However, the windows do not then reappear back on their own if you switched * focus to something else (as in preparing that something for the delayed * screenshot being taken). And it only works with GTK+1 */ //#define NO_ICONIFY void cmd_setv(void **slot, void *res, int idx) { // !!! Support only what actually used on int op = GET_OP(slot); if (op == op_WDONE) { if (idx == WDATA_ACTMAP) { v_dd *vdata = GET_VDATA(slot); if (vdata->actmask != (unsigned)res) // If anything changed act_state(vdata, (unsigned)res); return; } // skip to toplevel slot slot = NEXT_SLOT(slot) , op = GET_OP(slot); } if (IS_UNREAL(slot)) op = GET_UOP(slot); switch (op) { case op_uWINDOW: if (cmd_mode || (idx != WINDOW_DISAPPEAR)) break; // Fallthrough case op_MAINWINDOW: case op_WINDOW: case op_WINDOWm: case op_DIALOGm: { v_dd *vdata = GET_VDATA(PREV_SLOT(slot)); if (idx == WINDOW_TITLE) gtk_window_set_title(slot[0], res); else if (idx == WINDOW_ESC_BTN) { GtkAccelGroup *ag = gtk_accel_group_new(); gtk_widget_add_accelerator(*(void **)res, "clicked", ag, KEY(Escape), 0, (GtkAccelFlags)0); gtk_window_add_accel_group(slot[0], ag); } else if (idx == WINDOW_FOCUS) { /* Cannot move focus to nowhere while window is hidden */ if (!res && !GTK_WIDGET_VISIBLE(slot[0])) vdata->unfocus = TRUE; gtk_window_set_focus(slot[0], res ? *(void **)res : NULL); } else if (idx == WINDOW_RAISE) { if (GTK_WIDGET_VISIBLE(slot[0])) gdk_window_raise(gtk_widget_get_window( GTK_WIDGET(slot[0]))); /* Cannot raise hidden window, will do it later */ else vdata->raise = TRUE; } else if (idx == WINDOW_DISAPPEAR) { GtkWidget *w = slot[0]; if (IS_UNREAL(slot)) w = NULL; if (!res) /* Show again */ { if (!w) break; // Paranoia #if (GTK_MAJOR_VERSION >= 2) || !defined(NO_ICONIFY) set_iconify(w, FALSE); #endif gdk_window_raise(gtk_widget_get_window(w)); break; } if (w == main_window) w = NULL; /* Hide from view, to allow a screenshot */ #if (GTK_MAJOR_VERSION == 1) && defined(NO_ICONIFY) /* For gdk_window_lower() to clear the screen of all * mtPaint's windows, the window being lowered must be a * visible (mapped) transient. If none such is given, try * to find one; if not found, hope it means mainwindow * is the only one visible - WJ */ if (!w) { GList *top = gtk_container_get_toplevels(); for (; top; top = top->next) { GtkWidget *tw = top->data; if (!tw || (tw == main_window) || !GTK_WIDGET_MAPPED(tw) || !GTK_WINDOW(tw)->transient_parent) continue; w = tw; break; } } gdk_window_lower(main_window->window); if (w) gdk_window_lower(w->window); #else /* Iconify */ if (w) { gtk_window_set_transient_for(slot[0], NULL); set_iconify(w, TRUE); } set_iconify(main_window, TRUE); #endif gdk_flush(); handle_events(); // Wait for minimize #if GTK_MAJOR_VERSION == 1 sleep(1); // Wait a second for screen to redraw #else /* #if GTK_MAJOR_VERSION >= 2 */ g_usleep(400000); // Wait 0.4 s for screen to redraw #endif } else if (idx == WINDOW_TEXTENG) do_render_text(res); break; } case op_FPICKpm: fpick_set_filename(slot[0], res, idx); break; case op_uFPICK: { char *s, *ts, *s0 = ((swdata *)slot[0])->strs; /* !!! Pseudo widget uses system encoding in all modes */ if (idx == FPICK_RAW) { ts = strrchr(s0, DIR_SEP); // Guaranteed to be there s = wjstrcat(NULL, 0, s0, ts - s0 + 1, res, NULL); } else s = resolve_path(NULL, PATHBUF, res); free(s0); ((swdata *)slot[0])->strs = s; break; } case op_NBOOK: case op_NBOOKl: gtk_notebook_set_show_tabs(slot[0], (int)res); break; case op_SPINSLIDE: case op_SPINSLIDEa: case op_SPIN: case op_SPINc: case op_SPINa: { int *v = res, n = v[0]; spin_set_range(slot[0], v[1], v[2]); gtk_spin_button_set_value(slot[0], n); break; } case op_uSPIN: case op_uSPINa: { swdata *sd = slot[0]; int n, a, b, *v = res; sd->range[0] = a = v[1]; sd->range[1] = b = v[2]; n = v[0] > b ? b : v[0] < a ? a : v[0]; if (n != sd->value) { sd->value = n; cmd_event(slot, op_EVT_CHANGE); } break; } case op_MENUITEM: case op_MENUCHECK: case op_MENURITEM: gtk_label_set_text(GTK_LABEL(gtk_bin_get_child(GTK_BIN(slot[0]))), res); break; case op_LABEL: case op_WLABEL: case op_STLABEL: gtk_label_set_text(slot[0], res); break; case op_TEXT: set_textarea(slot[0], res); break; case op_ENTRY: case op_MLENTRY: gtk_entry_set_text(slot[0], res); break; case op_uENTRY: case op_uPATHSTR: set_uentry(slot[0], res); cmd_event(slot, op_EVT_CHANGE); break; case op_PENTRY: case op_PATH: case op_PATHs: set_path(slot[0], res, idx); break; case op_COMBOENTRY: comboentry_set_text(slot[0], res); break; case op_COLOR: case op_TCOLOR: { int *v = res; if (idx == COLOR_ALL) cpick_set_colour_previous(slot[0], v[2], v[3]); cpick_set_colour(slot[0], v[0], v[1]); break; } case op_uCOLOR: ((swdata *)slot[0])->value = *(int *)res; break; case op_COLORLIST: case op_COLORLISTN: colorlist_reset_color(slot, (int)res); break; case op_PROGRESS: #if GTK_MAJOR_VERSION == 3 gtk_progress_bar_set_fraction(slot[0], (int)res / 100.0); #else gtk_progress_set_percentage(slot[0], (int)res / 100.0); #endif break; case op_CSCROLL: { /* if (idx == CSCROLL_XYRANGE) */ /* Used as a way to preset position for a delayed resize */ GtkAdjustment *xa, *ya; int *v = res; get_scroll_adjustments(slot[0], &xa, &ya); #if GTK_MAJOR_VERSION == 3 { guint idv = g_signal_lookup("value_changed", G_TYPE_FROM_INSTANCE(xa)); guint idc = g_signal_lookup("changed", G_TYPE_FROM_INSTANCE(xa)); g_signal_handlers_block_matched(G_OBJECT(xa), G_SIGNAL_MATCH_ID, idv, 0, NULL, NULL, NULL); g_signal_handlers_block_matched(G_OBJECT(ya), G_SIGNAL_MATCH_ID, idv, 0, NULL, NULL, NULL); g_signal_handlers_block_matched(G_OBJECT(xa), G_SIGNAL_MATCH_ID, idc, 0, NULL, NULL, NULL); g_signal_handlers_block_matched(G_OBJECT(ya), G_SIGNAL_MATCH_ID, idc, 0, NULL, NULL, NULL); /* Set limit first and value after */ gtk_adjustment_set_upper(xa, v[2]); gtk_adjustment_set_upper(ya, v[3]); gtk_adjustment_set_value(xa, v[0]); gtk_adjustment_set_value(ya, v[1]); g_signal_handlers_unblock_matched(G_OBJECT(xa), G_SIGNAL_MATCH_ID, idv, 0, NULL, NULL, NULL); g_signal_handlers_unblock_matched(G_OBJECT(ya), G_SIGNAL_MATCH_ID, idv, 0, NULL, NULL, NULL); g_signal_handlers_unblock_matched(G_OBJECT(xa), G_SIGNAL_MATCH_ID, idc, 0, NULL, NULL, NULL); g_signal_handlers_unblock_matched(G_OBJECT(ya), G_SIGNAL_MATCH_ID, idc, 0, NULL, NULL, NULL); } #else xa->value = v[0]; ya->value = v[1]; xa->upper = v[2]; ya->upper = v[3]; #endif break; } case op_CANVASIMG: case op_CANVASIMGB: { rgbimage_data *rd = slot[2]; int *v = res; rd->w = v[0]; rd->h = v[1]; wjcanvas_size(slot[0], v[0], v[1]); break; } case op_CANVAS: { GtkWidget *w = slot[0]; int vport[4], rxy[4], *v = res; if (idx == CANVAS_SIZE) { wjcanvas_size(w, v[0], v[1]); break; } if (idx == CANVAS_REPAINT) { wjcanvas_redraw(w, v); break; } wjcanvas_get_vport(w, vport); if (idx == CANVAS_PAINT) { rgbcontext *ctx = res; /* Paint */ if (ctx->rgb) { #if GTK_MAJOR_VERSION == 3 wjcanvas_draw_rgb(w, ctx->xy[0], ctx->xy[1], ctx->xy[2] - ctx->xy[0], ctx->xy[3] - ctx->xy[1], ctx->rgb, (ctx->xy[2] - ctx->xy[0]) * 3, 0, TRUE); #else /* if GTK_MAJOR_VERSION <= 2 */ gdk_draw_rgb_image(w->window, w->style->black_gc, ctx->xy[0] - vport[0], ctx->xy[1] - vport[1], ctx->xy[2] - ctx->xy[0], ctx->xy[3] - ctx->xy[1], GDK_RGB_DITHER_NONE, ctx->rgb, (ctx->xy[2] - ctx->xy[0]) * 3); #endif free(ctx->rgb); } #if GTK_MAJOR_VERSION == 3 /* Handle as repaint if outside expose */ else if (!((canvas_data *)slot[2])->expose) wjcanvas_redraw(w, ctx->xy); #endif /* Prepare */ else if (clip(ctx->xy, vport[0], vport[1], vport[2], vport[3], ctx->xy)) ctx->rgb = malloc((ctx->xy[2] - ctx->xy[0]) * (ctx->xy[3] - ctx->xy[1]) * 3); } else if (idx == CANVAS_BMOVE_MOUSE) { gint x, y; gdk_window_get_pointer(gtk_widget_get_window(w), &x, &y, NULL); if ((x >= 0) && (y >= 0) && ((x += vport[0]) < vport[2]) && ((y += vport[1]) < vport[3]) && /* Autoscroll canvas if required */ wjcanvas_scroll_in(w, x + v[0], y + v[1])) { wjcanvas_get_vport(w, rxy); v[0] += vport[0] - rxy[0]; v[1] += vport[1] - rxy[1]; } if (move_mouse_relative(v[0], v[1])) v[0] = v[1] = 0; } break; } case op_FCIMAGEP: { fcimage_data *fd = slot[2]; int *v = res; if (!fd->xy) break; memcpy(fd->xy, v, sizeof(int) * 2); wjpixmap_move_cursor(slot[0], v[0], v[1]); break; } case op_LISTCCr: listcc_reset(slot, (int)res); // !!! May be needed if LISTCC_RESET_ROW w/GtkList gets used to display an added row // gtk_widget_queue_resize(slot[0]); break; case op_LISTC: case op_LISTCd: case op_LISTCu: case op_LISTCS: case op_LISTCX: if (idx == LISTC_RESET_ROW) listc_reset_row(slot[0], slot[2], (int)res); else if (idx == LISTC_SORT) listc_sort_by(slot[0], slot[2], (int)res); break; #if 0 /* Moving raw selection - not needed for now */ gtk_clist_select_row(slot[0], (int)res, 0); #endif case op_KEYMAP: if (idx == KEYMAP_KEY) keymap_find(slot[2], res); else /* if (idx == KEYMAP_MAP) */ { keymap_init(slot[2], res); keymap_reset(slot[2]); } break; case op_EV_DRAGFROM: { drag_den *dp = (void *)slot; if (idx == DRAG_ICON_RGB) dp->dc->color = (int)res; else /* if (idx == DRAG_DATA) */ { char **pp = res; gtk_selection_data_set(dp->ds->data, /* Could use "dp->ds->data->target" instead */ gdk_atom_intern(dp->d.format->target, FALSE), dp->d.format->format ? dp->d.format->format : 8, pp[0], pp[1] - pp[0]); } break; } case op_EV_COPY: { copy_den *cp = (void *)slot; char **pp = res; gtk_selection_data_set(cp->data, gtk_selection_data_get_target(cp->data), cp->c.format->format ? cp->c.format->format : 8, pp[0], pp[1] - pp[0]); break; } case op_CLIPBOARD: offer_text(slot, res); break; #if GTK_MAJOR_VERSION >= 2 case op_FONTSEL: { GtkFontSelection *fs = slot[0]; fontsel_data *fd = slot[2]; fd->dpi = (int)res; if (!fd->sysdpi) fd->sysdpi = window_dpi(main_window); // Init /* To cause full preview reset */ #if GTK_MAJOR_VERSION == 3 { GtkWidget *e = gtk_font_selection_get_size_entry(fs); char *s = strdup(gtk_entry_get_text(GTK_ENTRY(e))); gtk_entry_set_text(GTK_ENTRY(e), "0"); gtk_widget_activate(e); gtk_entry_set_text(GTK_ENTRY(e), s); gtk_widget_activate(e); free(s); /* Force style update if not triggered by the above */ if (fd->dpi != fd->lastdpi) fontsel_style( gtk_font_selection_get_preview_entry(fs), slot); } #else /* #if GTK_MAJOR_VERSION <= 2 */ { int size = fs->size; fs->size = 0; gtk_widget_activate(fs->size_entry); fs->size = size; } #endif break; } #endif } } void cmd_repaint(void **slot) { int op = op; if (IS_UNREAL(slot)) return; #if GTK_MAJOR_VERSION == 3 op = GET_OP(slot); /* Tell cached widgets to drop cache */ if (op == op_RGBIMAGE) reset_rgb(slot[0], slot[2]); else if ((op == op_CANVASIMG) || (op == op_CANVASIMGB) || (op == op_CANVAS)) { wjcanvas_redraw(slot[0], NULL); return; } #endif #ifdef U_LISTS_GTK1 op = GET_OP(slot); if ((op == op_COLORLIST) || (op == op_COLORLISTN)) /* Stupid GTK+ does nothing for gtk_widget_queue_draw(allcol_list) */ gtk_container_foreach(GTK_CONTAINER(slot[0]), (GtkCallback)gtk_widget_queue_draw, NULL); else #endif gtk_widget_queue_draw(slot[0]); } #define SETCUR_KEY "mtPaint.cursor" static void reset_cursor(GtkWidget *widget, gpointer user_data) { gpointer c = gtk_object_get_data_by_id(GTK_OBJECT(widget), (GQuark)user_data); if (c != (gpointer)(-1)) gdk_window_set_cursor(gtk_widget_get_window(widget), c); } void cmd_cursor(void **slot, void **cursor) { static GQuark setcur_key; GtkWidget *w = slot[0]; if (IS_UNREAL(slot)) return; /* Remember cursor for restoring it after realize */ if (!setcur_key) setcur_key = g_quark_from_static_string(SETCUR_KEY); if (!gtk_object_get_data_by_id(slot[0], setcur_key)) gtk_signal_connect(slot[0], "realize", GTK_SIGNAL_FUNC(reset_cursor), (gpointer)setcur_key); gtk_object_set_data_by_id(slot[0], setcur_key, cursor ? cursor[0] : (gpointer)(-1)); if (gtk_widget_get_window(w)) gdk_window_set_cursor(gtk_widget_get_window(w), cursor ? cursor[0] : NULL); } int cmd_checkv(void **slot, int idx) { int op = GET_OP(slot); if (op == op_WDONE) // skip head noop slot = NEXT_SLOT(slot) , op = GET_OP(slot); if (IS_UNREAL(slot)) { if (idx == SLOT_SENSITIVE) { /* Columns redirect to their list */ if ((op >= op_COLUMN_0) && (op < op_COLUMN_LAST)) { col_data *c = ((swdata *)slot[0])->strs; if (c) return (cmd_checkv(c->r, idx)); } return (!((swdata *)slot[0])->insens); } if (idx == SLOT_UNREAL) return (TRUE); op = GET_UOP(slot); } if (idx == SLOT_RADIO) return ((op == op_TBRBUTTON) || (op == op_MENURITEM) || (op == op_uMENURITEM)); if (op == op_CLIPBOARD) { if (idx == CLIP_OFFER) return (offer_clipboard(slot, FALSE)); if (idx == CLIP_PROCESS) return (process_clipboard(slot)); } else if (op == op_EV_MOUSE) { mouse_den *dp = (void *)slot; void **canvas = EV_PARENT(slot); if (dp->mouse->count) return (FALSE); // Not a move return (wjcanvas_bind_mouse(canvas[0], slot[0], dp->mouse->x - dp->vport[0], dp->mouse->y - dp->vport[1])); } else if (op < op_EVT_0) // Regular widget { if (idx == SLOT_SENSITIVE) return (GTK_WIDGET_SENSITIVE(get_wrap(slot))); if (idx == SLOT_FOCUSED) { GtkWidget *w = gtk_widget_get_toplevel(slot[0]); if (!GTK_IS_WINDOW(w)) return (FALSE); w = gtk_window_get_focus(GTK_WINDOW(w)); return (w && ((w == slot[0]) || gtk_widget_is_ancestor(w, slot[0]))); } if (idx == SLOT_SCRIPTABLE) return (!!(GET_OPF(slot) & WB_SFLAG)); /* if (idx == SLOT_UNREAL) return (FALSE); */ } return (FALSE); } void cmd_event(void **slot, int op) { slot = op_slot(slot, op); if (slot) get_evt_1(NULL, slot); // Found } mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/vcode.h000066400000000000000000001214241471325446300222170ustar00rootroot00000000000000/* vcode.h Copyright (C) 2013-2020 Dmitry Groshev This file is part of mtPaint. mtPaint 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. mtPaint 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 mtPaint in the file COPYING. */ enum { op_WEND = 0, op_WSHOW, op_WDIALOG, op_uWEND, op_uWSHOW, op_END_LAST, op_WDONE = op_END_LAST, op_MAINWINDOW, op_WINDOW, op_WINDOWm, op_DIALOGm, op_FPICKpm, op_POPUP, op_TOPVBOX, op_TOPVBOXV, op_uWINDOW, op_uFPICK, op_uTOPBOX, op_DOCK, op_HVSPLIT, op_PAGE, op_PAGEi, op_TABLE, op_VBOX, op_HBOX, op_EQBOX, op_FRAME, op_EFRAME, op_SCROLL, op_NBOOK, op_NBOOKl, op_PLAINBOOK, op_BOOKBTN, op_STATUSBAR, op_STLABEL, op_HSEP, op_LABEL, op_WLABEL, op_HLABEL, op_HLABELm, op_TLTEXT, op_PROGRESS, op_COLORPATCH, op_RGBIMAGE, op_RGBIMAGEP, op_CANVASIMG, op_CANVASIMGB, op_FCIMAGEP, op_NOSPIN, op_uOP, op_uFRAME, op_uLABEL, op_CSCROLL, op_CANVAS, op_SPIN, op_SPINc, op_FSPIN, op_SPINa, op_TLSPINPACK, op_SPINSLIDE, op_SPINSLIDEa, op_CHECK, op_CHECKb, op_RPACK, op_RPACKD, op_OPT, op_OPTD, op_COMBO, op_ENTRY, op_MLENTRY, op_PENTRY, op_PATH, op_PATHs, op_TEXT, op_COMBOENTRY, op_FONTSEL, op_HEXENTRY, op_EYEDROPPER, op_KEYBUTTON, op_TABLETBTN, op_COLOR, op_TCOLOR, op_COLORLIST, op_COLORLISTN, op_GRADBAR, op_PCTCOMBO, op_LISTCCr, op_LISTC, op_LISTCd, op_LISTCu, op_LISTCS, op_LISTCX, op_OKBTN, op_CANCELBTN, op_DONEBTN, op_TOGGLE, op_BUTTON, op_TOOLBAR, op_SMARTTBAR, op_SMARTTBMORE, op_TBBUTTON, op_TBTOGGLE, op_TBRBUTTON, op_TBBOXTOG, op_TBSPACE, op_TWOBOX, op_MENUBAR, op_SMARTMENU, op_SUBMENU, op_ESUBMENU, op_SSUBMENU, op_MENU_0, op_MENUITEM = op_MENU_0, op_MENUCHECK, op_MENURITEM, op_MENU_LAST, op_MENUTEAR = op_MENU_LAST, op_MENUSEP, op_MOUNT, op_REMOUNT, op_HEIGHTBAR, op_uCHECK, op_uCHECKb, op_uSPIN, op_uFSPIN, op_uSPINa, op_uSCALE, op_uOPT, op_uOPTD, op_uRPACK, op_uRPACKD, op_uENTRY, op_uPATHSTR, op_uCOLOR, op_uLISTCC, op_uLISTC, op_uOKBTN, op_uBUTTON, op_uMENUBAR, op_uMENU_0, op_uMENUITEM = op_uMENU_0, op_uMENUCHECK, op_uMENURITEM, op_uMENU_LAST, op_uMOUNT = op_uMENU_LAST, op_CLIPBOARD, op_XBMCURSOR, op_SYSCURSOR, op_CTL_0, // control tags - same for all modes op_WLIST = op_CTL_0, op_COLUMNDATA, op_COLUMN_0, op_IDXCOLUMN = op_COLUMN_0, op_TXTCOLUMN, op_XTXTCOLUMN, op_FILECOLUMN, op_CHKCOLUMN, op_COLUMN_LAST, op_EVT_0 = op_COLUMN_LAST, op_EVT_OK = op_EVT_0, op_EVT_CANCEL, op_EVT_CLICK, op_EVT_SELECT, op_EVT_CHANGE, op_EVT_DESTROY, // before deallocation op_EVT_SCRIPT, // by cmd_setstr() op_EVT_MULTI, // by same, with intlist data & ret op_EVT_KEY, // with key data & ret op_EVT_MOUSE, // with button data & ret op_EVT_MMOUSE, // movement, with same op_EVT_RMOUSE, // release, with same op_EVT_XMOUSE0, op_EVT_XMOUSE = op_EVT_XMOUSE0, // with button & pressure data & ret op_EVT_MXMOUSE, // movement, with same op_EVT_RXMOUSE, // release, with same op_EVT_CROSS, // enter/leave, with flag op_EVT_SCROLL, // with 2 directions op_EVT_EXT, // generic event with extra data op_EVT_DRAGFROM, // with drag data & ret op_EVT_DROP, // with drag data op_EVT_COPY, // with copy data op_EVT_PASTE, // with copy data & ret op_EVT_LAST, op_TRIGGER = op_EVT_LAST, op_EV_0, // dynamic tags - event values op_EV_MOUSE = op_EV_0, op_EV_DRAGFROM, op_EV_COPY, op_EV_LAST, // op_EXEC, op_GOTO, op_CALL, op_RET, op_IF, op_UNLESS, op_UNLESSbt, op_ENDIF, op_REF, op_CLEANUP, op_TALLOC, op_TCOPY, op_IDENT, op_uOPNAME, op_uALTNAME, op_CTL_LAST, op_CLIPFORM = op_CTL_LAST, op_DRAGDROP, op_ACTMAP, op_KEYMAP, op_SHORTCUT, op_WANTKEYS, op_MKSHRINK, op_NORESIZE, op_WANTMAX, op_KEEPSIZE, op_WXYWH, op_WPMOUSE, op_WPWHEREVER, op_HIDDEN, op_INSENS, op_FOCUS, op_WIDTH, op_HEIGHT, op_ONTOP, op_RAISED, op_BOR_0, op_BOR_TABLE = op_BOR_0, op_BOR_NBOOK, op_BOR_SCROLL, op_BOR_SPIN, op_BOR_SPINSLIDE, op_BOR_LABEL, op_BOR_OPT, op_BOR_BUTTON, op_BOR_TOOLBAR, op_BOR_POPUP, op_BOR_TOPVBOX, op_BOR_CHECK, op_BOR_FRAME, op_BOR_RPACK, op_BOR_ENTRY, op_BOR_LISTCC, op_BOR_PATH, op_BOR_LAST, op_LAST = op_BOR_LAST }; // Function to run with EXEC //typedef void **(*ext_fn)(void **r, GtkWidget ***wpp, void **wdata); // Function to run with MOUNT typedef void **(*mnt_fn)(void **wdata); // Structure which COLORLIST provides to EXT event typedef struct { int idx; // which row was clicked int button; // which button was clicked (1-3 etc) } colorlist_ext; // Structure which is provided to KEY event typedef struct { unsigned int key; // keysym unsigned int lowkey; // lowercase keysym unsigned int realkey; // keycode unsigned int state; // modifier flags } key_ext; #define MAX_PRESSURE 0xFF00 /* Nicest fixedpoint scale */ // Structure which is provided to MOUSE/MMOUSE/RMOUSE event typedef struct { int x, y; int button; // what was pressed, stays pressed, or got released int count; // 1/2/3 single/double/triple click, 0 move, -1 release unsigned int state; // button & modifier flags int pressure; // scaled to 0..MAX_PRESSURE } mouse_ext; // Structure which is provided to SCROLL event typedef struct { int xscroll, yscroll; unsigned int state; } scroll_ext; // Structure which is supplied to CLIPFORM typedef struct { char *target; // MIME type void *id; // anything int size; // fixed, or 0 for variable int format; // bit width: 8/16/32 (0 defaults to 8) } clipform_dd; // Structure which is provided to DRAGFROM and DROP event typedef struct { int x, y; clipform_dd *format; void *data; int len; } drag_ext; // Structure which is provided to COPY and PASTE event typedef struct { clipform_dd *format; void *data; int len; } copy_ext; // Structure which is provided by KEYMAP typedef struct { char *name; int slot; } key_dd; typedef struct { int nslots, nkeys, maxkeys; key_dd *keys; char **slotnames; } keymap_dd; // Structure which is provided to MULTI event typedef struct { int nrows, ncols; int mincols; // Minimum tuple size int fractcol; // Which column is fixedpoint (-1 if all integer) int *rows[1]; // Pointers to rows (int arrays preceded by their length) } multi_ext; // Structure which is supplied to WINDOW_TEXTENG typedef struct { char *text, *font; int angle, dpi, align, spacing; rgbcontext ctx; } texteng_dd; // Values of mouse count enum { MCOUNT_RELEASE = -1, MCOUNT_MOVE = 0, MCOUNT_CLICK = 1, MCOUNT_2CLICK = 2, MCOUNT_3CLICK = 3, /* Used to denote other events */ MCOUNT_ENTER = 10, MCOUNT_LEAVE, MCOUNT_NOTHING }; #define _0mask (0) #define _Cmask (GDK_CONTROL_MASK) #define _Smask (GDK_SHIFT_MASK) #define _Amask (GDK_MOD1_MASK) #define _CSmask (GDK_CONTROL_MASK | GDK_SHIFT_MASK) #define _CAmask (GDK_CONTROL_MASK | GDK_MOD1_MASK) #define _SAmask (GDK_SHIFT_MASK | GDK_MOD1_MASK) #define _CSAmask (GDK_CONTROL_MASK | GDK_SHIFT_MASK | GDK_MOD1_MASK) #define _B1mask (GDK_BUTTON1_MASK) #define _B2mask (GDK_BUTTON2_MASK) #define _B3mask (GDK_BUTTON3_MASK) #define _B13mask (GDK_BUTTON1_MASK | GDK_BUTTON3_MASK) // Functions to run with EVENT typedef void (*evt_fn)(void *ddata, void **wdata, int what, void **where); typedef void (*evtx_fn)(void *ddata, void **wdata, int what, void **where, void *xdata); typedef int (*evtxr_fn)(void *ddata, void **wdata, int what, void **where, void *xdata); // Textengine flags int texteng_aa; /* Antialias */ int texteng_rot; /* Rotate */ int texteng_spc; /* Set spacing */ int texteng_dpi; /* Set DPI */ int texteng_lf; /* Handle newlines */ int texteng_con; /* Work in console mode */ // Build a dialog window out of V-code decription //void **run_create(const void **ifcode, const void *ddata, int ddsize); void **run_create_(void **ifcode, void *ddata, int ddsize, char **script); #define run_create(A,B,C) run_create_(A, B, C, NULL) // Query dialog contents using its widget-map void run_query(void **wdata); // Destroy a dialog by its widget-map void run_destroy(void **wdata); #define VSLOT_SIZE 3 // Extract data structure out of widget-map #define GET_DDATA(V) ((V)[0]) // Extract toplevel window slot out of widget-map #define GET_WINDOW(V) ((V) + VSLOT_SIZE) // Extract actual toplevel window out of widget-map #define GET_REAL_WINDOW(V) ((V)[VSLOT_SIZE + 0]) // Iterate over slots #define NEXT_SLOT(V) ((V) + VSLOT_SIZE) #define PREV_SLOT(V) ((V) - VSLOT_SIZE) #define SLOT_N(V,N) ((V) + (N) * VSLOT_SIZE) // Extract ID out of toolbar item #define TOOL_ID(V) (int)(((void **)(V)[1])[2]) #define TOOL_IR(V) (int)(((void **)(V)[1])[5]) // Combine action and mode #define ACTMOD(A,M) (((A) << 16) | (((M) + 0x8000) & 0xFFFF)) // From widget to its wdata void **get_wdata(GtkWidget *widget, char *id); // Run event handler, defaulting to run_destroy() void do_evt_1_d(void **slot); // Search modes #define MLEVEL_FLAT (-1) /* All */ #define MLEVEL_GROUP (-2) /* Groups */ #define MLEVEL_BLOCK (-3) /* In group */ // Find slot by text name and menu level void **find_slot(void **slot, char *id, int l, int mlevel); // From slot to its wdata void **wdata_slot(void **slot); // From event to its originator void **origin_slot(void **slot); // From slot to its storage location (its own, *not* originator's) void *slot_data(void **slot, void *ddata); // Raise event on slot void cmd_event(void **slot, int op); // Set sensitive state on slot void cmd_sensitive(void **slot, int state); // Set visible state on slot void cmd_showhide(void **slot, int state); // Set value on slot void cmd_set(void **slot, int v); // Set text-encoded value on slot (-1 fail, 0 unused, 1 set) int cmd_setstr(void **slot, char *s); // Read back slot value (as is), return its storage location void *cmd_read(void **slot, void *ddata); // Read extra data from slot void cmd_peekv(void **slot, void *res, int size, int idx); // Set extra data on slot void cmd_setv(void **slot, void *res, int idx); // Repaint slot void cmd_repaint(void **slot); // Reset slot (or a group) void cmd_reset(void **slot, void *ddata); // Set cursor for slot window void cmd_cursor(void **slot, void **cursor); // Check extra state on slot int cmd_checkv(void **slot, int idx); // Run script on slot int cmd_run_script(void **slot, char **strs); /// Handler for dialog buttons void dialog_event(void *ddata, void **wdata, int what, void **where); enum { pk_NONE = 0, pk_PACK, pk_XPACK, pk_DEF = pk_XPACK, pk_EPACK, pk_PACKEND, pk_TABLE1x, pk_TABLE, pk_TABLEx, pk_LAST }; enum { col_DIRECT = 0, col_PTR, col_REL }; #define COL_LSHIFT 24 #define WB_OPBITS 12 #define WB_OPMASK 0x0FFF /* ((1 << WB_OPBITS) - 1) */ #define WB_PKBITS 4 #define WB_PKMASK 0xF /* ((1 << WB_PKBITS) - 1) */ #define WB_GETPK(X) (((X) >> WB_OPBITS) & WB_PKMASK) #define WB_SFLAG 0x100000 /* Scriptable */ #define WB_FFLAG 0x080000 #define WB_NFLAG 0x040000 #define WB_REF1 0x010000 #define WB_REF2 0x020000 #define WB_REF3 0x030000 #define WB_GETREF(X) (((X) >> (WB_OPBITS + WB_PKBITS)) & 3) #define WB_LSHIFT 24 #define WB_GETLEN(X) ((X) >> WB_LSHIFT) #define WBlen(L) ((L) << WB_LSHIFT) #define WBpk(P) ((P) << WB_OPBITS) #define WB_0 0 #define WB_F WB_FFLAG #define WB_S WB_SFLAG #define WB_R WB_REF1 #define WB_RF (WB_REF1 + WB_FFLAG) #define WB_RS (WB_REF1 + WB_SFLAG) #define WB_R2 WB_REF2 #define WB_R2F (WB_REF2 + WB_FFLAG) #define WB_R2S (WB_REF2 + WB_SFLAG) #define WB_R3 WB_REF3 #define WB_R3F (WB_REF3 + WB_FFLAG) #define WB_N WB_NFLAG #define WB_NF (WB_NFLAG + WB_FFLAG) #define WB_RNF (WB_REF1 + WB_NFLAG + WB_FFLAG) #define WB_R2NF (WB_REF2 + WB_NFLAG + WB_FFLAG) #define WBp_(OP,L,P,F) (void *)(OP + WBlen(L) + WBpk(pk_##P) + WB_##F) #define WBh(NM,L) WBp_(op_##NM, L, NONE, 0) #define WBh_(NM,L) WBp_(op_##NM, L, PACK, 0) #define WBh_x(NM,L) WBp_(op_##NM, L, XPACK, 0) #define WBh_e(NM,L) WBp_(op_##NM, L, PACKEND, 0) #define WBh_t(NM,L) WBp_(op_##NM, L, TABLE, 0) #define WBh_tx(NM,L) WBp_(op_##NM, L, TABLEx, 0) #define WBh_t1(NM,L) WBp_(op_##NM, L, TABLE1x, 0) #define WBhf(NM,L) WBp_(op_##NM, L, NONE, F) #define WBhf_(NM,L) WBp_(op_##NM, L, PACK, F) #define WBhf_t(NM,L) WBp_(op_##NM, L, TABLE, F) #define WBhs(NM,L) WBp_(op_##NM, L, NONE, S) #define WBrh(NM,L) WBp_(op_##NM, L, NONE, R) #define WBrh_(NM,L) WBp_(op_##NM, L, PACK, R) #define WBrh_x(NM,L) WBp_(op_##NM, L, XPACK, R) #define WBrh_c(NM,L) WBp_(op_##NM, L, EPACK, R) #define WBrh_e(NM,L) WBp_(op_##NM, L, PACKEND, R) #define WBrh_t(NM,L) WBp_(op_##NM, L, TABLE, R) #define WBrh_tx(NM,L) WBp_(op_##NM, L, TABLEx, R) #define WBrh_t1(NM,L) WBp_(op_##NM, L, TABLE1x, R) #define WBrhf(NM,L) WBp_(op_##NM, L, NONE, RF) #define WBrhf_(NM,L) WBp_(op_##NM, L, PACK, RF) #define WBrhf_x(NM,L) WBp_(op_##NM, L, XPACK, RF) #define WBrhf_t(NM,L) WBp_(op_##NM, L, TABLE, RF) #define WBrhf_tx(NM,L) WBp_(op_##NM, L, TABLEx, RF) #define WBrhf_t1(NM,L) WBp_(op_##NM, L, TABLE1x, RF) #define WBrhs(NM,L) WBp_(op_##NM, L, NONE, RS) #define WBrhs_(NM,L) WBp_(op_##NM, L, PACK, RS) #define WBr2h(NM,L) WBp_(op_##NM, L, NONE, R2) #define WBr2h_(NM,L) WBp_(op_##NM, L, PACK, R2) #define WBr2h_x(NM,L) WBp_(op_##NM, L, XPACK, R2) #define WBr2h_e(NM,L) WBp_(op_##NM, L, PACKEND, R2) #define WBr2h_t(NM,L) WBp_(op_##NM, L, TABLE, R2) #define WBr2hf_(NM,L) WBp_(op_##NM, L, PACK, R2F) #define WBr2hf_x(NM,L) WBp_(op_##NM, L, XPACK, R2F) #define WBr2hf_t(NM,L) WBp_(op_##NM, L, TABLE, R2F) #define WBr2hf_t1(NM,L) WBp_(op_##NM, L, TABLE1x, R2F) #define WBr2hs_(NM,L) WBp_(op_##NM, L, PACK, R2S) #define WBr2hs_x(NM,L) WBp_(op_##NM, L, XPACK, R2S) #define WBr2hs_e(NM,L) WBp_(op_##NM, L, PACKEND, R2S) #define WBr2hs_t(NM,L) WBp_(op_##NM, L, TABLE, R2S) #define WBr3h_(NM,L) WBp_(op_##NM, L, PACK, R3) #define WBr3h_e(NM,L) WBp_(op_##NM, L, PACKEND, R3) #define WBr3hf(NM,L) WBp_(op_##NM, L, NONE, R3F) #define WBr3hf_(NM,L) WBp_(op_##NM, L, PACK, R3F) #define WBhn(NM,L) WBp_(op_##NM, L, NONE, N) #define WBhnf(NM,L) WBp_(op_##NM, L, NONE, NF) #define WBhnf_(NM,L) WBp_(op_##NM, L, PACK, NF) #define WBhnf_x(NM,L) WBp_(op_##NM, L, XPACK, NF) #define WBhnf_t(NM,L) WBp_(op_##NM, L, TABLE, NF) #define WBrhnf(NM,L) WBp_(op_##NM, L, NONE, RNF) #define WBrhnf_(NM,L) WBp_(op_##NM, L, PACK, RNF) #define WBrhnf_t(NM,L) WBp_(op_##NM, L, TABLE, RNF) #define WBr2hnf_x(NM,L) WBp_(op_##NM, L, XPACK, R2NF) #define WBfield(V) (void *)offsetof(WBbase, V) #define WBwh(W,H) (void *)((H) + ((W) << 16)) #define WBxyl(X,Y,L) (void *)((Y) + ((X) << 8) + ((L - 1) << 16)) #define WBnh(N,H) (void *)(((H) & 255) + ((N) << 8)) #define WBbs(B,S) (void *)(((S) & 255) + ((B) << 8)) #define WBpbs(P,B,S) (void *)(((S) & 255) + ((B) << 8) + ((P) << 16)) #define WBppa(PX,PY,AX) (void *)((PY) + ((PX) << 8) + (AX << 16)) #define WBsizeof(V) sizeof(((WBbase *)NULL)->V) #define WEND WBh(WEND, 0) #define WSHOW WBh(WSHOW, 0) #define WDIALOG(V) WBhf(WDIALOG, 1), WBfield(V) #define WDONE WBh(WDONE, 0) #define MAINWINDOW(NM,ICN,W,H) WBrh(MAINWINDOW, 3), (NM), (ICN), WBwh(W, H) #define WINDOW(NM) WBrh(WINDOW, 1), (NM) #define WINDOWp(NP) WBrhnf(WINDOW, 1), WBfield(NP) #define WINDOWm(NM) WBrh(WINDOWm, 1), (NM) #define WINDOWpm(NP) WBrhnf(WINDOWm, 1), WBfield(NP) #define DIALOGpm(NP) WBrhnf(DIALOGm, 1), WBfield(NP) /* !!! Note: string "V" is in system encoding */ /* !!! This block holds 2 nested EVENT blocks */ #define FPICKpm(NP,F,V,HOK,HC) WBr3hf(FPICKpm, 3 + 2 * 2), WBfield(V), \ WBfield(NP), WBfield(F), EVENT(OK, HOK), EVENT(CANCEL, HC) #define POPUP(NM) WBrh(POPUP, 1), (NM) #define TOPVBOX WBrh(TOPVBOX, 0) #define TOPVBOXV WBrh(TOPVBOXV, 0) #define DOCK(K) WBrh_(DOCK, 1), (K) #define HVSPLIT WBrh_x(HVSPLIT, 0) #define VSPLIT WBrh_x(HVSPLIT, 1), (void *)2 #define PAGE(NM) WBh(PAGE, 1), (NM) #define PAGEvp(NP) WBhn(PAGE, 1), &(NP) #define PAGEi(ICN,S) WBh(PAGEi, 2), (ICN), (void *)(S) #define PAGEir(ICN,S) WBrh(PAGEi, 2), (ICN), (void *)(S) #define TABLE(W,H) WBh_(TABLE, 1), WBwh(W, H) #define TABLE2(H) TABLE(2, (H)) #define TABLEs(W,H,S) WBh_(TABLE, 2), WBwh(W, H), (void *)(S) #define TABLEr(W,H) WBrh_(TABLE, 1), WBwh(W, H) #define XTABLE(W,H) WBh_x(TABLE, 1), WBwh(W, H) #define ETABLE(W,H) WBh_e(TABLE, 1), WBwh(W, H) #define FTABLE(NM,W,H) FRAME(NM), TABLE(W, H) #define VBOX WBh_(VBOX, 0) #define VBOXr WBrh_(VBOX, 0) #define VBOXbp(S,B,P) WBh_(VBOX, 1), WBpbs(P, B, S) #define VBOXP VBOXbp(0, 0, 5) #define VBOXB VBOXbp(0, 5, 0) #define VBOXS VBOXbp(5, 0, 0) #define VBOXPS VBOXbp(5, 0, 5) #define VBOXBS VBOXbp(5, 5, 0) #define VBOXPBS VBOXbp(5, 5, 5) #define XVBOX WBh_x(VBOX, 0) #define XVBOXbp(S,B,P) WBh_x(VBOX, 1), WBpbs(P, B, S) #define XVBOXP XVBOXbp(0, 0, 5) #define XVBOXB XVBOXbp(0, 5, 0) #define XVBOXBS XVBOXbp(5, 5, 0) #define EVBOX WBh_e(VBOX, 0) #define HBOX WBh_(HBOX, 0) #define HBOXbp(S,B,P) WBh_(HBOX, 1), WBpbs(P, B, S) #define HBOXP HBOXbp(0, 0, 5) #define HBOXPr WBrh_(HBOX, 1), WBpbs(5, 0, 0) #define HBOXB HBOXbp(0, 5, 0) #define XHBOX WBh_x(HBOX, 0) #define XHBOXbp(S,B,P) WBh_x(HBOX, 1), WBpbs(P, B, S) #define XHBOXP XHBOXbp(0, 0, 5) #define XHBOXS XHBOXbp(5, 0, 0) #define XHBOXBS XHBOXbp(5, 5, 0) #define TLHBOXl(X,Y,L) WBh_t(HBOX, 1), WBxyl(X, Y, L) #define TLHBOXpl(P,X,Y,L) WBh_t(HBOX, 2), WBpbs(P, 0, 0), WBxyl(X, Y, L) #define FVBOX(NM) FRAME(NM), VBOX #define FVBOXB(NM) FRAME(NM), VBOXB #define FVBOXBS(NM) FRAME(NM), VBOXBS #define FXVBOX(NM) XFRAME(NM), VBOX #define FXVBOXB(NM) XFRAME(NM), VBOXB #define EFVBOX EFRAME, VBOXbp(0, 10, 0) #define FHBOXB(NM) FRAME(NM), HBOXB #define EQBOX WBh_(EQBOX, 0) #define EQBOXbp(S,B,P) WBh_(EQBOX, 1), WBpbs(P, B, S) #define EQBOXP EQBOXbp(0, 0, 5) #define EQBOXB EQBOXbp(0, 5, 0) #define EQBOXS EQBOXbp(5, 0, 0) #define EEQBOX WBh_e(EQBOX, 0) #define FRAME(NM) WBh_(FRAME, 1), (NM) #define XFRAME(NM) WBh_x(FRAME, 1), (NM) #define XFRAMEp(V) WBhnf_x(FRAME, 1), WBfield(V) #define EFRAME WBh_(EFRAME, 0) #define SCROLL(HP,VP) WBh_(SCROLL, 1), WBnh(VP, HP) #define XSCROLL(HP,VP) WBh_x(SCROLL, 1), WBnh(VP, HP) #define FSCROLL(HP,VP) XFRAME(NULL), SCROLL(HP, VP) #define CSCROLLv(A) WBrh_x(CSCROLL, 1), (A) #define NBOOK WBh_x(NBOOK, 0) #define NBOOKr WBrh_x(NBOOK, 0) #define NBOOKl WBh_x(NBOOKl, 0) #define PLAINBOOK WBrh_(PLAINBOOK, 0) #define PLAINBOOKn(N) WBrh_(PLAINBOOK, 1), (void *)(N) #define BOOKBTN(NM,V) WBhf_(BOOKBTN, 2), WBfield(V), (NM) #define STATUSBAR WBrh_e(STATUSBAR, 0) #define STLABEL(W,A) WBrh_(STLABEL, 1), (void *)((W) + ((A) << 16)) #define STLABELe(W,A) WBrh_e(STLABEL, 1), (void *)((W) + ((A) << 16)) #define HSEP WBh_(HSEP, 0) #define HSEPl(V) WBh_(HSEP, 1), (void *)(V) #define HSEPt WBh_(HSEP, 1), (void *)(-1) #define MLABEL(NM) WBh_(LABEL, 1), (NM) #define MLABELr(NM) WBrh_(LABEL, 1), (NM) #define MLABELc(NM) WBh_(LABEL, 2), (NM), WBppa(0, 0, 5) #define MLABELxr(NM,PX,PY,AX) WBrh_(LABEL, 2), (NM), WBppa(PX, PY, AX) #define MLABELcp(V) WBhnf_(LABEL, 2), WBfield(V), WBppa(0, 0, 5) #define MLABELpx(V,PX,PY,AX) WBhnf_(LABEL, 2), WBfield(V), WBppa(PX, PY, AX) #define WLABELp(V) WBhnf_x(WLABEL, 2), WBfield(V), WBppa(0, 0, 5) #define XLABELcr(NM) WBrh_x(LABEL, 2), (NM), WBppa(0, 0, 5) #define TLABEL(NM) WBh_t1(LABEL, 1), (NM) #define TLABELr(NM) WBrh_t1(LABEL, 1), (NM) #define TLABELx(NM,PX,PY,AX) WBh_t1(LABEL, 2), (NM), WBppa(PX, PY, AX) #define TLLABELl(NM,X,Y,L) WBh_t(LABEL, 2), (NM), WBxyl(X, Y, L) #define TLLABEL(NM,X,Y) TLLABELl(NM, X, Y, 1) #define TLLABELx(NM,X,Y,PX,PY,AX) WBh_t(LABEL, 3), (NM), \ WBppa(PX, PY, AX), WBxyl(X, Y, 1) #define TLLABELxr(NM,X,Y,PX,PY,AX) WBrh_t(LABEL, 3), (NM), \ WBppa(PX, PY, AX), WBxyl(X, Y, 1) #define TLLABELp(V,X,Y) WBhnf_t(LABEL, 2), WBfield(V), WBxyl(X, Y, 1) #define TLLABELpx(V,X,Y,PX,PY,AX) WBhnf_t(LABEL, 3), WBfield(V), \ WBppa(PX, PY, AX), WBxyl(X, Y, 1) #define TXLABEL(NM,X,Y) WBh_tx(LABEL, 3), (NM), WBppa(0, 0, 3), WBxyl(X, Y, 1) #define HLABELp(V) WBhnf_(HLABEL, 1), WBfield(V) #define HLABELmp(V) WBhnf_(HLABELm, 1), WBfield(V) #define TLTEXT(S,X,Y) WBh_t(TLTEXT, 2), (S), WBxyl(X, Y, 1) #define TLTEXTf(C,X,Y) WBhf_t(TLTEXT, 2), WBfield(C), WBxyl(X, Y, 1) #define TLTEXTp(V,X,Y) WBhnf_t(TLTEXT, 2), WBfield(V), WBxyl(X, Y, 1) #define PROGRESSp(V) WBrhnf_(PROGRESS, 1), WBfield(V) #define COLORPATCHv(CP,W,H) WBrh_x(COLORPATCH, 2), (CP), WBwh(W, H) #define RGBIMAGE(CP,A) WBrhnf_(RGBIMAGE, 2), WBfield(CP), WBfield(A) #define TLRGBIMAGE(CP,A,X,Y) WBrhnf_t(RGBIMAGE, 3), WBfield(CP), WBfield(A), \ WBxyl(X, Y, 1) #define RGBIMAGEP(CC,W,H) WBrhf_(RGBIMAGEP, 2), WBfield(CC), WBwh(W, H) #define CANVASIMGv(CC,W,H) WBrh_(CANVASIMG, 2), (CC), WBwh(W, H) #define CCANVASIMGv(CC,W,H) WBrh_c(CANVASIMG, 2), (CC), WBwh(W, H) #define CANVASIMGB(CP,A) WBrhnf_(CANVASIMGB, 2), WBfield(CP), WBfield(A) #define FCIMAGEP(CP,A,AS) WBrhnf_(FCIMAGEP, 3), WBfield(CP), WBfield(A), \ WBfield(AS) #define TLFCIMAGEP(CP,A,AS,X,Y) WBrhnf_t(FCIMAGEP, 4), WBfield(CP), \ WBfield(A), WBfield(AS), WBxyl(X, Y, 1) #define TLFCIMAGEPn(CP,AS,X,Y) WBrhnf_t(FCIMAGEP, 4), WBfield(CP), \ (void *)(-1), WBfield(AS), WBxyl(X, Y, 1) #define CANVAS(W,H,C,HX) WBr2h_(CANVAS, 2 + 2), WBwh(W, H), (void *)(C), \ EVENT(EXT, HX) #define TLNOSPIN(V,X,Y) WBhf_t(NOSPIN, 2), WBfield(V), WBxyl(X, Y, 1) #define TLNOSPINr(V,X,Y) WBrhf_t(NOSPIN, 2), WBfield(V), WBxyl(X, Y, 1) #define NOSPINv(V) WBh_(NOSPIN, 1), &(V) #define TLSPIN(V,V0,V1,X,Y) WBrhf_t(SPIN, 4), WBfield(V), \ (void *)(V0), (void *)(V1), WBxyl(X, Y, 1) #define TLXSPIN(V,V0,V1,X,Y) WBrhf_tx(SPIN, 4), WBfield(V), \ (void *)(V0), (void *)(V1), WBxyl(X, Y, 1) #define TLXSPINv(V,V0,V1,X,Y) WBrh_tx(SPIN, 4), &(V), \ (void *)(V0), (void *)(V1), WBxyl(X, Y, 1) #define T1SPIN(V,V0,V1) WBrhf_t1(SPIN, 3), WBfield(V), \ (void *)(V0), (void *)(V1) #define TSPIN(NM,V,V0,V1) T1SPIN(V,V0,V1), TLABEL(NM) #define TSPINv(NM,V,V0,V1) WBrh_t1(SPIN, 3), &(V), \ (void *)(V0), (void *)(V1), TLABEL(NM) #define TSPINa(NM,A) WBrhf_t1(SPINa, 1), WBfield(A), TLABEL(NM) #define SPIN(V,V0,V1) WBrhf_(SPIN, 3), WBfield(V), \ (void *)(V0), (void *)(V1) #define SPINv(V,V0,V1) WBrh_(SPIN, 3), &(V), \ (void *)(V0), (void *)(V1) #define SPINc(V,V0,V1) WBrhf_(SPINc, 3), WBfield(V), \ (void *)(V0), (void *)(V1) #define XSPIN(V,V0,V1) WBrhf_x(SPIN, 3), WBfield(V), \ (void *)(V0), (void *)(V1) #define FSPIN(V,V0,V1) WBrhf_(FSPIN, 3), WBfield(V), \ (void *)(V0), (void *)(V1) #define FSPINv(V,V0,V1) WBrh_(FSPIN, 3), &(V), \ (void *)(V0), (void *)(V1) #define TFSPIN(NM,V,V0,V1) WBrhf_t1(FSPIN, 3), WBfield(V), \ (void *)(V0), (void *)(V1), TLABEL(NM) #define TLFSPIN(V,V0,V1,X,Y) WBrhf_t(FSPIN, 4), WBfield(V), \ (void *)(V0), (void *)(V1), WBxyl(X, Y, 1) #define SPINa(A) WBrhf_(SPINa, 1), WBfield(A) #define XSPINa(A) WBrhf_x(SPINa, 1), WBfield(A) #define uSPIN(V,V0,V1) WBrhf_(uSPIN, 3), WBfield(V), (void *)(V0), (void *)(V1) #define uSPINv(V,V0,V1) WBrh_(uSPIN, 3), &(V), (void *)(V0), (void *)(V1) #define uFSPINv(V,V0,V1) WBrh_(uFSPIN, 3), &(V), (void *)(V0), (void *)(V1) #define uSPINa(A) WBrhf_(uSPINa, 1), WBfield(A) #define uSCALE(V,V0,V1) WBrhf_(uSCALE, 3), WBfield(V), \ (void *)(V0), (void *)(V1) /* !!! This block holds 1 nested EVENT block */ #define TLSPINPACKv(A,N,HC,W,X,Y) WBr2h_t(TLSPINPACK, 3 + 2), (A), (void *)(N), \ EVENT(CHANGE, HC), WBxyl(X, Y, W) #define T1SPINSLIDE(V,V0,V1) WBrhf_t1(SPINSLIDE, 4), WBfield(V), \ (void *)(V0), (void *)(V1), WBwh(255, 20) #define TSPINSLIDE(NM,V,V0,V1) T1SPINSLIDE(V,V0,V1), TLABEL(NM) #define TSPINSLIDEa(NM,A) WBrhf_t1(SPINSLIDEa, 1), WBfield(A), TLABEL(NM) #define TLSPINSLIDE(V,V0,V1,X,Y) WBrhf_t(SPINSLIDE, 4), WBfield(V), \ (void *)(V0), (void *)(V1), WBxyl(X, Y, 1) #define TLSPINSLIDEvs(V,V0,V1,X,Y) WBrh_t(SPINSLIDE, 5), &(V), \ (void *)(V0), (void *)(V1), WBwh(150, 0), WBxyl(X, Y, 1) #define TLSPINSLIDExl(V,V0,V1,X,Y,L) WBrhf_tx(SPINSLIDE, 4), WBfield(V), \ (void *)(V0), (void *)(V1), WBxyl(X, Y, L) #define TLSPINSLIDEx(V,V0,V1,X,Y) TLSPINSLIDExl(V, V0, V1, X, Y, 1) #define SPINSLIDEa(A) WBrhf_(SPINSLIDEa, 1), WBfield(A) #define XSPINSLIDEa(A) WBrhf_x(SPINSLIDEa, 1), WBfield(A) #define CHECK(NM,V) WBrhf_(CHECK, 2), WBfield(V), (NM) #define CHECKv(NM,V) WBrh_(CHECK, 2), &(V), (NM) #define CHECKb(NM,V,I) WBrhf_(CHECKb, 3), WBfield(V), (NM), (I) #define XCHECK(NM,V) WBrhf_x(CHECK, 2), WBfield(V), (NM) #define TLCHECKl(NM,V,X,Y,L) WBrhf_t(CHECK, 3), WBfield(V), (NM), WBxyl(X, Y, L) #define TLCHECK(NM,V,X,Y) TLCHECKl(NM, V, X, Y, 1) #define TLCHECKvl(NM,V,X,Y,L) WBrh_t(CHECK, 3), &(V), (NM), WBxyl(X, Y, L) #define TLCHECKv(NM,V,X,Y) TLCHECKvl(NM, V, X, Y, 1) #define uCHECK(NM,V) WBrhf_(uCHECK, 2), WBfield(V), (NM) #define uCHECKv(NM,V) WBrh_(uCHECK, 2), &(V), (NM) /* !!! No more than 255 choices */ #define RPACK(SS,N,H,V) WBrhf_x(RPACK, 3), WBfield(V), (SS), WBnh(N, H) #define RPACKv(SS,N,H,V) WBrh_x(RPACK, 3), &(V), (SS), WBnh(N, H) #define FRPACK(NM,SS,N,H,V) FRAME(NM), RPACK(SS,N,H,V) #define FRPACKv(NM,SS,N,H,V) FRAME(NM), RPACKv(SS,N,H,V) #define RPACKD(SP,H,V) WBrhf_x(RPACKD, 3), WBfield(V), WBfield(SP), (H) #define RPACKDv(SP,H,V) WBrh_x(RPACKD, 3), &(V), WBfield(SP), (H) /* !!! These blocks each hold 1 nested EVENT block */ #define RPACKe(SS,N,H,V,HS) WBr2hf_x(RPACK, 3 + 2), WBfield(V), (SS), \ WBnh(N, H), EVENT(SELECT, HS) #define FRPACKe(NM,SS,N,H,V,HS) FRAME(NM), RPACKe(SS,N,H,V,HS) #define RPACKDve(SP,H,V,HS) WBr2h_x(RPACKD, 3 + 2), &(V), WBfield(SP), \ (H), EVENT(SELECT, HS) #define OPT(SS,N,V) WBrhf_(OPT, 3), WBfield(V), (SS), (void *)(N) #define OPTv(SS,N,V) WBrh_(OPT, 3), &(V), (SS), (void *)(N) #define TOPTv(NM,SS,N,V) WBrh_t1(OPT, 3), &(V), (SS), (void *)(N), TLABEL(NM) #define TLOPT(SS,N,V,X,Y) WBrhf_t(OPT, 4), WBfield(V), (SS), (void *)(N), \ WBxyl(X, Y, 1) #define TLOPTv(SS,N,V,X,Y) WBrh_t(OPT, 4), &(V), (SS), (void *)(N), \ WBxyl(X, Y, 1) #define OPTD(SP,V) WBrhf_(OPTD, 2), WBfield(V), WBfield(SP) #define XOPTD(SP,V) WBrhf_x(OPTD, 2), WBfield(V), WBfield(SP) #define TOPTDv(NM,SP,V) WBrh_t1(OPTD, 2), &(V), WBfield(SP), TLABEL(NM) /* !!! These blocks each hold 1 nested EVENT block */ #define OPTve(SS,N,V,HS) WBr2h_(OPT, 3 + 2), &(V), (SS), (void *)(N), \ EVENT(SELECT, HS) #define OPTe(SS,N,V,HS) WBr2hf_(OPT, 3 + 2), WBfield(V), (SS), (void *)(N), \ EVENT(SELECT, HS) #define XOPTe(SS,N,V,HS) WBr2hf_x(OPT, 3 + 2), WBfield(V), (SS), (void *)(N), \ EVENT(SELECT, HS) #define TLOPTle(SS,N,V,HS,X,Y,L) WBr2hf_t(OPT, 4 + 2), WBfield(V), (SS), \ (void *)(N), EVENT(SELECT, HS), WBxyl(X, Y, L) #define TLOPTvle(SS,N,V,HS,X,Y,L) WBr2h_t(OPT, 4 + 2), &(V), (SS), \ (void *)(N), EVENT(SELECT, HS), WBxyl(X, Y, L) #define TLOPTve(SS,N,V,HS,X,Y) TLOPTvle(SS, N, V, HS, X, Y, 1) #define OPTDe(SP,V,HS) WBr2hf_(OPTD, 2 + 2), WBfield(V), WBfield(SP), \ EVENT(SELECT, HS) #define XOPTDe(SP,V,HS) WBr2hf_x(OPTD, 2 + 2), WBfield(V), WBfield(SP), \ EVENT(SELECT, HS) #define TOPTDe(NM,SP,V,HS) WBr2hf_t1(OPTD, 2 + 2), WBfield(V), WBfield(SP), \ EVENT(SELECT, HS), TLABEL(NM) #define COMBO(SS,N,V) WBrhf_(COMBO, 3), WBfield(V), (SS), (void *)(N) #define GRADBAR(M,V,L,MX,A,CC,HS) WBr2hf_(GRADBAR, 6 + 2), WBfield(V), \ WBfield(M), WBfield(L), WBfield(A), WBfield(CC), (void *)(MX), \ EVENT(SELECT, HS) #define PCTCOMBOv(V,A,HC) WBr2h_(PCTCOMBO, 2 + 2), &(V), (A), EVENT(CHANGE, HC) #define LISTCCHr(V,L,H,HS) WBr2hf_(LISTCCr, 3 + 2), WBfield(V), WBfield(L), \ (void *)(H), EVENT(SELECT, HS) #define LISTCCr(V,L,HS) LISTCCHr(V, L, 0, HS) #define LISTC(V,L,HS) WBr2hf_(LISTC, 3 + 2), WBfield(V), WBfield(L), \ NULL, EVENT(SELECT, HS) #define LISTCd(V,L,HS) WBr2hf_(LISTCd, 3 + 2), WBfield(V), WBfield(L), \ NULL, EVENT(SELECT, HS) #define LISTCu(V,L,HS) WBr2hf_(LISTCu, 3 + 2), WBfield(V), WBfield(L), \ NULL, EVENT(SELECT, HS) #define LISTCS(V,L,SM,HS) WBr2hf_(LISTCS, 3 + 2), WBfield(V), WBfield(L), \ WBfield(SM), EVENT(SELECT, HS) #define LISTCX(V,L,SM,M,HS,HX) WBr3hf_(LISTCX, 4 + 2 * 2), WBfield(V), \ WBfield(L), WBfield(SM), WBfield(M), EVENT(SELECT, HS), EVENT(EXT, HX) #define XENTRY(V) WBrhf_x(ENTRY, 1), WBfield(V) #define XLENTRY(V,MX) WBrhf_x(ENTRY, 2), WBfield(V), (void *)(MX) #define MLENTRY(V) WBrhf_(MLENTRY, 1), WBfield(V) #define TLENTRY(V,MX,X,Y,L) WBrhf_t(ENTRY, 3), WBfield(V), (void *)(MX), \ WBxyl(X, Y, L) #define XPENTRY(V,MX) WBrhf_x(PENTRY, 2), WBfield(V), (void *)(MX) #define TPENTRYv(NM,V,MX) WBrh_t1(PENTRY, 2), (V), (void *)(MX), TLABEL(NM) #define PATH(NM,T,M,V) FRAME(NM), WBrhf_(PATH, 3), WBfield(V), (T), (void *)(M) #define PATHv(NM,T,M,V) FRAME(NM), WBrh_(PATH, 3), (V), (T), (void *)(M) #define PATHs(NM,T,M,V) FRAME(NM), WBrh_(PATHs, 3), (V), (T), (void *)(M) #define TPATHv(NM,T,M,V) WBrh_t1(PATH, 3), (V), (T), (void *)(M), TLABEL(NM) #define uPATHSTR(V) WBrhf_(uPATHSTR, 1), WBfield(V) #define TEXT(V) WBrhf_x(TEXT, 1), WBfield(V) #define COMBOENTRY(V,SP,H) WBr2hf_x(COMBOENTRY, 2 + 2), WBfield(V), \ WBfield(SP), EVENT(OK, H) #define KEYBUTTON(V) WBrhf_(KEYBUTTON, 1), WBfield(V) #define TABLETBTN(NM) WBrh_(TABLETBTN, 1), (NM) #define FONTSEL(A) WBrhf_x(FONTSEL, 1), WBfield(A) #define HEXENTRY(V,HC,X,Y) WBr2hf_t(HEXENTRY, 2 + 2), WBfield(V), \ EVENT(CHANGE, HC), WBxyl(X, Y, 1) #define EYEDROPPER(V,HC,X,Y) WBr2hf_t(EYEDROPPER, 2 + 2), WBfield(V), \ EVENT(CHANGE, HC), WBxyl(X, Y, 1) #define COLOR(V) WBrhf_(COLOR, 1), WBfield(V) #define TCOLOR(A) WBrhf_(TCOLOR, 1), WBfield(A) /* !!! These blocks each hold 2 nested EVENT blocks */ /* !!! SELECT must be last, for it gets triggered */ #define COLORLIST(SP,V,CC,HS,HX) WBr3hf_(COLORLIST, 3 + 2 * 2), WBfield(V), \ WBfield(SP), WBfield(CC), EVENT(EXT, HX), EVENT(SELECT, HS) #define COLORLISTN(N,V,CC,HS,HX) WBr3hf_(COLORLISTN, 3 + 2 * 2), WBfield(V), \ WBfield(N), WBfield(CC), EVENT(EXT, HX), EVENT(SELECT, HS) #define OKBOX(NOK,HOK,NC,HC) EQBOX, CANCELBTN(NC, HC), OKBTN(NOK, HOK) #define OKBOXP(NOK,HOK,NC,HC) EQBOXP, CANCELBTN(NC, HC), OKBTN(NOK, HOK) #define OKBOXB(NOK,HOK,NC,HC) EQBOXB, CANCELBTN(NC, HC), OKBTN(NOK, HOK) #define OKBOX3(NOK,HOK,NC,HC,NB,HB) EQBOX, CANCELBTN(NC, HC), BUTTON(NB, HB), \ OKBTN(NOK, HOK) #define OKBOX3B(NOK,HOK,NC,HC,NB,HB) EQBOXB, CANCELBTN(NC, HC), BUTTON(NB, HB), \ OKBTN(NOK, HOK) // !!! These *BTN,*TOGGLE,*BUTTON blocks each hold 1 nested EVENT block */ #define OKBTN(NM,H) WBr2h_x(OKBTN, 1 + 2), (NM), EVENT(OK, H) #define uOKBTN(H) WBr2h_(uOKBTN, 0 + 2), EVENT(OK, H) #define CANCELBTN(NM,H) WBr2h_x(CANCELBTN, 1 + 2), (NM), EVENT(CANCEL, H) #define CANCELBTNp(NP,H) WBr2hnf_x(CANCELBTN, 1 + 2), WBfield(NP), \ EVENT(CANCEL, H) #define UCANCELBTN(NM,H) WBr2h_(CANCELBTN, 1 + 2), (NM), EVENT(CANCEL, H) #define ECANCELBTN(NM,H) WBr2h_e(CANCELBTN, 1 + 2), (NM), EVENT(CANCEL, H) #define UDONEBTN(NM,H) WBr2h_(DONEBTN, 1 + 2), (NM), EVENT(OK, H) #define TOGGLE(NM,V,H) WBr2hf_x(TOGGLE, 2 + 2), WBfield(V), (NM), \ EVENT(CHANGE, H) #define UTOGGLEv(NM,V,H) WBr2h_(TOGGLE, 2 + 2), &(V), (NM), EVENT(CHANGE, H) #define BUTTON(NM,H) WBr2h_x(BUTTON, 1 + 2), (NM), EVENT(CLICK, H) #define BUTTONs(NM,H) WBr2hs_x(BUTTON, 1 + 2), (NM), EVENT(CLICK, H) #define BUTTONp(NP,H) WBr2hnf_x(BUTTON, 1 + 2), WBfield(NP), EVENT(CLICK, H) #define UBUTTON(NM,H) WBr2h_(BUTTON, 1 + 2), (NM), EVENT(CLICK, H) #define EBUTTON(NM,H) WBr2h_e(BUTTON, 1 + 2), (NM), EVENT(CLICK, H) #define EBUTTONs(NM,H) WBr2hs_e(BUTTON, 1 + 2), (NM), EVENT(CLICK, H) #define TLBUTTON(NM,H,X,Y) WBr2h_t(BUTTON, 2 + 2), (NM), EVENT(CLICK, H), \ WBxyl(X, Y, 1) #define TLBUTTONs(NM,H,X,Y) WBr2hs_t(BUTTON, 2 + 2), (NM), EVENT(CLICK, H), \ WBxyl(X, Y, 1) #define uBUTTONs(NM,H) WBr2hs_(uBUTTON, 1 + 2), (NM), EVENT(CLICK, H) #define TOOLBAR(HC) WBr2h_(TOOLBAR, 0 + 2), EVENT(CHANGE, HC) #define TOOLBARx(HC,HR) WBr3h_(TOOLBAR, 0 + 2 * 2), EVENT(CHANGE, HC), \ EVENT(CLICK, HR) #define SMARTTBAR(HC) WBr2h_(SMARTTBAR, 0 + 2), EVENT(CHANGE, HC) #define SMARTTBARx(HC,HR) WBr3h_(SMARTTBAR, 0 + 2 * 2), EVENT(CHANGE, HC), \ EVENT(CLICK, HR) #define SMARTTBMORE(NM) WBh(SMARTTBMORE, 1), (NM) #define TBBUTTON(NM,IC,ID) WBrh(TBBUTTON, 4), NULL, (void *)(ID), (NM), (IC) #define TBBUTTONx(NM,IC,ID,IR) WBrh(TBBUTTON, 5), NULL, (void *)(ID), (NM), \ (IC), (void *)(IR) #define TBTOGGLE(NM,IC,ID,V) WBrhf(TBTOGGLE, 4), WBfield(V), (void *)(ID), \ (NM), (IC) #define TBTOGGLEv(NM,IC,ID,V) WBrh(TBTOGGLE, 4), &(V), (void *)(ID), (NM), (IC) #define TBTOGGLExv(NM,IC,ID,IR,V) WBrh(TBTOGGLE, 5), &(V), (void *)(ID), (NM), \ (IC), (void *)(IR) #define TBBOXTOGxv(NM,IC,ID,IR,V) WBrh(TBBOXTOG, 5), &(V), (void *)(ID), (NM), \ (IC), (void *)(IR) #define TBRBUTTONv(NM,IC,ID,V) WBrh(TBRBUTTON, 4), &(V), (void *)(ID), (NM), (IC) #define TBRBUTTONxv(NM,IC,ID,IR,V) WBrh(TBRBUTTON, 5), &(V), (void *)(ID), \ (NM), (IC), (void *)(IR) #define TBSPACE WBh(TBSPACE, 0) #define TWOBOX WBh_(TWOBOX, 0) #define MENUBAR(HC) WBr2h_(MENUBAR, 0 + 2), EVENT(CHANGE, HC) #define SMARTMENU(HC) WBr2h_(SMARTMENU, 0 + 2), EVENT(CHANGE, HC) #define SUBMENU(NM) WBrh_(SUBMENU, 1), (NM) #define ESUBMENU(NM) WBrh_(ESUBMENU, 1), (NM) #define SSUBMENU(NM) WBrh_(SSUBMENU, 1), (NM) #define MENUITEM(NM,ID) WBrh_(MENUITEM, 3), NULL, (void *)(ID), (NM) #define MENUITEMs(NM,ID) WBrhs_(MENUITEM, 3), NULL, (void *)(ID), (NM) #define MENUITEMi(NM,ID,IC) WBrh_(MENUITEM, 4), NULL, (void *)(ID), (NM), (IC) #define MENUITEMis(NM,ID,IC) WBrhs_(MENUITEM, 4), NULL, (void *)(ID), (NM), (IC) #define MENUCHECKv(NM,ID,V) WBrh_(MENUCHECK, 3), &(V), (void *)(ID), (NM) #define MENUCHECKvs(NM,ID,V) WBrhs_(MENUCHECK, 3), &(V), (void *)(ID), (NM) #define MENURITEMv(NM,ID,V) WBrh_(MENURITEM, 3), &(V), (void *)(ID), (NM) #define MENURITEMvs(NM,ID,V) WBrhs_(MENURITEM, 3), &(V), (void *)(ID), (NM) #define MENUTEAR WBh_(MENUTEAR, 0) #define MENUSEP WBh_(MENUSEP, 0) #define MENUSEPr WBrh_(MENUSEP, 0) #define uMENUBAR(HC) WBr2h_(uMENUBAR, 0 + 2), EVENT(CHANGE, HC) #define uMENUITEM(NM,ID) WBrh_(uMENUITEM, 3), NULL, (void *)(ID), (NM) #define uMENUITEMs(NM,ID) WBrhs_(uMENUITEM, 3), NULL, (void *)(ID), (NM) #define MOUNT(V,FN,H) WBr2hf_(MOUNT, 2 + 2), WBfield(V), (FN), EVENT(CHANGE, H) #define PMOUNT(V,FN,H,K,NK) WBr2hf_x(MOUNT, 4 + 2), WBfield(V), (FN), (K), \ (void *)(NK), EVENT(CHANGE, H) #define REMOUNTv(V) WBrh_x(REMOUNT, 1), &(V) #define HEIGHTBAR WBh_e(HEIGHTBAR, 0) //#define EXEC(FN) WBh(EXEC, 1), (FN) #define GOTO(A) WBh(GOTO, 1), (A) #define CALL(A) WBh(CALL, 1), (A) #define CALLp(V) WBhnf(CALL, 1), WBfield(V) #define RET WBh(RET, 0) #define IF(X) WBhf(IF, 1), WBfield(X) #define IFx(X,N) WBhf(IF, 2), WBfield(X), (void *)(N) #define IFv(X) WBh(IF, 1), &(X) #define IFvx(X,N) WBh(IF, 2), &(X), (void *)(N) #define UNLESS(X) WBhf(UNLESS, 1), WBfield(X) #define UNLESSx(X,N) WBhf(UNLESS, 2), WBfield(X), (void *)(N) #define UNLESSv(X) WBh(UNLESS, 1), &(X) #define UNLESSbt(V) WBh(UNLESSbt, 1), (V) #define ENDIF(N) WBh(ENDIF, 1), (void *)(N) #define REF(V) WBhf(REF, 1), WBfield(V) #define REFv(V) WBh(REF, 1), &(V) #define CLEANUP(V) WBrhf(CLEANUP, 1), WBfield(V) #define TALLOC(V,L) WBhf(TALLOC, 2), WBfield(V), WBfield(L) #define TCOPY(V,L) WBhf(TCOPY, 2), WBfield(V), WBfield(L) #define ACTMAP(N) WBh(ACTMAP, 1), (void *)(N) #define VISMASK(N) WBh(ACTMAP, 2), (void *)(N), NULL #define KEYMAP(V, NM) WBrhf(KEYMAP, 2), WBfield(V), (NM) #define SHORTCUTs(NM) WBh(SHORTCUT, 1), (NM) #define SHORTCUT(K,M) WBh(SHORTCUT, 2), (void *)KEY(K), (void *)(_##M##mask) #define SHORTCUT0 WBh(SHORTCUT, 0) #define GROUPR WBrh(uOP, 0) #define GROUP0 WBrhs(uOP, 0) #define GROUPN WBrhs(uOP, 1), NULL #define GROUP(NM) WBrhs(uOP, 1), (NM) #define IDENT(NM) WBh(IDENT, 1), (NM) #define BORDER(T,V) WBh(BOR_##T, 1), (void *)(V) #define DEFBORDER(T) WBh(BOR_##T, 0) #define MKSHRINK WBh(MKSHRINK, 0) #define NORESIZE WBh(NORESIZE, 0) #define WANTMAX WBh(WANTMAX, 0) #define WANTMAXW WBh(WANTMAX, 1), (void *)(2) #define WXYWH(NM,W,H) WBh(WXYWH, 2), (NM), WBwh(W, H) #define DEFW(V) WXYWH(NULL, V, 0) #define DEFH(V) WXYWH(NULL, 0, V) #define DEFSIZE(W,H) WXYWH(NULL, W, H) #define WPMOUSE WBh(WPMOUSE, 0) #define WPWHEREVER WBh(WPWHEREVER, 0) #define HIDDEN WBh(HIDDEN, 0) #define INSENS WBh(INSENS, 0) #define FOCUS WBh(FOCUS, 0) #define WIDTH(N) WBh(WIDTH, 1), (void *)(N) #define MINWIDTH(N) WBh(WIDTH, 1), (void *)(-(N)) #define KEEPWIDTH WBh(KEEPSIZE, 0) #define KEEPHEIGHT WBh(KEEPSIZE, 1), NULL #define HEIGHT(N) WBh(HEIGHT, 1), (void *)(N) #define ONTOP(V) WBhf(ONTOP, 1), WBfield(V) #define ONTOP0 WBh(ONTOP, 0) #define RAISED WBh(RAISED, 0) #define WLIST WBh(WLIST, 0) #define COLUMNDATA(V,S) WBhnf(COLUMNDATA, 2), WBfield(V), (void *)(S) #define IDXCOLUMN(N0,S,W,J) WBrh(IDXCOLUMN, 3), (void *)(N0), (void *)(S), \ (void *)((W) + ((J) << 16)) #define TXTCOLUMNv(A,S,W,J) WBrh(TXTCOLUMN, 3), &(A), (void *)(S), \ (void *)((W) + ((J) << 16)) #define XTXTCOLUMNv(A,S,W,J) WBrh(XTXTCOLUMN, 3), &(A), (void *)(S), \ (void *)((W) + ((J) << 16)) #define NTXTCOLUMNv(NM,A,S,W,J) WBrh(TXTCOLUMN, 4), &(A), (void *)(S), \ (void *)((W) + ((J) << 16)), (NM) #define NTXTCOLUMND(NM,ST,F,W,J) WBrh(TXTCOLUMN, 4), (void *)offsetof(ST, F), \ NULL, (void *)((W) + ((J) << 16)), (NM) #define PTXTCOLUMN(V,S,W,J) WBrhf(TXTCOLUMN, 3), WBfield(V), (void *)(S), \ (void *)((W) + ((J) << 16) + (col_PTR << COL_LSHIFT)) #define PTXTCOLUMNp(V,S,W,J) WBrhnf(TXTCOLUMN, 3), WBfield(V), (void *)(S), \ (void *)((W) + ((J) << 16) + (col_PTR << COL_LSHIFT)) #define RTXTCOLUMND(ST,F,W,J) WBrh(TXTCOLUMN, 3), (void *)offsetof(ST, F), \ NULL, (void *)((W) + ((J) << 16) + (col_REL << COL_LSHIFT)) #define RTXTCOLUMNDi(W,J) WBrh(TXTCOLUMN, 3), (void *)0, \ NULL, (void *)((W) + ((J) << 16) + (col_REL << COL_LSHIFT)) #define NRTXTCOLUMND(NM,ST,F,W,J) WBrh(TXTCOLUMN, 4), (void *)offsetof(ST, F), \ NULL, (void *)((W) + ((J) << 16) + (col_REL << COL_LSHIFT)), (NM) #define NRTXTCOLUMNDax(NM,F,W,J,I) WBrh(TXTCOLUMN, 5), (void *)(sizeof(int) * F), \ NULL, (void *)((W) + ((J) << 16) + (col_REL << COL_LSHIFT)), (NM), (I) #define NRTXTCOLUMNDaxx(NM,F,W,J,I,S) WBrh(TXTCOLUMN, 6), (void *)(sizeof(int) * F), \ NULL, (void *)((W) + ((J) << 16) + (col_REL << COL_LSHIFT)), (NM), (I), (S) #define NRFILECOLUMNDax(NM,F,W,J,I) WBrh(FILECOLUMN, 5), (void *)(sizeof(int) * F), \ NULL, (void *)((W) + ((J) << 16) + (col_REL << COL_LSHIFT)), (NM), (I) #define CHKCOLUMNv(A,S,W,J,HC) WBr2h(CHKCOLUMN, 3 + 2), &(A), (void *)(S), \ (void *)((W) + ((J) << 16)), EVENT(CHANGE, HC) #define XBMCURSOR(T,X,Y) WBrh(XBMCURSOR, 3), (xbm_##T##_bits), \ (xbm_##T##_mask_bits), WBxyl(X, Y, 20 + 1) #define SYSCURSOR(T) WBrh(SYSCURSOR, 1), (void *)(GDK_##T) #define EVENT(T,H) WBrh(EVT_##T, 1), (H) #define TRIGGER WBrh(TRIGGER, 0) #define MTRIGGER(H) WBr2h(TRIGGER, 0 + 2), EVENT(CHANGE, H) #define WANTKEYS(H) WBr2h(WANTKEYS, 0 + 2), EVENT(KEY, H) #define CLIPFORM(A,N) WBrh(CLIPFORM, 2), &(A), (void *)(N) #define DRAGDROP(F,HF,HT) WBr3hf(DRAGDROP, 2 + 2 * 2), WBfield(F), NULL, \ EVENT(DRAGFROM, HF), EVENT(DROP, HT) #define DRAGDROPm(F,HF,HT) WBr3hf(DRAGDROP, 2 + 2 * 2), WBfield(F), (void *)1, \ EVENT(DRAGFROM, HF), EVENT(DROP, HT) #define CLIPBOARD(F,T,HC,HP) WBr3hf(CLIPBOARD, 2 + 2 * 2), WBfield(F), \ (void *)(T), EVENT(COPY, HC), EVENT(PASTE, HP) #define ALTNAME(NM) WBrh(uALTNAME, 1), (NM) /* Make option strings referrable as widget names */ #define FLATTEN ALTNAME(":") #define OPNAME(NM) WBh(uOPNAME, 1), (NM) #define OPNAME0 WBh(uOPNAME, 0) /* Set an impossible name, to hide widget from script */ #define UNNAME OPNAME("=") #define SCRIPTED WBhs(uOPNAME, 0) #define ENDSCRIPT WBrhs(uOPNAME, 0) // Extra data of FPICK #define FPICK_VALUE 0 #define FPICK_RAW 1 // Mode flags for FPICK #define FPICK_ENTRY 1 #define FPICK_LOAD 2 #define FPICK_DIRS_ONLY 4 // Extra data of PATH and PENTRY #define PATH_VALUE 0 #define PATH_RAW 1 // Extra data of LISTCC #define LISTCC_RESET_ROW 0 // Extra data of LISTC #define LISTC_RESET_ROW 0 #define LISTC_ORDER 1 #define LISTC_SORT 2 // Extra data of LABEL and MENUITEM #define LABEL_VALUE 0 // Extra data of NBOOK #define NBOOK_TABS 0 // Extra data of ENTRY and COMBOENTRY #define ENTRY_VALUE 0 // Extra data of TEXT #define TEXT_VALUE 0 // Extra data of WDATA itself // !!! Must not clash with toplevels' data #define WDATA_ACTMAP (-1) /* Change state of slots which have ACTMAP */ #define WDATA_TABLET (-2) /* Query tablet device */ // Extra data of WINDOW #define WINDOW_TITLE 0 #define WINDOW_ESC_BTN 1 #define WINDOW_FOCUS 2 #define WINDOW_RAISE 3 #define WINDOW_DISAPPEAR 4 #define WINDOW_DPI 5 #define WINDOW_TEXTENG 6 // Extra data of COLOR #define COLOR_RGBA 0 #define COLOR_ALL 1 // Extra data of SPIN and SPINSLIDE #define SPIN_ALL 0 // Extra data of COLORLIST #define COLORLIST_RESET_ROW 0 // Extra data of PROGRESS #define PROGRESS_PERCENT 0 // Extra data of CSCROLL #define CSCROLL_XYSIZE 0 /* 4 ints: xywh; read-only */ #define CSCROLL_LIMITS 1 /* 2 ints: wh; read-only */ #define CSCROLL_XYRANGE 2 /* 4 ints: xywh */ // Extra data of CANVASIMG and CANVAS #define CANVAS_SIZE 0 #define CANVAS_VPORT 1 #define CANVAS_REPAINT 2 #define CANVAS_PAINT 3 #define CANVAS_FIND_MOUSE 4 /* mouse_ext: as motion event */ #define CANVAS_BMOVE_MOUSE 5 // Extra data of FCIMAGE #define FCIMAGE_XY 0 // Extra data of KEYMAP #define KEYMAP_KEY 0 #define KEYMAP_MAP 1 // Extra state of EV_MOUSE #define MOUSE_BOUND 0 // Extra data of EV_DRAGFROM #define DRAG_DATA 0 /* array of 2 pointers: start/end */ #define DRAG_ICON_RGB 1 // Extra data of EV_COPY #define COPY_DATA 0 // Extra data of CLIPBOARD #define CLIP_TEXT 0 // Extra state of CLIPBOARD #define CLIP_OFFER 0 #define CLIP_PROCESS 1 // Extra state of all regular widgets #define SLOT_SENSITIVE 0 #define SLOT_FOCUSED 1 #define SLOT_SCRIPTABLE 2 #define SLOT_UNREAL 3 #define SLOT_RADIO 4 // Extra data of FONTSEL #define FONTSEL_DPI 0 mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/viewer.c000066400000000000000000000756331471325446300224250ustar00rootroot00000000000000/* viewer.c Copyright (C) 2004-2019 Mark Tyler and Dmitry Groshev This file is part of mtPaint. mtPaint 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. mtPaint 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 mtPaint in the file COPYING. */ #include "global.h" #undef _ #define _(X) X #include "mygtk.h" #include "memory.h" #include "vcode.h" #include "ani.h" #include "png.h" #include "mainwindow.h" #include "viewer.h" #include "canvas.h" #include "inifile.h" #include "layer.h" #include "channels.h" #include "toolbar.h" #include "font.h" #include "thread.h" int font_aa, font_bk, font_r; int font_bkg, font_angle, font_align, font_spacing; int font_setdpi, font_dpi, sys_dpi; int view_showing; // 0: hidden, 1: horizontal split, 2: vertical split float vw_zoom = 1; int opaque_view; /// HELP WINDOW #include "help.c" #undef _ #define _(X) X typedef struct { char *name, *help[HELP_PAGE_COUNT]; } help_dd; static void click_help_end(help_dd *dt, void **wdata) { // Make sure the user can only open 1 help window cmd_sensitive(menu_slots[MENU_HELP], TRUE); run_destroy(wdata); } #if HELP_PAGE_COUNT != 4 #error Wrong number of help pages defined #endif #define WBbase help_dd static void *help_code[] = { HEIGHT(400), WINDOWp(name), DEFSIZE(600, 2), XVBOXbp(0, 4, 0), // originally the window was that way BORDER(NBOOK, 1), BORDER(FRAME, 10), /* BORDER(SCROLL, 0), */ NBOOKl, CLEANUP(help[0]), PAGEvp(help_titles[0]), FSCROLL(0, 2), // never/always WIDTH(380), HLABELp(help[0]), WDONE, // page 0 PAGEvp(help_titles[1]), FSCROLL(0, 2), // never/always WIDTH(380), HLABELmp(help[1]), WDONE, // page 1 PAGEvp(help_titles[2]), FSCROLL(0, 2), // never/always WIDTH(380), HLABELmp(help[2]), WDONE, // page 2 PAGEvp(help_titles[3]), FSCROLL(0, 2), // never/always WIDTH(380), HLABELp(help[3]), WDONE, // page 3 WDONE, // nbook BORDER(BUTTON, 1), UDONEBTN(_("Close"), click_help_end), // !!! originally had GTK_CAN_DEFAULT set on button WDONE, // xvbox ONTOP0, WSHOW }; #undef WBbase void pressed_help() { help_dd tdata; memx2 mem; char **tmp, txt[128]; int i, j, ofs[HELP_PAGE_COUNT]; // Make sure the user can only open 1 help help_window cmd_sensitive(menu_slots[MENU_HELP], FALSE); snprintf(txt, 120, "%s - %s", MT_VERSION, __("About")); tdata.name = txt; memset(&mem, 0, sizeof(mem)); getmemx2(&mem, 4000); // default size for (i = 0; i < HELP_PAGE_COUNT; i++) { ofs[i] = mem.here; tmp = help_pages[i]; for (j = 0; tmp[j]; j++) { addchars(&mem, '\n', 1); addstr(&mem, __(tmp[j]), 1); } addchars(&mem, '\0', 1); } for (i = 0; i < HELP_PAGE_COUNT; i++) tdata.help[i] = mem.buf + ofs[i]; run_create(help_code, &tdata, sizeof(tdata)); } /// PAN WINDOW int max_pan; typedef struct { int wh[3]; int wait_h, wait_v, in_pan; unsigned char *rgb; void **img; } pan_dd; void draw_pan_thumb(pan_dd *dt, int x1, int y1, int x2, int y2) { int i, j, k, ix, iy, zoom = 1, scale = 1; int pan_w = dt->wh[0], pan_h = dt->wh[1]; unsigned char *dest, *src; /* Create thumbnail */ dest = dt->rgb; for (i = 0; i < pan_h; i++) { iy = (i * mem_height) / pan_h; src = mem_img[CHN_IMAGE] + iy * mem_width * mem_img_bpp; if (mem_img_bpp == 3) /* RGB */ { for (j = 0; j < pan_w; j++ , dest += 3) { ix = ((j * mem_width) / pan_w) * 3; dest[0] = src[ix + 0]; dest[1] = src[ix + 1]; dest[2] = src[ix + 2]; } } else /* Indexed */ { for (j = 0; j < pan_w; j++ , dest += 3) { ix = src[(j * mem_width) / pan_w]; dest[0] = mem_pal[ix].red; dest[1] = mem_pal[ix].green; dest[2] = mem_pal[ix].blue; } } } /* !!! This uses the fact that zoom factor is either N or 1/N !!! */ if (can_zoom < 1.0) zoom = rint(1.0 / can_zoom); else scale = rint(can_zoom); /* Canvas coords to image coords */ x2 = ((x1 + x2) / scale) * zoom; y2 = ((y1 + y2) / scale) * zoom; x1 = (x1 / scale) * zoom; y1 = (y1 / scale) * zoom; x1 = x1 < 0 ? 0 : x1 >= mem_width ? mem_width - 1 : x1; x2 = x2 < 0 ? 0 : x2 >= mem_width ? mem_width - 1 : x2; y1 = y1 < 0 ? 0 : y1 >= mem_height ? mem_height - 1 : y1; y2 = y2 < 0 ? 0 : y2 >= mem_height ? mem_height - 1 : y2; /* Image coords to thumbnail coords */ x1 = (x1 * pan_w) / mem_width; x2 = (x2 * pan_w) / mem_width; y1 = (y1 * pan_h) / mem_height; y2 = (y2 * pan_h) / mem_height; /* Draw the border */ dest = src = dt->rgb + (y1 * pan_w + x1) * 3; j = y2 - y1; k = (x2 - x1) * 3; for (i = 0; i <= j; i++) { dest[k + 0] = dest[k + 1] = dest[k + 2] = dest[0] = dest[1] = dest[2] = ((i >> 2) & 1) * 255; dest += pan_w * 3; } j = x2 - x1; k = (y2 - y1) * pan_w * 3; for (i = 0; i <= j; i++) { src[k + 0] = src[k + 1] = src[k + 2] = src[0] = src[1] = src[2] = ((i >> 2) & 1) * 255; src += 3; } cmd_repaint(dt->img); } static void pan_thumbnail(pan_dd *dt) // Create thumbnail and selection box { int xyhv[4]; // Update main window first to get new scroll positions if necessary handle_events(); cmd_peekv(scrolledwindow_canvas, xyhv, sizeof(xyhv), CSCROLL_XYSIZE); draw_pan_thumb(dt, xyhv[0], xyhv[1], xyhv[2], xyhv[3]); } static void do_pan(pan_dd *dt, int w, int h, int nv_h, int nv_v) { int mx[2], *xy; cmd_peekv(scrolledwindow_canvas, mx, sizeof(mx), CSCROLL_LIMITS); nv_h = bounded(nv_h, 0, mx[0]); nv_v = bounded(nv_v, 0, mx[1]); if (dt->in_pan) /* Delay reaction */ { dt->wait_h = nv_h; dt->wait_v = nv_v; dt->in_pan |= 2; return; } xy = slot_data(scrolledwindow_canvas, NULL); while (TRUE) { dt->in_pan = 1; /* Update selection box */ draw_pan_thumb(dt, nv_h, nv_v, w, h); /* Update position of main window scrollbars */ xy[0] = nv_h; xy[1] = nv_v; cmd_reset(scrolledwindow_canvas, NULL); /* Process events */ handle_events(); if (dt->in_pan < 2) break; /* Do delayed update */ nv_h = dt->wait_h; nv_v = dt->wait_v; } dt->in_pan = 0; } static int key_pan(pan_dd *dt, void **wdata, int what, void **where, key_ext *key) { int nv_h, nv_v, hm, vm, xyhv[4]; if (!check_zoom_keys_real(wtf_pressed(key))) { /* xine-ui sends bogus keypresses so don't delete on this */ if (!arrow_key_(key->key, key->state, &hm, &vm, 4) && !XINE_FAKERY(key->key)) run_destroy(wdata); else { cmd_peekv(scrolledwindow_canvas, xyhv, sizeof(xyhv), CSCROLL_XYSIZE); nv_h = xyhv[0] + hm * (xyhv[2] / 4); nv_v = xyhv[1] + vm * (xyhv[3] / 4); do_pan(dt, xyhv[2], xyhv[3], nv_h, nv_v); } } else pan_thumbnail(dt); // Update selection box as user may have zoomed in/out return (TRUE); } static int pan_button(pan_dd *dt, void **wdata, int what, void **where, mouse_ext *mouse) { int nv_h, nv_v, xyhv[4]; float cent_x, cent_y; if (mouse->button == 1) // Left click = pan window { cmd_peekv(scrolledwindow_canvas, xyhv, sizeof(xyhv), CSCROLL_XYSIZE); cent_x = ((float) mouse->x) / dt->wh[0]; cent_y = ((float) mouse->y) / dt->wh[1]; nv_h = mem_width * can_zoom * cent_x - xyhv[2] * 0.5; nv_v = mem_height * can_zoom * cent_y - xyhv[3] * 0.5; do_pan(dt, xyhv[2], xyhv[3], nv_h, nv_v); } else if ((mouse->button == 3) || (mouse->button == 13)) run_destroy(wdata); // Right click = kill window return (TRUE); } #define WBbase pan_dd void *pan_code[] = { BORDER(POPUP, 2), WPMOUSE, POPUP(_("Pan Window")), EVENT(KEY, key_pan), TALLOC(rgb, wh[2]), REF(img), RGBIMAGE(rgb, wh), EVENT(MOUSE, pan_button), EVENT(MMOUSE, pan_button), WEND }; #undef WBbase void pressed_pan() { pan_dd tdata; void **wdata; int pan_w, pan_h; pan_w = pan_h = max_pan; if (mem_width < mem_height) pan_w = (max_pan * mem_width) / mem_height; else pan_h = (max_pan * mem_height) / mem_width; if (pan_w < 1) pan_w = 1; if (pan_h < 1) pan_h = 1; tdata.wh[0] = pan_w; tdata.wh[1] = pan_h; tdata.wh[2] = pan_w * pan_h * 3; tdata.wait_h = tdata.wait_v = tdata.in_pan = 0; wdata = run_create(pan_code, &tdata, sizeof(tdata)); if (!wdata) return; // can fail if no memory pan_thumbnail(GET_DDATA(wdata)); cmd_showhide(wdata, TRUE); } //// VIEW WINDOW static int vw_width = 1, vw_height = 1; static int vw_last_x, vw_last_y, vw_move_layer; static int vwxy[2]; // view window position static int vw_mouse_status; static void **vw_scrolledwindow; void **vw_drawing; int vw_focus_on; size_t render_layers(unsigned char *rgb, int cxy[4], int pw, int zoom, int scale, int lr0, int lr1, int view) { renderstate rs; int rxy[4], txy[4] = { cxy[2], cxy[3], cxy[0], cxy[1] }; image_info *image; unsigned char *tmp, **img; int i, j, ii, jj, ll, wx0, wy0, wx1, wy1, xpm, opac; int dx, dy, ddx, ddy, mx, mw, my, mh; int px = cxy[0], py = cxy[1]; size_t npix = 0, nrow = 0; /* Align view on background, canvas on image */ dx = layer_table[0].x; dy = layer_table[0].y; if (!view) { dx = layer_table_p[layer_selected].x; dy = layer_table_p[layer_selected].y; } /* Clip to background if needed */ if (view && ani_state) { image = layer_selected ? &layer_table[0].image->image_ : &mem_image; ddx = (layer_table[0].x - dx) * scale - 1; ddy = (layer_table[0].y - dy) * scale - 1; if (!clip(cxy, floor_div(ddx + zoom, zoom), floor_div(ddy + zoom, zoom), floor_div(ddx + image->width * scale, zoom) + 1, floor_div(ddy + image->height * scale, zoom) + 1, cxy)) return (0); } /* Get image-space bounds */ wx0 = floor_div(cxy[0] * zoom, scale); wy0 = floor_div(cxy[1] * zoom, scale); wx1 = floor_div((cxy[2] - 1) * zoom, scale); wy1 = floor_div((cxy[3] - 1) * zoom, scale); for (ll = lr0; ll <= lr1; ll++) { layer_node *t = (view ? layer_table : layer_table_p) + ll; image = ll == layer_selected ? &mem_image : &t->image->image_; /* !!! When sizing canvas, do not skip selected layer */ if (!t->visible && (view || (ll != layer_selected))) continue; i = t->x - dx; j = t->y - dy; ii = i + image->width; jj = j + image->height; if ((i > wx1) || (j > wy1) || (ii <= wx0) || (jj <= wy0)) continue; if (!clip(rxy, ceil_div(i * scale, zoom), ceil_div(j * scale, zoom), floor_div(ii * scale - 1, zoom) + 1, floor_div(jj * scale - 1, zoom) + 1, cxy)) continue; #ifdef U_THREADS if (!rgb) /* Calculating area & load */ { int mw = rxy[2] - rxy[0], mh = rxy[3] - rxy[1]; npix += mw * mh; nrow += mh; if (txy[0] > rxy[0]) txy[0] = rxy[0]; if (txy[1] > rxy[1]) txy[1] = rxy[1]; if (txy[2] < rxy[2]) txy[2] = rxy[2]; if (txy[3] < rxy[3]) txy[3] = rxy[3]; continue; } #endif xpm = ll ? image->trans : -1; // above background opac = (t->opacity * 255 + 50) / 100; mw = rxy[2] - (mx = rxy[0]); setup_row(&rs, mx, mw, zoom, scale, image->width, xpm, opac, image->bpp, image->pal); mh = rxy[3] - (my = rxy[1]); tmp = rgb + (my - py) * pw + (mx - px) * 3; ddx = floor_div(mx * zoom, scale) - i; ddy = floor_div(my * zoom, scale) - j; i = my % scale; if (i < 0) i += scale; mh = mh * zoom + i; img = image->img; for (j = -1; i < mh; i += zoom , tmp += pw) { if ((i / scale == j) && !async_bk) { memcpy(tmp, tmp - pw, mw * 3); continue; } j = i / scale; render_row(&rs, tmp, img, ddx, ddy + j, NULL); } } #ifdef U_THREADS if (rgb) return (0); /* Total work to do */ if (async_bk) scale = 1; // Weight coefficients are empirical npix = npix / 6 + npix / (scale * scale) + (nrow / scale) * 75; copy4(cxy, txy); #endif return (npix); } typedef struct { unsigned char *rgb; int cxy[4]; int pw, zoom, scale; threaddata *tdata; // For simplicity } lr_render_state; #ifdef U_THREADS static void do_layers_render(tcb *thread) { lr_render_state *ls = thread->data; int rxy[4]; int scale = ls->scale, h = thread->nsteps * scale; int y0, d, ofs = 0; copy4(rxy, ls->cxy); d = floor_mod(y0 = rxy[1], scale); if (thread->step0) rxy[1] = y0 += ofs = thread->step0 * scale - d; else h -= d; if (y0 + h < rxy[3]) rxy[3] = y0 + h; /* Always align on background layer */ render_layers(ls->rgb + ofs * ls->pw, rxy, ls->pw, ls->zoom, scale, 0, layers_total, TRUE); } #endif void view_render_rgb( unsigned char *rgb, int px, int py, int pw, int ph, double czoom ) { lr_render_state ls = { rgb, { px, py, px + pw, py + ph }, pw * 3, 1, 1 }; int tmp = overlay_alpha; #ifdef U_THREADS int wh, nt, nt2; size_t vpix; #endif if (!rgb) return; /* Paranoia */ /* Control transparency separately */ overlay_alpha = opaque_view; /* !!! This uses the fact that zoom factor is either N or 1/N !!! */ if (czoom < 1.0) ls.zoom = rint(1.0 / czoom); else ls.scale = rint(czoom); #ifdef U_THREADS /* Calculate amount of work for threads */ vpix = render_layers(NULL, ls.cxy, 0, ls.zoom, ls.scale, 0, layers_total, TRUE); wh = xy_span(ls.cxy, ls.scale, 1); nt = image_threads(xy_span(ls.cxy, ls.scale, 0), wh); // !!! Heuristic weight; maybe 1/8 would be better? nt2 = ceil_div(vpix, kpix_threads * 1024 * 4); if (nt2 > nt) nt2 = nt; ls.rgb += ((ls.cxy[1] - py) * pw + ls.cxy[0] - px) * 3; ls.tdata = talloc(MA_SKIP_ZEROSIZE | MA_FLAG_NONE, nt2, &ls, sizeof(ls), NULL, NULL); if (ls.tdata && (ls.tdata != MEM_NONE)) // 2+ threads w/allocation { nt /= ls.tdata->count; if (nt > MAX_TH_STRIPS) nt = MAX_TH_STRIPS; ls.tdata->chunks = nt; ls.tdata->silent = TRUE; launch_threads(do_layers_render, ls.tdata, NULL, wh); free(ls.tdata); } else if (vpix) // No alloc, single thread, something to draw #endif { /* Always align on background layer */ render_layers(ls.rgb, ls.cxy, ls.pw, ls.zoom, ls.scale, 0, layers_total, TRUE); } overlay_alpha = tmp; } //// COMPOSITE ALPHA int comp_need_alpha(int ftype) { layer_node *t = layer_table; image_info *image = layer_selected ? &t->image->image_ : &mem_image; unsigned char *alpha = image->img[CHN_ALPHA]; /* Format has to support alpha */ ftype &= FTM_FTYPE; if ((ftype != FT_NONE) && !(file_formats[ftype].flags & FF_ALPHAR)) return (FALSE); /* Background has to not be solid */ return (!t->visible || (!opaque_view && ((t->opacity < 100) || (alpha && !is_filled(alpha, 255, image->width * image->height))))); } void collect_alpha(unsigned char *alpha, int pw, int ph) { int rxy[4], cxy[4] = { 0, 0, pw, ph }; unsigned char buf[MAX_WIDTH]; image_info *image; unsigned char *tmp, *src, **img; int i, j, k, ll, xpm, opac; int dx, dy, ddx, ddy, mx, mw, my, mh, loc; /* Align on background */ dx = layer_table[0].x; dy = layer_table[0].y; memset(alpha, 0, pw * ph); for (ll = 0; ll <= layers_total; ll++) { layer_node *t = layer_table + ll; if (!t->visible) continue; i = t->x - dx; j = t->y - dy; image = ll == layer_selected ? &mem_image : &t->image->image_; if (!clip(rxy, i, j, i + image->width, j + image->height, cxy)) continue; xpm = t != layer_table ? image->trans : -1; // above background if ((xpm > -1) && (image->bpp == 3)) xpm = PNG_2_INT(image->pal[xpm]); opac = opaque_view ? 255 : (t->opacity * 255 + 50) / 100; mw = rxy[2] - (mx = rxy[0]); mh = rxy[3] - (my = rxy[1]); tmp = alpha + my * pw + mx; ddx = mx - i; ddy = my - j; img = image->img; for (i = 0; i < mh; i++ , tmp += pw) { loc = (ddy + i) * image->width + ddx; /* Prepare effective source alpha */ if (!img[CHN_ALPHA] || opaque_view) memset(buf, 255, mw); else memcpy(buf, img[CHN_ALPHA] + loc, mw); if (opaque_view); // Forced opaque else if (image->bpp == 1) // Indexed { /* Force on-off transparency */ for (j = 0; j < mw; j++) if (buf[j]) buf[j] = 255; /* Apply transparent color */ if (xpm > -1) { src = img[CHN_IMAGE] + loc; for (j = 0; j < mw; j++) if (src[j] == xpm) buf[j] = 0; } } else if (xpm > -1) // RGB with transparent color { src = img[CHN_IMAGE] + loc * 3; for (j = 0; j < mw; j++) if (MEM_2_INT(src, j * 3) == xpm) buf[j] = 0; } /* Mix into destination */ for (j = 0; j < mw; j++) { k = opac * buf[j]; k = (k + (k >> 8) + 1) >> 8; k = (tmp[j] + k) * 255 - tmp[j] * k; tmp[j] = (k + (k >> 8) + 1) >> 8; } } } } static guint idle_focus; void vw_focus_view() // Focus view window to main window { int w0, h0, xyhv[4], nv_hv[2] = { 0, 0 }; float px, py, main_hv[2]; if (idle_focus) gtk_idle_remove(idle_focus); idle_focus = 0; if (!view_showing) return; // Bail out if not visible if (!vw_focus_on) return; // Only focus if user wants to if (vw_mouse_status) /* Dragging in progress - delay focus */ { vw_mouse_status |= 2; return; } canvas_center(main_hv); /* If we are editing a layer above the background make adjustments */ if (layers_total && layer_selected) { w0 = layer_table[0].image->image_.width; h0 = layer_table[0].image->image_.height; px = main_hv[0] * mem_width + layer_table[layer_selected].x - layer_table[0].x; py = main_hv[1] * mem_height + layer_table[layer_selected].y - layer_table[0].y; px = px < 0.0 ? 0.0 : px >= w0 ? w0 - 1 : px; py = py < 0.0 ? 0.0 : py >= h0 ? h0 - 1 : py; main_hv[0] = px / w0; main_hv[1] = py / h0; } cmd_peekv(vw_scrolledwindow, xyhv, sizeof(xyhv), CSCROLL_XYSIZE); if (xyhv[2] < vw_width) { nv_hv[0] = vw_width * main_hv[0] - xyhv[2] * 0.5; if (nv_hv[0] + xyhv[2] > vw_width) nv_hv[0] = vw_width - xyhv[2]; if (nv_hv[0] < 0) nv_hv[0] = 0; } if (xyhv[3] < vw_height) { nv_hv[1] = vw_height * main_hv[1] - xyhv[3] * 0.5; if (nv_hv[1] + xyhv[3] > vw_height) nv_hv[1] = vw_height - xyhv[3]; if (nv_hv[1] < 0) nv_hv[1] = 0; } /* Do nothing if nothing changed */ if (!((xyhv[0] ^ nv_hv[0]) | (xyhv[1] ^ nv_hv[1]))) return; /* Update position of view window scrollbars */ vwxy[0] = nv_hv[0]; vwxy[1] = nv_hv[1]; cmd_reset(vw_scrolledwindow, NULL); } void vw_focus_idle() { if (idle_focus) return; if (!view_showing) return; if (!vw_focus_on) return; idle_focus = threads_idle_add_priority(GTK_PRIORITY_REDRAW + 5, (GtkFunction)vw_focus_view, NULL); } void vw_configure() { int new_margin_x = 0, new_margin_y = 0; if (canvas_image_centre) { int wh[2]; cmd_peekv(vw_drawing, wh, sizeof(wh), CANVAS_SIZE); if ((wh[0] -= vw_width) > 0) new_margin_x = wh[0] >> 1; if ((wh[1] -= vw_height) > 0) new_margin_y = wh[1] >> 1; } if ((new_margin_x != margin_view_x) || (new_margin_y != margin_view_y)) { margin_view_x = new_margin_x; margin_view_y = new_margin_y; /* Force redraw of whole canvas as the margin has shifted */ cmd_repaint(vw_drawing); } if (idle_focus) vw_focus_view(); // Time to refocus is NOW } void vw_align_size(float new_zoom) { if (!view_showing) return; if (new_zoom < MIN_ZOOM) new_zoom = MIN_ZOOM; if (new_zoom > MAX_ZOOM) new_zoom = MAX_ZOOM; if (new_zoom == vw_zoom) return; vw_zoom = new_zoom; vw_realign(); toolbar_zoom_update(); // View zoom doesn't get changed elsewhere } void vw_realign() { int sw = mem_width, sh = mem_height, i; if (!view_showing || cmd_mode) return; if (layers_total && layer_selected) { sw = layer_table[0].image->image_.width; sh = layer_table[0].image->image_.height; } if (vw_zoom < 1.0) { i = rint(1.0 / vw_zoom); sw = (sw + i - 1) / i; sh = (sh + i - 1) / i; } else { i = rint(vw_zoom); sw *= i; sh *= i; } if ((vw_width != sw) || (vw_height != sh)) { int wh[2] = { sw, sh }; vw_width = sw; vw_height = sh; cmd_setv(vw_drawing, wh, CANVAS_SIZE); } /* !!! Let refocus wait a bit - if window is being resized, view pane's * allocation could be not yet updated (canvas is done first) - WJ */ vw_focus_idle(); } static int vw_repaint(void *dt, void **wdata, int what, void **where, rgbcontext *ctx) { unsigned char *rgb = ctx->rgb; int px, py, pw, ph; pw = ctx->xy[2] - (px = ctx->xy[0]); ph = ctx->xy[3] - (py = ctx->xy[1]); memset(rgb, mem_background, pw * ph * 3); view_render_rgb(rgb, px - margin_view_x, py - margin_view_y, pw, ph, vw_zoom); return (TRUE); // now draw this } void lr_update_area(int lr, int x, int y, int w, int h) // Update x,y,w,h area of a layer { int mx, my, zoom, scale, rxy[4]; if ((lr < LR_ANIM) && (show_layers_main || (lr == layer_selected))) { mx = x + layer_table_p[lr].x - layer_table_p[layer_selected].x; my = y + layer_table_p[lr].y - layer_table_p[layer_selected].y; main_update_area(mx, my, w, h); } if (!view_showing) return; lr &= LR_ANIM - 1; // Drop view-only flag x += layer_table[lr].x - layer_table[0].x; y += layer_table[lr].y - layer_table[0].y; if (vw_zoom < 1.0) { zoom = rint(1.0 / vw_zoom); w += x; h += y; x = floor_div(x + zoom - 1, zoom); y = floor_div(y + zoom - 1, zoom); w = (w - x * zoom + zoom - 1) / zoom; h = (h - y * zoom + zoom - 1) / zoom; if ((w <= 0) || (h <= 0)) return; } else { scale = rint(vw_zoom); x *= scale; y *= scale; w *= scale; h *= scale; } rxy[2] = (rxy[0] = x + margin_view_x) + w; rxy[3] = (rxy[1] = y + margin_view_y) + h; cmd_setv(vw_drawing, rxy, CANVAS_REPAINT); } static int vw_mouse_event(void *dt, void **wdata, int what, void **where, mouse_ext *mouse) { image_info *image; unsigned char *rgb, **img; int x, y, dx, dy, i, lx, ly, lw, lh, bpp, tpix, ppix, ofs; int pflag = mouse->count >= 0, zoom = 1, scale = 1; png_color *pal; /* Steal focus from dock window */ if ((mouse->count > 0) && dock_focused()) cmd_setv(main_window_, NULL, WINDOW_FOCUS); /* If cursor got warped, will have another movement event to handle */ if (!mouse->count && mouse->button && cmd_checkv(where, MOUSE_BOUND)) return (TRUE); i = vw_mouse_status; if (!pflag || !mouse->button || !layers_total) { vw_mouse_status = 0; if (i & 2) vw_focus_view(); /* Delayed focus event */ return (pflag); } if (vw_zoom < 1.0) zoom = rint(1.0 / vw_zoom); else scale = rint(vw_zoom); dx = vw_last_x; dy = vw_last_y; vw_last_x = x = floor_div((mouse->x - margin_view_x) * zoom, scale); vw_last_y = y = floor_div((mouse->y - margin_view_y) * zoom, scale); vw_mouse_status |= 1; if (i & 1) { if (vw_move_layer > 0) move_layer_relative(vw_move_layer, x - dx, y - dy); } else { dx = layer_table[0].x; dy = layer_table[0].y; vw_move_layer = -1; // Which layer has the user clicked? for (i = layers_total; i > 0; i--) { lx = layer_table[i].x - dx; ly = layer_table[i].y - dy; image = i == layer_selected ? &mem_image : &layer_table[i].image->image_; lw = image->width; lh = image->height; bpp = image->bpp; img = image->img; pal = image->pal; rgb = img[CHN_IMAGE]; /* Is click within layer box? */ if ( x>=lx && x<(lx + lw) && y>=ly && y<(ly + lh) && layer_table[i].visible ) { ofs = (x-lx) + lw*(y-ly); /* Is transparency disabled? */ if (opaque_view) break; /* Is click on a non transparent pixel? */ if (img[CHN_ALPHA]) { if (img[CHN_ALPHA][ofs] < (bpp == 1 ? 255 : 1)) continue; } tpix = image->trans; if (tpix >= 0) { if (bpp == 1) ppix = rgb[ofs]; else { tpix = PNG_2_INT(pal[tpix]); ppix = MEM_2_INT(rgb, ofs * 3); } if (tpix == ppix) continue; } break; } } if (i > 0) vw_move_layer = i; layer_choose(i); } return (pflag); } void view_show() { if (view_showing == view_vsplit + 1) return; cmd_set(main_split, view_vsplit + 1); view_showing = view_vsplit + 1; toolbar_viewzoom(TRUE); cmd_set(menu_slots[MENU_VIEW], TRUE); vw_realign(); } void view_hide() { if (!view_showing) return; view_showing = 0; cmd_set(main_split, 0); toolbar_viewzoom(FALSE); cmd_set(menu_slots[MENU_VIEW], FALSE); } void pressed_centralize(int state) { canvas_image_centre = state; force_main_configure(); // Force configure of main window - for centalizing code } void pressed_view_focus(int state) { vw_focus_on = state; vw_focus_view(); } #define REPAINT_VIEW_COST 256 void *init_view_code[] = { REFv(vw_scrolledwindow), CSCROLLv(vwxy), HIDDEN, REFv(vw_drawing), CANVAS(1, 1, REPAINT_VIEW_COST, vw_repaint), EVENT(CHANGE, vw_configure), EVENT(MOUSE, vw_mouse_event), EVENT(RMOUSE, vw_mouse_event), EVENT(MMOUSE, vw_mouse_event), /* !!! Caller adds another event to vw_drawing */ RET }; //// TEXT TOOL /* !!! This function invalidates "img" (may free or realloc it) */ int make_text_clipboard(unsigned char *img, int w, int h, int src_bpp) { unsigned char bkg[3], *src, *dest, *tmp, *pix = img, *mask = NULL; int i, l = w *h; int idx, masked, aa, ab, back, dest_bpp = MEM_BPP; idx = (mem_channel == CHN_IMAGE) && (mem_img_bpp == 1); /* Indexed image can't be antialiased */ aa = !idx && font_aa; ab = font_bk; back = font_bkg; // !!! Bug - who said palette is unchanged? bkg[0] = mem_pal[back].red; bkg[1] = mem_pal[back].green; bkg[2] = mem_pal[back].blue; // !!! Inconsistency - why not use mask for utility channels, too? masked = !ab && (mem_channel == CHN_IMAGE); if (masked) { if ((src_bpp == 3) && (dest_bpp == 3)) mask = calloc(1, l); else mask = img , pix = NULL; if (!mask) goto fail; } else if (src_bpp < dest_bpp) pix = NULL; if (mask) /* Set up clipboard mask */ { src = img; dest = mask; for (i = 0; i < l; i++ , src += src_bpp) *dest++ = *src; /* Image is white on black */ if (!aa) mem_threshold(mask, l, 128); } if ((mask == img) && (src_bpp == 3)) /* Release excess memory */ if ((tmp = realloc(mask, l))) mask = img = tmp; if (!pix) pix = malloc(l * dest_bpp); if (!pix) { fail: free(img); return (FALSE); } src = img; dest = pix; /* Utility channel - have inversion instead of masking */ if (mem_channel != CHN_IMAGE) { int i, j = ab ? 0 : 255; for (i = 0; i < l; i++ , src += src_bpp) *dest++ = *src ^ j; /* Image is white on black */ if (!aa) mem_threshold(pix, l, 128); } /* Image with mask */ else if (mask) { int i, j, k = w * dest_bpp, l8 = 8 * dest_bpp, k8 = k * 8; int h8 = h < 8 ? h : 8, w8 = w < 8 ? k : l8; unsigned char *tmp = dest_bpp == 1 ? mem_col_pat : mem_col_pat24; for (j = 0; j < h8; j++) /* First strip */ { dest = pix + w * j * dest_bpp; memcpy(dest, tmp + l8 * j, w8); for (i = l8; i < k; i++ , dest++) dest[l8] = *dest; } src = pix; for (j = 8; j < h; j++ , src += k) /* Repeat strips */ memcpy(src + k8, src, k); } /* Indexed image */ else if (dest_bpp == 1) { int i, j; unsigned char *tmp; for (j = 0; j < h; j++) { tmp = mem_col_pat + (j & 7) * 8; for (i = 0; i < w; i++ , src += src_bpp) *dest++ = *src < 128 ? back : tmp[i & 7]; } } /* Non-antialiased RGB */ else if (!aa) { int i, j; unsigned char *tmp; for (j = 0; j < h; j++) { tmp = mem_col_pat24 + (j & 7) * (8 * 3); for (i = 0; i < w; i++ , src += src_bpp , dest += 3) { unsigned char *t2 = *src < 128 ? bkg : tmp + (i & 7) * 3; dest[0] = t2[0]; dest[1] = t2[1]; dest[2] = t2[2]; } } } /* Background-merged RGB */ else { int i, j; unsigned char *tmp; for (j = 0; j < h; j++) { tmp = mem_col_pat24 + (j & 7) * (8 * 3); for (i = 0; i < w; i++ , src += src_bpp , dest += 3) { unsigned char *t2 = tmp + (i & 7) * 3; int m = *src ^ 255, r = t2[0], g = t2[1], b = t2[2]; int kk; kk = 255 * r + m * (bkg[0] - r); dest[0] = (kk + (kk >> 8) + 1) >> 8; kk = 255 * g + m * (bkg[1] - g); dest[1] = (kk + (kk >> 8) + 1) >> 8; kk = 255 * b + m * (bkg[2] - b); dest[2] = (kk + (kk >> 8) + 1) >> 8; } } } /* Release excess memory */ if ((pix == img) && (dest_bpp < src_bpp)) if ((tmp = realloc(pix, l * dest_bpp))) pix = img = tmp; if ((img != pix) && (img != mask)) free(img); mem_clip_new(w, h, dest_bpp, 0, NULL); mem_clipboard = pix; mem_clip_mask = mask; return (TRUE); } void render_text() { texteng_dd td = { inifile_get("textString", ""), inifile_get("lastTextFont", ""), font_r ? font_angle : 0, font_setdpi ? font_dpi : 0, font_align, font_spacing }; td.ctx.rgb = NULL; cmd_setv(main_window_, &td, WINDOW_TEXTENG); text_paste = TEXT_PASTE_NONE; if (td.ctx.rgb && make_text_clipboard(td.ctx.rgb, td.ctx.xy[2], td.ctx.xy[3], 3)) text_paste = TEXT_PASTE_GTK; else alert_box(_("Error"), _("Not enough memory to create clipboard"), NULL); } typedef struct { char *fsel[2]; int bkg[3], dpi[3]; int img, idx; int script, angle; void **book, **fs; } text_dd; static void paste_text_ok(text_dd *dt, void **wdata, int what) { run_query(wdata); if (dt->fsel[0]) inifile_set("lastTextFont", dt->fsel[0]); else { alert_box(_("Error"), _("No font selected"), NULL); if (script_cmds) run_destroy(wdata); return; } if (mem_channel == CHN_IMAGE) { if (!script_cmds || (font_bk = dt->bkg[0] >= 0)) font_bkg = dt->bkg[0]; } if (!script_cmds || (font_r = !!dt->angle)) font_angle = dt->angle; if (!script_cmds || (font_setdpi = !!dt->dpi[0])) font_dpi = dt->dpi[0]; inifile_set("textString", dt->fsel[1]); render_text(); update_stuff(UPD_XCOPY); if (mem_clipboard) pressed_paste(TRUE); run_destroy(wdata); } static void dpi_changed(text_dd *dt, void **wdata, int what, void **where) { if (cmd_read(where, dt) == &font_setdpi) cmd_set(dt->book, font_setdpi); cmd_setv(dt->fs, (void *)(font_setdpi ? dt->dpi[0] : 0), FONTSEL_DPI); } char *align_txt[] = { _("Left"), _("Centre"), _("Right") }; #define WBbase text_dd static void *text_code[] = { WINDOWm(_("Paste Text")), DEFSIZE(400, 400), REF(fs), FONTSEL(fsel), FOCUS, OPNAME("Font"), IFx(script, 1), XENTRY(fsel[1]), OPNAME("Text"), ENDIF(1), HSEPl(200), HBOXP, IFvx(texteng_aa, 1), UNLESSx(idx, 1), /* && */ CHECKv(_("Antialias"), font_aa), ENDIF(1), UNLESS(img), CHECKv(_("Invert"), font_bk), IFx(img, 1), UNLESSx(script, 1), /* && */ CHECKv(_("Background colour ="), font_bk), ENDIF(1), IFx(img, 1), SPINa(bkg), OPNAME("Background colour ="), ENDIF(1), IFvx(texteng_dpi, 2), UNLESSx(script, 1), CHECKv(_("DPI ="), font_setdpi), EVENT(CHANGE, dpi_changed), TRIGGER, ENDIF(1), REF(book), PLAINBOOK, NOSPINv(sys_dpi), WDONE, // page 0 SPINa(dpi), EVENT(CHANGE, dpi_changed), OPNAME("DPI ="), WDONE, // page 1 ENDIF(2), WDONE, HBOX, IFvx(texteng_rot, 1), UNLESS(script), CHECKv(_("Angle of rotation ="), font_r), FSPIN(angle, -36000, 36000), OPNAME("Angle of rotation ="), ENDIF(1), IFvx(texteng_lf, 1), MLABEL(_("Align")), OPTv(align_txt, 3, font_align), ENDIF(1), WDONE, IFvx(texteng_spc, 1), HBOX, MLABEL(_("Spacing")), FSPINv(font_spacing, -MAX_WIDTH * 100, MAX_WIDTH * 100), WDONE, ENDIF(1), HSEPl(200), OKBOXP(_("Paste Text"), paste_text_ok, _("Cancel"), NULL), WSHOW }; #undef WBbase void pressed_text() { text_dd tdata = { { inifile_get("lastTextFont", "-misc-fixed-bold-r-normal-*-*-120-*-*-c-*-iso8859-1"), inifile_get("textString", __("Enter Text Here")) }, { font_bkg % mem_cols, 0, mem_cols - 1 }, { font_dpi, 1, 65535 }, mem_channel == CHN_IMAGE, tdata.img && (mem_img_bpp == 1), !!script_cmds, font_angle }; cmd_peekv(main_window_, &sys_dpi, sizeof(sys_dpi), WINDOW_DPI); if (script_cmds) // Simplified controls - spins w/o toggles { if (!font_bk) tdata.bkg[0] = -1; tdata.bkg[1] = -1; if (!font_r) tdata.angle = 0; if (!font_setdpi) tdata.dpi[0] = 0; tdata.dpi[1] = 0; } run_create_(text_code, &tdata, sizeof(tdata), script_cmds); } mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/viewer.h000066400000000000000000000040441471325446300224160ustar00rootroot00000000000000/* viewer.h Copyright (C) 2004-2019 Mark Tyler and Dmitry Groshev This file is part of mtPaint. mtPaint 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. mtPaint 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 mtPaint in the file COPYING. */ int font_aa, font_bk, font_r; int font_bkg, font_angle, font_align, font_spacing; int font_setdpi, font_dpi, sys_dpi; extern char *align_txt[]; int view_showing; // 0: hidden, 1: horizontal split, 2: vertical split int vw_focus_on; float vw_zoom; int opaque_view; int max_pan; void **vw_drawing; void create_cline_area( GtkWidget *vbox1 ); void pressed_pan(); void pressed_centralize(int state); void pressed_view_focus(int state); extern void *init_view_code[]; // Initial setup void view_show(); void view_hide(); int make_text_clipboard(unsigned char *img, int w, int h, int src_bpp); void pressed_help(); void pressed_text(); void render_text(); void vw_align_size( float new_zoom ); // Set new zoom void vw_realign(); // Reapply old zoom void vw_focus_view(); // Focus view window to main window void vw_focus_idle(); // Same but done in idle cycles void view_render_rgb( unsigned char *rgb, int px, int py, int pw, int ph, double czoom ); size_t render_layers(unsigned char *rgb, int cxy[4], int pw, int zoom, int scale, int lr0, int lr1, int view); void lr_update_area(int lr, int x, int y, int w, int h); // Update x,y,w,h area of a layer #define LR_ANIM 0x10000 /* Update only view window */ int comp_need_alpha(int ftype); // Need RGBA compositing void collect_alpha(unsigned char *alpha, int pw, int ph); // Composite alpha channel void vw_configure(); mtPaint-f37cf09c02b0ebd81d29c67be9741f54d76a9171/src/wu.c000066400000000000000000000300471471325446300215450ustar00rootroot00000000000000/* The following quantizing algorithm is the work of Xiaolin Wu - see the attached notes I downloaded it from: http://www.ece.mcmaster.ca/~xwu/cq.c During September 2005 I adjusted the code slightly to get it to work with mtPaint, and for the code to conform to my programming style, but the colour selection algorithm remains the same. Mark Tyler, September 2005. I updated the integration code to use mtPaint 3.30 interfaces. Dmitry Groshev, July 2008. And added "diameter weighting" mode. Dmitry Groshev, November 2008. Switched from float to double for better numeric stability. Dmitry Groshev, November 2013. */ #include "mygtk.h" #include "memory.h" /* Having received many constructive comments and bug reports about my previous C implementation of my color quantizer (Graphics Gems vol. II, p. 126-133), I am posting the following second version of my program (hopefully 100% healthy) as a reply to all those who are interested in the problem. */ /********************************************************************** C Implementation of Wu's Color Quantizer (v. 2) (see Graphics Gems vol. II, pp. 126-133) Author: Xiaolin Wu Dept. of Computer Science Univ. of Western Ontario London, Ontario N6A 5B7 wu@csd.uwo.ca Algorithm: Greedy orthogonal bipartition of RGB space for variance minimization aided by inclusion-exclusion tricks. For speed no nearest neighbor search is done. Slightly better performance can be expected by more sophisticated but more expensive versions. The author thanks Tom Lane at Tom_Lane@G.GP.CS.CMU.EDU for much of additional documentation and a cure to a previous bug. Free to distribute, comments and suggestions are appreciated. **********************************************************************/ #define MAXCOLOR 256 #define RED 2 #define GREEN 1 #define BLUE 0 struct box { int r0, r1, g0, g1, b0, b1, vol; // min value, exclusive. max value, inclusive }; /* Histogram is in elements 1..HISTSIZE along each axis, * element 0 is for base or marginal value * NB: these must start out 0! */ static double *m2; static int *wt, *mr, *mg, *mb; static int size; // image size static int K; // color look-up table size static void Hist3d(inbuf, vwt, vmr, vmg, vmb) // build 3-D color histogram of counts, r/g/b, c^2 unsigned char *inbuf; int *vwt, *vmr, *vmg, *vmb; { register int ind, r, g, b; int inr, ing, inb, table[256]; register long int i; for(i=0; i<256; ++i) table[i]=i*i; for(i=0; i>3)+1; ing=(g>>3)+1; inb=(b>>3)+1; ind=(inr<<10)+(inr<<6)+inr+(ing<<5)+ing+inb; // [inr][ing][inb] ++vwt[ind]; vmr[ind] += r; vmg[ind] += g; vmb[ind] += b; m2[ind] += table[r]+table[g]+table[b]; } if (!quan_sqrt) return; // "Diameter weighting" in action for (i = 0; i < 33 * 33 * 33; i++) { double d; if (!vwt[i]) continue; d = vwt[i]; d = (vwt[i] = sqrt(d)) / d; vmr[i] *= d; vmg[i] *= d; vmb[i] *= d; m2[i] *= d; } } /* At conclusion of the histogram step, we can interpret * wt[r][g][b] = sum over voxel of P(c) * mr[r][g][b] = sum over voxel of r*P(c) , similarly for mg, mb * m2[r][g][b] = sum over voxel of c^2*P(c) * Actually each of these should be divided by 'size' to give the usual * interpretation of P() as ranging from 0 to 1, but we needn't do that here. */ /* We now convert histogram into moments so that we can rapidly calculate * the sums of the above quantities over any desired box. */ static void M3d(vwt, vmr, vmg, vmb) // compute cumulative moments. int *vwt, *vmr, *vmg, *vmb; { register unsigned short int ind1, ind2; register unsigned char i, r, g, b; long int line, line_r, line_g, line_b, area[33], area_r[33], area_g[33], area_b[33]; double line2, area2[33]; for(r=1; r<=32; ++r) { for(i=0; i<=32; ++i) area2[i]=area[i]=area_r[i]=area_g[i]=area_b[i]=0; for(g=1; g<=32; ++g) { line2 = line = line_r = line_g = line_b = 0; for(b=1; b<=32; ++b) { ind1 = (r<<10) + (r<<6) + r + (g<<5) + g + b; // [r][g][b] line += vwt[ind1]; line_r += vmr[ind1]; line_g += vmg[ind1]; line_b += vmb[ind1]; line2 += m2[ind1]; area[b] += line; area_r[b] += line_r; area_g[b] += line_g; area_b[b] += line_b; area2[b] += line2; ind2 = ind1 - 1089; /* [r-1][g][b] */ vwt[ind1] = vwt[ind2] + area[b]; vmr[ind1] = vmr[ind2] + area_r[b]; vmg[ind1] = vmg[ind2] + area_g[b]; vmb[ind1] = vmb[ind2] + area_b[b]; m2[ind1] = m2[ind2] + area2[b]; } } } } static long int Vol(cube, mmt) // Compute sum over a box of any given statistic struct box *cube; int mmt[33][33][33]; { return( mmt[cube->r1][cube->g1][cube->b1] -mmt[cube->r1][cube->g1][cube->b0] -mmt[cube->r1][cube->g0][cube->b1] +mmt[cube->r1][cube->g0][cube->b0] -mmt[cube->r0][cube->g1][cube->b1] +mmt[cube->r0][cube->g1][cube->b0] +mmt[cube->r0][cube->g0][cube->b1] -mmt[cube->r0][cube->g0][cube->b0] ); } /* The next two routines allow a slightly more efficient calculation * of Vol() for a proposed subbox of a given box. The sum of Top() * and Bottom() is the Vol() of a subbox split in the given direction * and with the specified new upper bound. */ static long int Bottom(cube, dir, mmt) // Compute part of Vol(cube, mmt) that doesn't depend on r1, g1, or b1 // (depending on dir) struct box *cube; unsigned char dir; int mmt[33][33][33]; { switch(dir) { case RED: return( -mmt[cube->r0][cube->g1][cube->b1] +mmt[cube->r0][cube->g1][cube->b0] +mmt[cube->r0][cube->g0][cube->b1] -mmt[cube->r0][cube->g0][cube->b0] ); break; case GREEN: return( -mmt[cube->r1][cube->g0][cube->b1] +mmt[cube->r1][cube->g0][cube->b0] +mmt[cube->r0][cube->g0][cube->b1] -mmt[cube->r0][cube->g0][cube->b0] ); break; case BLUE: return( -mmt[cube->r1][cube->g1][cube->b0] +mmt[cube->r1][cube->g0][cube->b0] +mmt[cube->r0][cube->g1][cube->b0] -mmt[cube->r0][cube->g0][cube->b0] ); break; } return 0; } static long int Top(cube, dir, pos, mmt) // Compute remainder of Vol(cube, mmt), substituting pos for // r1, g1, or b1 (depending on dir) struct box *cube; unsigned char dir; int pos; int mmt[33][33][33]; { switch(dir) { case RED: return( mmt[pos][cube->g1][cube->b1] -mmt[pos][cube->g1][cube->b0] -mmt[pos][cube->g0][cube->b1] +mmt[pos][cube->g0][cube->b0] ); break; case GREEN: return( mmt[cube->r1][pos][cube->b1] -mmt[cube->r1][pos][cube->b0] -mmt[cube->r0][pos][cube->b1] +mmt[cube->r0][pos][cube->b0] ); break; case BLUE: return( mmt[cube->r1][cube->g1][pos] -mmt[cube->r1][cube->g0][pos] -mmt[cube->r0][cube->g1][pos] +mmt[cube->r0][cube->g0][pos] ); break; } return 0; } static double Var(cube) // Compute the weighted variance of a box // NB: as with the raw statistics, this is really the variance * size struct box *cube; { double dr, dg, db, xx; dr = Vol(cube, mr); dg = Vol(cube, mg); db = Vol(cube, mb); xx = m2[ 33*33*cube->r1 + 33*cube->g1 + cube->b1] -m2[ 33*33*cube->r1 + 33*cube->g1 + cube->b0] -m2[ 33*33*cube->r1 + 33*cube->g0 + cube->b1] +m2[ 33*33*cube->r1 + 33*cube->g0 + cube->b0] -m2[ 33*33*cube->r0 + 33*cube->g1 + cube->b1] +m2[ 33*33*cube->r0 + 33*cube->g1 + cube->b0] +m2[ 33*33*cube->r0 + 33*cube->g0 + cube->b1] -m2[ 33*33*cube->r0 + 33*cube->g0 + cube->b0]; return( xx - (dr*dr+dg*dg+db*db)/(double)Vol(cube,wt) ); } /* We want to minimize the sum of the variances of two subboxes. * The sum(c^2) terms can be ignored since their sum over both subboxes * is the same (the sum for the whole box) no matter where we split. * The remaining terms have a minus sign in the variance formula, * so we drop the minus sign and MAXIMIZE the sum of the two terms. */ static double Maximize(cube, dir, first, last, cut, whole_r, whole_g, whole_b, whole_w) struct box *cube; unsigned char dir; int first, last, *cut; long int whole_r, whole_g, whole_b, whole_w; { register long int half_r, half_g, half_b, half_w; long int base_r, base_g, base_b, base_w; register int i; register double temp, max; base_r = Bottom(cube, dir, mr); base_g = Bottom(cube, dir, mg); base_b = Bottom(cube, dir, mb); base_w = Bottom(cube, dir, wt); max = 0.0; *cut = -1; for(i=first; i max) { max=temp; *cut=i; } } return(max); } static int Cut(struct box *set1, struct box *set2) { unsigned char dir; int cutr, cutg, cutb; double maxr, maxg, maxb; long int whole_r, whole_g, whole_b, whole_w; whole_r = Vol(set1, mr); whole_g = Vol(set1, mg); whole_b = Vol(set1, mb); whole_w = Vol(set1, wt); maxr = Maximize(set1, RED, set1->r0+1, set1->r1, &cutr, whole_r, whole_g, whole_b, whole_w); maxg = Maximize(set1, GREEN, set1->g0+1, set1->g1, &cutg, whole_r, whole_g, whole_b, whole_w); maxb = Maximize(set1, BLUE, set1->b0+1, set1->b1, &cutb, whole_r, whole_g, whole_b, whole_w); if( (maxr>=maxg)&&(maxr>=maxb) ) { dir = RED; if (cutr < 0) return 0; // can't split the box } else if( (maxg>=maxr)&&(maxg>=maxb) ) dir = GREEN; else dir = BLUE; set2->r1 = set1->r1; set2->g1 = set1->g1; set2->b1 = set1->b1; switch (dir) { case RED: set2->r0 = set1->r1 = cutr; set2->g0 = set1->g0; set2->b0 = set1->b0; break; case GREEN: set2->g0 = set1->g1 = cutg; set2->r0 = set1->r0; set2->b0 = set1->b0; break; case BLUE: set2->b0 = set1->b1 = cutb; set2->r0 = set1->r0; set2->g0 = set1->g0; break; } set1->vol=(set1->r1-set1->r0)*(set1->g1-set1->g0)*(set1->b1-set1->b0); set2->vol=(set2->r1-set2->r0)*(set2->g1-set2->g0)*(set2->b1-set2->b0); return 1; } static void Mark(struct box *cube, int label, unsigned char *tag) { register int r, g, b; for(r=cube->r0+1; r<=cube->r1; ++r) for(g=cube->g0+1; g<=cube->g1; ++g) for(b=cube->b0+1; b<=cube->b1; ++b) tag[(r<<10) + (r<<6) + r + (g<<5) + g + b] = label; } int wu_quant(unsigned char *inbuf, int width, int height, int quant_to, png_color *pal) { void *mem; struct box cube[MAXCOLOR]; unsigned char *tag; long int next; register long int i, k, weight; double vv[MAXCOLOR], temp; K = quant_to; size = width*height; mem = multialloc(MA_ALIGN_DOUBLE, &m2, 33*33*33 * sizeof(double), &wt, 33*33*33 * sizeof(int), &mr, 33*33*33 * sizeof(int), &mg, 33*33*33 * sizeof(int), &mb, 33*33*33 * sizeof(int), &tag, 33*33*33, NULL); if (!mem) return (-1); Hist3d(inbuf, wt, mr, mg, mb); M3d(wt, mr, mg, mb); cube[0].r0 = cube[0].g0 = cube[0].b0 = 0; cube[0].r1 = cube[0].g1 = cube[0].b1 = 32; next = 0; for(i=1; i1) ? Var(&cube[next]) : 0.0; vv[i] = (cube[i].vol>1) ? Var(&cube[i]) : 0.0; } else { vv[next] = 0.0; // don't try to split this box again i--; // didn't create box i } next = 0; temp = vv[0]; for(k=1; k<=i; ++k) if (vv[k] > temp) { temp = vv[k]; next = k; } if (temp <= 0.0) { K = i+1; // Only got K boxes break; } } for(k=0; k