From d42b1c1a2e1b7303fb1ad280e7e518b5e60f49d9 Mon Sep 17 00:00:00 2001 From: Stephen Gaito Date: Fri, 29 May 2020 18:16:50 +0000 Subject: [PATCH] removed poppler Cairo source copies inside pdf2htmlEX source tree --- pdf2htmlEX/3rdparty/poppler/COPYING3 | 674 ---- .../3rdparty/poppler/git/CairoFontEngine.cc | 856 ---- .../3rdparty/poppler/git/CairoFontEngine.h | 128 - .../3rdparty/poppler/git/CairoOutputDev.cc | 3573 ----------------- .../3rdparty/poppler/git/CairoOutputDev.h | 525 --- .../3rdparty/poppler/git/CairoRescaleBox.cc | 379 -- .../3rdparty/poppler/git/CairoRescaleBox.h | 64 - pdf2htmlEX/CMakeLists.txt | 29 +- 8 files changed, 10 insertions(+), 6218 deletions(-) delete mode 100644 pdf2htmlEX/3rdparty/poppler/COPYING3 delete mode 100644 pdf2htmlEX/3rdparty/poppler/git/CairoFontEngine.cc delete mode 100644 pdf2htmlEX/3rdparty/poppler/git/CairoFontEngine.h delete mode 100644 pdf2htmlEX/3rdparty/poppler/git/CairoOutputDev.cc delete mode 100644 pdf2htmlEX/3rdparty/poppler/git/CairoOutputDev.h delete mode 100644 pdf2htmlEX/3rdparty/poppler/git/CairoRescaleBox.cc delete mode 100644 pdf2htmlEX/3rdparty/poppler/git/CairoRescaleBox.h diff --git a/pdf2htmlEX/3rdparty/poppler/COPYING3 b/pdf2htmlEX/3rdparty/poppler/COPYING3 deleted file mode 100644 index 94a9ed0..0000000 --- a/pdf2htmlEX/3rdparty/poppler/COPYING3 +++ /dev/null @@ -1,674 +0,0 @@ - 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 -. diff --git a/pdf2htmlEX/3rdparty/poppler/git/CairoFontEngine.cc b/pdf2htmlEX/3rdparty/poppler/git/CairoFontEngine.cc deleted file mode 100644 index 776b6de..0000000 --- a/pdf2htmlEX/3rdparty/poppler/git/CairoFontEngine.cc +++ /dev/null @@ -1,856 +0,0 @@ -//======================================================================== -// -// CairoFontEngine.cc -// -// Copyright 2003 Glyph & Cog, LLC -// Copyright 2004 Red Hat, Inc -// -//======================================================================== - -//======================================================================== -// -// Modified under the Poppler project - http://poppler.freedesktop.org -// -// All changes made under the Poppler project to this file are licensed -// under GPL version 2 or later -// -// Copyright (C) 2005-2007 Jeff Muizelaar -// Copyright (C) 2005, 2006 Kristian Høgsberg -// Copyright (C) 2005 Martin Kretzschmar -// Copyright (C) 2005, 2009, 2012, 2013, 2015, 2017-2019 Albert Astals Cid -// Copyright (C) 2006, 2007, 2010, 2011 Carlos Garcia Campos -// Copyright (C) 2007 Koji Otani -// Copyright (C) 2008, 2009 Chris Wilson -// Copyright (C) 2008, 2012, 2014, 2016, 2017 Adrian Johnson -// Copyright (C) 2009 Darren Kenny -// Copyright (C) 2010 Suzuki Toshiya -// Copyright (C) 2010 Jan Kümmel -// Copyright (C) 2012 Hib Eris -// Copyright (C) 2013 Thomas Freitag -// Copyright (C) 2015, 2016 Jason Crain -// Copyright (C) 2018 Adam Reichold -// Copyright (C) 2019 Christian Persch -// -// To see a description of the changes please see the Changelog file that -// came with your tarball or type make ChangeLog if you are building from git -// -//======================================================================== - -#include - -#include -#include "CairoFontEngine.h" -#include "CairoOutputDev.h" -#include "GlobalParams.h" -#include -#include -#include "goo/gfile.h" -#include "Error.h" -#include "XRef.h" -#include "Gfx.h" -#include "Page.h" - -#if defined(HAVE_FCNTL_H) && defined(HAVE_SYS_MMAN_H) && defined(HAVE_SYS_STAT_H) -#include -#include -#include -#define CAN_CHECK_OPEN_FACES 1 -#endif - -//------------------------------------------------------------------------ -// CairoFont -//------------------------------------------------------------------------ - -CairoFont::CairoFont(Ref refA, - cairo_font_face_t *cairo_font_faceA, - int *codeToGIDA, - unsigned int codeToGIDLenA, - bool substituteA, - bool printingA) : ref(refA), - cairo_font_face(cairo_font_faceA), - codeToGID(codeToGIDA), - codeToGIDLen(codeToGIDLenA), - substitute(substituteA), - printing(printingA) { } - -CairoFont::~CairoFont() { - cairo_font_face_destroy (cairo_font_face); - gfree(codeToGID); -} - -bool -CairoFont::matches(Ref &other, bool printingA) { - return (other == ref); -} - -cairo_font_face_t * -CairoFont::getFontFace(void) { - return cairo_font_face; -} - -unsigned long -CairoFont::getGlyph(CharCode code, - const Unicode *u, int uLen) { - FT_UInt gid; - - if (codeToGID && code < codeToGIDLen) { - gid = (FT_UInt)codeToGID[code]; - } else { - gid = (FT_UInt)code; - } - return gid; -} - -double -CairoFont::getSubstitutionCorrection(GfxFont *gfxFont) -{ - double w1, w2, w3; - CharCode code; - const char *name; - - // for substituted fonts: adjust the font matrix -- compare the - // width of 'm' in the original font and the substituted font - if (isSubstitute() && !gfxFont->isCIDFont()) { - for (code = 0; code < 256; ++code) { - if ((name = ((Gfx8BitFont *)gfxFont)->getCharName(code)) && - name[0] == 'm' && name[1] == '\0') { - break; - } - } - if (code < 256) { - w1 = ((Gfx8BitFont *)gfxFont)->getWidth(code); - { - cairo_matrix_t m; - cairo_matrix_init_identity(&m); - cairo_font_options_t *options = cairo_font_options_create(); - cairo_font_options_set_hint_style(options, CAIRO_HINT_STYLE_NONE); - cairo_font_options_set_hint_metrics(options, CAIRO_HINT_METRICS_OFF); - cairo_scaled_font_t *scaled_font = cairo_scaled_font_create(cairo_font_face, &m, &m, options); - - cairo_text_extents_t extents; - cairo_scaled_font_text_extents(scaled_font, "m", &extents); - - cairo_scaled_font_destroy(scaled_font); - cairo_font_options_destroy(options); - w2 = extents.x_advance; - } - w3 = ((Gfx8BitFont *)gfxFont)->getWidth(0); - if (!gfxFont->isSymbolic() && w2 > 0 && w1 > w3) { - // if real font is substantially narrower than substituted - // font, reduce the font size accordingly - if (w1 > 0.01 && w1 < 0.9 * w2) { - w1 /= w2; - return w1; - } - } - } - } - return 1.0; -} - -//------------------------------------------------------------------------ -// CairoFreeTypeFont -//------------------------------------------------------------------------ - -static cairo_user_data_key_t _ft_cairo_key; - -static void -_ft_done_face_uncached (void *closure) -{ - FT_Face face = (FT_Face) closure; - FT_Done_Face (face); -} - -static bool -_ft_new_face_uncached (FT_Library lib, - const char *filename, - char *font_data, - int font_data_len, - FT_Face *face_out, - cairo_font_face_t **font_face_out) -{ - FT_Face face; - cairo_font_face_t *font_face; - - if (font_data == nullptr) { - if (FT_New_Face (lib, filename, 0, &face)) - return false; - } else { - if (FT_New_Memory_Face (lib, (unsigned char *)font_data, font_data_len, 0, &face)) - return false; - } - - font_face = cairo_ft_font_face_create_for_ft_face (face, - FT_LOAD_NO_HINTING | - FT_LOAD_NO_BITMAP); - if (cairo_font_face_set_user_data (font_face, - &_ft_cairo_key, - face, - _ft_done_face_uncached)) - { - _ft_done_face_uncached (face); - cairo_font_face_destroy (font_face); - return false; - } - - *face_out = face; - *font_face_out = font_face; - return true; -} - -#ifdef CAN_CHECK_OPEN_FACES -static struct _ft_face_data { - struct _ft_face_data *prev, *next, **head; - - int fd; - unsigned long hash; - size_t size; - unsigned char *bytes; - - FT_Library lib; - FT_Face face; - cairo_font_face_t *font_face; -} *_ft_open_faces; - -static unsigned long -_djb_hash (const unsigned char *bytes, size_t len) -{ - unsigned long hash = 5381; - while (len--) { - unsigned char c = *bytes++; - hash *= 33; - hash ^= c; - } - return hash; -} - -static bool -_ft_face_data_equal (struct _ft_face_data *a, struct _ft_face_data *b) -{ - if (a->lib != b->lib) - return false; - if (a->size != b->size) - return false; - if (a->hash != b->hash) - return false; - - return memcmp (a->bytes, b->bytes, a->size) == 0; -} - -static void -_ft_done_face (void *closure) -{ - struct _ft_face_data *data = (struct _ft_face_data *) closure; - - if (data->next) - data->next->prev = data->prev; - if (data->prev) - data->prev->next = data->next; - else - _ft_open_faces = data->next; - - if (data->fd != -1) { -#if defined(__SUNPRO_CC) && defined(__sun) && defined(__SVR4) - munmap ((char*)data->bytes, data->size); -#else - munmap (data->bytes, data->size); -#endif - close (data->fd); - } else { - gfree (data->bytes); - } - - FT_Done_Face (data->face); - gfree (data); -} - -static bool -_ft_new_face (FT_Library lib, - const char *filename, - char *font_data, - int font_data_len, - FT_Face *face_out, - cairo_font_face_t **font_face_out) -{ - struct _ft_face_data *l; - struct stat st; - struct _ft_face_data tmpl; - - tmpl.fd = -1; - - if (font_data == nullptr) { - /* if we fail to mmap the file, just pass it to FreeType instead */ - tmpl.fd = openFileDescriptor (filename, O_RDONLY); - if (tmpl.fd == -1) - return _ft_new_face_uncached (lib, filename, font_data, font_data_len, face_out, font_face_out); - - if (fstat (tmpl.fd, &st) == -1) { - close (tmpl.fd); - return _ft_new_face_uncached (lib, filename, font_data, font_data_len, face_out, font_face_out); - } - - tmpl.bytes = (unsigned char *) mmap (nullptr, st.st_size, - PROT_READ, MAP_PRIVATE, - tmpl.fd, 0); - if (tmpl.bytes == MAP_FAILED) { - close (tmpl.fd); - return _ft_new_face_uncached (lib, filename, font_data, font_data_len, face_out, font_face_out); - } - tmpl.size = st.st_size; - } else { - tmpl.bytes = (unsigned char*) font_data; - tmpl.size = font_data_len; - } - - /* check to see if this is a duplicate of any of the currently open fonts */ - tmpl.lib = lib; - tmpl.hash = _djb_hash (tmpl.bytes, tmpl.size); - - for (l = _ft_open_faces; l; l = l->next) { - if (_ft_face_data_equal (l, &tmpl)) { - if (tmpl.fd != -1) { -#if defined(__SUNPRO_CC) && defined(__sun) && defined(__SVR4) - munmap ((char*)tmpl.bytes, tmpl.size); -#else - munmap (tmpl.bytes, tmpl.size); -#endif - close (tmpl.fd); - } else { - gfree (tmpl.bytes); - } - *face_out = l->face; - *font_face_out = cairo_font_face_reference (l->font_face); - return true; - } - } - - /* not a dup, open and insert into list */ - if (FT_New_Memory_Face (lib, - (FT_Byte *) tmpl.bytes, tmpl.size, - 0, &tmpl.face)) - { - if (tmpl.fd != -1) { -#if defined(__SUNPRO_CC) && defined(__sun) && defined(__SVR4) - munmap ((char*)tmpl.bytes, tmpl.size); -#else - munmap (tmpl.bytes, tmpl.size); -#endif - - close (tmpl.fd); - } - return false; - } - - l = (struct _ft_face_data *) gmallocn (1, sizeof (struct _ft_face_data)); - *l = tmpl; - l->prev = nullptr; - l->next = _ft_open_faces; - if (_ft_open_faces) - _ft_open_faces->prev = l; - _ft_open_faces = l; - - l->font_face = cairo_ft_font_face_create_for_ft_face (tmpl.face, - FT_LOAD_NO_HINTING | - FT_LOAD_NO_BITMAP); - if (cairo_font_face_set_user_data (l->font_face, - &_ft_cairo_key, - l, - _ft_done_face)) - { - cairo_font_face_destroy (l->font_face); - _ft_done_face (l); - return false; - } - - *face_out = l->face; - *font_face_out = l->font_face; - return true; -} -#else -#define _ft_new_face _ft_new_face_uncached -#endif - -CairoFreeTypeFont::CairoFreeTypeFont(Ref refA, - cairo_font_face_t *cairo_font_faceA, - int *codeToGIDA, - unsigned int codeToGIDLenA, - bool substituteA) : CairoFont(refA, - cairo_font_faceA, - codeToGIDA, - codeToGIDLenA, - substituteA, - true) { } - -CairoFreeTypeFont::~CairoFreeTypeFont() { } - -CairoFreeTypeFont *CairoFreeTypeFont::create(GfxFont *gfxFont, XRef *xref, - FT_Library lib, bool useCIDs) { - GooString *fileName; - const char *fileNameC; - char *font_data; - int font_data_len; - int i, n; - GfxFontType fontType; - GfxFontLoc *fontLoc; - char **enc; - const char *name; - FoFiTrueType *ff; - FoFiType1C *ff1c; - Ref ref; - FT_Face face; - cairo_font_face_t *font_face; - - int *codeToGID; - unsigned int codeToGIDLen; - - codeToGID = nullptr; - codeToGIDLen = 0; - font_data = nullptr; - font_data_len = 0; - fileName = nullptr; - fileNameC = nullptr; - - bool substitute = false; - - ref = *gfxFont->getID(); - fontType = gfxFont->getType(); - - if (!(fontLoc = gfxFont->locateFont(xref, nullptr))) { - error(errSyntaxError, -1, "Couldn't find a font for '{0:s}'", - gfxFont->getName() ? gfxFont->getName()->c_str() - : "(unnamed)"); - goto err2; - } - - // embedded font - if (fontLoc->locType == gfxFontLocEmbedded) { - font_data = gfxFont->readEmbFontFile(xref, &font_data_len); - if (nullptr == font_data) - goto err2; - - // external font - } else { // gfxFontLocExternal - fileName = fontLoc->path; - fontType = fontLoc->fontType; - substitute = true; - } - - if (fileName != nullptr) { - fileNameC = fileName->c_str(); - } - - switch (fontType) { - case fontType1: - case fontType1C: - case fontType1COT: - if (! _ft_new_face (lib, fileNameC, font_data, font_data_len, &face, &font_face)) { - error(errSyntaxError, -1, "could not create type1 face"); - goto err2; - } - - enc = ((Gfx8BitFont *)gfxFont)->getEncoding(); - - codeToGID = (int *)gmallocn(256, sizeof(int)); - codeToGIDLen = 256; - for (i = 0; i < 256; ++i) { - codeToGID[i] = 0; - if ((name = enc[i])) { - codeToGID[i] = FT_Get_Name_Index(face, (char*)name); - if (codeToGID[i] == 0) { - Unicode u; - u = globalParams->mapNameToUnicodeText (name); - codeToGID[i] = FT_Get_Char_Index (face, u); - } - if (codeToGID[i] == 0) { - name = GfxFont::getAlternateName(name); - if (name) { - codeToGID[i] = FT_Get_Name_Index(face, (char*)name); - } - } - } - } - break; - case fontCIDType2: - case fontCIDType2OT: - codeToGID = nullptr; - n = 0; - if (((GfxCIDFont *)gfxFont)->getCIDToGID()) { - n = ((GfxCIDFont *)gfxFont)->getCIDToGIDLen(); - if (n) { - codeToGID = (int *)gmallocn(n, sizeof(int)); - memcpy(codeToGID, ((GfxCIDFont *)gfxFont)->getCIDToGID(), - n * sizeof(int)); - } - } else { - if (font_data != nullptr) { - ff = FoFiTrueType::make(font_data, font_data_len); - } else { - ff = FoFiTrueType::load(fileNameC); - } - if (! ff) - goto err2; - codeToGID = ((GfxCIDFont *)gfxFont)->getCodeToGIDMap(ff, &n); - delete ff; - } - codeToGIDLen = n; - /* Fall through */ - case fontTrueType: - case fontTrueTypeOT: - if (font_data != nullptr) { - ff = FoFiTrueType::make(font_data, font_data_len); - } else { - ff = FoFiTrueType::load(fileNameC); - } - if (! ff) { - error(errSyntaxError, -1, "failed to load truetype font\n"); - goto err2; - } - /* This might be set already for the CIDType2 case */ - if (fontType == fontTrueType || fontType == fontTrueTypeOT) { - codeToGID = ((Gfx8BitFont *)gfxFont)->getCodeToGIDMap(ff); - codeToGIDLen = 256; - } - delete ff; - if (! _ft_new_face (lib, fileNameC, font_data, font_data_len, &face, &font_face)) { - error(errSyntaxError, -1, "could not create truetype face\n"); - goto err2; - } - break; - - case fontCIDType0: - case fontCIDType0C: - - codeToGID = nullptr; - codeToGIDLen = 0; - - if (!useCIDs) - { - if (font_data != nullptr) { - ff1c = FoFiType1C::make(font_data, font_data_len); - } else { - ff1c = FoFiType1C::load(fileNameC); - } - if (ff1c) { - codeToGID = ff1c->getCIDToGIDMap((int *)&codeToGIDLen); - delete ff1c; - } - } - - if (! _ft_new_face (lib, fileNameC, font_data, font_data_len, &face, &font_face)) { - error(errSyntaxError, -1, "could not create cid face\n"); - goto err2; - } - break; - - case fontCIDType0COT: - codeToGID = nullptr; - n = 0; - if (((GfxCIDFont *)gfxFont)->getCIDToGID()) { - n = ((GfxCIDFont *)gfxFont)->getCIDToGIDLen(); - if (n) { - codeToGID = (int *)gmallocn(n, sizeof(int)); - memcpy(codeToGID, ((GfxCIDFont *)gfxFont)->getCIDToGID(), - n * sizeof(int)); - } - } - codeToGIDLen = n; - - if (!codeToGID) { - if (!useCIDs) { - if (font_data != nullptr) { - ff = FoFiTrueType::make(font_data, font_data_len); - } else { - ff = FoFiTrueType::load(fileNameC); - } - if (ff) { - if (ff->isOpenTypeCFF()) { - codeToGID = ff->getCIDToGIDMap((int *)&codeToGIDLen); - } - delete ff; - } - } - } - if (! _ft_new_face (lib, fileNameC, font_data, font_data_len, &face, &font_face)) { - error(errSyntaxError, -1, "could not create cid (OT) face\n"); - goto err2; - } - break; - - default: - fprintf (stderr, "font type %d not handled\n", (int)fontType); - goto err2; - break; - } - - delete fontLoc; - return new CairoFreeTypeFont(ref, - font_face, - codeToGID, codeToGIDLen, - substitute); - - err2: - /* hmm? */ - delete fontLoc; - gfree (codeToGID); - gfree (font_data); - fprintf (stderr, "some font thing failed\n"); - return nullptr; -} - -//------------------------------------------------------------------------ -// CairoType3Font -//------------------------------------------------------------------------ - -static const cairo_user_data_key_t type3_font_key = {0}; - -typedef struct _type3_font_info { - GfxFont *font; - PDFDoc *doc; - CairoFontEngine *fontEngine; - bool printing; - XRef *xref; -} type3_font_info_t; - -static void -_free_type3_font_info(void *closure) -{ - type3_font_info_t *info = (type3_font_info_t *) closure; - - info->font->decRefCnt(); - free (info); -} - -static cairo_status_t -_init_type3_glyph (cairo_scaled_font_t *scaled_font, - cairo_t *cr, - cairo_font_extents_t *extents) -{ - type3_font_info_t *info; - GfxFont *font; - - info = (type3_font_info_t *) - cairo_font_face_get_user_data (cairo_scaled_font_get_font_face (scaled_font), - &type3_font_key); - font = info->font; - const double *mat = font->getFontBBox(); - extents->ascent = mat[3]; /* y2 */ - extents->descent = -mat[3]; /* -y1 */ - extents->height = extents->ascent + extents->descent; - extents->max_x_advance = mat[2] - mat[1]; /* x2 - x1 */ - extents->max_y_advance = 0; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_render_type3_glyph (cairo_scaled_font_t *scaled_font, - unsigned long glyph, - cairo_t *cr, - cairo_text_extents_t *metrics) -{ - Dict *charProcs; - Object charProc; - CairoOutputDev *output_dev; - cairo_matrix_t matrix, invert_y_axis; - const double *mat; - double wx, wy; - PDFRectangle box; - type3_font_info_t *info; - GfxFont *font; - Dict *resDict; - Gfx *gfx; - - info = (type3_font_info_t *) - cairo_font_face_get_user_data (cairo_scaled_font_get_font_face (scaled_font), - &type3_font_key); - - font = info->font; - resDict = ((Gfx8BitFont *)font)->getResources(); - charProcs = ((Gfx8BitFont *)(info->font))->getCharProcs(); - if (!charProcs) - return CAIRO_STATUS_USER_FONT_ERROR; - - if ((int)glyph >= charProcs->getLength()) - return CAIRO_STATUS_USER_FONT_ERROR; - - mat = font->getFontMatrix(); - matrix.xx = mat[0]; - matrix.yx = mat[1]; - matrix.xy = mat[2]; - matrix.yy = mat[3]; - matrix.x0 = mat[4]; - matrix.y0 = mat[5]; - cairo_matrix_init_scale (&invert_y_axis, 1, -1); - cairo_matrix_multiply (&matrix, &matrix, &invert_y_axis); - cairo_transform (cr, &matrix); - - output_dev = new CairoOutputDev(); - output_dev->setCairo(cr); - output_dev->setPrinting(info->printing); - - mat = font->getFontBBox(); - box.x1 = mat[0]; - box.y1 = mat[1]; - box.x2 = mat[2]; - box.y2 = mat[3]; - gfx = new Gfx(info->doc, output_dev, resDict, &box, nullptr); - output_dev->startDoc(info->doc, info->fontEngine); - output_dev->startPage (1, gfx->getState(), gfx->getXRef()); - output_dev->setInType3Char(true); - charProc = charProcs->getVal(glyph); - gfx->display(&charProc); - - output_dev->getType3GlyphWidth (&wx, &wy); - cairo_matrix_transform_distance (&matrix, &wx, &wy); - metrics->x_advance = wx; - metrics->y_advance = wy; - if (output_dev->hasType3GlyphBBox()) { - double *bbox = output_dev->getType3GlyphBBox(); - - cairo_matrix_transform_point (&matrix, &bbox[0], &bbox[1]); - cairo_matrix_transform_point (&matrix, &bbox[2], &bbox[3]); - metrics->x_bearing = bbox[0]; - metrics->y_bearing = bbox[1]; - metrics->width = bbox[2] - bbox[0]; - metrics->height = bbox[3] - bbox[1]; - } - - delete gfx; - delete output_dev; - - return CAIRO_STATUS_SUCCESS; -} - - -CairoType3Font *CairoType3Font::create(GfxFont *gfxFont, PDFDoc *doc, - CairoFontEngine *fontEngine, - bool printing, XRef *xref) { - type3_font_info_t *info; - cairo_font_face_t *font_face; - Ref ref; - int *codeToGID; - unsigned int codeToGIDLen; - int i, j; - char **enc; - Dict *charProcs; - char *name; - - charProcs = ((Gfx8BitFont *)gfxFont)->getCharProcs(); - info = (type3_font_info_t *) malloc(sizeof(*info)); - ref = *gfxFont->getID(); - font_face = cairo_user_font_face_create(); - cairo_user_font_face_set_init_func (font_face, _init_type3_glyph); - cairo_user_font_face_set_render_glyph_func (font_face, _render_type3_glyph); - gfxFont->incRefCnt(); - info->font = gfxFont; - info->doc = doc; - info->fontEngine = fontEngine; - info->printing = printing; - info->xref = xref; - - cairo_font_face_set_user_data (font_face, &type3_font_key, (void *) info, _free_type3_font_info); - - enc = ((Gfx8BitFont *)gfxFont)->getEncoding(); - codeToGID = (int *)gmallocn(256, sizeof(int)); - codeToGIDLen = 256; - for (i = 0; i < 256; ++i) { - codeToGID[i] = 0; - if (charProcs && (name = enc[i])) { - for (j = 0; j < charProcs->getLength(); j++) { - if (strcmp(name, charProcs->getKey(j)) == 0) { - codeToGID[i] = j; - } - } - } - } - - return new CairoType3Font(ref, font_face, codeToGID, codeToGIDLen, printing, xref); -} - -CairoType3Font::CairoType3Font(Ref refA, - cairo_font_face_t *cairo_font_faceA, - int *codeToGIDA, - unsigned int codeToGIDLenA, - bool printingA, XRef *xref) : CairoFont(refA, - cairo_font_faceA, - codeToGIDA, - codeToGIDLenA, - false, - printingA) -{ } - -CairoType3Font::~CairoType3Font() { } - -bool -CairoType3Font::matches(Ref &other, bool printingA) { - return (other == ref && printing == printingA); -} - - -//------------------------------------------------------------------------ -// CairoFontEngine -//------------------------------------------------------------------------ - -#define fontEngineLocker() std::unique_lock locker(mutex) - -CairoFontEngine::CairoFontEngine(FT_Library libA) { - int i; - - lib = libA; - for (i = 0; i < cairoFontCacheSize; ++i) { - fontCache[i] = nullptr; - } - - FT_Int major, minor, patch; - // as of FT 2.1.8, CID fonts are indexed by CID instead of GID - FT_Library_Version(lib, &major, &minor, &patch); - useCIDs = major > 2 || - (major == 2 && (minor > 1 || (minor == 1 && patch > 7))); -} - -CairoFontEngine::~CairoFontEngine() { - int i; - - for (i = 0; i < cairoFontCacheSize; ++i) { - if (fontCache[i]) - delete fontCache[i]; - } -} - -CairoFont * -CairoFontEngine::getFont(GfxFont *gfxFont, PDFDoc *doc, bool printing, XRef *xref) { - int i, j; - Ref ref; - CairoFont *font; - GfxFontType fontType; - - fontEngineLocker(); - ref = *gfxFont->getID(); - - for (i = 0; i < cairoFontCacheSize; ++i) { - font = fontCache[i]; - if (font && font->matches(ref, printing)) { - for (j = i; j > 0; --j) { - fontCache[j] = fontCache[j-1]; - } - fontCache[0] = font; - return font; - } - } - - fontType = gfxFont->getType(); - if (fontType == fontType3) - font = CairoType3Font::create (gfxFont, doc, this, printing, xref); - else - font = CairoFreeTypeFont::create (gfxFont, xref, lib, useCIDs); - - //XXX: if font is null should we still insert it into the cache? - if (fontCache[cairoFontCacheSize - 1]) { - delete fontCache[cairoFontCacheSize - 1]; - } - for (j = cairoFontCacheSize - 1; j > 0; --j) { - fontCache[j] = fontCache[j-1]; - } - fontCache[0] = font; - return font; -} diff --git a/pdf2htmlEX/3rdparty/poppler/git/CairoFontEngine.h b/pdf2htmlEX/3rdparty/poppler/git/CairoFontEngine.h deleted file mode 100644 index 34802c1..0000000 --- a/pdf2htmlEX/3rdparty/poppler/git/CairoFontEngine.h +++ /dev/null @@ -1,128 +0,0 @@ -//======================================================================== -// -// CairoFontEngine.h -// -// Copyright 2003 Glyph & Cog, LLC -// Copyright 2004 Red Hat, Inc -// -//======================================================================== - -//======================================================================== -// -// Modified under the Poppler project - http://poppler.freedesktop.org -// -// All changes made under the Poppler project to this file are licensed -// under GPL version 2 or later -// -// Copyright (C) 2005, 2006 Kristian Høgsberg -// Copyright (C) 2005, 2018, 2019 Albert Astals Cid -// Copyright (C) 2006, 2007 Jeff Muizelaar -// Copyright (C) 2006, 2010 Carlos Garcia Campos -// Copyright (C) 2008, 2017 Adrian Johnson -// Copyright (C) 2013 Thomas Freitag -// Copyright (C) 2018 Adam Reichold -// -// To see a description of the changes please see the Changelog file that -// came with your tarball or type make ChangeLog if you are building from git -// -//======================================================================== - -#ifndef CAIROFONTENGINE_H -#define CAIROFONTENGINE_H - -#include - -#include "poppler-config.h" -#include - -#include "GfxFont.h" -#include "PDFDoc.h" - -class CairoFontEngine; - -class CairoFont { -public: - CairoFont(Ref ref, - cairo_font_face_t *face, - int *codeToGID, - unsigned int codeToGIDLen, - bool substitute, - bool printing); - virtual ~CairoFont(); - CairoFont(const CairoFont &) = delete; - CairoFont& operator=(const CairoFont &other) = delete; - - virtual bool matches(Ref &other, bool printing); - cairo_font_face_t *getFontFace(void); - unsigned long getGlyph(CharCode code, const Unicode *u, int uLen); - double getSubstitutionCorrection(GfxFont *gfxFont); - - bool isSubstitute() { return substitute; } -protected: - Ref ref; - cairo_font_face_t *cairo_font_face; - - int *codeToGID; - unsigned int codeToGIDLen; - - bool substitute; - bool printing; -}; - -//------------------------------------------------------------------------ - -class CairoFreeTypeFont : public CairoFont { -public: - static CairoFreeTypeFont *create(GfxFont *gfxFont, XRef *xref, FT_Library lib, bool useCIDs); - ~CairoFreeTypeFont(); - -private: - CairoFreeTypeFont(Ref ref, cairo_font_face_t *cairo_font_face, - int *codeToGID, unsigned int codeToGIDLen, bool substitute); -}; - -//------------------------------------------------------------------------ - -class CairoType3Font : public CairoFont { -public: - static CairoType3Font *create(GfxFont *gfxFont, PDFDoc *doc, - CairoFontEngine *fontEngine, - bool printing, XRef *xref); - ~CairoType3Font(); - - bool matches(Ref &other, bool printing) override; - -private: - CairoType3Font(Ref ref, - cairo_font_face_t *cairo_font_face, - int *codeToGID, unsigned int codeToGIDLen, - bool printing, XRef *xref); -}; - -//------------------------------------------------------------------------ - -#define cairoFontCacheSize 64 - -//------------------------------------------------------------------------ -// CairoFontEngine -//------------------------------------------------------------------------ - -class CairoFontEngine { -public: - - // Create a font engine. - CairoFontEngine(FT_Library libA); - ~CairoFontEngine(); - CairoFontEngine(const CairoFontEngine &) = delete; - CairoFontEngine& operator=(const CairoFontEngine &other) = delete; - - CairoFont *getFont(GfxFont *gfxFont, PDFDoc *doc, bool printing, XRef *xref); - -private: - CairoFont *fontCache[cairoFontCacheSize]; - FT_Library lib; - bool useCIDs; - mutable std::recursive_mutex mutex; -}; - -#endif diff --git a/pdf2htmlEX/3rdparty/poppler/git/CairoOutputDev.cc b/pdf2htmlEX/3rdparty/poppler/git/CairoOutputDev.cc deleted file mode 100644 index 0f3c156..0000000 --- a/pdf2htmlEX/3rdparty/poppler/git/CairoOutputDev.cc +++ /dev/null @@ -1,3573 +0,0 @@ -//======================================================================== -// -// CairoOutputDev.cc -// -// Copyright 2003 Glyph & Cog, LLC -// Copyright 2004 Red Hat, Inc -// -//======================================================================== - -//======================================================================== -// -// Modified under the Poppler project - http://poppler.freedesktop.org -// -// All changes made under the Poppler project to this file are licensed -// under GPL version 2 or later -// -// Copyright (C) 2005-2008 Jeff Muizelaar -// Copyright (C) 2005, 2006 Kristian Høgsberg -// Copyright (C) 2005, 2009, 2012, 2017-2019 Albert Astals Cid -// Copyright (C) 2005 Nickolay V. Shmyrev -// Copyright (C) 2006-2011, 2013, 2014, 2017, 2018 Carlos Garcia Campos -// Copyright (C) 2008 Carl Worth -// Copyright (C) 2008-2018 Adrian Johnson -// Copyright (C) 2008 Michael Vrable -// Copyright (C) 2008, 2009 Chris Wilson -// Copyright (C) 2008, 2012 Hib Eris -// Copyright (C) 2009, 2010 David Benjamin -// Copyright (C) 2011-2014 Thomas Freitag -// Copyright (C) 2012 Patrick Pfeifer -// Copyright (C) 2012, 2015, 2016 Jason Crain -// Copyright (C) 2015 Suzuki Toshiya -// Copyright (C) 2018 Klarälvdalens Datakonsult AB, a KDAB Group company, . Work sponsored by the LiMux project of the city of Munich -// Copyright (C) 2018 Adam Reichold -// Copyright (C) 2019 Marek Kasik -// -// To see a description of the changes please see the Changelog file that -// came with your tarball or type make ChangeLog if you are building from git -// -//======================================================================== - -#include - -#include -#include -#include -#include -#include - -#include "goo/gfile.h" -#include "GlobalParams.h" -#include "Error.h" -#include "Object.h" -#include "Gfx.h" -#include "GfxState.h" -#include "GfxFont.h" -#include "Page.h" -#include "Link.h" -#include "FontEncodingTables.h" -#include "PDFDocEncoding.h" -#include -#include -#include "CairoOutputDev.h" -#include "CairoFontEngine.h" -#include "CairoRescaleBox.h" -#include "UnicodeMap.h" -#include "JBIG2Stream.h" -//------------------------------------------------------------------------ - -// #define LOG_CAIRO - -// To limit memory usage and improve performance when printing, limit -// cairo images to this size. 8192 is sufficient for an A2 sized -// 300ppi image. -#define MAX_PRINT_IMAGE_SIZE 8192 - -#ifdef LOG_CAIRO -#define LOG(x) (x) -#else -#define LOG(x) -#endif - - -#define MIN(a,b) (((a) < (b)) ? (a) : (b)) -#define MAX(a,b) (((a) > (b)) ? (a) : (b)) - - -//------------------------------------------------------------------------ -// CairoImage -//------------------------------------------------------------------------ - -CairoImage::CairoImage (double x1A, double y1A, double x2A, double y2A) { - image = nullptr; - x1 = x1A; - y1 = y1A; - x2 = x2A; - y2 = y2A; -} - -CairoImage::~CairoImage () { - if (image) - cairo_surface_destroy (image); -} - -void CairoImage::setImage (cairo_surface_t *i) { - if (image) - cairo_surface_destroy (image); - image = cairo_surface_reference (i); -} - -//------------------------------------------------------------------------ -// CairoOutputDev -//------------------------------------------------------------------------ - -// We cannot tie the lifetime of an FT_Library object to that of -// CairoOutputDev, since any FT_Faces created with it may end up with a -// reference by Cairo which can be held long after the CairoOutputDev is -// deleted. The simplest way to avoid problems is to never tear down the -// FT_Library instance; to avoid leaks, just use a single global instance -// initialized the first time it is needed. -FT_Library CairoOutputDev::ft_lib; -bool CairoOutputDev::ft_lib_initialized = false; - -CairoOutputDev::CairoOutputDev() { - doc = nullptr; - - if (!ft_lib_initialized) { - FT_Init_FreeType(&ft_lib); - ft_lib_initialized = true; - } - - fontEngine = nullptr; - fontEngine_owner = false; - glyphs = nullptr; - fill_pattern = nullptr; - fill_color.r = fill_color.g = fill_color.b = 0; - stroke_pattern = nullptr; - stroke_color.r = stroke_color.g = stroke_color.b = 0; - stroke_opacity = 1.0; - fill_opacity = 1.0; - textClipPath = nullptr; - strokePathClip = nullptr; - cairo = nullptr; - currentFont = nullptr; -#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 14, 0) - prescaleImages = false; -#else - prescaleImages = true; -#endif - printing = true; - use_show_text_glyphs = false; - inUncoloredPattern = false; - inType3Char = false; - t3_glyph_has_bbox = false; - text_matrix_valid = true; - antialias = CAIRO_ANTIALIAS_DEFAULT; - - groupColorSpaceStack = nullptr; - maskStack = nullptr; - group = nullptr; - mask = nullptr; - shape = nullptr; - cairo_shape = nullptr; - knockoutCount = 0; - - textPage = nullptr; - actualText = nullptr; - - // the SA parameter supposedly defaults to false, but Acrobat - // apparently hardwires it to true - stroke_adjust = true; - align_stroke_coords = false; - adjusted_stroke_width = false; - xref = nullptr; -} - -CairoOutputDev::~CairoOutputDev() { - if (fontEngine_owner && fontEngine) { - delete fontEngine; - } - - if (cairo) - cairo_destroy (cairo); - cairo_pattern_destroy (stroke_pattern); - cairo_pattern_destroy (fill_pattern); - if (group) - cairo_pattern_destroy (group); - if (mask) - cairo_pattern_destroy (mask); - if (shape) - cairo_pattern_destroy (shape); - if (textPage) - textPage->decRefCnt(); - if (actualText) - delete actualText; -} - -void CairoOutputDev::setCairo(cairo_t *c) -{ - if (cairo != nullptr) { - cairo_status_t status = cairo_status (cairo); - if (status) { - error(errInternal, -1, "cairo context error: {0:s}\n", cairo_status_to_string(status)); - } - cairo_destroy (cairo); - assert(!cairo_shape); - } - if (c != nullptr) { - cairo = cairo_reference (c); - /* save the initial matrix so that we can use it for type3 fonts. */ - //XXX: is this sufficient? could we miss changes to the matrix somehow? - cairo_get_matrix(cairo, &orig_matrix); - setContextAntialias(cairo, antialias); - } else { - cairo = nullptr; - cairo_shape = nullptr; - } -} - -void CairoOutputDev::setTextPage(TextPage *text) -{ - if (textPage) - textPage->decRefCnt(); - if (actualText) - delete actualText; - if (text) { - textPage = text; - textPage->incRefCnt(); - actualText = new ActualText(text); - } else { - textPage = nullptr; - actualText = nullptr; - } -} - -void CairoOutputDev::setAntialias(cairo_antialias_t a) -{ - antialias = a; - if (cairo) - setContextAntialias (cairo, antialias); - if (cairo_shape) - setContextAntialias (cairo_shape, antialias); -} - -void CairoOutputDev::setContextAntialias(cairo_t *cr, cairo_antialias_t antialias) -{ - cairo_font_options_t *font_options; - cairo_set_antialias (cr, antialias); - font_options = cairo_font_options_create (); - cairo_get_font_options (cr, font_options); - cairo_font_options_set_antialias (font_options, antialias); - cairo_set_font_options (cr, font_options); - cairo_font_options_destroy (font_options); -} - -void CairoOutputDev::startDoc(PDFDoc *docA, - CairoFontEngine *parentFontEngine) { - doc = docA; - if (parentFontEngine) { - fontEngine = parentFontEngine; - } else { - if (fontEngine) { - delete fontEngine; - } - fontEngine = new CairoFontEngine(ft_lib); - fontEngine_owner = true; - } - xref = doc->getXRef(); -} - -void CairoOutputDev::startPage(int pageNum, GfxState *state, XRef *xrefA) { - /* set up some per page defaults */ - cairo_pattern_destroy(fill_pattern); - cairo_pattern_destroy(stroke_pattern); - - fill_pattern = cairo_pattern_create_rgb(0., 0., 0.); - fill_color.r = fill_color.g = fill_color.b = 0; - stroke_pattern = cairo_pattern_reference(fill_pattern); - stroke_color.r = stroke_color.g = stroke_color.b = 0; - - if (textPage) - textPage->startPage(state); - if (xrefA != nullptr) { - xref = xrefA; - } -} - -void CairoOutputDev::endPage() { - if (textPage) { - textPage->endPage(); - textPage->coalesce(true, 0, false); - } -} - -void CairoOutputDev::saveState(GfxState *state) { - LOG(printf ("save\n")); - cairo_save (cairo); - if (cairo_shape) - cairo_save (cairo_shape); - - MaskStack *ms = new MaskStack; - ms->mask = cairo_pattern_reference(mask); - ms->mask_matrix = mask_matrix; - ms->next = maskStack; - maskStack = ms; - - if (strokePathClip) - strokePathClip->ref_count++; -} - -void CairoOutputDev::restoreState(GfxState *state) { - LOG(printf ("restore\n")); - cairo_restore (cairo); - if (cairo_shape) - cairo_restore (cairo_shape); - - text_matrix_valid = true; - - /* These aren't restored by cairo_restore() since we keep them in - * the output device. */ - updateFillColor(state); - updateStrokeColor(state); - updateFillOpacity(state); - updateStrokeOpacity(state); - updateBlendMode(state); - - MaskStack* ms = maskStack; - if (ms) { - if (mask) - cairo_pattern_destroy(mask); - mask = ms->mask; - mask_matrix = ms->mask_matrix; - maskStack = ms->next; - delete ms; - } - - if (strokePathClip && --strokePathClip->ref_count == 0) { - delete strokePathClip->path; - if (strokePathClip->dashes) - gfree (strokePathClip->dashes); - gfree (strokePathClip); - strokePathClip = nullptr; - } -} - -void CairoOutputDev::updateAll(GfxState *state) { - updateLineDash(state); - updateLineJoin(state); - updateLineCap(state); - updateLineWidth(state); - updateFlatness(state); - updateMiterLimit(state); - updateFillColor(state); - updateStrokeColor(state); - updateFillOpacity(state); - updateStrokeOpacity(state); - updateBlendMode(state); - needFontUpdate = true; - if (textPage) - textPage->updateFont(state); -} - -void CairoOutputDev::setDefaultCTM(const double *ctm) { - cairo_matrix_t matrix; - matrix.xx = ctm[0]; - matrix.yx = ctm[1]; - matrix.xy = ctm[2]; - matrix.yy = ctm[3]; - matrix.x0 = ctm[4]; - matrix.y0 = ctm[5]; - - cairo_transform (cairo, &matrix); - if (cairo_shape) - cairo_transform (cairo_shape, &matrix); - - OutputDev::setDefaultCTM(ctm); -} - -void CairoOutputDev::updateCTM(GfxState *state, double m11, double m12, - double m21, double m22, - double m31, double m32) { - cairo_matrix_t matrix, invert_matrix; - matrix.xx = m11; - matrix.yx = m12; - matrix.xy = m21; - matrix.yy = m22; - matrix.x0 = m31; - matrix.y0 = m32; - - /* Make sure the matrix is invertible before setting it. - * cairo will blow up if we give it a matrix that's not - * invertible, so we need to check before passing it - * to cairo_transform. Ignoring it is likely to give better - * results than not rendering anything at all. See #14398 - * - * Ideally, we could do the cairo_transform - * and then check if anything went wrong and fix it then - * instead of having to invert the matrix. */ - invert_matrix = matrix; - if (cairo_matrix_invert(&invert_matrix)) { - error(errSyntaxWarning, -1, "matrix not invertible\n"); - return; - } - - cairo_transform (cairo, &matrix); - if (cairo_shape) - cairo_transform (cairo_shape, &matrix); - updateLineDash(state); - updateLineJoin(state); - updateLineCap(state); - updateLineWidth(state); -} - -void CairoOutputDev::updateLineDash(GfxState *state) { - double *dashPattern; - int dashLength; - double dashStart; - - state->getLineDash(&dashPattern, &dashLength, &dashStart); - cairo_set_dash (cairo, dashPattern, dashLength, dashStart); - if (cairo_shape) - cairo_set_dash (cairo_shape, dashPattern, dashLength, dashStart); -} - -void CairoOutputDev::updateFlatness(GfxState *state) { - // cairo_set_tolerance (cairo, state->getFlatness()); -} - -void CairoOutputDev::updateLineJoin(GfxState *state) { - switch (state->getLineJoin()) { - case 0: - cairo_set_line_join (cairo, CAIRO_LINE_JOIN_MITER); - break; - case 1: - cairo_set_line_join (cairo, CAIRO_LINE_JOIN_ROUND); - break; - case 2: - cairo_set_line_join (cairo, CAIRO_LINE_JOIN_BEVEL); - break; - } - if (cairo_shape) - cairo_set_line_join (cairo_shape, cairo_get_line_join(cairo)); -} - -void CairoOutputDev::updateLineCap(GfxState *state) { - switch (state->getLineCap()) { - case 0: - cairo_set_line_cap (cairo, CAIRO_LINE_CAP_BUTT); - break; - case 1: - cairo_set_line_cap (cairo, CAIRO_LINE_CAP_ROUND); - break; - case 2: - cairo_set_line_cap (cairo, CAIRO_LINE_CAP_SQUARE); - break; - } - if (cairo_shape) - cairo_set_line_cap (cairo_shape, cairo_get_line_cap(cairo)); -} - -void CairoOutputDev::updateMiterLimit(GfxState *state) { - cairo_set_miter_limit (cairo, state->getMiterLimit()); - if (cairo_shape) - cairo_set_miter_limit (cairo_shape, state->getMiterLimit()); -} - -void CairoOutputDev::updateLineWidth(GfxState *state) { - LOG(printf ("line width: %f\n", state->getLineWidth())); - adjusted_stroke_width = false; - double width = state->getLineWidth(); - if (stroke_adjust && !printing) { - double x, y; - x = y = width; - - /* find out line width in device units */ - cairo_user_to_device_distance(cairo, &x, &y); - if (fabs(x) <= 1.0 && fabs(y) <= 1.0) { - /* adjust width to at least one device pixel */ - x = y = 1.0; - cairo_device_to_user_distance(cairo, &x, &y); - width = MIN(fabs(x),fabs(y)); - adjusted_stroke_width = true; - } - } else if (width == 0.0) { - /* Cairo does not support 0 line width == 1 device pixel. Find out - * how big pixels (device unit) are in the x and y - * directions. Choose the smaller of the two as our line width. - */ - double x = 1.0, y = 1.0; - if (printing) { - // assume printer pixel size is 1/600 inch - x = 72.0/600; - y = 72.0/600; - } - cairo_device_to_user_distance(cairo, &x, &y); - width = MIN(fabs(x),fabs(y)); - } - cairo_set_line_width (cairo, width); - if (cairo_shape) - cairo_set_line_width (cairo_shape, cairo_get_line_width (cairo)); -} - -void CairoOutputDev::updateFillColor(GfxState *state) { - GfxRGB color = fill_color; - - if (inUncoloredPattern) - return; - - state->getFillRGB(&fill_color); - if (cairo_pattern_get_type (fill_pattern) != CAIRO_PATTERN_TYPE_SOLID || - color.r != fill_color.r || - color.g != fill_color.g || - color.b != fill_color.b) - { - cairo_pattern_destroy(fill_pattern); - fill_pattern = cairo_pattern_create_rgba(colToDbl(fill_color.r), - colToDbl(fill_color.g), - colToDbl(fill_color.b), - fill_opacity); - - LOG(printf ("fill color: %d %d %d\n", - fill_color.r, fill_color.g, fill_color.b)); - } -} - -void CairoOutputDev::updateStrokeColor(GfxState *state) { - GfxRGB color = stroke_color; - - if (inUncoloredPattern) - return; - - state->getStrokeRGB(&stroke_color); - if (cairo_pattern_get_type (fill_pattern) != CAIRO_PATTERN_TYPE_SOLID || - color.r != stroke_color.r || - color.g != stroke_color.g || - color.b != stroke_color.b) - { - cairo_pattern_destroy(stroke_pattern); - stroke_pattern = cairo_pattern_create_rgba(colToDbl(stroke_color.r), - colToDbl(stroke_color.g), - colToDbl(stroke_color.b), - stroke_opacity); - - LOG(printf ("stroke color: %d %d %d\n", - stroke_color.r, stroke_color.g, stroke_color.b)); - } -} - -void CairoOutputDev::updateFillOpacity(GfxState *state) { - double opacity = fill_opacity; - - if (inUncoloredPattern) - return; - - fill_opacity = state->getFillOpacity(); - if (opacity != fill_opacity) { - cairo_pattern_destroy(fill_pattern); - fill_pattern = cairo_pattern_create_rgba(colToDbl(fill_color.r), - colToDbl(fill_color.g), - colToDbl(fill_color.b), - fill_opacity); - - LOG(printf ("fill opacity: %f\n", fill_opacity)); - } -} - -void CairoOutputDev::updateStrokeOpacity(GfxState *state) { - double opacity = stroke_opacity; - - if (inUncoloredPattern) - return; - - stroke_opacity = state->getStrokeOpacity(); - if (opacity != stroke_opacity) { - cairo_pattern_destroy(stroke_pattern); - stroke_pattern = cairo_pattern_create_rgba(colToDbl(stroke_color.r), - colToDbl(stroke_color.g), - colToDbl(stroke_color.b), - stroke_opacity); - - LOG(printf ("stroke opacity: %f\n", stroke_opacity)); - } -} - -void CairoOutputDev::updateFillColorStop(GfxState *state, double offset) { - if (inUncoloredPattern) - return; - - state->getFillRGB(&fill_color); - - cairo_pattern_add_color_stop_rgba(fill_pattern, offset, - colToDbl(fill_color.r), - colToDbl(fill_color.g), - colToDbl(fill_color.b), - fill_opacity); - LOG(printf ("fill color stop: %f (%d, %d, %d)\n", - offset, fill_color.r, fill_color.g, fill_color.b)); -} - -void CairoOutputDev::updateBlendMode(GfxState *state) { - switch (state->getBlendMode()) { - default: - case gfxBlendNormal: - cairo_set_operator (cairo, CAIRO_OPERATOR_OVER); - break; - case gfxBlendMultiply: - cairo_set_operator (cairo, CAIRO_OPERATOR_MULTIPLY); - break; - case gfxBlendScreen: - cairo_set_operator (cairo, CAIRO_OPERATOR_SCREEN); - break; - case gfxBlendOverlay: - cairo_set_operator (cairo, CAIRO_OPERATOR_OVERLAY); - break; - case gfxBlendDarken: - cairo_set_operator (cairo, CAIRO_OPERATOR_DARKEN); - break; - case gfxBlendLighten: - cairo_set_operator (cairo, CAIRO_OPERATOR_LIGHTEN); - break; - case gfxBlendColorDodge: - cairo_set_operator (cairo, CAIRO_OPERATOR_COLOR_DODGE); - break; - case gfxBlendColorBurn: - cairo_set_operator (cairo, CAIRO_OPERATOR_COLOR_BURN); - break; - case gfxBlendHardLight: - cairo_set_operator (cairo, CAIRO_OPERATOR_HARD_LIGHT); - break; - case gfxBlendSoftLight: - cairo_set_operator (cairo, CAIRO_OPERATOR_SOFT_LIGHT); - break; - case gfxBlendDifference: - cairo_set_operator (cairo, CAIRO_OPERATOR_DIFFERENCE); - break; - case gfxBlendExclusion: - cairo_set_operator (cairo, CAIRO_OPERATOR_EXCLUSION); - break; - case gfxBlendHue: - cairo_set_operator (cairo, CAIRO_OPERATOR_HSL_HUE); - break; - case gfxBlendSaturation: - cairo_set_operator (cairo, CAIRO_OPERATOR_HSL_SATURATION); - break; - case gfxBlendColor: - cairo_set_operator (cairo, CAIRO_OPERATOR_HSL_COLOR); - break; - case gfxBlendLuminosity: - cairo_set_operator (cairo, CAIRO_OPERATOR_HSL_LUMINOSITY); - break; - } - LOG(printf ("blend mode: %d\n", (int)state->getBlendMode())); -} - -void CairoOutputDev::updateFont(GfxState *state) { - cairo_font_face_t *font_face; - cairo_matrix_t matrix, invert_matrix; - - LOG(printf ("updateFont() font=%s\n", state->getFont()->getName()->c_str())); - - needFontUpdate = false; - - //FIXME: use cairo font engine? - if (textPage) - textPage->updateFont(state); - - currentFont = fontEngine->getFont (state->getFont(), doc, printing, xref); - - if (!currentFont) - return; - - font_face = currentFont->getFontFace(); - cairo_set_font_face (cairo, font_face); - - use_show_text_glyphs = state->getFont()->hasToUnicodeCMap() && - cairo_surface_has_show_text_glyphs (cairo_get_target (cairo)); - - double fontSize = state->getFontSize(); - const double *m = state->getTextMat(); - /* NOTE: adjusting by a constant is hack. The correct solution - * is probably to use user-fonts and compute the scale on a per - * glyph basis instead of for the entire font */ - double w = currentFont->getSubstitutionCorrection(state->getFont()); - matrix.xx = m[0] * fontSize * state->getHorizScaling() * w; - matrix.yx = m[1] * fontSize * state->getHorizScaling() * w; - matrix.xy = -m[2] * fontSize; - matrix.yy = -m[3] * fontSize; - matrix.x0 = 0; - matrix.y0 = 0; - - LOG(printf ("font matrix: %f %f %f %f\n", matrix.xx, matrix.yx, matrix.xy, matrix.yy)); - - /* Make sure the font matrix is invertible before setting it. cairo - * will blow up if we give it a matrix that's not invertible, so we - * need to check before passing it to cairo_set_font_matrix. Ignoring it - * is likely to give better results than not rendering anything at - * all. See #18254. - */ - invert_matrix = matrix; - if (cairo_matrix_invert(&invert_matrix)) { - error(errSyntaxWarning, -1, "font matrix not invertible"); - text_matrix_valid = false; - return; - } - - cairo_set_font_matrix (cairo, &matrix); - text_matrix_valid = true; -} - -/* Tolerance in pixels for checking if strokes are horizontal or vertical - * lines in device space */ -#define STROKE_COORD_TOLERANCE 0.5 - -/* Align stroke coordinate i if the point is the start or end of a - * horizontal or vertical line */ -void CairoOutputDev::alignStrokeCoords(const GfxSubpath *subpath, int i, double *x, double *y) -{ - double x1, y1, x2, y2; - bool align = false; - - x1 = subpath->getX(i); - y1 = subpath->getY(i); - cairo_user_to_device (cairo, &x1, &y1); - - // Does the current coord and prev coord form a horiz or vert line? - if (i > 0 && !subpath->getCurve(i - 1)) { - x2 = subpath->getX(i - 1); - y2 = subpath->getY(i - 1); - cairo_user_to_device (cairo, &x2, &y2); - if (fabs(x2 - x1) < STROKE_COORD_TOLERANCE || fabs(y2 - y1) < STROKE_COORD_TOLERANCE) - align = true; - } - - // Does the current coord and next coord form a horiz or vert line? - if (i < subpath->getNumPoints() - 1 && !subpath->getCurve(i + 1)) { - x2 = subpath->getX(i + 1); - y2 = subpath->getY(i + 1); - cairo_user_to_device (cairo, &x2, &y2); - if (fabs(x2 - x1) < STROKE_COORD_TOLERANCE || fabs(y2 - y1) < STROKE_COORD_TOLERANCE) - align = true; - } - - *x = subpath->getX(i); - *y = subpath->getY(i); - if (align) { - /* see http://www.cairographics.org/FAQ/#sharp_lines */ - cairo_user_to_device (cairo, x, y); - *x = floor(*x) + 0.5; - *y = floor(*y) + 0.5; - cairo_device_to_user (cairo, x, y); - } -} - -#undef STROKE_COORD_TOLERANCE - -void CairoOutputDev::doPath(cairo_t *c, GfxState *state, const GfxPath *path) { - int i, j; - double x, y; - cairo_new_path (c); - for (i = 0; i < path->getNumSubpaths(); ++i) { - const GfxSubpath *subpath = path->getSubpath(i); - if (subpath->getNumPoints() > 0) { - if (align_stroke_coords) { - alignStrokeCoords(subpath, 0, &x, &y); - } else { - x = subpath->getX(0); - y = subpath->getY(0); - } - cairo_move_to (c, x, y); - j = 1; - while (j < subpath->getNumPoints()) { - if (subpath->getCurve(j)) { - if (align_stroke_coords) { - alignStrokeCoords(subpath, j + 2, &x, &y); - } else { - x = subpath->getX(j+2); - y = subpath->getY(j+2); - } - cairo_curve_to( c, - subpath->getX(j), subpath->getY(j), - subpath->getX(j+1), subpath->getY(j+1), - x, y); - - j += 3; - } else { - if (align_stroke_coords) { - alignStrokeCoords(subpath, j, &x, &y); - } else { - x = subpath->getX(j); - y = subpath->getY(j); - } - cairo_line_to (c, x, y); - ++j; - } - } - if (subpath->isClosed()) { - LOG (printf ("close\n")); - cairo_close_path (c); - } - } - } -} - -void CairoOutputDev::stroke(GfxState *state) { - if (inType3Char) { - GfxGray gray; - state->getFillGray(&gray); - if (colToDbl(gray) > 0.5) - return; - } - - if (adjusted_stroke_width) - align_stroke_coords = true; - doPath (cairo, state, state->getPath()); - align_stroke_coords = false; - cairo_set_source (cairo, stroke_pattern); - LOG(printf ("stroke\n")); - if (strokePathClip) { - cairo_push_group (cairo); - cairo_stroke (cairo); - cairo_pop_group_to_source (cairo); - fillToStrokePathClip (state); - } else { - cairo_stroke (cairo); - } - if (cairo_shape) { - doPath (cairo_shape, state, state->getPath()); - cairo_stroke (cairo_shape); - } -} - -void CairoOutputDev::fill(GfxState *state) { - if (inType3Char) { - GfxGray gray; - state->getFillGray(&gray); - if (colToDbl(gray) > 0.5) - return; - } - - doPath (cairo, state, state->getPath()); - cairo_set_fill_rule (cairo, CAIRO_FILL_RULE_WINDING); - cairo_set_source (cairo, fill_pattern); - LOG(printf ("fill\n")); - //XXX: how do we get the path - if (mask) { - cairo_save (cairo); - cairo_clip (cairo); - if (strokePathClip) { - cairo_push_group (cairo); - fillToStrokePathClip (state); - cairo_pop_group_to_source (cairo); - } - cairo_set_matrix (cairo, &mask_matrix); - cairo_mask (cairo, mask); - cairo_restore (cairo); - } else if (strokePathClip) { - fillToStrokePathClip(state); - } else { - cairo_fill (cairo); - } - if (cairo_shape) { - cairo_set_fill_rule (cairo_shape, CAIRO_FILL_RULE_WINDING); - doPath (cairo_shape, state, state->getPath()); - cairo_fill (cairo_shape); - } -} - -void CairoOutputDev::eoFill(GfxState *state) { - doPath (cairo, state, state->getPath()); - cairo_set_fill_rule (cairo, CAIRO_FILL_RULE_EVEN_ODD); - cairo_set_source (cairo, fill_pattern); - LOG(printf ("fill-eo\n")); - - if (mask) { - cairo_save (cairo); - cairo_clip (cairo); - cairo_set_matrix (cairo, &mask_matrix); - cairo_mask (cairo, mask); - cairo_restore (cairo); - } else { - cairo_fill (cairo); - } - if (cairo_shape) { - cairo_set_fill_rule (cairo_shape, CAIRO_FILL_RULE_EVEN_ODD); - doPath (cairo_shape, state, state->getPath()); - cairo_fill (cairo_shape); - } - -} - -bool CairoOutputDev::tilingPatternFill(GfxState *state, Gfx *gfxA, Catalog *cat, Object *str, - const double *pmat, int paintType, int /*tilingType*/, Dict *resDict, - const double *mat, const double *bbox, - int x0, int y0, int x1, int y1, - double xStep, double yStep) -{ - PDFRectangle box; - Gfx *gfx; - cairo_pattern_t *pattern; - cairo_surface_t *surface; - cairo_matrix_t matrix; - cairo_matrix_t pattern_matrix; - cairo_t *old_cairo; - double xMin, yMin, xMax, yMax; - double width, height; - double scaleX, scaleY; - int surface_width, surface_height; - StrokePathClip *strokePathTmp; - bool adjusted_stroke_width_tmp; - cairo_pattern_t *maskTmp; - - width = bbox[2] - bbox[0]; - height = bbox[3] - bbox[1]; - - if (xStep != width || yStep != height) - return false; - /* TODO: implement the other cases here too */ - - // Find the width and height of the transformed pattern - cairo_get_matrix (cairo, &matrix); - cairo_matrix_init (&pattern_matrix, mat[0], mat[1], mat[2], mat[3], mat[4], mat[5]); - cairo_matrix_multiply (&matrix, &matrix, &pattern_matrix); - - double widthX = width, widthY = 0; - cairo_matrix_transform_distance (&matrix, &widthX, &widthY); - surface_width = ceil (sqrt (widthX * widthX + widthY * widthY)); - - double heightX = 0, heightY = height; - cairo_matrix_transform_distance (&matrix, &heightX, &heightY); - surface_height = ceil (sqrt (heightX * heightX + heightY * heightY)); - scaleX = surface_width / width; - scaleY = surface_height / height; - - surface = cairo_surface_create_similar (cairo_get_target (cairo), - CAIRO_CONTENT_COLOR_ALPHA, - surface_width, surface_height); - if (cairo_surface_status (surface)) - return false; - - old_cairo = cairo; - cairo = cairo_create (surface); - cairo_surface_destroy (surface); - setContextAntialias(cairo, antialias); - - box.x1 = bbox[0]; box.y1 = bbox[1]; - box.x2 = bbox[2]; box.y2 = bbox[3]; - cairo_scale (cairo, scaleX, scaleY); - cairo_translate (cairo, -box.x1, -box.y1); - - strokePathTmp = strokePathClip; - strokePathClip = nullptr; - adjusted_stroke_width_tmp = adjusted_stroke_width; - maskTmp = mask; - mask = nullptr; - gfx = new Gfx(doc, this, resDict, &box, nullptr, nullptr, nullptr, gfxA); - if (paintType == 2) - inUncoloredPattern = true; - gfx->display(str); - if (paintType == 2) - inUncoloredPattern = false; - delete gfx; - strokePathClip = strokePathTmp; - adjusted_stroke_width = adjusted_stroke_width_tmp; - mask = maskTmp; - - pattern = cairo_pattern_create_for_surface (cairo_get_target (cairo)); - cairo_destroy (cairo); - cairo = old_cairo; - if (cairo_pattern_status (pattern)) - return false; - - state->getUserClipBBox(&xMin, &yMin, &xMax, &yMax); - cairo_rectangle (cairo, xMin, yMin, xMax - xMin, yMax - yMin); - - cairo_matrix_init_scale (&matrix, scaleX, scaleY); - cairo_matrix_translate (&matrix, -box.x1, -box.y1); - cairo_pattern_set_matrix (pattern, &matrix); - - cairo_transform (cairo, &pattern_matrix); - cairo_set_source (cairo, pattern); - cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT); - if (strokePathClip) { - fillToStrokePathClip(state); - } else { - cairo_fill (cairo); - } - - cairo_pattern_destroy (pattern); - - return true; -} - -#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 12, 0) -bool CairoOutputDev::functionShadedFill(GfxState *state, GfxFunctionShading *shading) -{ - // Function shaded fills are subdivided to rectangles that are the - // following size in device space. Note when printing this size is - // in points. - const int subdivide_pixels = 10; - - double x_begin, x_end, x1, x2; - double y_begin, y_end, y1, y2; - double x_step; - double y_step; - GfxColor color; - GfxRGB rgb; - cairo_matrix_t mat; - - const double *matrix = shading->getMatrix(); - mat.xx = matrix[0]; - mat.yx = matrix[1]; - mat.xy = matrix[2]; - mat.yy = matrix[3]; - mat.x0 = matrix[4]; - mat.y0 = matrix[5]; - if (cairo_matrix_invert(&mat)) { - error(errSyntaxWarning, -1, "matrix not invertible\n"); - return false; - } - - // get cell size in pattern space - x_step = y_step = subdivide_pixels; - cairo_matrix_transform_distance (&mat, &x_step, &y_step); - - cairo_pattern_destroy(fill_pattern); - fill_pattern = cairo_pattern_create_mesh (); - cairo_pattern_set_matrix(fill_pattern, &mat); - shading->getDomain(&x_begin, &y_begin, &x_end, &y_end); - - for (x1 = x_begin; x1 < x_end; x1 += x_step) { - x2 = x1 + x_step; - if (x2 > x_end) - x2 = x_end; - - for (y1 = y_begin; y1 < y_end; y1 += y_step) { - y2 = y1 + y_step; - if (y2 > y_end) - y2 = y_end; - - cairo_mesh_pattern_begin_patch (fill_pattern); - cairo_mesh_pattern_move_to (fill_pattern, x1, y1); - cairo_mesh_pattern_line_to (fill_pattern, x2, y1); - cairo_mesh_pattern_line_to (fill_pattern, x2, y2); - cairo_mesh_pattern_line_to (fill_pattern, x1, y2); - - shading->getColor(x1, y1, &color); - shading->getColorSpace()->getRGB(&color, &rgb); - cairo_mesh_pattern_set_corner_color_rgb (fill_pattern, 0, - colToDbl(rgb.r), - colToDbl(rgb.g), - colToDbl(rgb.b)); - - shading->getColor(x2, y1, &color); - shading->getColorSpace()->getRGB(&color, &rgb); - cairo_mesh_pattern_set_corner_color_rgb (fill_pattern, 1, - colToDbl(rgb.r), - colToDbl(rgb.g), - colToDbl(rgb.b)); - - shading->getColor(x2, y2, &color); - shading->getColorSpace()->getRGB(&color, &rgb); - cairo_mesh_pattern_set_corner_color_rgb (fill_pattern, 2, - colToDbl(rgb.r), - colToDbl(rgb.g), - colToDbl(rgb.b)); - - shading->getColor(x1, y2, &color); - shading->getColorSpace()->getRGB(&color, &rgb); - cairo_mesh_pattern_set_corner_color_rgb (fill_pattern, 3, - colToDbl(rgb.r), - colToDbl(rgb.g), - colToDbl(rgb.b)); - - cairo_mesh_pattern_end_patch (fill_pattern); - } - } - - double xMin, yMin, xMax, yMax; - // get the clip region bbox - state->getUserClipBBox(&xMin, &yMin, &xMax, &yMax); - state->moveTo(xMin, yMin); - state->lineTo(xMin, yMax); - state->lineTo(xMax, yMax); - state->lineTo(xMax, yMin); - state->closePath(); - fill(state); - state->clearPath(); - - return true; -} -#endif /* CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 12, 0) */ - -bool CairoOutputDev::axialShadedFill(GfxState *state, GfxAxialShading *shading, double tMin, double tMax) { - double x0, y0, x1, y1; - double dx, dy; - - shading->getCoords(&x0, &y0, &x1, &y1); - dx = x1 - x0; - dy = y1 - y0; - - cairo_pattern_destroy(fill_pattern); - fill_pattern = cairo_pattern_create_linear (x0 + tMin * dx, y0 + tMin * dy, - x0 + tMax * dx, y0 + tMax * dy); - if (!shading->getExtend0() && !shading->getExtend1()) - cairo_pattern_set_extend (fill_pattern, CAIRO_EXTEND_NONE); - else - cairo_pattern_set_extend (fill_pattern, CAIRO_EXTEND_PAD); - - LOG (printf ("axial-sh\n")); - - // TODO: use the actual stops in the shading in the case - // of linear interpolation (Type 2 Exponential functions with N=1) - return false; -} - -bool CairoOutputDev::axialShadedSupportExtend(GfxState *state, GfxAxialShading *shading) -{ - return (shading->getExtend0() == shading->getExtend1()); -} - -bool CairoOutputDev::radialShadedFill(GfxState *state, GfxRadialShading *shading, double sMin, double sMax) { - double x0, y0, r0, x1, y1, r1; - double dx, dy, dr; - cairo_matrix_t matrix; - double scale; - - shading->getCoords(&x0, &y0, &r0, &x1, &y1, &r1); - dx = x1 - x0; - dy = y1 - y0; - dr = r1 - r0; - - // Cairo/pixman do not work well with a very large or small scaled - // matrix. See cairo bug #81657. - // - // As a workaround, scale the pattern by the average of the vertical - // and horizontal scaling of the current transformation matrix. - cairo_get_matrix(cairo, &matrix); - scale = (sqrt(matrix.xx * matrix.xx + matrix.yx * matrix.yx) - + sqrt(matrix.xy * matrix.xy + matrix.yy * matrix.yy)) / 2; - cairo_matrix_init_scale(&matrix, scale, scale); - - cairo_pattern_destroy(fill_pattern); - fill_pattern = cairo_pattern_create_radial ((x0 + sMin * dx) * scale, - (y0 + sMin * dy) * scale, - (r0 + sMin * dr) * scale, - (x0 + sMax * dx) * scale, - (y0 + sMax * dy) * scale, - (r0 + sMax * dr) * scale); - cairo_pattern_set_matrix(fill_pattern, &matrix); - if (shading->getExtend0() && shading->getExtend1()) - cairo_pattern_set_extend (fill_pattern, CAIRO_EXTEND_PAD); - else - cairo_pattern_set_extend (fill_pattern, CAIRO_EXTEND_NONE); - - LOG (printf ("radial-sh\n")); - - return false; -} - -bool CairoOutputDev::radialShadedSupportExtend(GfxState *state, GfxRadialShading *shading) -{ - return (shading->getExtend0() == shading->getExtend1()); -} - -#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 12, 0) -bool CairoOutputDev::gouraudTriangleShadedFill(GfxState *state, GfxGouraudTriangleShading *shading) -{ - double x0, y0, x1, y1, x2, y2; - GfxColor color[3]; - int i, j; - GfxRGB rgb; - - cairo_pattern_destroy(fill_pattern); - fill_pattern = cairo_pattern_create_mesh (); - - for (i = 0; i < shading->getNTriangles(); i++) { - if (shading->isParameterized()) { - double color0, color1, color2; - shading->getTriangle(i, &x0, &y0, &color0, - &x1, &y1, &color1, - &x2, &y2, &color2); - shading->getParameterizedColor(color0, &color[0]); - shading->getParameterizedColor(color1, &color[1]); - shading->getParameterizedColor(color2, &color[2]); - } else { - shading->getTriangle(i, - &x0, &y0, &color[0], - &x1, &y1, &color[1], - &x2, &y2, &color[2]); - - } - - cairo_mesh_pattern_begin_patch (fill_pattern); - - cairo_mesh_pattern_move_to (fill_pattern, x0, y0); - cairo_mesh_pattern_line_to (fill_pattern, x1, y1); - cairo_mesh_pattern_line_to (fill_pattern, x2, y2); - - for (j = 0; j < 3; j++) { - shading->getColorSpace()->getRGB(&color[j], &rgb); - cairo_mesh_pattern_set_corner_color_rgb (fill_pattern, j, - colToDbl(rgb.r), - colToDbl(rgb.g), - colToDbl(rgb.b)); - } - - cairo_mesh_pattern_end_patch (fill_pattern); - } - - double xMin, yMin, xMax, yMax; - // get the clip region bbox - state->getUserClipBBox(&xMin, &yMin, &xMax, &yMax); - state->moveTo(xMin, yMin); - state->lineTo(xMin, yMax); - state->lineTo(xMax, yMax); - state->lineTo(xMax, yMin); - state->closePath(); - fill(state); - state->clearPath(); - - return true; -} - -bool CairoOutputDev::patchMeshShadedFill(GfxState *state, GfxPatchMeshShading *shading) -{ - int i, j, k; - - cairo_pattern_destroy(fill_pattern); - fill_pattern = cairo_pattern_create_mesh (); - - for (i = 0; i < shading->getNPatches(); i++) { - const GfxPatch *patch = shading->getPatch(i); - GfxColor color; - GfxRGB rgb; - - cairo_mesh_pattern_begin_patch (fill_pattern); - - cairo_mesh_pattern_move_to (fill_pattern, patch->x[0][0], patch->y[0][0]); - cairo_mesh_pattern_curve_to (fill_pattern, - patch->x[0][1], patch->y[0][1], - patch->x[0][2], patch->y[0][2], - patch->x[0][3], patch->y[0][3]); - - cairo_mesh_pattern_curve_to (fill_pattern, - patch->x[1][3], patch->y[1][3], - patch->x[2][3], patch->y[2][3], - patch->x[3][3], patch->y[3][3]); - - cairo_mesh_pattern_curve_to (fill_pattern, - patch->x[3][2], patch->y[3][2], - patch->x[3][1], patch->y[3][1], - patch->x[3][0], patch->y[3][0]); - - cairo_mesh_pattern_curve_to (fill_pattern, - patch->x[2][0], patch->y[2][0], - patch->x[1][0], patch->y[1][0], - patch->x[0][0], patch->y[0][0]); - - cairo_mesh_pattern_set_control_point (fill_pattern, 0, patch->x[1][1], patch->y[1][1]); - cairo_mesh_pattern_set_control_point (fill_pattern, 1, patch->x[1][2], patch->y[1][2]); - cairo_mesh_pattern_set_control_point (fill_pattern, 2, patch->x[2][2], patch->y[2][2]); - cairo_mesh_pattern_set_control_point (fill_pattern, 3, patch->x[2][1], patch->y[2][1]); - - for (j = 0; j < 4; j++) { - int u, v; - - switch (j) { - case 0: - u = 0; v = 0; - break; - case 1: - u = 0; v = 1; - break; - case 2: - u = 1; v = 1; - break; - case 3: - u = 1; v = 0; - break; - } - - if (shading->isParameterized()) { - shading->getParameterizedColor (patch->color[u][v].c[0], &color); - } else { - for (k = 0; k < shading->getColorSpace()->getNComps(); k++) { - // simply cast to the desired type; that's all what is needed. - color.c[k] = GfxColorComp (patch->color[u][v].c[k]); - } - } - - shading->getColorSpace()->getRGB(&color, &rgb); - cairo_mesh_pattern_set_corner_color_rgb (fill_pattern, j, - colToDbl(rgb.r), - colToDbl(rgb.g), - colToDbl(rgb.b)); - } - cairo_mesh_pattern_end_patch (fill_pattern); - } - - double xMin, yMin, xMax, yMax; - // get the clip region bbox - state->getUserClipBBox(&xMin, &yMin, &xMax, &yMax); - state->moveTo(xMin, yMin); - state->lineTo(xMin, yMax); - state->lineTo(xMax, yMax); - state->lineTo(xMax, yMin); - state->closePath(); - fill(state); - state->clearPath(); - - return true; -} -#endif /* CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 12, 0) */ - -void CairoOutputDev::clip(GfxState *state) { - doPath (cairo, state, state->getPath()); - cairo_set_fill_rule (cairo, CAIRO_FILL_RULE_WINDING); - cairo_clip (cairo); - LOG (printf ("clip\n")); - if (cairo_shape) { - doPath (cairo_shape, state, state->getPath()); - cairo_set_fill_rule (cairo_shape, CAIRO_FILL_RULE_WINDING); - cairo_clip (cairo_shape); - } -} - -void CairoOutputDev::eoClip(GfxState *state) { - doPath (cairo, state, state->getPath()); - cairo_set_fill_rule (cairo, CAIRO_FILL_RULE_EVEN_ODD); - cairo_clip (cairo); - LOG (printf ("clip-eo\n")); - if (cairo_shape) { - doPath (cairo_shape, state, state->getPath()); - cairo_set_fill_rule (cairo_shape, CAIRO_FILL_RULE_EVEN_ODD); - cairo_clip (cairo_shape); - } - -} - -void CairoOutputDev::clipToStrokePath(GfxState *state) { - LOG(printf("clip-to-stroke-path\n")); - strokePathClip = (StrokePathClip*)gmalloc (sizeof(*strokePathClip)); - strokePathClip->path = state->getPath()->copy(); - cairo_get_matrix (cairo, &strokePathClip->ctm); - strokePathClip->line_width = cairo_get_line_width (cairo); - strokePathClip->dash_count = cairo_get_dash_count (cairo); - if (strokePathClip->dash_count) { - strokePathClip->dashes = (double*) gmallocn (sizeof(double), strokePathClip->dash_count); - cairo_get_dash (cairo, strokePathClip->dashes, &strokePathClip->dash_offset); - } else { - strokePathClip->dashes = nullptr; - } - strokePathClip->cap = cairo_get_line_cap (cairo); - strokePathClip->join = cairo_get_line_join (cairo); - strokePathClip->miter = cairo_get_miter_limit (cairo); - strokePathClip->ref_count = 1; -} - -void CairoOutputDev::fillToStrokePathClip(GfxState *state) { - cairo_save (cairo); - - cairo_set_matrix (cairo, &strokePathClip->ctm); - cairo_set_line_width (cairo, strokePathClip->line_width); - cairo_set_dash (cairo, strokePathClip->dashes, strokePathClip->dash_count, strokePathClip->dash_offset); - cairo_set_line_cap (cairo, strokePathClip->cap); - cairo_set_line_join (cairo, strokePathClip->join); - cairo_set_miter_limit (cairo, strokePathClip->miter); - doPath (cairo, state, strokePathClip->path); - cairo_stroke (cairo); - - cairo_restore (cairo); -} - -void CairoOutputDev::beginString(GfxState *state, const GooString *s) -{ - int len = s->getLength(); - - if (needFontUpdate) - updateFont(state); - - if (!currentFont) - return; - - glyphs = (cairo_glyph_t *) gmallocn (len, sizeof (cairo_glyph_t)); - glyphCount = 0; - if (use_show_text_glyphs) { - clusters = (cairo_text_cluster_t *) gmallocn (len, sizeof (cairo_text_cluster_t)); - clusterCount = 0; - utf8Max = len*2; // start with twice the number of glyphs. we will realloc if we need more. - utf8 = (char *) gmalloc (utf8Max); - utf8Count = 0; - } -} - -void CairoOutputDev::drawChar(GfxState *state, double x, double y, - double dx, double dy, - double originX, double originY, - CharCode code, int nBytes, const Unicode *u, int uLen) -{ - if (currentFont) { - glyphs[glyphCount].index = currentFont->getGlyph (code, u, uLen); - glyphs[glyphCount].x = x - originX; - glyphs[glyphCount].y = y - originY; - glyphCount++; - if (use_show_text_glyphs) { - GooString enc("UTF-8"); - UnicodeMap *utf8Map = globalParams->getUnicodeMap(&enc); - if (utf8Max - utf8Count < uLen*6) { - // utf8 encoded characters can be up to 6 bytes - if (utf8Max > uLen*6) - utf8Max *= 2; - else - utf8Max += 2*uLen*6; - utf8 = (char *) grealloc (utf8, utf8Max); - } - clusters[clusterCount].num_bytes = 0; - for (int i = 0; i < uLen; i++) { - int size = utf8Map->mapUnicode(u[i], utf8 + utf8Count, utf8Max - utf8Count); - utf8Count += size; - clusters[clusterCount].num_bytes += size; - } - clusters[clusterCount].num_glyphs = 1; - clusterCount++; - } - } - - if (!textPage) - return; - actualText->addChar (state, x, y, dx, dy, code, nBytes, u, uLen); -} - -void CairoOutputDev::endString(GfxState *state) -{ - int render; - - if (!currentFont) - return; - - // endString can be called without a corresponding beginString. If this - // happens glyphs will be null so don't draw anything, just return. - // XXX: OutputDevs should probably not have to deal with this... - if (!glyphs) - return; - - // ignore empty strings and invisible text -- this is used by - // Acrobat Capture - render = state->getRender(); - if (render == 3 || glyphCount == 0 || !text_matrix_valid) { - goto finish; - } - - if (!(render & 1)) { - LOG (printf ("fill string\n")); - cairo_set_source (cairo, fill_pattern); - if (use_show_text_glyphs) - cairo_show_text_glyphs (cairo, utf8, utf8Count, glyphs, glyphCount, clusters, clusterCount, (cairo_text_cluster_flags_t)0); - else - cairo_show_glyphs (cairo, glyphs, glyphCount); - if (cairo_shape) - cairo_show_glyphs (cairo_shape, glyphs, glyphCount); - } - - // stroke - if ((render & 3) == 1 || (render & 3) == 2) { - LOG (printf ("stroke string\n")); - cairo_set_source (cairo, stroke_pattern); - cairo_glyph_path (cairo, glyphs, glyphCount); - cairo_stroke (cairo); - if (cairo_shape) { - cairo_glyph_path (cairo_shape, glyphs, glyphCount); - cairo_stroke (cairo_shape); - } - } - - // clip - if ((render & 4)) { - LOG (printf ("clip string\n")); - // append the glyph path to textClipPath. - - // set textClipPath as the currentPath - if (textClipPath) { - cairo_append_path (cairo, textClipPath); - if (cairo_shape) { - cairo_append_path (cairo_shape, textClipPath); - } - cairo_path_destroy (textClipPath); - } - - // append the glyph path - cairo_glyph_path (cairo, glyphs, glyphCount); - - // move the path back into textClipPath - // and clear the current path - textClipPath = cairo_copy_path (cairo); - cairo_new_path (cairo); - if (cairo_shape) { - cairo_new_path (cairo_shape); - } - } - -finish: - gfree (glyphs); - glyphs = nullptr; - if (use_show_text_glyphs) { - gfree (clusters); - clusters = nullptr; - gfree (utf8); - utf8 = nullptr; - } -} - - -bool CairoOutputDev::beginType3Char(GfxState *state, double x, double y, - double dx, double dy, - CharCode code, const Unicode *u, int uLen) { - - cairo_save (cairo); - cairo_matrix_t matrix; - - const double *ctm = state->getCTM(); - matrix.xx = ctm[0]; - matrix.yx = ctm[1]; - matrix.xy = ctm[2]; - matrix.yy = ctm[3]; - matrix.x0 = ctm[4]; - matrix.y0 = ctm[5]; - /* Restore the original matrix and then transform to matrix needed for the - * type3 font. This is ugly but seems to work. Perhaps there is a better way to do it?*/ - cairo_set_matrix(cairo, &orig_matrix); - cairo_transform(cairo, &matrix); - if (cairo_shape) { - cairo_save (cairo_shape); - cairo_set_matrix(cairo_shape, &orig_matrix); - cairo_transform(cairo_shape, &matrix); - } - cairo_pattern_destroy(stroke_pattern); - cairo_pattern_reference(fill_pattern); - stroke_pattern = fill_pattern; - return false; -} - -void CairoOutputDev::endType3Char(GfxState *state) { - cairo_restore (cairo); - if (cairo_shape) { - cairo_restore (cairo_shape); - } -} - -void CairoOutputDev::type3D0(GfxState *state, double wx, double wy) { - t3_glyph_wx = wx; - t3_glyph_wy = wy; -} - -void CairoOutputDev::type3D1(GfxState *state, double wx, double wy, - double llx, double lly, double urx, double ury) { - t3_glyph_wx = wx; - t3_glyph_wy = wy; - t3_glyph_bbox[0] = llx; - t3_glyph_bbox[1] = lly; - t3_glyph_bbox[2] = urx; - t3_glyph_bbox[3] = ury; - t3_glyph_has_bbox = true; -} - -void CairoOutputDev::beginTextObject(GfxState *state) { -} - -void CairoOutputDev::endTextObject(GfxState *state) { - if (textClipPath) { - // clip the accumulated text path - cairo_append_path (cairo, textClipPath); - cairo_clip (cairo); - if (cairo_shape) { - cairo_append_path (cairo_shape, textClipPath); - cairo_clip (cairo_shape); - } - cairo_path_destroy (textClipPath); - textClipPath = nullptr; - } -} - -void CairoOutputDev::beginActualText(GfxState *state, const GooString *text) -{ - if (textPage) - actualText->begin(state, text); -} - -void CairoOutputDev::endActualText(GfxState *state) -{ - if (textPage) - actualText->end(state); -} - -static inline int splashRound(SplashCoord x) { - return (int)floor(x + 0.5); -} - -static inline int splashCeil(SplashCoord x) { - return (int)ceil(x); -} - -static inline int splashFloor(SplashCoord x) { - return (int)floor(x); -} - -static -cairo_surface_t *cairo_surface_create_similar_clip (cairo_t *cairo, cairo_content_t content) -{ - cairo_pattern_t *pattern; - cairo_surface_t *surface = nullptr; - - cairo_push_group_with_content (cairo, content); - pattern = cairo_pop_group (cairo); - cairo_pattern_get_surface (pattern, &surface); - cairo_surface_reference (surface); - cairo_pattern_destroy (pattern); - return surface; -} - - - -void CairoOutputDev::beginTransparencyGroup(GfxState * /*state*/, const double * /*bbox*/, - GfxColorSpace * blendingColorSpace, - bool /*isolated*/, bool knockout, - bool forSoftMask) { - /* push color space */ - ColorSpaceStack* css = new ColorSpaceStack; - css->cs = blendingColorSpace; - css->knockout = knockout; - cairo_get_matrix(cairo, &css->group_matrix); - css->next = groupColorSpaceStack; - groupColorSpaceStack = css; - - LOG(printf ("begin transparency group. knockout: %s\n", knockout ? "yes":"no")); - - if (knockout) { - knockoutCount++; - if (!cairo_shape) { - /* create a surface for tracking the shape */ - cairo_surface_t *cairo_shape_surface = cairo_surface_create_similar_clip (cairo, CAIRO_CONTENT_ALPHA); - cairo_shape = cairo_create (cairo_shape_surface); - cairo_surface_destroy (cairo_shape_surface); - setContextAntialias(cairo_shape, antialias); - - /* the color doesn't matter as long as it is opaque */ - cairo_set_source_rgb (cairo_shape, 0, 0, 0); - cairo_matrix_t matrix; - cairo_get_matrix (cairo, &matrix); - cairo_set_matrix (cairo_shape, &matrix); - } - } - if (groupColorSpaceStack->next && groupColorSpaceStack->next->knockout) { - /* we need to track the shape */ - cairo_push_group (cairo_shape); - } - if (0 && forSoftMask) - cairo_push_group_with_content (cairo, CAIRO_CONTENT_ALPHA); - else - cairo_push_group (cairo); - - /* push_group has an implicit cairo_save() */ - if (knockout) { - /*XXX: let's hope this matches the semantics needed */ - cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); - } else { - cairo_set_operator(cairo, CAIRO_OPERATOR_OVER); - } -} - -void CairoOutputDev::endTransparencyGroup(GfxState * /*state*/) { - if (group) - cairo_pattern_destroy(group); - group = cairo_pop_group (cairo); - - LOG(printf ("end transparency group\n")); - - if (groupColorSpaceStack->next && groupColorSpaceStack->next->knockout) { - if (shape) - cairo_pattern_destroy(shape); - shape = cairo_pop_group (cairo_shape); - } -} - -void CairoOutputDev::paintTransparencyGroup(GfxState * /*state*/, const double * /*bbox*/) { - LOG(printf ("paint transparency group\n")); - - cairo_save (cairo); - cairo_set_matrix (cairo, &groupColorSpaceStack->group_matrix); - - if (shape) { - /* OPERATOR_SOURCE w/ a mask is defined as (src IN mask) ADD (dest OUT mask) - * however our source has already been clipped to mask so we only need to - * do ADD and OUT */ - - /* clear the shape mask */ - cairo_set_source (cairo, shape); - cairo_set_operator (cairo, CAIRO_OPERATOR_DEST_OUT); - cairo_paint (cairo); - cairo_set_operator (cairo, CAIRO_OPERATOR_ADD); - } - cairo_set_source (cairo, group); - - if (!mask) { - cairo_paint_with_alpha (cairo, fill_opacity); - cairo_status_t status = cairo_status(cairo); - if (status) - printf("BAD status: %s\n", cairo_status_to_string(status)); - } else { - if (fill_opacity < 1.0) { - cairo_push_group(cairo); - } - cairo_save(cairo); - cairo_set_matrix(cairo, &mask_matrix); - cairo_mask(cairo, mask); - cairo_restore(cairo); - if (fill_opacity < 1.0) { - cairo_pop_group_to_source(cairo); - cairo_paint_with_alpha (cairo, fill_opacity); - } - cairo_pattern_destroy(mask); - mask = nullptr; - } - - if (shape) { - if (cairo_shape) { - cairo_set_source (cairo_shape, shape); - cairo_paint (cairo_shape); - cairo_set_source_rgb (cairo_shape, 0, 0, 0); - } - cairo_pattern_destroy (shape); - shape = nullptr; - } - - popTransparencyGroup(); - cairo_restore(cairo); -} - -static int luminocity(uint32_t x) -{ - int r = (x >> 16) & 0xff; - int g = (x >> 8) & 0xff; - int b = (x >> 0) & 0xff; - // an arbitrary integer approximation of .3*r + .59*g + .11*b - int y = (r*19661+g*38666+b*7209 + 32829)>>16; - return y; -} - - -/* XXX: do we need to deal with shape here? */ -void CairoOutputDev::setSoftMask(GfxState * state, const double * bbox, bool alpha, - Function * transferFunc, GfxColor * backdropColor) { - cairo_pattern_destroy(mask); - - LOG(printf ("set softMask\n")); - - if (!alpha || transferFunc) { - /* We need to mask according to the luminocity of the group. - * So we paint the group to an image surface convert it to a luminocity map - * and then use that as the mask. */ - - /* Get clip extents in device space */ - double x1, y1, x2, y2, x_min, y_min, x_max, y_max; - cairo_clip_extents(cairo, &x1, &y1, &x2, &y2); - cairo_user_to_device(cairo, &x1, &y1); - cairo_user_to_device(cairo, &x2, &y2); - x_min = MIN(x1, x2); - y_min = MIN(y1, y2); - x_max = MAX(x1, x2); - y_max = MAX(y1, y2); - cairo_clip_extents(cairo, &x1, &y1, &x2, &y2); - cairo_user_to_device(cairo, &x1, &y2); - cairo_user_to_device(cairo, &x2, &y1); - x_min = MIN(x_min,MIN(x1, x2)); - y_min = MIN(y_min,MIN(y1, y2)); - x_max = MAX(x_max,MAX(x1, x2)); - y_max = MAX(y_max,MAX(y1, y2)); - - int width = (int)(ceil(x_max) - floor(x_min)); - int height = (int)(ceil(y_max) - floor(y_min)); - - /* Get group device offset */ - double x_offset, y_offset; - if (cairo_get_group_target(cairo) == cairo_get_target(cairo)) { - cairo_surface_get_device_offset(cairo_get_group_target(cairo), &x_offset, &y_offset); - } else { - cairo_surface_t *pats; - cairo_pattern_get_surface(group, &pats); - cairo_surface_get_device_offset(pats, &x_offset, &y_offset); - } - - /* Adjust extents by group offset */ - x_min += x_offset; - y_min += y_offset; - - cairo_surface_t *source = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); - cairo_t *maskCtx = cairo_create(source); - setContextAntialias(maskCtx, antialias); - - //XXX: hopefully this uses the correct color space */ - if (!alpha && groupColorSpaceStack->cs) { - GfxRGB backdropColorRGB; - groupColorSpaceStack->cs->getRGB(backdropColor, &backdropColorRGB); - /* paint the backdrop */ - cairo_set_source_rgb(maskCtx, - colToDbl(backdropColorRGB.r), - colToDbl(backdropColorRGB.g), - colToDbl(backdropColorRGB.b)); - } - cairo_paint(maskCtx); - - /* Copy source ctm to mask ctm and translate origin so that the - * mask appears it the same location on the source surface. */ - cairo_matrix_t mat, tmat; - cairo_matrix_init_translate(&tmat, -x_min, -y_min); - cairo_get_matrix(cairo, &mat); - cairo_matrix_multiply(&mat, &mat, &tmat); - cairo_set_matrix(maskCtx, &mat); - - /* make the device offset of the new mask match that of the group */ - cairo_surface_set_device_offset(source, x_offset, y_offset); - - /* paint the group */ - cairo_set_source(maskCtx, group); - cairo_paint(maskCtx); - - /* XXX status = cairo_status(maskCtx); */ - cairo_destroy(maskCtx); - - /* convert to a luminocity map */ - uint32_t *source_data = reinterpret_cast(cairo_image_surface_get_data(source)); - /* get stride in units of 32 bits */ - ptrdiff_t stride = cairo_image_surface_get_stride(source)/4; - for (int y=0; ytransform(&lum_in, &lum_out); - lum = (int)(lum_out * 255.0 + 0.5); - } - source_data[y*stride + x] = lum << 24; - } - } - cairo_surface_mark_dirty (source); - - /* setup the new mask pattern */ - mask = cairo_pattern_create_for_surface(source); - cairo_get_matrix(cairo, &mask_matrix); - - if (cairo_get_group_target(cairo) == cairo_get_target(cairo)) { - cairo_pattern_set_matrix(mask, &mat); - } else { - cairo_matrix_t patMatrix; - cairo_pattern_get_matrix(group, &patMatrix); - /* Apply x_min, y_min offset to it appears in the same location as source. */ - cairo_matrix_multiply(&patMatrix, &patMatrix, &tmat); - cairo_pattern_set_matrix(mask, &patMatrix); - } - - cairo_surface_destroy(source); - } else if (alpha) { - mask = cairo_pattern_reference(group); - cairo_get_matrix(cairo, &mask_matrix); - } - - popTransparencyGroup(); -} - -void CairoOutputDev::popTransparencyGroup() { - /* pop color space */ - ColorSpaceStack *css = groupColorSpaceStack; - if (css->knockout) { - knockoutCount--; - if (!knockoutCount) { - /* we don't need to track the shape anymore because - * we are not above any knockout groups */ - cairo_destroy(cairo_shape); - cairo_shape = nullptr; - } - } - groupColorSpaceStack = css->next; - delete css; -} - - -void CairoOutputDev::clearSoftMask(GfxState * /*state*/) { - if (mask) - cairo_pattern_destroy(mask); - mask = nullptr; -} - -/* Taken from cairo/doc/tutorial/src/singular.c */ -static void -get_singular_values (const cairo_matrix_t *matrix, - double *major, - double *minor) -{ - double xx = matrix->xx, xy = matrix->xy; - double yx = matrix->yx, yy = matrix->yy; - - double a = xx*xx+yx*yx; - double b = xy*xy+yy*yy; - double k = xx*xy+yx*yy; - - double f = (a+b) * .5; - double g = (a-b) * .5; - double delta = sqrt (g*g + k*k); - - if (major) - *major = sqrt (f + delta); - if (minor) - *minor = sqrt (f - delta); -} - -void CairoOutputDev::getScaledSize(const cairo_matrix_t *matrix, - int orig_width, - int orig_height, - int *scaledWidth, - int *scaledHeight) -{ - double xScale; - double yScale; - if (orig_width > orig_height) - get_singular_values (matrix, &xScale, &yScale); - else - get_singular_values (matrix, &yScale, &xScale); - - int tx, tx2, ty, ty2; /* the integer co-ordinates of the resulting image */ - if (xScale >= 0) { - tx = splashRound(matrix->x0 - 0.01); - tx2 = splashRound(matrix->x0 + xScale + 0.01) - 1; - } else { - tx = splashRound(matrix->x0 + 0.01) - 1; - tx2 = splashRound(matrix->x0 + xScale - 0.01); - } - *scaledWidth = abs(tx2 - tx) + 1; - //scaledWidth = splashRound(fabs(xScale)); - if (*scaledWidth == 0) { - // technically, this should draw nothing, but it generally seems - // better to draw a one-pixel-wide stripe rather than throwing it - // away - *scaledWidth = 1; - } - if (yScale >= 0) { - ty = splashFloor(matrix->y0 + 0.01); - ty2 = splashCeil(matrix->y0 + yScale - 0.01); - } else { - ty = splashCeil(matrix->y0 - 0.01); - ty2 = splashFloor(matrix->y0 + yScale + 0.01); - } - *scaledHeight = abs(ty2 - ty); - if (*scaledHeight == 0) { - *scaledHeight = 1; - } -} - -cairo_filter_t -CairoOutputDev::getFilterForSurface(cairo_surface_t *image, - bool interpolate) -{ - if (interpolate) - return CAIRO_FILTER_GOOD; - - int orig_width = cairo_image_surface_get_width (image); - int orig_height = cairo_image_surface_get_height (image); - if (orig_width == 0 || orig_height == 0) - return CAIRO_FILTER_NEAREST; - - /* When printing, don't change the interpolation. */ - if (printing) - return CAIRO_FILTER_NEAREST; - - cairo_matrix_t matrix; - cairo_get_matrix(cairo, &matrix); - int scaled_width, scaled_height; - getScaledSize (&matrix, orig_width, orig_height, &scaled_width, &scaled_height); - - /* When scale factor is >= 400% we don't interpolate. See bugs #25268, #9860 */ - if (scaled_width / orig_width >= 4 || scaled_height / orig_height >= 4) - return CAIRO_FILTER_NEAREST; - - return CAIRO_FILTER_GOOD; -} - -void CairoOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str, - int width, int height, bool invert, - bool interpolate, bool inlineImg) { - - /* FIXME: Doesn't the image mask support any colorspace? */ - cairo_set_source (cairo, fill_pattern); - - /* work around a cairo bug when scaling 1x1 surfaces */ - if (width == 1 && height == 1) { - ImageStream *imgStr; - unsigned char pix; - int invert_bit; - - imgStr = new ImageStream(str, width, 1, 1); - imgStr->reset(); - imgStr->getPixel(&pix); - imgStr->close(); - delete imgStr; - - invert_bit = invert ? 1 : 0; - if (pix ^ invert_bit) - return; - - cairo_save (cairo); - cairo_rectangle (cairo, 0., 0., width, height); - cairo_fill (cairo); - cairo_restore (cairo); - if (cairo_shape) { - cairo_save (cairo_shape); - cairo_rectangle (cairo_shape, 0., 0., width, height); - cairo_fill (cairo_shape); - cairo_restore (cairo_shape); - } - return; - } - - /* shape is 1.0 for painted areas, 0.0 for unpainted ones */ - - cairo_matrix_t matrix; - cairo_get_matrix (cairo, &matrix); - //XXX: it is possible that we should only do sub pixel positioning if - // we are rendering fonts */ - if (!printing && prescaleImages - /* not rotated */ - && matrix.xy == 0 && matrix.yx == 0 - /* axes not flipped / not 180 deg rotated */ - && matrix.xx > 0 && (upsideDown() ? -1 : 1) * matrix.yy > 0) { - drawImageMaskPrescaled(state, ref, str, width, height, invert, interpolate, inlineImg); - } else { - drawImageMaskRegular(state, ref, str, width, height, invert, interpolate, inlineImg); - } - -} - -void CairoOutputDev::setSoftMaskFromImageMask(GfxState *state, Object *ref, Stream *str, - int width, int height, bool invert, - bool inlineImg, double *baseMatrix) { - - /* FIXME: Doesn't the image mask support any colorspace? */ - cairo_set_source (cairo, fill_pattern); - - /* work around a cairo bug when scaling 1x1 surfaces */ - if (width == 1 && height == 1) { - ImageStream *imgStr; - unsigned char pix; - int invert_bit; - - imgStr = new ImageStream(str, width, 1, 1); - imgStr->reset(); - imgStr->getPixel(&pix); - imgStr->close(); - delete imgStr; - - invert_bit = invert ? 1 : 0; - if (!(pix ^ invert_bit)) { - cairo_save (cairo); - cairo_rectangle (cairo, 0., 0., width, height); - cairo_fill (cairo); - cairo_restore (cairo); - if (cairo_shape) { - cairo_save (cairo_shape); - cairo_rectangle (cairo_shape, 0., 0., width, height); - cairo_fill (cairo_shape); - cairo_restore (cairo_shape); - } - } - } else { - cairo_push_group_with_content (cairo, CAIRO_CONTENT_ALPHA); - - /* shape is 1.0 for painted areas, 0.0 for unpainted ones */ - - cairo_matrix_t matrix; - cairo_get_matrix (cairo, &matrix); - //XXX: it is possible that we should only do sub pixel positioning if - // we are rendering fonts */ - if (!printing && prescaleImages && matrix.xy == 0.0 && matrix.yx == 0.0) { - drawImageMaskPrescaled(state, ref, str, width, height, invert, false, inlineImg); - } else { - drawImageMaskRegular(state, ref, str, width, height, invert, false, inlineImg); - } - - if (state->getFillColorSpace()->getMode() == csPattern) { - cairo_set_source_rgb (cairo, 1, 1, 1); - cairo_set_matrix (cairo, &mask_matrix); - cairo_mask (cairo, mask); - } - - if (mask) - cairo_pattern_destroy (mask); - mask = cairo_pop_group (cairo); - } - - saveState(state); - double bbox[4] = {0,0,1,1}; // dummy - beginTransparencyGroup(state, bbox, state->getFillColorSpace(), - true, false, false); -} - -void CairoOutputDev::unsetSoftMaskFromImageMask(GfxState *state, double *baseMatrix) { - double bbox[4] = {0,0,1,1}; // dummy - - endTransparencyGroup(state); - restoreState(state); - paintTransparencyGroup(state, bbox); - clearSoftMask(state); -} - -void CairoOutputDev::drawImageMaskRegular(GfxState *state, Object *ref, Stream *str, - int width, int height, bool invert, - bool interpolate, bool inlineImg) { - unsigned char *buffer; - unsigned char *dest; - cairo_surface_t *image; - cairo_pattern_t *pattern; - int x, y, i, bit; - ImageStream *imgStr; - unsigned char *pix; - cairo_matrix_t matrix; - int invert_bit; - ptrdiff_t row_stride; - cairo_filter_t filter; - - /* TODO: Do we want to cache these? */ - imgStr = new ImageStream(str, width, 1, 1); - imgStr->reset(); - - image = cairo_image_surface_create (CAIRO_FORMAT_A1, width, height); - if (cairo_surface_status (image)) - goto cleanup; - - buffer = cairo_image_surface_get_data (image); - row_stride = cairo_image_surface_get_stride (image); - - invert_bit = invert ? 1 : 0; - - for (y = 0; y < height; y++) { - pix = imgStr->getLine(); - dest = buffer + y * row_stride; - i = 0; - bit = 0; - for (x = 0; x < width; x++) { - if (bit == 0) - dest[i] = 0; - if (!(pix[x] ^ invert_bit)) { -#ifdef WORDS_BIGENDIAN - dest[i] |= (1 << (7 - bit)); -#else - dest[i] |= (1 << bit); -#endif - } - bit++; - if (bit > 7) { - bit = 0; - i++; - } - } - } - - filter = getFilterForSurface (image, interpolate); - - cairo_surface_mark_dirty (image); - pattern = cairo_pattern_create_for_surface (image); - cairo_surface_destroy (image); - if (cairo_pattern_status (pattern)) - goto cleanup; - - LOG (printf ("drawImageMask %dx%d\n", width, height)); - - cairo_pattern_set_filter (pattern, filter); - - cairo_matrix_init_translate (&matrix, 0, height); - cairo_matrix_scale (&matrix, width, -height); - cairo_pattern_set_matrix (pattern, &matrix); - if (cairo_pattern_status (pattern)) { - cairo_pattern_destroy (pattern); - goto cleanup; - } - - if (state->getFillColorSpace()->getMode() == csPattern) { - mask = cairo_pattern_reference (pattern); - cairo_get_matrix (cairo, &mask_matrix); - } else if (!printing) { - cairo_save (cairo); - cairo_rectangle (cairo, 0., 0., 1., 1.); - cairo_clip (cairo); - if (strokePathClip) { - cairo_push_group (cairo); - fillToStrokePathClip (state); - cairo_pop_group_to_source (cairo); - } - cairo_mask (cairo, pattern); - cairo_restore (cairo); - } else { - cairo_mask (cairo, pattern); - } - - if (cairo_shape) { - cairo_save (cairo_shape); - cairo_set_source (cairo_shape, pattern); - if (!printing) { - cairo_rectangle (cairo_shape, 0., 0., 1., 1.); - cairo_fill (cairo_shape); - } else { - cairo_mask (cairo_shape, pattern); - } - cairo_restore (cairo_shape); - } - - cairo_pattern_destroy (pattern); - -cleanup: - imgStr->close(); - delete imgStr; -} - - -void CairoOutputDev::drawImageMaskPrescaled(GfxState *state, Object *ref, Stream *str, - int width, int height, bool invert, - bool interpolate, bool inlineImg) { - unsigned char *buffer; - cairo_surface_t *image; - cairo_pattern_t *pattern; - ImageStream *imgStr; - unsigned char *pix; - cairo_matrix_t matrix; - int invert_bit; - ptrdiff_t row_stride; - - /* cairo does a very poor job of scaling down images so we scale them ourselves */ - - LOG (printf ("drawImageMaskPrescaled %dx%d\n", width, height)); - - /* this scaling code is adopted from the splash image scaling code */ - cairo_get_matrix(cairo, &matrix); -#if 0 - printf("[%f %f], [%f %f], %f %f\n", matrix.xx, matrix.xy, matrix.yx, matrix.yy, matrix.x0, matrix.y0); -#endif - /* this whole computation should be factored out */ - double xScale = matrix.xx; - double yScale = matrix.yy; - int tx, tx2, ty, ty2; /* the integer co-ordinates of the resulting image */ - int scaledHeight; - int scaledWidth; - if (xScale >= 0) { - tx = splashRound(matrix.x0 - 0.01); - tx2 = splashRound(matrix.x0 + xScale + 0.01) - 1; - } else { - tx = splashRound(matrix.x0 + 0.01) - 1; - tx2 = splashRound(matrix.x0 + xScale - 0.01); - } - scaledWidth = abs(tx2 - tx) + 1; - //scaledWidth = splashRound(fabs(xScale)); - if (scaledWidth == 0) { - // technically, this should draw nothing, but it generally seems - // better to draw a one-pixel-wide stripe rather than throwing it - // away - scaledWidth = 1; - } - if (yScale >= 0) { - ty = splashFloor(matrix.y0 + 0.01); - ty2 = splashCeil(matrix.y0 + yScale - 0.01); - } else { - ty = splashCeil(matrix.y0 - 0.01); - ty2 = splashFloor(matrix.y0 + yScale + 0.01); - } - scaledHeight = abs(ty2 - ty); - if (scaledHeight == 0) { - scaledHeight = 1; - } -#if 0 - printf("xscale: %g, yscale: %g\n", xScale, yScale); - printf("width: %d, height: %d\n", width, height); - printf("scaledWidth: %d, scaledHeight: %d\n", scaledWidth, scaledHeight); -#endif - - /* compute the required padding */ - /* Padding is used to preserve the aspect ratio. - We compute total_pad to make (height+total_pad)/scaledHeight as close to height/yScale as possible */ - int head_pad = 0; - int tail_pad = 0; - int total_pad = splashRound(height*(scaledHeight/fabs(yScale)) - height); - - /* compute the two pieces of padding */ - if (total_pad > 0) { - //XXX: i'm not positive fabs() is correct - float tail_error = fabs(matrix.y0 - ty); - float head_error = fabs(ty2 - (matrix.y0 + yScale)); - float tail_fraction = tail_error/(tail_error + head_error); - tail_pad = splashRound(total_pad*tail_fraction); - head_pad = total_pad - tail_pad; - } else { - tail_pad = 0; - head_pad = 0; - } - int origHeight = height; - height += tail_pad; - height += head_pad; -#if 0 - printf("head_pad: %d tail_pad: %d\n", head_pad, tail_pad); - printf("origHeight: %d height: %d\n", origHeight, height); - printf("ty: %d, ty2: %d\n", ty, ty2); -#endif - - /* TODO: Do we want to cache these? */ - imgStr = new ImageStream(str, width, 1, 1); - imgStr->reset(); - - invert_bit = invert ? 1 : 0; - - image = cairo_image_surface_create (CAIRO_FORMAT_A8, scaledWidth, scaledHeight); - if (cairo_surface_status (image)) { - imgStr->close(); - delete imgStr; - return; - } - - buffer = cairo_image_surface_get_data (image); - row_stride = cairo_image_surface_get_stride (image); - - int yp = height / scaledHeight; - int yq = height % scaledHeight; - int xp = width / scaledWidth; - int xq = width % scaledWidth; - int yt = 0; - int origHeight_c = origHeight; - /* use MIN() because yp might be > origHeight because of padding */ - unsigned char *pixBuf = (unsigned char *)malloc(MIN(yp+1, origHeight)*width); - int lastYStep = 1; - int total = 0; - for (int y = 0; y < scaledHeight; y++) { - // y scale Bresenham - int yStep = yp; - yt += yq; - - if (yt >= scaledHeight) { - yt -= scaledHeight; - ++yStep; - } - - // read row (s) from image ignoring the padding as appropriate - { - int n = (yp > 0) ? yStep : lastYStep; - total += n; - if (n > 0) { - unsigned char *p = pixBuf; - int head_pad_count = head_pad; - int origHeight_count = origHeight; - int tail_pad_count = tail_pad; - for (int i=0; igetLine(); - for (int j=0; j 0 ? yStep : 1; - int origN = n; - - /* compute the size of padding and pixels that will be used for this row */ - int head_pad_size = MIN(n, head_pad); - n -= head_pad_size; - head_pad -= MIN(head_pad_size, yStep); - - int pix_size = MIN(n, origHeight); - n -= pix_size; - origHeight -= MIN(pix_size, yStep); - - int tail_pad_size = MIN(n, tail_pad); - n -= tail_pad_size; - tail_pad -= MIN(tail_pad_size, yStep); - if (n != 0) { - printf("n = %d (%d %d %d)\n", n, head_pad_size, pix_size, tail_pad_size); - assert(n == 0); - } - - for (int x = 0; x < scaledWidth; ++x) { - int xStep = xp; - xt += xq; - if (xt >= scaledWidth) { - xt -= scaledWidth; - ++xStep; - } - int m = xStep > 0 ? xStep : 1; - float pixAcc0 = 0; - /* could m * head_pad_size * tail_pad_size overflow? */ - if (invert_bit) { - pixAcc0 += m * head_pad_size * tail_pad_size * 255; - } else { - pixAcc0 += m * head_pad_size * tail_pad_size * 0; - } - /* Accumulate all of the source pixels for the destination pixel */ - for (int i = 0; i < pix_size; ++i) { - for (int j = 0; j< m; ++j) { - if (xSrc + i*width + j > MIN(yp + 1, origHeight_c)*width) { - printf("%d > %d (%d %d %d %d) (%d %d %d)\n", xSrc + i*width + j, MIN(yp + 1, origHeight_c)*width, xSrc, i , width, j, yp, origHeight_c, width); - printf("%d %d %d\n", head_pad_size, pix_size, tail_pad_size); - assert(0 && "bad access\n"); - } - pixAcc0 += pixBuf[xSrc + i*width + j]; - } - } - buffer[y * row_stride + x] = splashFloor(pixAcc0 / (origN*m)); - xSrc += xStep; - x1 += 1; - } - - } - free(pixBuf); - - cairo_surface_mark_dirty (image); - pattern = cairo_pattern_create_for_surface (image); - cairo_surface_destroy (image); - if (cairo_pattern_status (pattern)) { - imgStr->close(); - delete imgStr; - return; - } - - /* we should actually be using CAIRO_FILTER_NEAREST here. However, - * cairo doesn't yet do minifaction filtering causing scaled down - * images with CAIRO_FILTER_NEAREST to look really bad */ - cairo_pattern_set_filter (pattern, - interpolate ? CAIRO_FILTER_GOOD : CAIRO_FILTER_FAST); - - if (state->getFillColorSpace()->getMode() == csPattern) { - cairo_matrix_init_translate (&matrix, 0, scaledHeight); - cairo_matrix_scale (&matrix, scaledWidth, -scaledHeight); - cairo_pattern_set_matrix (pattern, &matrix); - if (cairo_pattern_status (pattern)) { - cairo_pattern_destroy (pattern); - imgStr->close(); - delete imgStr; - return; - } - - mask = cairo_pattern_reference (pattern); - cairo_get_matrix (cairo, &mask_matrix); - } else { - cairo_save (cairo); - - /* modify our current transformation so that the prescaled image - * goes where it is supposed to */ - cairo_get_matrix(cairo, &matrix); - cairo_scale(cairo, 1.0/matrix.xx, 1.0/matrix.yy); - // get integer co-ords - cairo_translate (cairo, tx - matrix.x0, ty2 - matrix.y0); - if (yScale > 0) - cairo_scale(cairo, 1, -1); - - cairo_rectangle (cairo, 0., 0., scaledWidth, scaledHeight); - cairo_clip (cairo); - if (strokePathClip) { - cairo_push_group (cairo); - fillToStrokePathClip (state); - cairo_pop_group_to_source (cairo); - } - cairo_mask (cairo, pattern); - - //cairo_get_matrix(cairo, &matrix); - //printf("mask at: [%f %f], [%f %f], %f %f\n\n", matrix.xx, matrix.xy, matrix.yx, matrix.yy, matrix.x0, matrix.y0); - cairo_restore(cairo); - } - - if (cairo_shape) { - cairo_save (cairo_shape); - - /* modify our current transformation so that the prescaled image - * goes where it is supposed to */ - cairo_get_matrix(cairo_shape, &matrix); - cairo_scale(cairo_shape, 1.0/matrix.xx, 1.0/matrix.yy); - // get integer co-ords - cairo_translate (cairo_shape, tx - matrix.x0, ty2 - matrix.y0); - if (yScale > 0) - cairo_scale(cairo_shape, 1, -1); - - cairo_rectangle (cairo_shape, 0., 0., scaledWidth, scaledHeight); - cairo_fill (cairo_shape); - - cairo_restore(cairo_shape); - } - - cairo_pattern_destroy (pattern); - - imgStr->close(); - delete imgStr; -} - -void CairoOutputDev::drawMaskedImage(GfxState *state, Object *ref, - Stream *str, int width, int height, - GfxImageColorMap *colorMap, - bool interpolate, - Stream *maskStr, int maskWidth, - int maskHeight, bool maskInvert, - bool maskInterpolate) -{ - ImageStream *maskImgStr, *imgStr; - ptrdiff_t row_stride; - unsigned char *maskBuffer, *buffer; - unsigned char *maskDest; - unsigned int *dest; - cairo_surface_t *maskImage, *image; - cairo_pattern_t *maskPattern, *pattern; - cairo_matrix_t matrix; - cairo_matrix_t maskMatrix; - unsigned char *pix; - int x, y; - int invert_bit; - cairo_filter_t filter; - cairo_filter_t maskFilter; - - maskImgStr = new ImageStream(maskStr, maskWidth, 1, 1); - maskImgStr->reset(); - - maskImage = cairo_image_surface_create (CAIRO_FORMAT_A8, maskWidth, maskHeight); - if (cairo_surface_status (maskImage)) { - maskImgStr->close(); - delete maskImgStr; - return; - } - - maskBuffer = cairo_image_surface_get_data (maskImage); - row_stride = cairo_image_surface_get_stride (maskImage); - - invert_bit = maskInvert ? 1 : 0; - - for (y = 0; y < maskHeight; y++) { - pix = maskImgStr->getLine(); - maskDest = maskBuffer + y * row_stride; - for (x = 0; x < maskWidth; x++) { - if (pix[x] ^ invert_bit) - *maskDest++ = 0; - else - *maskDest++ = 255; - } - } - - maskImgStr->close(); - delete maskImgStr; - - maskFilter = getFilterForSurface (maskImage, maskInterpolate); - - cairo_surface_mark_dirty (maskImage); - maskPattern = cairo_pattern_create_for_surface (maskImage); - cairo_surface_destroy (maskImage); - if (cairo_pattern_status (maskPattern)) - return; - -#if 0 - /* ICCBased color space doesn't do any color correction - * so check its underlying color space as well */ - int is_identity_transform; - is_identity_transform = colorMap->getColorSpace()->getMode() == csDeviceRGB || - (colorMap->getColorSpace()->getMode() == csICCBased && - ((GfxICCBasedColorSpace*)colorMap->getColorSpace())->getAlt()->getMode() == csDeviceRGB); -#endif - - /* TODO: Do we want to cache these? */ - imgStr = new ImageStream(str, width, - colorMap->getNumPixelComps(), - colorMap->getBits()); - imgStr->reset(); - - image = cairo_image_surface_create (CAIRO_FORMAT_RGB24, width, height); - if (cairo_surface_status (image)) - goto cleanup; - - buffer = cairo_image_surface_get_data (image); - row_stride = cairo_image_surface_get_stride (image); - for (y = 0; y < height; y++) { - dest = reinterpret_cast(buffer + y * row_stride); - pix = imgStr->getLine(); - colorMap->getRGBLine (pix, dest, width); - } - - filter = getFilterForSurface (image, interpolate); - - cairo_surface_mark_dirty (image); - pattern = cairo_pattern_create_for_surface (image); - cairo_surface_destroy (image); - if (cairo_pattern_status (pattern)) - goto cleanup; - - LOG (printf ("drawMaskedImage %dx%d\n", width, height)); - - cairo_pattern_set_filter (pattern, filter); - cairo_pattern_set_filter (maskPattern, maskFilter); - - if (!printing) { - cairo_pattern_set_extend (pattern, CAIRO_EXTEND_PAD); - cairo_pattern_set_extend (maskPattern, CAIRO_EXTEND_PAD); - } - - cairo_matrix_init_translate (&matrix, 0, height); - cairo_matrix_scale (&matrix, width, -height); - cairo_pattern_set_matrix (pattern, &matrix); - if (cairo_pattern_status (pattern)) { - cairo_pattern_destroy (pattern); - cairo_pattern_destroy (maskPattern); - goto cleanup; - } - - cairo_matrix_init_translate (&maskMatrix, 0, maskHeight); - cairo_matrix_scale (&maskMatrix, maskWidth, -maskHeight); - cairo_pattern_set_matrix (maskPattern, &maskMatrix); - if (cairo_pattern_status (maskPattern)) { - cairo_pattern_destroy (maskPattern); - cairo_pattern_destroy (pattern); - goto cleanup; - } - - if (!printing) { - cairo_save (cairo); - cairo_set_source (cairo, pattern); - cairo_rectangle (cairo, 0., 0., 1., 1.); - cairo_clip (cairo); - cairo_mask (cairo, maskPattern); - cairo_restore (cairo); - } else { - cairo_set_source (cairo, pattern); - cairo_mask (cairo, maskPattern); - } - - if (cairo_shape) { - cairo_save (cairo_shape); - cairo_set_source (cairo_shape, pattern); - if (!printing) { - cairo_rectangle (cairo_shape, 0., 0., 1., 1.); - cairo_fill (cairo_shape); - } else { - cairo_mask (cairo_shape, pattern); - } - cairo_restore (cairo_shape); - } - - cairo_pattern_destroy (maskPattern); - cairo_pattern_destroy (pattern); - -cleanup: - imgStr->close(); - delete imgStr; -} - - -//XXX: is this affect by AIS(alpha is shape)? -void CairoOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref, Stream *str, - int width, int height, - GfxImageColorMap *colorMap, - bool interpolate, - Stream *maskStr, - int maskWidth, int maskHeight, - GfxImageColorMap *maskColorMap, - bool maskInterpolate) -{ - ImageStream *maskImgStr, *imgStr; - ptrdiff_t row_stride; - unsigned char *maskBuffer, *buffer; - unsigned char *maskDest; - unsigned int *dest; - cairo_surface_t *maskImage, *image; - cairo_pattern_t *maskPattern, *pattern; - cairo_matrix_t maskMatrix, matrix; - unsigned char *pix; - int y; - cairo_filter_t filter; - cairo_filter_t maskFilter; - - maskImgStr = new ImageStream(maskStr, maskWidth, - maskColorMap->getNumPixelComps(), - maskColorMap->getBits()); - maskImgStr->reset(); - - maskImage = cairo_image_surface_create (CAIRO_FORMAT_A8, maskWidth, maskHeight); - if (cairo_surface_status (maskImage)) { - maskImgStr->close(); - delete maskImgStr; - return; - } - - maskBuffer = cairo_image_surface_get_data (maskImage); - row_stride = cairo_image_surface_get_stride (maskImage); - for (y = 0; y < maskHeight; y++) { - maskDest = (unsigned char *) (maskBuffer + y * row_stride); - pix = maskImgStr->getLine(); - if (likely(pix != nullptr)) { - maskColorMap->getGrayLine (pix, maskDest, maskWidth); - } - } - - maskImgStr->close(); - delete maskImgStr; - - maskFilter = getFilterForSurface (maskImage, maskInterpolate); - - cairo_surface_mark_dirty (maskImage); - maskPattern = cairo_pattern_create_for_surface (maskImage); - cairo_surface_destroy (maskImage); - if (cairo_pattern_status (maskPattern)) - return; - -#if 0 - /* ICCBased color space doesn't do any color correction - * so check its underlying color space as well */ - int is_identity_transform; - is_identity_transform = colorMap->getColorSpace()->getMode() == csDeviceRGB || - (colorMap->getColorSpace()->getMode() == csICCBased && - ((GfxICCBasedColorSpace*)colorMap->getColorSpace())->getAlt()->getMode() == csDeviceRGB); -#endif - - /* TODO: Do we want to cache these? */ - imgStr = new ImageStream(str, width, - colorMap->getNumPixelComps(), - colorMap->getBits()); - imgStr->reset(); - - image = cairo_image_surface_create (CAIRO_FORMAT_RGB24, width, height); - if (cairo_surface_status (image)) - goto cleanup; - - buffer = cairo_image_surface_get_data (image); - row_stride = cairo_image_surface_get_stride (image); - for (y = 0; y < height; y++) { - dest = reinterpret_cast(buffer + y * row_stride); - pix = imgStr->getLine(); - colorMap->getRGBLine (pix, dest, width); - } - - filter = getFilterForSurface (image, interpolate); - - cairo_surface_mark_dirty (image); - - setMimeData(state, str, ref, colorMap, image, height); - - pattern = cairo_pattern_create_for_surface (image); - cairo_surface_destroy (image); - if (cairo_pattern_status (pattern)) - goto cleanup; - - LOG (printf ("drawSoftMaskedImage %dx%d\n", width, height)); - - cairo_pattern_set_filter (pattern, filter); - cairo_pattern_set_filter (maskPattern, maskFilter); - - if (!printing) { - cairo_pattern_set_extend (pattern, CAIRO_EXTEND_PAD); - cairo_pattern_set_extend (maskPattern, CAIRO_EXTEND_PAD); - } - - cairo_matrix_init_translate (&matrix, 0, height); - cairo_matrix_scale (&matrix, width, -height); - cairo_pattern_set_matrix (pattern, &matrix); - if (cairo_pattern_status (pattern)) { - cairo_pattern_destroy (pattern); - cairo_pattern_destroy (maskPattern); - goto cleanup; - } - - cairo_matrix_init_translate (&maskMatrix, 0, maskHeight); - cairo_matrix_scale (&maskMatrix, maskWidth, -maskHeight); - cairo_pattern_set_matrix (maskPattern, &maskMatrix); - if (cairo_pattern_status (maskPattern)) { - cairo_pattern_destroy (maskPattern); - cairo_pattern_destroy (pattern); - goto cleanup; - } - - if (fill_opacity != 1.0) - cairo_push_group (cairo); - else - cairo_save (cairo); - - cairo_set_source (cairo, pattern); - if (!printing) { - cairo_rectangle (cairo, 0., 0., 1., 1.); - cairo_clip (cairo); - } - cairo_mask (cairo, maskPattern); - - if (fill_opacity != 1.0) { - cairo_pop_group_to_source (cairo); - cairo_save (cairo); - if (!printing) { - cairo_rectangle (cairo, 0., 0., 1., 1.); - cairo_clip (cairo); - } - cairo_paint_with_alpha (cairo, fill_opacity); - } - cairo_restore (cairo); - - if (cairo_shape) { - cairo_save (cairo_shape); - cairo_set_source (cairo_shape, pattern); - if (!printing) { - cairo_rectangle (cairo_shape, 0., 0., 1., 1.); - cairo_fill (cairo_shape); - } else { - cairo_mask (cairo_shape, pattern); - } - cairo_restore (cairo_shape); - } - - cairo_pattern_destroy (maskPattern); - cairo_pattern_destroy (pattern); - -cleanup: - imgStr->close(); - delete imgStr; -} - -bool CairoOutputDev::getStreamData (Stream *str, char **buffer, int *length) -{ - int len, i; - char *strBuffer; - - len = 0; - str->close(); - str->reset(); - while (str->getChar() != EOF) len++; - if (len == 0) - return false; - - strBuffer = (char *)gmalloc (len); - - str->close(); - str->reset(); - for (i = 0; i < len; ++i) - strBuffer[i] = str->getChar(); - - *buffer = strBuffer; - *length = len; - - return true; -} - -static bool colorMapHasIdentityDecodeMap(GfxImageColorMap *colorMap) -{ - for (int i = 0; i < colorMap->getNumPixelComps(); i++) { - if (colorMap->getDecodeLow(i) != 0.0 || colorMap->getDecodeHigh(i) != 1.0) - return false; - } - return true; -} - -#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 11, 2) -static cairo_status_t setMimeIdFromRef(cairo_surface_t *surface, - const char *mime_type, - const char *mime_id_prefix, - Ref ref) -{ - GooString *mime_id; - char *idBuffer; - cairo_status_t status; - - mime_id = new GooString; - - if (mime_id_prefix) - mime_id->append(mime_id_prefix); - - mime_id->appendf("{0:d}-{1:d}", ref.gen, ref.num); - - idBuffer = copyString(mime_id->c_str()); - status = cairo_surface_set_mime_data (surface, mime_type, - (const unsigned char *)idBuffer, - mime_id->getLength(), - gfree, idBuffer); - delete mime_id; - if (status) - gfree (idBuffer); - return status; -} -#endif - -#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 14, 0) -bool CairoOutputDev::setMimeDataForJBIG2Globals(Stream *str, - cairo_surface_t *image) -{ - JBIG2Stream *jb2Str = static_cast(str); - Object* globalsStr = jb2Str->getGlobalsStream(); - char *globalsBuffer; - int globalsLength; - - // nothing to do for JBIG2 stream without Globals - if (!globalsStr->isStream()) - return true; - - if (setMimeIdFromRef(image, CAIRO_MIME_TYPE_JBIG2_GLOBAL_ID, nullptr, - jb2Str->getGlobalsStreamRef())) - return false; - - if (!getStreamData(globalsStr->getStream(), &globalsBuffer, &globalsLength)) - return false; - - if (cairo_surface_set_mime_data (image, CAIRO_MIME_TYPE_JBIG2_GLOBAL, - (const unsigned char*)globalsBuffer, - globalsLength, - gfree, (void*)globalsBuffer)) - { - gfree (globalsBuffer); - return false; - } - - return true; -} -#endif - -#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 15, 10) -bool CairoOutputDev::setMimeDataForCCITTParams(Stream *str, - cairo_surface_t *image, int height) -{ - CCITTFaxStream *ccittStr = static_cast(str); - - GooString params; - params.appendf("Columns={0:d}", ccittStr->getColumns()); - params.appendf(" Rows={0:d}", height); - params.appendf(" K={0:d}", ccittStr->getEncoding()); - params.appendf(" EndOfLine={0:d}", ccittStr->getEndOfLine() ? 1 : 0); - params.appendf(" EncodedByteAlign={0:d}", ccittStr->getEncodedByteAlign() ? 1 : 0); - params.appendf(" EndOfBlock={0:d}", ccittStr->getEndOfBlock() ? 1 : 0); - params.appendf(" BlackIs1={0:d}", ccittStr->getBlackIs1() ? 1 : 0); - params.appendf(" DamagedRowsBeforeError={0:d}", ccittStr->getDamagedRowsBeforeError()); - - char *p = strdup(params.c_str()); - if (cairo_surface_set_mime_data (image, CAIRO_MIME_TYPE_CCITT_FAX_PARAMS, - (const unsigned char*)p, - params.getLength(), - gfree, (void*)p)) - { - gfree (p); - return false; - } - - return true; -} -#endif - -void CairoOutputDev::setMimeData(GfxState *state, Stream *str, Object *ref, - GfxImageColorMap *colorMap, cairo_surface_t *image, int height) -{ - char *strBuffer; - int len; - Object obj; - GfxColorSpace *colorSpace; - StreamKind strKind = str->getKind(); - const char *mime_type; - - if (!printing) - return; - - switch (strKind) { - case strDCT: - mime_type = CAIRO_MIME_TYPE_JPEG; - break; - case strJPX: - mime_type = CAIRO_MIME_TYPE_JP2; - break; -#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 14, 0) - case strJBIG2: - mime_type = CAIRO_MIME_TYPE_JBIG2; - break; -#endif -#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 15, 10) - case strCCITTFax: - mime_type = CAIRO_MIME_TYPE_CCITT_FAX; - break; -#endif - default: - return; - } - - obj = str->getDict()->lookup("ColorSpace"); - colorSpace = GfxColorSpace::parse(nullptr, &obj, this, state); - - // colorspace in stream dict may be different from colorspace in jpx - // data - if (strKind == strJPX && colorSpace) - return; - - // only embed mime data for gray, rgb, and cmyk colorspaces. - if (colorSpace) { - GfxColorSpaceMode mode = colorSpace->getMode(); - delete colorSpace; - switch (mode) { - case csDeviceGray: - case csCalGray: - case csDeviceRGB: - case csCalRGB: - case csDeviceCMYK: - case csICCBased: - break; - - case csLab: - case csIndexed: - case csSeparation: - case csDeviceN: - case csPattern: - return; - } - } - - if (!colorMapHasIdentityDecodeMap(colorMap)) - return; - -#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 14, 0) - if (strKind == strJBIG2 && !setMimeDataForJBIG2Globals(str, image)) - return; -#endif - -#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 15, 10) - if (strKind == strCCITTFax && !setMimeDataForCCITTParams(str, image, height)) - return; -#endif - - if (getStreamData (str->getNextStream(), &strBuffer, &len)) { - cairo_status_t status = CAIRO_STATUS_SUCCESS; - -#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 11, 2) - // Since 1.5.10 the cairo PS backend stores images with UNIQUE_ID in PS memory so the - // image can be re-used multiple times. As we don't know how large the images are or - // how many times they are used, there is no benefit in enabling this. Issue #106 - if (cairo_surface_get_type (cairo_get_target (cairo)) != CAIRO_SURFACE_TYPE_PS) { - if (ref && ref->isRef()) { - status = setMimeIdFromRef(image, CAIRO_MIME_TYPE_UNIQUE_ID, - "poppler-surface-", ref->getRef()); - } - } -#endif - if (!status) { - status = cairo_surface_set_mime_data (image, mime_type, - (const unsigned char *)strBuffer, len, - gfree, strBuffer); - } - - if (status) - gfree (strBuffer); - } -} - -class RescaleDrawImage : public CairoRescaleBox { -private: - ImageStream *imgStr; - GfxRGB *lookup; - int width; - GfxImageColorMap *colorMap; - const int *maskColors; - int current_row; - bool imageError; - -public: - cairo_surface_t *getSourceImage(Stream *str, - int widthA, int height, - int scaledWidth, int scaledHeight, - bool printing, - GfxImageColorMap *colorMapA, - const int *maskColorsA) { - cairo_surface_t *image = nullptr; - int i; - - lookup = nullptr; - colorMap = colorMapA; - maskColors = maskColorsA; - width = widthA; - current_row = -1; - imageError = false; - - /* TODO: Do we want to cache these? */ - imgStr = new ImageStream(str, width, - colorMap->getNumPixelComps(), - colorMap->getBits()); - imgStr->reset(); - -#if 0 - /* ICCBased color space doesn't do any color correction - * so check its underlying color space as well */ - int is_identity_transform; - is_identity_transform = colorMap->getColorSpace()->getMode() == csDeviceRGB || - (colorMap->getColorSpace()->getMode() == csICCBased && - ((GfxICCBasedColorSpace*)colorMap->getColorSpace())->getAlt()->getMode() == csDeviceRGB); -#endif - - // special case for one-channel (monochrome/gray/separation) images: - // build a lookup table here - if (colorMap->getNumPixelComps() == 1) { - int n; - unsigned char pix; - - n = 1 << colorMap->getBits(); - lookup = (GfxRGB *)gmallocn(n, sizeof(GfxRGB)); - for (i = 0; i < n; ++i) { - pix = (unsigned char)i; - - colorMap->getRGB(&pix, &lookup[i]); - } - } - -#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 14, 0) - bool needsCustomDownscaling = false; -#else - bool needsCustomDownscaling = true; -#endif - - if (printing) { - if (width > MAX_PRINT_IMAGE_SIZE || height > MAX_PRINT_IMAGE_SIZE) { - if (width > height) { - scaledWidth = MAX_PRINT_IMAGE_SIZE; - scaledHeight = MAX_PRINT_IMAGE_SIZE * (double)height/width; - } else { - scaledHeight = MAX_PRINT_IMAGE_SIZE; - scaledWidth = MAX_PRINT_IMAGE_SIZE * (double)width/height; - } - needsCustomDownscaling = true; - - if (scaledWidth == 0) { - scaledWidth = 1; - } - if (scaledHeight == 0) { - scaledHeight = 1; - } - } else { - needsCustomDownscaling = false; - } - } - - if (!needsCustomDownscaling || scaledWidth >= width || scaledHeight >= height) { - // No downscaling. Create cairo image containing the source image data. - unsigned char *buffer; - ptrdiff_t stride; - - image = cairo_image_surface_create (maskColors ? - CAIRO_FORMAT_ARGB32 : - CAIRO_FORMAT_RGB24, - width, height); - if (cairo_surface_status (image)) - goto cleanup; - - buffer = cairo_image_surface_get_data (image); - stride = cairo_image_surface_get_stride (image); - for (int y = 0; y < height; y++) { - uint32_t *dest = reinterpret_cast(buffer + y * stride); - getRow(y, dest); - } - } else { - // // Downscaling required. Create cairo image the size of the - // rescaled image and // downscale the source image data into - // the cairo image. downScaleImage() will call getRow() to read - // source image data from the image stream. This avoids having - // to create an image the size of the source image which may - // exceed cairo's 32676x32767 image size limit (and also saves a - // lot of memory). - image = cairo_image_surface_create (maskColors ? - CAIRO_FORMAT_ARGB32 : - CAIRO_FORMAT_RGB24, - scaledWidth, scaledHeight); - if (cairo_surface_status (image)) - goto cleanup; - - downScaleImage(width, height, - scaledWidth, scaledHeight, - 0, 0, scaledWidth, scaledHeight, - image); - } - cairo_surface_mark_dirty (image); - - cleanup: - gfree(lookup); - imgStr->close(); - delete imgStr; - return image; - } - - void getRow(int row_num, uint32_t *row_data) override { - unsigned char *pix; - - if (row_num <= current_row) - return; - - while (current_row < row_num) { - pix = imgStr->getLine(); - current_row++; - } - - if (unlikely(pix == nullptr)) { - memset(row_data, 0, width*4); - if (!imageError) { - error(errInternal, -1, "Bad image stream"); - imageError = true; - } - } else if (lookup) { - unsigned char *p = pix; - GfxRGB rgb; - - for (int i = 0; i < width; i++) { - rgb = lookup[*p]; - row_data[i] = - ((int) colToByte(rgb.r) << 16) | - ((int) colToByte(rgb.g) << 8) | - ((int) colToByte(rgb.b) << 0); - p++; - } - } else { - colorMap->getRGBLine (pix, row_data, width); - } - - if (maskColors) { - for (int x = 0; x < width; x++) { - bool is_opaque = false; - for (int i = 0; i < colorMap->getNumPixelComps(); ++i) { - if (pix[i] < maskColors[2*i] || - pix[i] > maskColors[2*i+1]) { - is_opaque = true; - break; - } - } - if (is_opaque) - *row_data |= 0xff000000; - else - *row_data = 0; - row_data++; - pix += colorMap->getNumPixelComps(); - } - } - } - -}; - -void CairoOutputDev::drawImage(GfxState *state, Object *ref, Stream *str, - int widthA, int heightA, - GfxImageColorMap *colorMap, - bool interpolate, - const int *maskColors, bool inlineImg) -{ - cairo_surface_t *image; - cairo_pattern_t *pattern, *maskPattern; - cairo_matrix_t matrix; - int width, height; - int scaledWidth, scaledHeight; - cairo_filter_t filter = CAIRO_FILTER_GOOD; - RescaleDrawImage rescale; - - LOG (printf ("drawImage %dx%d\n", widthA, heightA)); - - cairo_get_matrix(cairo, &matrix); - getScaledSize (&matrix, widthA, heightA, &scaledWidth, &scaledHeight); - image = rescale.getSourceImage(str, widthA, heightA, scaledWidth, scaledHeight, printing, colorMap, maskColors); - if (!image) - return; - - width = cairo_image_surface_get_width (image); - height = cairo_image_surface_get_height (image); - if (width == widthA && height == heightA) - filter = getFilterForSurface (image, interpolate); - - if (!inlineImg) { /* don't read stream twice if it is an inline image */ - // cairo 1.15.10 allows mime image data to have different size to cairo image - // mime image size will be scaled to same size as cairo image -#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 15, 10) - bool requireSameSize = false; -#else - bool requireSameSize = true; -#endif - if (!requireSameSize || (width == widthA && height == heightA)) - setMimeData(state, str, ref, colorMap, image, heightA); - } - - pattern = cairo_pattern_create_for_surface (image); - cairo_surface_destroy (image); - if (cairo_pattern_status (pattern)) - return; - - cairo_pattern_set_filter (pattern, filter); - - if (!printing) - cairo_pattern_set_extend (pattern, CAIRO_EXTEND_PAD); - - cairo_matrix_init_translate (&matrix, 0, height); - cairo_matrix_scale (&matrix, width, -height); - cairo_pattern_set_matrix (pattern, &matrix); - if (cairo_pattern_status (pattern)) { - cairo_pattern_destroy (pattern); - return; - } - - if (!mask && fill_opacity != 1.0) { - maskPattern = cairo_pattern_create_rgba (1., 1., 1., fill_opacity); - } else if (mask) { - maskPattern = cairo_pattern_reference (mask); - } else { - maskPattern = nullptr; - } - - cairo_save (cairo); - cairo_set_source (cairo, pattern); - if (!printing) - cairo_rectangle (cairo, 0., 0., 1., 1.); - if (maskPattern) { - if (!printing) - cairo_clip (cairo); - if (mask) - cairo_set_matrix (cairo, &mask_matrix); - cairo_mask (cairo, maskPattern); - } else { - if (printing) - cairo_paint (cairo); - else - cairo_fill (cairo); - } - cairo_restore (cairo); - - cairo_pattern_destroy (maskPattern); - - if (cairo_shape) { - cairo_save (cairo_shape); - cairo_set_source (cairo_shape, pattern); - if (printing) { - cairo_paint (cairo_shape); - } else { - cairo_rectangle (cairo_shape, 0., 0., 1., 1.); - cairo_fill (cairo_shape); - } - cairo_restore (cairo_shape); - } - - cairo_pattern_destroy (pattern); -} - - -//------------------------------------------------------------------------ -// ImageOutputDev -//------------------------------------------------------------------------ - -CairoImageOutputDev::CairoImageOutputDev() -{ - images = nullptr; - numImages = 0; - size = 0; - imgDrawCbk = nullptr; - imgDrawCbkData = nullptr; -} - -CairoImageOutputDev::~CairoImageOutputDev() -{ - int i; - - for (i = 0; i < numImages; i++) - delete images[i]; - gfree (images); -} - -void CairoImageOutputDev::saveImage(CairoImage *image) -{ - if (numImages >= size) { - size += 16; - images = (CairoImage **) greallocn (images, size, sizeof (CairoImage *)); - } - images[numImages++] = image; -} - -void CairoImageOutputDev::getBBox(GfxState *state, int width, int height, - double *x1, double *y1, double *x2, double *y2) -{ - const double *ctm = state->getCTM(); - cairo_matrix_t matrix; - cairo_matrix_init(&matrix, - ctm[0], ctm[1], - -ctm[2], -ctm[3], - ctm[2] + ctm[4], ctm[3] + ctm[5]); - - int scaledWidth, scaledHeight; - getScaledSize (&matrix, width, height, &scaledWidth, &scaledHeight); - - if (matrix.xx >= 0) { - *x1 = matrix.x0; - } else { - *x1 = matrix.x0 - scaledWidth; - } - *x2 = *x1 + scaledWidth; - - if (matrix.yy >= 0) { - *y1 = matrix.y0; - } else { - *y1 = matrix.y0 - scaledHeight; - } - *y2 = *y1 + scaledHeight; -} - -void CairoImageOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str, - int width, int height, bool invert, - bool interpolate, bool inlineImg) -{ - cairo_t *cr; - cairo_surface_t *surface; - double x1, y1, x2, y2; - CairoImage *image; - - getBBox(state, width, height, &x1, &y1, &x2, &y2); - - image = new CairoImage (x1, y1, x2, y2); - saveImage (image); - - if (imgDrawCbk && imgDrawCbk (numImages - 1, imgDrawCbkData)) { - surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height); - cr = cairo_create (surface); - setCairo (cr); - cairo_translate (cr, 0, height); - cairo_scale (cr, width, -height); - - CairoOutputDev::drawImageMask(state, ref, str, width, height, invert, interpolate, inlineImg); - image->setImage (surface); - - setCairo (nullptr); - cairo_surface_destroy (surface); - cairo_destroy (cr); - } -} - -void CairoImageOutputDev::setSoftMaskFromImageMask(GfxState *state, Object *ref, Stream *str, - int width, int height, bool invert, - bool inlineImg, double *baseMatrix) -{ - cairo_t *cr; - cairo_surface_t *surface; - double x1, y1, x2, y2; - CairoImage *image; - - getBBox(state, width, height, &x1, &y1, &x2, &y2); - - image = new CairoImage (x1, y1, x2, y2); - saveImage (image); - - if (imgDrawCbk && imgDrawCbk (numImages - 1, imgDrawCbkData)) { - surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height); - cr = cairo_create (surface); - setCairo (cr); - cairo_translate (cr, 0, height); - cairo_scale (cr, width, -height); - - CairoOutputDev::drawImageMask(state, ref, str, width, height, invert, inlineImg, false); - if (state->getFillColorSpace()->getMode() == csPattern) { - cairo_mask (cairo, mask); - } - image->setImage (surface); - - setCairo (nullptr); - cairo_surface_destroy (surface); - cairo_destroy (cr); - } -} - -void CairoImageOutputDev::drawImage(GfxState *state, Object *ref, Stream *str, - int width, int height, GfxImageColorMap *colorMap, - bool interpolate, const int *maskColors, bool inlineImg) -{ - cairo_t *cr; - cairo_surface_t *surface; - double x1, y1, x2, y2; - CairoImage *image; - - getBBox(state, width, height, &x1, &y1, &x2, &y2); - - image = new CairoImage (x1, y1, x2, y2); - saveImage (image); - - if (imgDrawCbk && imgDrawCbk (numImages - 1, imgDrawCbkData)) { - surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height); - cr = cairo_create (surface); - setCairo (cr); - cairo_translate (cr, 0, height); - cairo_scale (cr, width, -height); - - CairoOutputDev::drawImage(state, ref, str, width, height, colorMap, interpolate, maskColors, inlineImg); - image->setImage (surface); - - setCairo (nullptr); - cairo_surface_destroy (surface); - cairo_destroy (cr); - } -} - -void CairoImageOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref, Stream *str, - int width, int height, - GfxImageColorMap *colorMap, - bool interpolate, - Stream *maskStr, - int maskWidth, int maskHeight, - GfxImageColorMap *maskColorMap, - bool maskInterpolate) -{ - cairo_t *cr; - cairo_surface_t *surface; - double x1, y1, x2, y2; - CairoImage *image; - - getBBox(state, width, height, &x1, &y1, &x2, &y2); - - image = new CairoImage (x1, y1, x2, y2); - saveImage (image); - - if (imgDrawCbk && imgDrawCbk (numImages - 1, imgDrawCbkData)) { - surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height); - cr = cairo_create (surface); - setCairo (cr); - cairo_translate (cr, 0, height); - cairo_scale (cr, width, -height); - - CairoOutputDev::drawSoftMaskedImage(state, ref, str, width, height, colorMap, interpolate, - maskStr, maskWidth, maskHeight, maskColorMap, maskInterpolate); - image->setImage (surface); - - setCairo (nullptr); - cairo_surface_destroy (surface); - cairo_destroy (cr); - } -} - -void CairoImageOutputDev::drawMaskedImage(GfxState *state, Object *ref, Stream *str, - int width, int height, - GfxImageColorMap *colorMap, - bool interpolate, - Stream *maskStr, - int maskWidth, int maskHeight, - bool maskInvert, bool maskInterpolate) -{ - cairo_t *cr; - cairo_surface_t *surface; - double x1, y1, x2, y2; - CairoImage *image; - - getBBox(state, width, height, &x1, &y1, &x2, &y2); - - image = new CairoImage (x1, y1, x2, y2); - saveImage (image); - - if (imgDrawCbk && imgDrawCbk (numImages - 1, imgDrawCbkData)) { - surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height); - cr = cairo_create (surface); - setCairo (cr); - cairo_translate (cr, 0, height); - cairo_scale (cr, width, -height); - - CairoOutputDev::drawMaskedImage(state, ref, str, width, height, colorMap, interpolate, - maskStr, maskWidth, maskHeight, maskInvert, maskInterpolate); - image->setImage (surface); - - setCairo (nullptr); - cairo_surface_destroy (surface); - cairo_destroy (cr); - } -} diff --git a/pdf2htmlEX/3rdparty/poppler/git/CairoOutputDev.h b/pdf2htmlEX/3rdparty/poppler/git/CairoOutputDev.h deleted file mode 100644 index 9e6f497..0000000 --- a/pdf2htmlEX/3rdparty/poppler/git/CairoOutputDev.h +++ /dev/null @@ -1,525 +0,0 @@ -//======================================================================== -// -// CairoOutputDev.h -// -// Copyright 2003 Glyph & Cog, LLC -// Copyright 2004 Red Hat, INC -// -//======================================================================== - -//======================================================================== -// -// Modified under the Poppler project - http://poppler.freedesktop.org -// -// All changes made under the Poppler project to this file are licensed -// under GPL version 2 or later -// -// Copyright (C) 2005-2008 Jeff Muizelaar -// Copyright (C) 2005, 2006 Kristian Høgsberg -// Copyright (C) 2005 Nickolay V. Shmyrev -// Copyright (C) 2006-2011, 2013 Carlos Garcia Campos -// Copyright (C) 2008, 2009, 2011-2017 Adrian Johnson -// Copyright (C) 2008 Michael Vrable -// Copyright (C) 2010-2013 Thomas Freitag -// Copyright (C) 2015 Suzuki Toshiya -// Copyright (C) 2016 Jason Crain -// Copyright (C) 2018, 2019 Albert Astals Cid -// Copyright (C) 2018 Klarälvdalens Datakonsult AB, a KDAB Group company, . Work sponsored by the LiMux project of the city of Munich -// -// To see a description of the changes please see the Changelog file that -// came with your tarball or type make ChangeLog if you are building from git -// -//======================================================================== - -#ifndef CAIROOUTPUTDEV_H -#define CAIROOUTPUTDEV_H - -#include -#include "OutputDev.h" -#include "TextOutputDev.h" -#include "GfxState.h" - -class PDFDoc; -class GfxState; -class GfxPath; -class Gfx8BitFont; -struct GfxRGB; -class CairoFontEngine; -class CairoFont; - -//------------------------------------------------------------------------ - -//------------------------------------------------------------------------ -// CairoImage -//------------------------------------------------------------------------ -class CairoImage { -public: - // Constructor. - CairoImage (double x1, double y1, double x2, double y2); - - // Destructor. - ~CairoImage (); - - CairoImage(const CairoImage &) = delete; - CairoImage& operator=(const CairoImage &) = delete; - - // Set the image cairo surface - void setImage (cairo_surface_t *image); - - // Get the image cairo surface - cairo_surface_t *getImage () const { return image; } - - // Get the image rectangle - void getRect (double *xa1, double *ya1, double *xa2, double *ya2) - { *xa1 = x1; *ya1 = y1; *xa2 = x2; *ya2 = y2; } - -private: - cairo_surface_t *image; // image cairo surface - double x1, y1; // upper left corner - double x2, y2; // lower right corner -}; - - -//------------------------------------------------------------------------ -// CairoOutputDev -//------------------------------------------------------------------------ - -class CairoOutputDev: public OutputDev { -public: - - // Constructor. - CairoOutputDev(); - - // Destructor. - virtual ~CairoOutputDev(); - - //----- get info about output device - - // Does this device use upside-down coordinates? - // (Upside-down means (0,0) is the top left corner of the page.) - bool upsideDown() override { return true; } - - // Does this device use drawChar() or drawString()? - bool useDrawChar() override { return true; } - - // Does this device use tilingPatternFill()? If this returns false, - // tiling pattern fills will be reduced to a series of other drawing - // operations. - bool useTilingPatternFill() override { return true; } - - // Does this device use functionShadedFill(), axialShadedFill(), and - // radialShadedFill()? If this returns false, these shaded fills - // will be reduced to a series of other drawing operations. -#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 12, 0) - bool useShadedFills(int type) override { return type <= 7; } -#else - bool useShadedFills(int type) override { return type > 1 && type < 4; } -#endif - - // Does this device use FillColorStop()? - bool useFillColorStop() override { return true; } - - // Does this device use beginType3Char/endType3Char? Otherwise, - // text in Type 3 fonts will be drawn with drawChar/drawString. - bool interpretType3Chars() override { return false; } - - // Does this device need to clip pages to the crop box even when the - // box is the crop box? - bool needClipToCropBox() override { return true; } - - //----- initialization and control - - // Start a page. - void startPage(int pageNum, GfxState *state, XRef *xref) override; - - // End a page. - void endPage() override; - - //----- save/restore graphics state - void saveState(GfxState *state) override; - void restoreState(GfxState *state) override; - - //----- update graphics state - void updateAll(GfxState *state) override; - void setDefaultCTM(const double *ctm) override; - void updateCTM(GfxState *state, double m11, double m12, - double m21, double m22, double m31, double m32) override; - void updateLineDash(GfxState *state) override; - void updateFlatness(GfxState *state) override; - void updateLineJoin(GfxState *state) override; - void updateLineCap(GfxState *state) override; - void updateMiterLimit(GfxState *state) override; - void updateLineWidth(GfxState *state) override; - void updateFillColor(GfxState *state) override; - void updateStrokeColor(GfxState *state) override; - void updateFillOpacity(GfxState *state) override; - void updateStrokeOpacity(GfxState *state) override; - void updateFillColorStop(GfxState *state, double offset) override; - void updateBlendMode(GfxState *state) override; - - //----- update text state - void updateFont(GfxState *state) override; - - //----- path painting - void stroke(GfxState *state) override; - void fill(GfxState *state) override; - void eoFill(GfxState *state) override; - void clipToStrokePath(GfxState *state) override; - bool tilingPatternFill(GfxState *state, Gfx *gfx, Catalog *cat, Object *str, - const double *pmat, int paintType, int tilingType, Dict *resDict, - const double *mat, const double *bbox, - int x0, int y0, int x1, int y1, - double xStep, double yStep) override; -#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 12, 0) - bool functionShadedFill(GfxState *state, GfxFunctionShading *shading) override; -#endif - bool axialShadedFill(GfxState *state, GfxAxialShading *shading, double tMin, double tMax) override; - bool axialShadedSupportExtend(GfxState *state, GfxAxialShading *shading) override; - bool radialShadedFill(GfxState *state, GfxRadialShading *shading, double sMin, double sMax) override; - bool radialShadedSupportExtend(GfxState *state, GfxRadialShading *shading) override; -#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 12, 0) - bool gouraudTriangleShadedFill(GfxState *state, GfxGouraudTriangleShading *shading) override; - bool patchMeshShadedFill(GfxState *state, GfxPatchMeshShading *shading) override; -#endif - - //----- path clipping - void clip(GfxState *state) override; - void eoClip(GfxState *state) override; - - //----- text drawing - void beginString(GfxState *state, const GooString *s) override; - void endString(GfxState *state) override; - void drawChar(GfxState *state, double x, double y, - double dx, double dy, - double originX, double originY, - CharCode code, int nBytes, const Unicode *u, int uLen) override; - void beginActualText(GfxState *state, const GooString *text) override; - void endActualText(GfxState *state) override; - - bool beginType3Char(GfxState *state, double x, double y, - double dx, double dy, - CharCode code, const Unicode *u, int uLen) override; - void endType3Char(GfxState *state) override; - void beginTextObject(GfxState *state) override; - void endTextObject(GfxState *state) override; - - //----- image drawing - void drawImageMask(GfxState *state, Object *ref, Stream *str, - int width, int height, bool invert, bool interpolate, - bool inlineImg) override; - void setSoftMaskFromImageMask(GfxState *state, - Object *ref, Stream *str, - int width, int height, bool invert, - bool inlineImg, double *baseMatrix) override; - void unsetSoftMaskFromImageMask(GfxState *state, double *baseMatrix) override; - void drawImageMaskPrescaled(GfxState *state, Object *ref, Stream *str, - int width, int height, bool invert, bool interpolate, - bool inlineImg); - void drawImageMaskRegular(GfxState *state, Object *ref, Stream *str, - int width, int height, bool invert, bool interpolate, - bool inlineImg); - - void drawImage(GfxState *state, Object *ref, Stream *str, - int width, int height, GfxImageColorMap *colorMap, - bool interpolate, const int *maskColors, bool inlineImg) override; - void drawSoftMaskedImage(GfxState *state, Object *ref, Stream *str, - int width, int height, - GfxImageColorMap *colorMap, - bool interpolate, - Stream *maskStr, - int maskWidth, int maskHeight, - GfxImageColorMap *maskColorMap, - bool maskInterpolate) override; - - void drawMaskedImage(GfxState *state, Object *ref, Stream *str, - int width, int height, - GfxImageColorMap *colorMap, - bool interpolate, - Stream *maskStr, - int maskWidth, int maskHeight, - bool maskInvert, bool maskInterpolate) override; - - //----- transparency groups and soft masks - void beginTransparencyGroup(GfxState * /*state*/, const double * /*bbox*/, - GfxColorSpace * /*blendingColorSpace*/, - bool /*isolated*/, bool /*knockout*/, - bool /*forSoftMask*/) override; - void endTransparencyGroup(GfxState * /*state*/) override; - void popTransparencyGroup(); - void paintTransparencyGroup(GfxState * /*state*/, const double * /*bbox*/) override; - void setSoftMask(GfxState * /*state*/, const double * /*bbox*/, bool /*alpha*/, - Function * /*transferFunc*/, GfxColor * /*backdropColor*/) override; - void clearSoftMask(GfxState * /*state*/) override; - - //----- Type 3 font operators - void type3D0(GfxState *state, double wx, double wy) override; - void type3D1(GfxState *state, double wx, double wy, - double llx, double lly, double urx, double ury) override; - - //----- special access - - // Called to indicate that a new PDF document has been loaded. - void startDoc(PDFDoc *docA, CairoFontEngine *fontEngine = nullptr); - - bool isReverseVideo() { return false; } - - void setCairo (cairo_t *cr); - void setTextPage (TextPage *text); - void setPrinting (bool printingA) { printing = printingA; needFontUpdate = true; } - void setAntialias(cairo_antialias_t antialias); - - void setInType3Char(bool inType3CharA) { inType3Char = inType3CharA; } - void getType3GlyphWidth (double *wx, double *wy) { *wx = t3_glyph_wx; *wy = t3_glyph_wy; } - bool hasType3GlyphBBox () { return t3_glyph_has_bbox; } - double *getType3GlyphBBox () { return t3_glyph_bbox; } - -protected: - void doPath(cairo_t *cairo, GfxState *state, const GfxPath *path); - cairo_surface_t *downscaleSurface(cairo_surface_t *orig_surface); - void getScaledSize(const cairo_matrix_t *matrix, - int orig_width, int orig_height, - int *scaledWidth, int *scaledHeight); - cairo_filter_t getFilterForSurface(cairo_surface_t *image, - bool interpolate); - bool getStreamData (Stream *str, char **buffer, int *length); - void setMimeData(GfxState *state, Stream *str, Object *ref, - GfxImageColorMap *colorMap, cairo_surface_t *image, int height); - void fillToStrokePathClip(GfxState *state); - void alignStrokeCoords(const GfxSubpath *subpath, int i, double *x, double *y); -#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 14, 0) - bool setMimeDataForJBIG2Globals (Stream *str, cairo_surface_t *image); -#endif -#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 15, 10) - bool setMimeDataForCCITTParams(Stream *str, cairo_surface_t *image, int height); -#endif - static void setContextAntialias(cairo_t *cr, cairo_antialias_t antialias); - - GfxRGB fill_color, stroke_color; - cairo_pattern_t *fill_pattern, *stroke_pattern; - double fill_opacity; - double stroke_opacity; - bool stroke_adjust; - bool adjusted_stroke_width; - bool align_stroke_coords; - CairoFont *currentFont; - XRef *xref; - - struct StrokePathClip { - GfxPath *path; - cairo_matrix_t ctm; - double line_width; - double *dashes; - int dash_count; - double dash_offset; - cairo_line_cap_t cap; - cairo_line_join_t join; - double miter; - int ref_count; - } *strokePathClip; - - PDFDoc *doc; // the current document - - static FT_Library ft_lib; - static bool ft_lib_initialized; - - CairoFontEngine *fontEngine; - bool fontEngine_owner; - - cairo_t *cairo; - cairo_matrix_t orig_matrix; - bool needFontUpdate; // set when the font needs to be updated - bool printing; - bool use_show_text_glyphs; - bool text_matrix_valid; - cairo_glyph_t *glyphs; - int glyphCount; - cairo_text_cluster_t *clusters; - int clusterCount; - char *utf8; - int utf8Count; - int utf8Max; - cairo_path_t *textClipPath; - bool inUncoloredPattern; // inside a uncolored pattern (PaintType = 2) - bool inType3Char; // inside a Type 3 CharProc - double t3_glyph_wx, t3_glyph_wy; - bool t3_glyph_has_bbox; - double t3_glyph_bbox[4]; - cairo_antialias_t antialias; - bool prescaleImages; - - TextPage *textPage; // text for the current page - ActualText *actualText; - - cairo_pattern_t *group; - cairo_pattern_t *shape; - cairo_pattern_t *mask; - cairo_matrix_t mask_matrix; - cairo_t *cairo_shape; - int knockoutCount; - struct ColorSpaceStack { - bool knockout; - GfxColorSpace *cs; - cairo_matrix_t group_matrix; - struct ColorSpaceStack *next; - } * groupColorSpaceStack; - - struct MaskStack { - cairo_pattern_t *mask; - cairo_matrix_t mask_matrix; - struct MaskStack *next; - } *maskStack; - -}; - -//------------------------------------------------------------------------ -// CairoImageOutputDev -//------------------------------------------------------------------------ - -//XXX: this should ideally not inherit from CairoOutputDev but use it instead perhaps -class CairoImageOutputDev: public CairoOutputDev { -public: - - // Constructor. - CairoImageOutputDev(); - - // Destructor. - virtual ~CairoImageOutputDev(); - - //----- get info about output device - - // Does this device use upside-down coordinates? - // (Upside-down means (0,0) is the top left corner of the page.) - bool upsideDown() override { return true; } - - // Does this device use drawChar() or drawString()? - bool useDrawChar() override { return false; } - - // Does this device use tilingPatternFill()? If this returns false, - // tiling pattern fills will be reduced to a series of other drawing - // operations. - bool useTilingPatternFill() override { return true; } - - // Does this device use functionShadedFill(), axialShadedFill(), and - // radialShadedFill()? If this returns false, these shaded fills - // will be reduced to a series of other drawing operations. -#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 11, 2) - bool useShadedFills(int type) override { return type <= 7; } -#else - bool useShadedFills(int type) override { return type < 4; } -#endif - - // Does this device use FillColorStop()? - bool useFillColorStop() override { return false; } - - // Does this device use beginType3Char/endType3Char? Otherwise, - // text in Type 3 fonts will be drawn with drawChar/drawString. - bool interpretType3Chars() override { return false; } - - // Does this device need non-text content? - bool needNonText() override { return true; } - - //----- save/restore graphics state - void saveState(GfxState *state) override { } - void restoreState(GfxState *state) override { } - - //----- update graphics state - void updateAll(GfxState *state) override { } - void setDefaultCTM(const double *ctm) override { } - void updateCTM(GfxState *state, double m11, double m12, - double m21, double m22, double m31, double m32) override { } - void updateLineDash(GfxState *state) override { } - void updateFlatness(GfxState *state) override { } - void updateLineJoin(GfxState *state) override { } - void updateLineCap(GfxState *state) override { } - void updateMiterLimit(GfxState *state) override { } - void updateLineWidth(GfxState *state) override { } - void updateFillColor(GfxState *state) override { } - void updateStrokeColor(GfxState *state) override { } - void updateFillOpacity(GfxState *state) override { } - void updateStrokeOpacity(GfxState *state) override { } - void updateBlendMode(GfxState *state) override { } - - //----- update text state - void updateFont(GfxState *state) override { } - - //----- path painting - void stroke(GfxState *state) override { } - void fill(GfxState *state) override { } - void eoFill(GfxState *state) override { } - void clipToStrokePath(GfxState *state) override { } - bool tilingPatternFill(GfxState *state, Gfx *gfx, Catalog *cat, Object *str, - const double *pmat, int paintType, int tilingType, Dict *resDict, - const double *mat, const double *bbox, - int x0, int y0, int x1, int y1, - double xStep, double yStep) override { return true; } - bool axialShadedFill(GfxState *state, - GfxAxialShading *shading, - double tMin, double tMax) override { return true; } - bool radialShadedFill(GfxState *state, - GfxRadialShading *shading, - double sMin, double sMax) override { return true; } - - //----- path clipping - void clip(GfxState *state) override { } - void eoClip(GfxState *state) override { } - - //----- image drawing - void drawImageMask(GfxState *state, Object *ref, Stream *str, - int width, int height, bool invert, - bool interpolate, bool inlineImg) override; - void drawImage(GfxState *state, Object *ref, Stream *str, - int width, int height, GfxImageColorMap *colorMap, - bool interpolate, const int *maskColors, bool inlineImg) override; - void drawSoftMaskedImage(GfxState *state, Object *ref, Stream *str, - int width, int height, - GfxImageColorMap *colorMap, - bool interpolate, - Stream *maskStr, - int maskWidth, int maskHeight, - GfxImageColorMap *maskColorMap, - bool maskInterpolate) override; - void drawMaskedImage(GfxState *state, Object *ref, Stream *str, - int width, int height, - GfxImageColorMap *colorMap, - bool interpolate, - Stream *maskStr, - int maskWidth, int maskHeight, - bool maskInvert, bool maskInterpolate) override; - void setSoftMaskFromImageMask(GfxState *state, Object *ref, Stream *str, - int width, int height, bool invert, - bool inlineImg, double *baseMatrix) override; - void unsetSoftMaskFromImageMask(GfxState *state, double *baseMatrix) override {} - - - //----- transparency groups and soft masks - void beginTransparencyGroup(GfxState * /*state*/, const double * /*bbox*/, - GfxColorSpace * /*blendingColorSpace*/, - bool /*isolated*/, bool /*knockout*/, - bool /*forSoftMask*/) override {} - void endTransparencyGroup(GfxState * /*state*/) override {} - void paintTransparencyGroup(GfxState * /*state*/, const double * /*bbox*/) override {} - void setSoftMask(GfxState * /*state*/, const double * /*bbox*/, bool /*alpha*/, - Function * /*transferFunc*/, GfxColor * /*backdropColor*/) override {} - void clearSoftMask(GfxState * /*state*/) override {} - - //----- Image list - // By default images are not rendred - void setImageDrawDecideCbk(bool (*cbk)(int img_id, void *data), - void *data) { imgDrawCbk = cbk; imgDrawCbkData = data; } - // Iterate through list of images. - int getNumImages() const { return numImages; } - CairoImage *getImage(int i) const { return images[i]; } - -private: - void saveImage(CairoImage *image); - void getBBox(GfxState *state, int width, int height, - double *x1, double *y1, double *x2, double *y2); - - CairoImage **images; - int numImages; - int size; - bool (*imgDrawCbk)(int img_id, void *data); - void *imgDrawCbkData; -}; - -#endif diff --git a/pdf2htmlEX/3rdparty/poppler/git/CairoRescaleBox.cc b/pdf2htmlEX/3rdparty/poppler/git/CairoRescaleBox.cc deleted file mode 100644 index 1c7ccd1..0000000 --- a/pdf2htmlEX/3rdparty/poppler/git/CairoRescaleBox.cc +++ /dev/null @@ -1,379 +0,0 @@ -/* -*- Mode: c; c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t; -*- */ -/* - * Copyright © 2009 Mozilla Corporation - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the name of Mozilla Corporation not be used in - * advertising or publicity pertaining to distribution of the software without - * specific, written prior permission. Mozilla Corporation makes no - * representations about the suitability of this software for any purpose. It - * is provided "as is" without express or implied warranty. - * - * MOZILLA CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT - * SHALL MOZILLA CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE - * OF THIS SOFTWARE. - * - * Author: Jeff Muizelaar, Mozilla Corp. - */ - -//======================================================================== -// -// Modified under the Poppler project - http://poppler.freedesktop.org -// -// All changes made under the Poppler project to this file are licensed -// under GPL version 2 or later -// -// Copyright (C) 2012 Hib Eris -// Copyright (C) 2012, 2017 Adrian Johnson -// Copyright (C) 2018 Adam Reichold -// Copyright (C) 2019 Albert Astals Cid -// Copyright (C) 2019 Marek Kasik -// -// To see a description of the changes please see the Changelog file that -// came with your tarball or type make ChangeLog if you are building from git -// -//======================================================================== - - -/* This implements a box filter that supports non-integer box sizes */ - -#include - -#include -#include -#include -#include -#include -#include -#include "goo/gmem.h" -#include "CairoRescaleBox.h" - - -/* we work in fixed point where 1. == 1 << 24 */ -#define FIXED_SHIFT 24 - - -static void downsample_row_box_filter ( - int start, int width, - uint32_t *src, const uint32_t *src_limit, uint32_t *dest, - const int coverage[], int pixel_coverage) -{ - /* we need an array of the pixel contribution of each destination pixel on the boundaries. - * we invert the value to get the value on the other size of the box */ - /* - - value = a * contribution * 1/box_size - value += a * 1/box_size - value += a * 1/box_size - value += a * 1/box_size - value += a * (1 - contribution) * 1/box_size - a * (1/box_size - contribution * 1/box_size) - - box size is constant - - - value = a * contribution_a * 1/box_size + b * contribution_b * 1/box_size - contribution_b = (1 - contribution_a) - = (1 - contribution_a_next) - */ - - /* box size = ceil(src_width/dest_width) */ - int x = 0; - - /* skip to start */ - /* XXX: it might be possible to do this directly instead of iteratively, however - * the iterative solution is simple */ - while (x < start && src < src_limit) - { - int box = 1 << FIXED_SHIFT; - int start_coverage = coverage[x]; - box -= start_coverage; - src++; - while (box >= pixel_coverage && src < src_limit) - { - src++; - box -= pixel_coverage; - } - x++; - } - - while (x < start + width && src < src_limit) - { - uint32_t a = 0; - uint32_t r = 0; - uint32_t g = 0; - uint32_t b = 0; - int box = 1 << FIXED_SHIFT; - int start_coverage = coverage[x]; - - a = ((*src >> 24) & 0xff) * start_coverage; - r = ((*src >> 16) & 0xff) * start_coverage; - g = ((*src >> 8) & 0xff) * start_coverage; - b = ((*src >> 0) & 0xff) * start_coverage; - src++; - x++; - box -= start_coverage; - - while (box >= pixel_coverage && src < src_limit) - { - a += ((*src >> 24) & 0xff) * pixel_coverage; - r += ((*src >> 16) & 0xff) * pixel_coverage; - g += ((*src >> 8) & 0xff) * pixel_coverage; - b += ((*src >> 0) & 0xff) * pixel_coverage; - src++; - - box -= pixel_coverage; - } - - /* multiply by whatever is leftover - * this ensures that we don't bias down. - * i.e. start_coverage + n*pixel_coverage + box == 1 << 24 */ - if (box > 0 && src < src_limit) - { - a += ((*src >> 24) & 0xff) * box; - r += ((*src >> 16) & 0xff) * box; - g += ((*src >> 8) & 0xff) * box; - b += ((*src >> 0) & 0xff) * box; - } - - a >>= FIXED_SHIFT; - r >>= FIXED_SHIFT; - g >>= FIXED_SHIFT; - b >>= FIXED_SHIFT; - - *dest = (a << 24) | (r << 16) | (g << 8) | b; - dest++; - } -} - -static void downsample_columns_box_filter ( - int n, - int start_coverage, - int pixel_coverage, - uint32_t *src, uint32_t *dest) -{ - int stride = n; - while (n--) { - uint32_t a = 0; - uint32_t r = 0; - uint32_t g = 0; - uint32_t b = 0; - uint32_t *column_src = src; - int box = 1 << FIXED_SHIFT; - - a = ((*column_src >> 24) & 0xff) * start_coverage; - r = ((*column_src >> 16) & 0xff) * start_coverage; - g = ((*column_src >> 8) & 0xff) * start_coverage; - b = ((*column_src >> 0) & 0xff) * start_coverage; - column_src += stride; - box -= start_coverage; - - while (box >= pixel_coverage) - { - a += ((*column_src >> 24) & 0xff) * pixel_coverage; - r += ((*column_src >> 16) & 0xff) * pixel_coverage; - g += ((*column_src >> 8) & 0xff) * pixel_coverage; - b += ((*column_src >> 0) & 0xff) * pixel_coverage; - column_src += stride; - box -= pixel_coverage; - } - - if (box > 0) { - a += ((*column_src >> 24) & 0xff) * box; - r += ((*column_src >> 16) & 0xff) * box; - g += ((*column_src >> 8) & 0xff) * box; - b += ((*column_src >> 0) & 0xff) * box; - } - - a >>= FIXED_SHIFT; - r >>= FIXED_SHIFT; - g >>= FIXED_SHIFT; - b >>= FIXED_SHIFT; - - *dest = (a << 24) | (r << 16) | (g << 8) | b; - dest++; - src++; - } -} - -static int compute_coverage (int coverage[], int src_length, int dest_length) -{ - int i; - /* num = src_length/dest_length - total = sum(pixel) / num - - pixel * 1/num == pixel * dest_length / src_length - */ - /* the average contribution of each source pixel */ - int ratio = ((1 << 24)*(long long int)dest_length)/src_length; - /* because ((1 << 24)*(long long int)dest_length) won't always be divisible by src_length - * we'll need someplace to put the other bits. - * - * We want to ensure a + n*ratio < 1<<24 - * - * 1<<24 - * */ - - double scale = (double)src_length/dest_length; - - /* for each destination pixel compute the coverage of the left most pixel included in the box */ - /* I have a proof of this, which this margin is too narrow to contain */ - for (i=0; i= i*scale - - floor((i+1)*scale) - ceil(i*scale) <= scale - - further since: floor((i+1)*scale) - ceil(i*scale) is an integer - - therefore: - floor((i+1)*scale) - ceil(i*scale) <= floor(scale) - */ - - if (left_fract == 0.) - count--; - - /* compute how much the right-most pixel contributes */ - overage = ratio*(right_fract); - - /* the remainder is the amount that the left-most pixel - * contributes */ - coverage[i] = (1<<24) - (count * ratio + overage); - } - - return ratio; -} - - -bool CairoRescaleBox::downScaleImage(unsigned orig_width, unsigned orig_height, - signed scaled_width, signed scaled_height, - unsigned short int start_column, unsigned short int start_row, - unsigned short int width, unsigned short int height, - cairo_surface_t *dest_surface) { - int pixel_coverage_x, pixel_coverage_y; - int dest_y; - int src_y = 0; - uint32_t *scanline; - int *x_coverage = nullptr; - int *y_coverage = nullptr; - uint32_t *temp_buf = nullptr; - bool retval = false; - unsigned int *dest; - int dst_stride; - - dest = reinterpret_cast(cairo_image_surface_get_data (dest_surface)); - dst_stride = cairo_image_surface_get_stride (dest_surface); - - scanline = (uint32_t*)gmallocn (orig_width, sizeof(int)); - - x_coverage = (int *)gmallocn (orig_width, sizeof(int)); - y_coverage = (int *)gmallocn (orig_height, sizeof(int)); - - /* we need to allocate enough room for ceil(src_height/dest_height)+1 - Example: - src_height = 140 - dest_height = 50 - src_height/dest_height = 2.8 - - |-------------| 2.8 pixels - |----|----|----|----| 4 pixels - need to sample 3 pixels - - |-------------| 2.8 pixels - |----|----|----|----| 4 pixels - need to sample 4 pixels - */ - - temp_buf = (uint32_t *)gmallocn3 ((orig_height + scaled_height-1)/scaled_height+1, scaled_width, sizeof(uint32_t)); - - if (!x_coverage || !y_coverage || !scanline || !temp_buf) - goto cleanup; - - pixel_coverage_x = compute_coverage (x_coverage, orig_width, scaled_width); - pixel_coverage_y = compute_coverage (y_coverage, orig_height, scaled_height); - - assert (width + start_column <= scaled_width); - - - - /* skip the rows at the beginning */ - for (dest_y = 0; dest_y < start_row; dest_y++) - { - int box = 1 << FIXED_SHIFT; - int start_coverage_y = y_coverage[dest_y]; - box -= start_coverage_y; - src_y++; - while (box >= pixel_coverage_y) - { - box -= pixel_coverage_y; - src_y++; - } - } - - for (; dest_y < start_row + height; dest_y++) - { - int columns = 0; - int box = 1 << FIXED_SHIFT; - int start_coverage_y = y_coverage[dest_y]; - - getRow(src_y, scanline); - downsample_row_box_filter (start_column, width, scanline, scanline + orig_width, temp_buf + width * columns, x_coverage, pixel_coverage_x); - columns++; - src_y++; - box -= start_coverage_y; - - while (box >= pixel_coverage_y) - { - getRow(src_y, scanline); - downsample_row_box_filter (start_column, width, scanline, scanline + orig_width, temp_buf + width * columns, x_coverage, pixel_coverage_x); - columns++; - src_y++; - box -= pixel_coverage_y; - } - - /* downsample any leftovers */ - if (box > 0) - { - getRow(src_y, scanline); - downsample_row_box_filter (start_column, width, scanline, scanline + orig_width, temp_buf + width * columns, x_coverage, pixel_coverage_x); - columns++; - } - - /* now scale the rows we just downsampled in the y direction */ - downsample_columns_box_filter (width, start_coverage_y, pixel_coverage_y, temp_buf, dest); - dest += dst_stride / 4; - -// assert(width*columns <= ((orig_height + scaled_height-1)/scaled_height+1) * width); - } -// assert (src_y<=orig_height); - - retval = true; - -cleanup: - free (x_coverage); - free (y_coverage); - free (temp_buf); - free (scanline); - - return retval; -} diff --git a/pdf2htmlEX/3rdparty/poppler/git/CairoRescaleBox.h b/pdf2htmlEX/3rdparty/poppler/git/CairoRescaleBox.h deleted file mode 100644 index b00ad6a..0000000 --- a/pdf2htmlEX/3rdparty/poppler/git/CairoRescaleBox.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright © 2009 Mozilla Corporation - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the name of Mozilla Corporation not be used in - * advertising or publicity pertaining to distribution of the software without - * specific, written prior permission. Mozilla Corporation makes no - * representations about the suitability of this software for any purpose. It - * is provided "as is" without express or implied warranty. - * - * MOZILLA CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT - * SHALL MOZILLA CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE - * OF THIS SOFTWARE. - * - * Author: Jeff Muizelaar, Mozilla Corp. - */ - -//======================================================================== -// -// Modified under the Poppler project - http://poppler.freedesktop.org -// -// All changes made under the Poppler project to this file are licensed -// under GPL version 2 or later -// -// Copyright (C) 2012 Adrian Johnson -// Copyright (C) 2018 Albert Astals Cid -// -// To see a description of the changes please see the Changelog file that -// came with your tarball or type make ChangeLog if you are building from git -// -//======================================================================== - -#ifndef CAIRO_RESCALE_BOX_H -#define CAIRO_RESCALE_BOX_H - -#include - -class CairoRescaleBox { -public: - - CairoRescaleBox() {}; - virtual ~CairoRescaleBox() {}; - - CairoRescaleBox(const CairoRescaleBox &) = delete; - CairoRescaleBox& operator=(const CairoRescaleBox &) = delete; - - virtual bool downScaleImage(unsigned orig_width, unsigned orig_height, - signed scaled_width, signed scaled_height, - unsigned short int start_column, unsigned short int start_row, - unsigned short int width, unsigned short int height, - cairo_surface_t *dest_surface); - - virtual void getRow(int row_num, uint32_t *row_data) = 0; - -}; - -#endif /* CAIRO_RESCALE_BOX_H */ diff --git a/pdf2htmlEX/CMakeLists.txt b/pdf2htmlEX/CMakeLists.txt index 7cb7cd0..2bc76a0 100644 --- a/pdf2htmlEX/CMakeLists.txt +++ b/pdf2htmlEX/CMakeLists.txt @@ -23,41 +23,32 @@ find_package(PkgConfig) # SINCE we have a very intimate relationship with a particular version of # poppler... we explicitly describe the poppler include and library # paths. - +# include_directories( ../poppler/build/poppler ../poppler/build ../poppler/poppler ../poppler ) - -#link_directories( -# ../poppler/build -#) +# +# The following order is critical as the glib functions use functions +# located in the main poppler library +# set(POPPLER_LIBRARIES ${POPPLER_LIBRARIES} - ${CMAKE_SOURCE_DIR}/../poppler/build/libpoppler.a ${CMAKE_SOURCE_DIR}/../poppler/build/glib/libpoppler-glib.a + ${CMAKE_SOURCE_DIR}/../poppler/build/libpoppler.a ) if(ENABLE_SVG) pkg_check_modules(CAIRO REQUIRED cairo>=1.10.0) - message("Trying to locate cairo-svg...") + message("-- Trying to locate cairo-svg...") find_path(CAIRO_SVG_INCLUDE_PATH cairo-svg.h PATHS ${CAIRO_INCLUDE_DIRS} NO_DEFAULT_PATH) if(CAIRO_SVG_INCLUDE_PATH) + message("-- found cairo-svg...") include_directories(${CAIRO_INCLUDE_DIRS}) link_directories(${CAIRO_LIBRARY_DIRS}) set(PDF2HTMLEX_LIBS ${PDF2HTMLEX_LIBS} ${CAIRO_LIBRARIES}) set(ENABLE_SVG 1) - set(CAIROOUTPUTDEV_PATH 3rdparty/poppler/git) - include_directories(${CAIROOUTPUTDEV_PATH}) - set(PDF2HTMLEX_SRC ${PDF2HTMLEX_SRC} - ${CAIROOUTPUTDEV_PATH}/CairoFontEngine.h - ${CAIROOUTPUTDEV_PATH}/CairoFontEngine.cc - ${CAIROOUTPUTDEV_PATH}/CairoRescaleBox.h - ${CAIROOUTPUTDEV_PATH}/CairoRescaleBox.cc - ${CAIROOUTPUTDEV_PATH}/CairoOutputDev.h - ${CAIROOUTPUTDEV_PATH}/CairoOutputDev.cc - ) else() message(FATAL_ERROR "Error: no SVG support found in Cairo") endif() @@ -71,14 +62,14 @@ endif() # SINCE we have a very intimate relationship with a particular version of # fontforge... we explicitly describe the fontforge include and library # paths. - +# include_directories( ../fontforge/fontforge ../fontforge ../fontforge/build/inc ../fontforge/inc ) - +# include_directories(${FONTFORGE_INCLUDE_DIRS}) link_directories(${FONTFORGE_LIBRARY_DIRS}) set(FONTFORGE_LIBRARIES ${FONTFORGE_LIBRARIES}